diff --git a/dist/button.d.ts b/dist/button.d.ts new file mode 100644 index 0000000..9b04a89 --- /dev/null +++ b/dist/button.d.ts @@ -0,0 +1,115 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +declare const _default: OperationAuth; + +/** 按钮操作权限的单例;维护一份 uuid -> 是否有权限的映射,供 Button 组件的鉴权逻辑查询 */ +declare class OperationAuth { + /** @type {OperationAuth} */ + static "__#private@#instance": OperationAuth; + /** @returns {OperationAuth} 单例实例 */ + static getInstance: () => OperationAuth; + /** + * 用一批权限数据初始化/覆盖内部映射 + * @param {Iterable<[string, boolean]>} data uuid 到权限布尔值的键值对集合 + */ + init: (data: Iterable<[string, boolean]>) => Map; + /** + * 判断某个操作是否有权限;没有记录该 uuid 时默认视为有权限 + * @param {string} uuid 操作标识 + * @returns {boolean} 是否有权限 + */ + check: (uuid: string) => boolean; + #private; +} + +/** + * Button 组件点击行为的核心 hook;按 widgetType 把点击行为分发到对应的处理器 + * (跳转/自定义函数/弹窗组件/表单弹窗/数据列表弹窗/删除请求等) + * @param {Object} config + * @param {*} config.widget 目标(组件/函数名/表达式/路由等,含义随 widgetType 而定) + * @param {'redirect'|'func'|'component'|'fsdpf-component'|'grid-layout-form'|'data-list'|'destroy'} [config.widgetType] 行为类型 + * @param {*} [config.widgetData] 触发时附带的数据 + * @param {Object} [config.widgetProps] 触发前解析的 props 配置(经 getWidgetPropsData) + * @param {Object} [config.widgetSetting] 传给目标(弹窗/表单/请求)的配置 + * @param {Object} [config.widgetContainerProps] 传给弹窗容器的 props + * @param {Object} [handlers] + * @param {(result: *) => void} [handlers.onAfterClick] 动作完成后的回调 + * @param {(data: *) => void} [handlers.onBeforeClick] 动作开始前的回调 + * @returns {[(data: *) => void, {loading?: boolean, disabled?: boolean}]} [点击处理函数(已做 300ms 防抖), 当前 loading/disabled 状态] + */ +declare function useButton({ widget, widgetType, widgetData, widgetProps, widgetSetting, widgetContainerProps, }: { + widget: any; + widgetType?: "redirect" | "func" | "component" | "fsdpf-component" | "grid-layout-form" | "data-list" | "destroy"; + widgetData?: any; + widgetProps?: any; + widgetSetting?: any; + widgetContainerProps?: any; +}, { onAfterClick, onBeforeClick }?: { + onAfterClick?: (result: any) => void; + onBeforeClick?: (data: any) => void; +}): [(data: any) => void, { + loading?: boolean; + disabled?: boolean; +}]; + +declare function Button({ className, variant, children, name, icon, type, iconPosition, noAuthType, onAfterClick, onBeforeClick, data, loading: customLoading, disabled: customDisabled, tooltip, confirm, widget, widgetType, widgetData, widgetProps, widgetSetting, widgetContainerProps, ...props }: { + [x: string]: any; + className: any; + variant: any; + children: any; + name: any; + icon: any; + type?: string; + iconPosition?: string; + noAuthType: any; + onAfterClick: any; + onBeforeClick: any; + data: any; + loading: any; + disabled: any; + tooltip: any; + confirm: any; + widget?: () => void; + widgetType: any; + widgetData: any; + widgetProps: any; + widgetSetting: any; + widgetContainerProps: any; +}): React.JSX.Element; +declare namespace Button { + namespace propTypes { + let type: PropTypes.Requireable; + let size: PropTypes.Requireable; + let name: PropTypes.Requireable; + let icon: PropTypes.Requireable; + let iconPosition: PropTypes.Requireable; + let data: PropTypes.Requireable; + let widget: PropTypes.Requireable; + let widgetType: PropTypes.Requireable; + let widgetData: PropTypes.Requireable; + let widgetProps: PropTypes.Requireable; + let widgetSetting: PropTypes.Requireable; + let widgetContainerProps: PropTypes.Requireable; + let tooltip: PropTypes.Requireable; + placement: PropTypes.Requireable; + enabled: PropTypes.Requireable>; + getPopupContainer: PropTypes.Requireable<(...args: any[]) => any>; + }>>>; + let confirm: PropTypes.Requireable; + cancelText: PropTypes.Requireable; + okText: PropTypes.Requireable; + okType: PropTypes.Requireable; + placement: PropTypes.Requireable; + enabled: PropTypes.Requireable>; + getPopupContainer: PropTypes.Requireable<(...args: any[]) => any>; + arrow: PropTypes.Requireable; + }>>>>; + }>>>; + } +} + +export { _default as auth, Button as default, useButton }; diff --git a/dist/button.js b/dist/button.js index c810bc4..e2ca141 100644 --- a/dist/button.js +++ b/dist/button.js @@ -1,4 +1,4 @@ -import { am as s, al as u, an as e } from "./common/main-DsRa-iMx.js"; +import { am as s, al as u, an as e } from "./common/main-DahsFEqk.js"; export { s as auth, u as default, diff --git a/dist/common/main-DsRa-iMx.js b/dist/common/main-DahsFEqk.js similarity index 99% rename from dist/common/main-DsRa-iMx.js rename to dist/common/main-DahsFEqk.js index 94272ce..2a2c23e 100644 --- a/dist/common/main-DsRa-iMx.js +++ b/dist/common/main-DahsFEqk.js @@ -698,7 +698,7 @@ const $n = { null2json: (t) => Object.create(), null2array: (t) => [], null2numb if (!Array.isArray(t)) return t; for (let r = 0; r < t.length; r++) t[r].value = ue((n = t[r]) == null ? void 0 : n.value, e), t[r] && Reflect.has(t[r], "children") && (t[r].children = rr(t[r].children, e)); return t; -}, Wo = (t, e = "json", n = "string", r, i = null) => { +}, Wo = (t, e = "json", n = "string", r = null, i = null) => { const [o] = ae.useForm(r), [a, s] = L([{ label: "无", value: "", disabled: !0 }]), l = H([]), c = ae.useWatch((u) => l.current.length === 0 ? null : w.pick(u, l.current), o) || null; return W(() => { Array.isArray(t) ? s(t) : e === "javascript" && t ? Le.exec(t, {}, { getFieldValue: (u) => (l.current.includes(u) || l.current.push(u), o.getFieldValue(u)), getFieldValueForBasicForm: (u) => (l.current.includes(u) || l.current.push(u), i ? i.getFieldValue(u) : o.getFieldValue(u)) }).then((u) => { diff --git a/dist/components.d.ts b/dist/components.d.ts new file mode 100644 index 0000000..c485947 --- /dev/null +++ b/dist/components.d.ts @@ -0,0 +1,115 @@ +import * as React from 'react'; +import React__default from 'react'; +import PropTypes from 'prop-types'; + +/** + * 渲染一个 iconfont symbol 图标(依赖 Iconfont.init 注入的 SVG symbol 脚本) + * @param {Object} props + * @param {string} [props.className] 额外的 class 名 + * @param {string} props.type 图标名,对应 svg symbol 的 id + * @param {Object} [props.style] 行内样式 + */ +declare function Iconfont({ className, type, style, ...props }: { + className?: string; + type: string; + style?: any; +}): React__default.JSX.Element; +declare namespace Iconfont { + export namespace propTypes { + let className: PropTypes.Requireable; + let type: PropTypes.Validator; + let style: PropTypes.Requireable; + } + export { createScriptUrlElements as init }; +} + +/** + * 依次注入 iconfont symbol 的 script 地址(单个 url 只会注入一次); + * 也是 Iconfont.init 挂载的实现,支持传入多个 url 按顺序加载(前一个 load/error 后再加载下一个) + * @param {string[]} [scriptUrls] iconfont symbol 脚本地址列表 + * @param {number} [index] 内部递归用的当前下标 + */ +declare function createScriptUrlElements(scriptUrls?: string[], index?: number): void; + +/** + * 包装一个弹窗内容组件,让它可以通过 $setProps 更新自己的 props(与外部传入的 widgetProps 做浅合并), + * 同时注入 $close 用于关闭弹窗 + * @param {Object} props + * @param {import('react').ReactElement|Function} props.widget 要渲染的元素或组件 + * @param {Object} [props.widgetProps] 外部传入的初始 props,变化时会合并进内部状态 + * @param {(result?: *) => void} props.$close 关闭弹窗的函数,会透传给 widget + * @param {(patch: Object) => void} [props.onSetProps] $setProps 被调用时的回调,用于同步外部状态 + */ +declare function SetPropsWrapper({ widget, widgetProps: externalProps, $close, onSetProps }: { + widget: React.ReactElement | Function; + widgetProps?: any; + $close: (result?: any) => void; + onSetProps?: (patch: any) => void; +}): Function | React__default.ReactElement>; + +/** 空状态占位组件 */ +declare function Empty(): React__default.JSX.Element; + +/** 加载中占位组件 */ +declare function Loading(): React__default.JSX.Element; + +/** 未找到占位组件 */ +declare function NotFound(): React__default.JSX.Element; + +declare namespace FFPopup { + export { modal }; + export { confirm }; + export { form }; + export { notification }; + export { success }; + export { error }; +} + +/** + * 打开一个任意组件的弹窗 + * @param {Function} widget 要渲染的组件 + * @param {Object} [widgetData] 传给组件的 props + * @param {Object} [widgetContainerProps] 传给弹窗容器(PopupContainer)的 props + * @returns {Promise<*>&{update: Function}} resolve 弹窗关闭时传入的值;promise.update(patch, containerPatch) 可用来更新弹窗内容 + */ +declare function modal(widget: Function, widgetData?: any, widgetContainerProps?: any): Promise & { + update: Function; +}; +/** + * 弹出一个确认框 + * @param {*} content 确认框内容 + * @param {Object} [opts] 其余透传给 Confirm 组件的 props + * @returns {Promise<*>} 点击确认时 resolve,点击取消/关闭时按 modal 的语义处理 + */ +declare function confirm(content: any, opts?: any): Promise; +/** + * 弹出一个模态表单;取消时 reject(false) + * @param {Array} fields 表单字段配置(传给 FormModal 的 fields) + * @param {Object} [widgetContainerProps] 传给弹窗容器的 props + * @param {Object} [formProps] 传给表单的额外 props + * @returns {Promise} 提交后的表单数据 + */ +declare function form(fields: any[], widgetContainerProps?: any, formProps?: any): Promise; +/** + * 弹出一条消息提示 + * @param {*} content 提示内容 + * @param {Object} [opts] 其余透传给 Notification 组件的 props,duration/showProgress 会转发到容器 props + * @returns {Promise<*>} + */ +declare function notification(content: any, { showProgress, duration, ...opts }?: any): Promise; +/** + * 成功提示(绿色图标样式的 notification) + * @param {*} content 提示内容 + * @param {Object} [opts] 其余透传给 notification 的选项 + * @returns {Promise<*>} + */ +declare function success(content: any, opts?: any): Promise; +/** + * 错误提示(红色图标样式的 notification) + * @param {*} content 提示内容 + * @param {Object} [opts] 其余透传给 notification 的选项 + * @returns {Promise<*>} + */ +declare function error(content: any, opts?: any): Promise; + +export { Empty, Iconfont as Icon, Loading, NotFound, FFPopup as Popup, SetPropsWrapper }; diff --git a/dist/components.js b/dist/components.js index 2860b7f..4ea518b 100644 --- a/dist/components.js +++ b/dist/components.js @@ -1,4 +1,4 @@ -import { at as s, ak as p, au as r, av as t, as as e, aI as n } from "./common/main-DsRa-iMx.js"; +import { at as s, ak as p, au as r, av as t, as as e, aI as n } from "./common/main-DahsFEqk.js"; export { s as Empty, p as Icon, diff --git a/dist/container.d.ts b/dist/container.d.ts new file mode 100644 index 0000000..1bf6a80 --- /dev/null +++ b/dist/container.d.ts @@ -0,0 +1,152 @@ +import * as React from 'react'; +import React__default from 'react'; +import PropTypes from 'prop-types'; + +/** 空状态占位组件 */ +declare function Empty(): React__default.JSX.Element; + +/** 加载中占位组件 */ +declare function Loading(): React__default.JSX.Element; + +/** 未找到占位组件 */ +declare function NotFound(): React__default.JSX.Element; + +/** + * 为页面级布局提供 SlotContext,把子元素(通常是 FFContainer)挂载的 + * title/subTitle/actions/extras 等插槽内容收集起来,再作为 props 传回给这个子元素 + * @param {Object} props + * @param {import('react').ReactElement} props.children 单个子元素(字符串类型的元素会跳过插槽逻辑,原样返回) + */ +declare function FFPageRender({ children }: { + children: React.ReactElement; +}): React__default.JSX.Element; +declare namespace FFPageRender { + namespace propTypes { + let children: PropTypes.Validator; + } +} + +/** FFContainer 内部用来把 title/subTitle/actions/extras 等具名插槽挂载到外层布局的 context */ +declare const SlotContext: React__default.Context<{ + ele: {}; + mount: () => void; + unmount: () => void; +}>; + +/** + * 页面级容器,通过 SlotContext 把 title/subTitle/actions/extras 挂载到外层布局的对应插槽位置 + * @param {Object} props + * @param {string} [props.rootClassName] 挂载到外层布局根节点的 className + * @param {string} [props.className] 容器自身的 className + * @param {*} [props.children] 容器内容 + * @param {*} [props.actions] 挂载到 actions 插槽的内容 + * @param {*} [props.title] 挂载到 title 插槽的内容 + * @param {*} [props.subTitle] 挂载到 sub-title 插槽的内容 + * @param {*} [props.extras] 挂载到 extras 插槽的内容 + * @param {Object} [props.style] 容器行内样式 + */ +declare function FFContainer({ rootClassName, className, children, actions, title, subTitle, extras, style }: { + rootClassName?: string; + className?: string; + children?: any; + actions?: any; + title?: any; + subTitle?: any; + extras?: any; + style?: any; +}): React__default.JSX.Element; +declare namespace FFContainer { + function Action({ children, className }: { + children: any; + className: any; + }): any; + function Title({ children, className }: { + children: any; + className: any; + }): any; + function SubTitle({ children, className }: { + children: any; + className: any; + }): any; + function Extra({ children, className }: { + children: any; + className: any; + }): any; + namespace propTypes { + let className: PropTypes.Requireable; + let style: PropTypes.Requireable; + let title: PropTypes.Requireable; + let subTitle: PropTypes.Requireable; + let actions: PropTypes.Requireable; + let extras: PropTypes.Requireable; + } +} + +declare namespace FFPopup { + export { modal }; + export { confirm }; + export { form }; + export { notification }; + export { success }; + export { error }; +} + +/** + * 打开一个任意组件的弹窗 + * @param {Function} widget 要渲染的组件 + * @param {Object} [widgetData] 传给组件的 props + * @param {Object} [widgetContainerProps] 传给弹窗容器(PopupContainer)的 props + * @returns {Promise<*>&{update: Function}} resolve 弹窗关闭时传入的值;promise.update(patch, containerPatch) 可用来更新弹窗内容 + */ +declare function modal(widget: Function, widgetData?: any, widgetContainerProps?: any): Promise & { + update: Function; +}; +/** + * 弹出一个确认框 + * @param {*} content 确认框内容 + * @param {Object} [opts] 其余透传给 Confirm 组件的 props + * @returns {Promise<*>} 点击确认时 resolve,点击取消/关闭时按 modal 的语义处理 + */ +declare function confirm(content: any, opts?: any): Promise; +/** + * 弹出一个模态表单;取消时 reject(false) + * @param {Array} fields 表单字段配置(传给 FormModal 的 fields) + * @param {Object} [widgetContainerProps] 传给弹窗容器的 props + * @param {Object} [formProps] 传给表单的额外 props + * @returns {Promise} 提交后的表单数据 + */ +declare function form(fields: any[], widgetContainerProps?: any, formProps?: any): Promise; +/** + * 弹出一条消息提示 + * @param {*} content 提示内容 + * @param {Object} [opts] 其余透传给 Notification 组件的 props,duration/showProgress 会转发到容器 props + * @returns {Promise<*>} + */ +declare function notification(content: any, { showProgress, duration, ...opts }?: any): Promise; +/** + * 成功提示(绿色图标样式的 notification) + * @param {*} content 提示内容 + * @param {Object} [opts] 其余透传给 notification 的选项 + * @returns {Promise<*>} + */ +declare function success(content: any, opts?: any): Promise; +/** + * 错误提示(红色图标样式的 notification) + * @param {*} content 提示内容 + * @param {Object} [opts] 其余透传给 notification 的选项 + * @returns {Promise<*>} + */ +declare function error(content: any, opts?: any): Promise; +/** + * 弹层渲染出口(通常挂载一份到页面根部);负责渲染 FFPopup 触发的所有弹窗/模态框和 notification。 + * 在挂载前调用 FFPopup 的方法会被排队,挂载后统一渲染出来 + */ +declare function FFPopupRender(): React__default.JSX.Element; +declare namespace FFPopupRender { + let $popups: Map; + let $index: number; + let $queue: any[]; + function $onClick(...args: any[]): Promise; +} + +export { SlotContext as Context, Empty, Loading, NotFound, FFPageRender as PageRender, FFPopup as Popup, FFPopupRender as PopupRender, FFContainer as default }; diff --git a/dist/container.js b/dist/container.js index 5e8579b..41fffec 100644 --- a/dist/container.js +++ b/dist/container.js @@ -1,4 +1,4 @@ -import { ap as s, at as e, au as p, av as t, aq as d, as as n, ar as r, ao as u } from "./common/main-DsRa-iMx.js"; +import { ap as s, at as e, au as p, av as t, aq as d, as as n, ar as r, ao as u } from "./common/main-DahsFEqk.js"; export { s as Context, e as Empty, diff --git a/dist/data-converter.d.ts b/dist/data-converter.d.ts new file mode 100644 index 0000000..58142f9 --- /dev/null +++ b/dist/data-converter.d.ts @@ -0,0 +1,33 @@ +import React from 'react'; + +/** + * 按一串中间件(middleware)链式转换数据;每个中间件可以是函数,也可以是要动态加载的 + * 组件名字符串(通过 core.getWidgetComponent 解析),支持嵌套数组表示的中间件组 + */ +declare class DataConverter { + static "__#private@#resolver": any; + static "__#private@#newMiddleware": any; + /** + * @param {...(Array|[string|Function, *])} middlewares 中间件列表,每项是 + * [中间件名或函数, 传给中间件的配置],或者是这种元组的嵌套数组(会被展开) + */ + constructor(...middlewares: (any[] | [string | Function, any])[]); + /** + * 依次跑完所有中间件,把 value 转换成最终结果;单个中间件报错会被跳过,不中断整条链 + * @param {*} value 原始值 + * @param {*} [record] 关联的记录数据,中间件里可通过 this.getRecord() 取到 + * @returns {Promise<*>} 转换后的结果 + */ + toValue: (value: any, record?: any) => Promise; + /** + * 把 toValue 的异步转换结果渲染成 React 元素;转换完成前显示 loading,转换出错则显示错误信息 + * @param {*} value 原始值 + * @param {*} record 关联的记录数据 + * @param {*} [loading] 转换完成前显示的占位内容 + * @returns {React.ReactElement} + */ + toRender: (value: any, record: any, loading?: any) => React.ReactElement; + #private; +} + +export { DataConverter as default }; diff --git a/dist/data-converter.js b/dist/data-converter.js index d5dda21..e261842 100644 --- a/dist/data-converter.js +++ b/dist/data-converter.js @@ -1,6 +1,6 @@ import "lodash"; import "react"; -import { D as i } from "./common/main-DsRa-iMx.js"; +import { D as i } from "./common/main-DahsFEqk.js"; import "react-use"; export { i as default diff --git a/dist/data-list.d.ts b/dist/data-list.d.ts new file mode 100644 index 0000000..2f82fd2 --- /dev/null +++ b/dist/data-list.d.ts @@ -0,0 +1,418 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +/** + * 处理表格列配置:为每列注入 onCell,并按 middlewares/widgetByJs 组装渲染中间件链(通过 DataConverter)生成最终的 render 函数 + * @param {Array} columns 原始列配置(可能包含 widgetByJs/widgetByJsSetting/middlewares/render) + * @param {Object} [base62params={}] 分页/查询参数,仅作为依赖项触发重新计算 + * @returns {Array} 处理后可直接传给 antd Table 的列配置 + */ +declare function useColumnsRender(columns: Array, base62params?: any): Array; +/** + * 补全 antd Table 的 components 配置,确保 body.cell 默认使用可编辑单元格组件 DataListCellEditable + * @param {Object} [components={}] 原始 components 配置 + * @returns {Object} 补全后的 components 配置 + */ +declare function useCellEditableComponents(components?: any): any; +/** + * 根据 listCode 拉取列表结构配置(字段/列/分页/布局等元数据) + * @param {string} listCode 列表标识 + * @returns {Object} 列表结构配置,请求完成前为空对象 + */ +declare function useStructure(listCode: string): any; +/** + * 根据 listCode 及查询参数拉取列表数据 + * @param {string} listCode 列表标识 + * @param {Object} [base62params={}] 查询参数,会与 page:1 合并后进行 base62 编码请求 + * @returns {Object} 接口返回的数据,包含 dataSource 等字段;请求完成前为 { dataSource: [] } + */ +declare function useDataSource(listCode: string, base62params?: any): any; +/** + * 生成一个按权限映射过滤某行数据可用行内操作按钮的函数 + * @param {Array} [itemOperations=[]] 行内操作按钮配置 + * @param {Map} [itemOperationsAccess=new Map] 操作 uuid 到有权限的数据主键列表的映射 + * @param {string} [pk='id'] 主键字段名 + * @param {string} [resource] 数据嵌套的资源字段名(主键从 data[resource][pk] 取值) + * @returns {(data: Object) => Array} 传入一行数据,返回其可用操作按钮列表 + */ +declare function useItemOperationsAccess(itemOperations?: Array, itemOperationsAccess?: Map, pk?: string, resource?: string): (data: any) => Array; +/** + * 判断是否需要渲染操作列:操作按钮需通过全局权限校验(auth.check),且(若配置了行级权限映射)当前数据中至少一行拥有权限 + * @param {Array} [operations=[]] 操作按钮配置 + * @param {Map} [itemOperationsAccess=new Map] 操作 uuid 到有权限的数据主键列表的映射 + * @param {Array} [dataSource=[]] 当前页数据 + * @param {string} [pk='id'] 主键字段名 + * @param {string} [resource] 数据嵌套的资源字段名 + * @returns {boolean} 是否存在可展示的操作列 + */ +declare function useHasOperationColumn(operations?: Array, itemOperationsAccess?: Map, dataSource?: Array, pk?: string, resource?: string): boolean; +/** + * 生成行内/批量操作点击后的处理逻辑:isRefresh=1 触发整体刷新(onReload),isRefresh=2 仅拉取该行最新详情与权限并合并回 dataSource(局部刷新) + * @param {Object} props 列表状态,须包含 dataSource/itemOperationsAccess/onReload + * @param {string} listCode 列表标识 + * @param {string} [primaryKey='id'] 主键字段名 + * @param {string} [resource=null] 数据嵌套的资源字段名 + * @returns {[Object, (isRefresh: number, item?: Object) => void]} 元组:可能已合并局部刷新结果的 props,以及操作点击回调 + */ +declare function useOperationCallback(props: any, listCode: string, primaryKey?: string, resource?: string): [any, (isRefresh: number, item?: any) => void]; +/** + * 组合式获取并管理列表数据(分页/tab/筛选条件/侧边栏/关键字等),供 DataListHelper 使用 + * @param {string} listCode 列表标识 + * @param {Object} base62params 初始查询参数 + * @returns {Object} 列表状态与操作方法(dataSource/tab/page/pageSize/condition/sider/keyword/total/itemOperationsAccess/onXxxChange/onReload/payload 等) + */ +declare function useDataListHelper(listCode: string, base62params: any): any; + +/** + * 数据列表根组件:根据 isItemGridLayout 选择宫格(DataListFramework)或表格(DataTableFramework)布局, + * 也可通过 theme 动态加载自定义主题组件替代默认布局;并通过 DataListContext 向下透传分页/筛选/选中等状态与操作方法 + * @param {Object} props + * @param {boolean} [props.isItemGridLayout] 是否使用宫格布局(否则使用表格布局,theme 设置时忽略) + * @param {string} [props.theme] 自定义主题组件标识,设置后通过 core.getWidgetComponent 动态加载并替代默认布局 + * @param {Object} [props.themeProps] 传给自定义主题组件的 $setting + * @param {Function} [props.onClickCallback] 行内/批量操作点击后的回调 + * @param {Function} [props.onReload] 刷新回调 + * @param {string} [props.listCode] 列表标识 + * @param {number} [props.total=0] 数据总条数 + * @param {number} [props.page=0] 当前页码 + * @param {Function} [props.onPageChange] 页码变更回调 + * @param {number} [props.pageSize=30] 每页条数 + * @param {Function} [props.onPageSizeChange] 每页条数变更回调 + * @param {*} [props.tab] 当前选中的 tab + * @param {Function} [props.onTabChange] tab 变更回调 + * @param {string} [props.keyword] 关键字搜索值 + * @param {Function} [props.onKeywordChange] 关键字变更回调 + * @param {Object} [props.condition] 筛选条件 + * @param {Function} [props.onConditionChange] 筛选条件变更回调 + * @param {*} [props.sider] 侧边栏选中值 + * @param {Function} [props.onSiderChange] 侧边栏选中值变更回调 + * @param {boolean|Object} [props.layouts] 自定义子布局组件集合(sider/filter/footer/toolbar/empty),false 表示全部隐藏 + * @param {Object} [props.classNames={}] 各区块自定义 className + * @param {Object} [props.payload={}] 附加请求参数 + * @param {Array} [props.dataSource=[]] 列表数据 + * @param {Object} [props.rowSelection] 行选择配置 + * @param {Function} [props.getSelectedRows] 获取已选中行的方法,未提供时默认返回 dataSource + * @param {string} [props.primaryKey] 主键字段名 + */ +declare function DataList({ isItemGridLayout, theme, themeProps, onClickCallback, onReload, listCode, total, page, onPageChange, pageSize, onPageSizeChange, tab, onTabChange, keyword, onKeywordChange, condition, onConditionChange, sider, onSiderChange, layouts, classNames, payload, dataSource, rowSelection, getSelectedRows: getSelectedRowsProp, primaryKey, ...props }: { + isItemGridLayout?: boolean; + theme?: string; + themeProps?: any; + onClickCallback?: Function; + onReload?: Function; + listCode?: string; + total?: number; + page?: number; + onPageChange?: Function; + pageSize?: number; + onPageSizeChange?: Function; + tab?: any; + onTabChange?: Function; + keyword?: string; + onKeywordChange?: Function; + condition?: any; + onConditionChange?: Function; + sider?: any; + onSiderChange?: Function; + layouts?: boolean | any; + classNames?: any; + payload?: any; + dataSource?: any[]; + rowSelection?: any; + getSelectedRows?: Function; + primaryKey?: string; +}): React.JSX.Element; +declare namespace DataList { + namespace propTypes { + let classNames: PropTypes.Requireable; + filter: PropTypes.Requireable; + footer: PropTypes.Requireable; + toolbar: PropTypes.Requireable; + container: PropTypes.Requireable; + content: PropTypes.Requireable; + item: PropTypes.Requireable; + empty: PropTypes.Requireable; + }>>>; + let layouts: PropTypes.Requireable>; + filter: PropTypes.Requireable>; + footer: PropTypes.Requireable>; + toolbar: PropTypes.Requireable>; + empty: PropTypes.Requireable>; + }>>>>; + } +} + +/** + * 列表筛选区:isConditionFormLayout 为 true 时拉取后台配置的条件表单结构并渲染 GridLayoutForm,否则渲染默认的关键字搜索框 + * @param {Object} props + * @param {string} [props.className] 自定义 className + * @param {boolean} [props.isConditionFormLayout] 是否使用后台配置的条件表单布局 + */ +declare function DataListFilter({ className, isConditionFormLayout }: { + className?: string; + isConditionFormLayout?: boolean; +}): React.JSX.Element; +declare namespace DataListFilter { + let reservedFields: { + x: number; + y: number; + h: number; + w: number; + field: { + isVirtual: boolean; + widgetPrefix: string; + widget: string; + code: string; + label: string; + placeholder: string; + extras: { + prefix: string; + }; + }; + }[]; +} + +/** + * 列表工具栏:展示标题、tab 面包屑导航以及刷新等操作按钮 + * @param {Object} props + * @param {string} [props.className] 自定义 className + * @param {string} [props.title] 列表标题 + * @param {Array} [props.tabs] tab 配置列表 + */ +declare function DataListToolbar({ className, title, tabs }: { + className?: string; + title?: string; + tabs?: Array; +}): React.JSX.Element; + +/** + * 列表侧边栏:isTreeSider 为 true 时渲染目录树(当前 treeData 为占位示例数据) + * @param {Object} props + * @param {string} [props.className] 自定义 className + * @param {number} [props.width=280] 侧边栏宽度 + * @param {boolean} [props.isTreeSider] 是否渲染树形侧边栏 + */ +declare function DataListSider({ className, width, isTreeSider }: { + className?: string; + width?: number; + isTreeSider?: boolean; +}): React.JSX.Element; + +/** + * 列表底部:渲染批量操作按钮与分页器;operations 为空且不分页时不渲染任何内容 + * @param {Object} props + * @param {string} [props.className] 自定义 className + * @param {Array} [props.operations] 批量操作按钮配置 + * @param {boolean} [props.isOperations] 是否展示批量操作按钮 + * @param {boolean} [props.isPaginate] 是否展示分页器 + */ +declare function DataListFooter({ className, operations, isOperations, isPaginate }: { + className?: string; + operations?: Array; + isOperations?: boolean; + isPaginate?: boolean; +}): React.JSX.Element; + +/** + * DataList 的开箱即用封装:根据 listCode 自动拉取结构与数据、管理分页/筛选/选中等状态, + * 并通过 ref 暴露 onReload/onClickCallback/getSelectedRows + * @param {Object} props + * @param {string} props.listCode 列表标识 + * @param {Object} [props.base62params] 初始查询参数 + * @param {string} [props.className] 自定义 className + * @param {string} [props.theme] 自定义主题组件标识,未传时使用结构配置中的 theme + * @param {Object} [props.themeProps] 传给主题组件的 $setting,会与结构配置中的 themeConfig 合并 + * @param {boolean|Object} [props.layouts] 自定义子布局组件集合 + * @param {Object} [props.classNames] 各区块自定义 className + * @param {Object} [props.rowSelection] 行选择配置(type/selectedRowKeys/defaultSelectedRowKeys/onChange 等) + * @param {(dataSource: Array, meta: Object) => void} [props.onDataSourceChange] dataSource 变更后的回调 + */ +declare const DataListHelper: React.ForwardRefExoticComponent>; + +declare const _default: React.Context<{ + listCode: string; + classNames: {}; + getBase62params: (k: any, defaultValue: any) => void; + getSelectedRows: () => any[]; + onReload: () => void; + onClickCallback: () => void; + onConditionChange: () => void; + onTabChange: () => void; + onSiderChange: () => void; + onKeywordChange: () => void; + onPageChange: () => void; + onPageSizeChange: () => void; + reload: () => void; + setPage: () => void; + setPageSize: () => void; + setTab: () => void; + setSider: () => void; + setKeyword: () => void; + setCondition: () => void; +}>; + +/** + * 列表表格视图:在 antd Table 基础上支持列宽按容器自适应缩放、单元格可编辑、默认展开行等能力 + * @param {Object} props + * @param {string} [props.className] 自定义 className + * @param {string} [props.primaryKey] 主键字段名 + * @param {Array} [props.columns=[]] 列配置 + * @param {Array} [props.dataSource=[]] 表格数据 + * @param {(record: Object, index: number) => *} [props.operationRender] 操作列渲染函数,提供时会追加一列操作列 + * @param {number} [props.operationWidth=180] 操作列宽度 + * @param {Object} [props.components={}] antd Table 的 components 配置 + * @param {Object} [props.rowSelection] 行选择配置 + */ +declare function DataListTable({ className, primaryKey, columns, dataSource, operationRender, operationWidth, components, rowSelection, ...props }: { + className?: string; + primaryKey?: string; + columns?: Array; + dataSource?: Array; + operationRender?: (record: any, index: number) => any; + operationWidth?: number; + components?: any; + rowSelection?: any; +}): React.JSX.Element; + +/** + * 列表宫格(卡片)视图:基于 GridLayout 渲染每条数据的卡片,并处理行选中状态 + * @param {Object} props + * @param {number} [props.column=0] 每行列数 + * @param {number} [props.colWidth=0] 列宽 + * @param {number} [props.cols] GridLayout 栅格总列数 + * @param {number} [props.rowHeight] 行高 + * @param {[number, number]} [props.itemMargin] 卡片间距 [marginX, marginY] + * @param {*} [props.containerPadding] 容器内边距 + * @param {Array} [props.fields] 卡片内字段/组件布局配置 + * @param {string} [props.primaryKey] 主键字段名 + * @param {Array} [props.dataSource] 列表数据 + * @param {(dataSource: Array) => *} [props.beforeRender=null] 数据渲染前的额外内容 + * @param {(dataSource: Array) => *} [props.afterRender=null] 数据渲染后的额外内容 + * @param {string} [props.itemClassName] 传给每张卡片(itemRender.children)的 className + * @param {(children: *, data: Object, index: number) => *} [props.itemRender] 卡片渲染包装函数 + * @param {*} [props.empty] 空数据时展示的内容 + * @param {string} [props.className] 自定义 className + * @param {Object} [props.style={}] 容器行内样式 + * @param {string} [props.theme] GridLayout 主题 + * @param {Object} [props.themeProps={}] GridLayout 主题参数 + * @param {Array} [props.groups=[{ key: 'default', label: '默认' }]] 分组配置 + * @param {Object} [props.rowSelection] 行选择配置(selectedRowKeys/onChange/type) + */ +declare function DataListContent({ column, colWidth, cols, rowHeight, itemMargin, containerPadding, fields, primaryKey, dataSource, beforeRender, afterRender, itemClassName, itemRender, empty, className, style, theme, themeProps, groups, rowSelection, }: { + column?: number; + colWidth?: number; + cols?: number; + rowHeight?: number; + itemMargin?: [number, number]; + containerPadding?: any; + fields?: Array; + primaryKey?: string; + dataSource?: Array; + beforeRender?: (dataSource: any[]) => any; + afterRender?: (dataSource: any[]) => any; + itemClassName?: string; + itemRender?: (children: any, data: any, index: number) => any; + empty?: any; + className?: string; + style?: any; + theme?: string; + themeProps?: any; + groups?: Array; + rowSelection?: any; +}): React.JSX.Element; + +/** + * 宫格列表整体布局:组合侧边栏/筛选/工具栏/内容(卡片列表)/底部分页等子区块,并为每条数据包装行内操作按钮 + * @param {Object} props + * @param {string} [props.listCode] 列表标识 + * @param {string} [props.className] 自定义 className + * @param {Object} [props.layouts={}] 子布局组件集合 { sider, filter, toolbar, footer, empty } + * @param {Array} [props.dataSource] 列表数据 + * @param {boolean} [props.isPaginate] 是否分页 + * @param {boolean} [props.isItemOperations] 是否展示行内操作按钮 + * @param {boolean} [props.isBatchOperations] 是否展示批量操作按钮 + * @param {Array} [props.batchOperations] 批量操作按钮配置 + * @param {Array} [props.itemOperations] 行内操作按钮配置 + * @param {Map} [props.itemOperationsAccess] 行内操作权限映射 + * @param {string} [props.resource] 数据嵌套的资源字段名 + * @param {string} [props.primaryKey] 主键字段名 + * @param {string} [props.title] 列表标题 + * @param {Object} [props.itemGridLayout] 卡片宫格布局配置,透传给 DataListContent + * @param {Object} [props.$setting] 主题设置,包含 column/colWidth/beforeRender/afterRender/style/itemMargin/containerPadding/isMarkSelected + * @param {Array} [props.tabs] tab 配置 + * @param {boolean} [props.isConditionFormLayout] 是否使用条件表单布局 + * @param {boolean} [props.isTreeSider] 是否展示树形侧边栏 + * @param {Object} [props.treeSiderConfig] 树形侧边栏配置 + * @param {Object} [props.rowSelection] 行选择配置 + */ +declare function DataListFramework({ listCode, className, layouts, dataSource, isPaginate, isItemOperations, isBatchOperations, batchOperations, itemOperations, itemOperationsAccess, resource, primaryKey, title, itemGridLayout, $setting, tabs, isConditionFormLayout, isTreeSider, treeSiderConfig, rowSelection, }: { + listCode?: string; + className?: string; + layouts?: any; + dataSource?: Array; + isPaginate?: boolean; + isItemOperations?: boolean; + isBatchOperations?: boolean; + batchOperations?: Array; + itemOperations?: Array; + itemOperationsAccess?: Map; + resource?: string; + primaryKey?: string; + title?: string; + itemGridLayout?: any; + $setting?: any; + tabs?: Array; + isConditionFormLayout?: boolean; + isTreeSider?: boolean; + treeSiderConfig?: any; + rowSelection?: any; +}): React.JSX.Element; + +/** + * 表格列表整体布局:组合侧边栏/筛选/工具栏/表格(DataListTable)/底部分页等子区块,并按权限计算操作列 + * @param {Object} props + * @param {string} [props.listCode] 列表标识 + * @param {string} [props.className] 自定义 className + * @param {Object} [props.layouts={}] 子布局组件集合 { sider, filter, toolbar, footer } + * @param {Array} [props.dataSource] 表格数据 + * @param {Array} [props.columns] 表格列配置 + * @param {boolean} [props.isItemOperations] 是否展示行内操作按钮(结合权限计算实际是否展示操作列) + * @param {boolean} [props.isBatchOperations] 是否展示批量操作按钮 + * @param {Array} [props.batchOperations] 批量操作按钮配置 + * @param {Array} [props.itemOperations] 行内操作按钮配置 + * @param {Map} [props.itemOperationsAccess] 行内操作权限映射 + * @param {string} [props.resource] 数据嵌套的资源字段名 + * @param {string} [props.primaryKey] 主键字段名 + * @param {string} [props.title] 列表标题 + * @param {Array} [props.tabs] tab 配置 + * @param {boolean} [props.isPaginate] 是否分页 + * @param {Object} [props.rowSelection] 行选择配置 + * @param {boolean} [props.isTreeSider] 是否展示树形侧边栏 + * @param {Object} [props.treeSiderConfig] 树形侧边栏配置 + * @param {boolean} [props.isConditionFormLayout] 是否使用条件表单布局 + */ +declare function DataTableFramework({ listCode, className, layouts, dataSource, columns, isItemOperations, isBatchOperations, batchOperations, itemOperations, itemOperationsAccess, resource, primaryKey, title, tabs, isPaginate, rowSelection, isTreeSider, treeSiderConfig, isConditionFormLayout, ...props }: { + listCode?: string; + className?: string; + layouts?: any; + dataSource?: Array; + columns?: Array; + isItemOperations?: boolean; + isBatchOperations?: boolean; + batchOperations?: Array; + itemOperations?: Array; + itemOperationsAccess?: Map; + resource?: string; + primaryKey?: string; + title?: string; + tabs?: Array; + isPaginate?: boolean; + rowSelection?: any; + isTreeSider?: boolean; + treeSiderConfig?: any; + isConditionFormLayout?: boolean; +}): React.JSX.Element; + +export { DataListContent, _default as DataListContext, DataListFilter, DataListFooter, DataListFramework, DataListHelper, DataListSider, DataListTable, DataListToolbar, DataTableFramework, DataList as default, useCellEditableComponents, useColumnsRender, useDataListHelper, useDataSource, useHasOperationColumn, useItemOperationsAccess, useOperationCallback, useStructure }; diff --git a/dist/data-list.js b/dist/data-list.js index fc5fabb..ee8a5c8 100644 --- a/dist/data-list.js +++ b/dist/data-list.js @@ -1,4 +1,4 @@ -import { w as t, t as e, o as r, r as o, x as i, s as l, q as u, v as n, p as D, y as L, n as p, A as C, z as m, J as b, C as c, F, E as d, I as k, B as w } from "./common/main-DsRa-iMx.js"; +import { w as t, t as e, o as r, r as o, x as i, s as l, q as u, v as n, p as D, y as L, n as p, A as C, z as m, J as b, C as c, F, E as d, I as k, B as w } from "./common/main-DahsFEqk.js"; export { t as DataListContent, e as DataListContext, diff --git a/dist/data-list/utils.d.ts b/dist/data-list/utils.d.ts new file mode 100644 index 0000000..69c5eff --- /dev/null +++ b/dist/data-list/utils.d.ts @@ -0,0 +1,10 @@ +/** + * 递归计算树形数据中应默认展开的行 key 列表(存在 children 的节点会被记录为父节点) + * @param {Array} data 树形数据 + * @param {string} key 作为行标识的字段名 + * @param {number|true} [depth=true] 递归层级限制,true 表示不限制层级 + * @returns {Array} 默认展开的行 key 数组 + */ +declare function getDefaultExpandRowKeys(data: Array, key: string, depth?: number | true): any[]; + +export { getDefaultExpandRowKeys }; diff --git a/dist/data-list/utils.js b/dist/data-list/utils.js index 50585bf..881e14a 100644 --- a/dist/data-list/utils.js +++ b/dist/data-list/utils.js @@ -1,5 +1,5 @@ import "lodash"; -import { f as a } from "../common/main-DsRa-iMx.js"; +import { f as a } from "../common/main-DahsFEqk.js"; export { a as getDefaultExpandRowKeys }; diff --git a/dist/grid-layout-form.d.ts b/dist/grid-layout-form.d.ts new file mode 100644 index 0000000..9addb62 --- /dev/null +++ b/dist/grid-layout-form.d.ts @@ -0,0 +1,233 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +/** + * 执行一段 JS 表达式/函数并跟踪其依赖的表单字段,依赖字段变化时自动重新执行 + * @param {string} fn 要执行的表达式源码,为空时直接返回 initialValue + * @param {*} initialValue 初始值/执行出错时的回退值 + * @param {Object} [params] 传给表达式的额外参数 + * @param {Object} [fns] 传给表达式的额外可调用函数 + * @param {*} [basicForm] 表达式里 getFieldValueForBasicForm 取值用的外层表单实例 + * @param {string} [resultType] 结果值的目标类型,用于类型转换 + * @returns {[*, *]} [执行结果(按 resultType 转换后), 执行出错时的错误对象] + */ +declare function useFnRun(fn: string, initialValue: any, params?: any, fns?: any, basicForm?: any, resultType?: string): [any, any]; + +/** + * 按表单编码(code)拉取表单结构定义,并把字段列表拆分为可见项(items)与隐藏项(hides) + * @param {string} code 表单编码,为空时不发起请求 + * @returns {{items?: Array, hides?: Array, pk?: *, uuid?: string, code?: string, resource?: string, align?: *, cols?: number, rowHeight?: number, marginX?: number, marginY?: number, theme?: string, themeProps?: Object, groups?: Array, listenChangeFields?: *, listenChangeFieldsFunc?: *}} 表单结构数据,请求完成前为 `{ items: [], hides: [] }` + */ +declare function useStructure(code: string): { + items?: Array; + hides?: Array; + pk?: any; + uuid?: string; + code?: string; + resource?: string; + align?: any; + cols?: number; + rowHeight?: number; + marginX?: number; + marginY?: number; + theme?: string; + themeProps?: any; + groups?: Array; + listenChangeFields?: any; + listenChangeFieldsFunc?: any; +}; +/** + * 根据字段的校验配置生成 rc-field-form 的 rules 数组;支持必填、长度限制、正则、自定义校验函数 + * @param {Object} [config] + * @param {number} [config.max=0] 最大长度/值(type 为 'string' 时使用) + * @param {number} [config.min=0] 最小长度/值(type 为 'string' 时使用) + * @param {'string'|'pattern'|'validator'|''} [config.type=''] 校验类型 + * @param {string} [config.message] 校验失败提示语 + * @param {string|RegExp} [config.pattern] type 为 'pattern' 时使用的正则 + * @param {boolean} [config.required=false] 是否必填 + * @param {*} [config.validator] type 为 'validator' 时执行的表达式/函数(经 func.exec 执行) + * @param {string} fieldName 字段名,传给自定义 validator 表达式 + * @param {string} fieldType 字段类型('number'|'string'|'array'|'bool'|'json' 等),决定必填校验的 type 及 bool/json 的映射 + * @returns {Array} rc-field-form 规则数组 + */ +declare function useRules({ max, min, type, message, pattern, required, validator, }?: { + max?: number; + min?: number; + type?: "string" | "pattern" | "validator" | ""; + message?: string; + pattern?: string | RegExp; + required?: boolean; + validator?: any; +}, fieldName: string, fieldType: string): Array; +/** + * 按主键(primaryKey)拉取表单初始数据;primaryKey 为空时不请求 + * @param {string} code 表单编码,用于拼接默认的请求地址 `/api/{code}` + * @param {string|number} primaryKey 记录主键,为空时不发起请求 + * @param {Object} [formSetting] 表单配置 + * @param {string} [formSetting.initDataUri] 初始化数据的请求地址,默认 `/api/{code}` + * @param {string} [formSetting.initDataMethod='GET'] 初始化数据的请求方法 + * @returns {Object|null} 拉取到的表单数据,请求完成前为 `null` + */ +declare function useFormData(code: string, primaryKey: string | number, formSetting?: { + initDataUri?: string; + initDataMethod?: string; +}): any | null; +/** + * 生成提交表单的回调函数;校验通过后按 `__RESOURCE__` 字段值裁剪数据(若存在),经 opt.serialize 序列化后提交 + * @param {string} code 表单编码,用于拼接默认的请求地址 `/api/{code}` + * @param {string|number} primaryKey 记录主键,存在时拼到请求地址后面 + * @param {Object} [formSetting] 表单配置 + * @param {string} [formSetting.submitDataUri] 提交数据的请求地址,默认 `/api/{code}` + * @param {string} [formSetting.submitDataMethod='POST'] 提交数据的请求方法 + * @returns {(form: Object, opt?: {serialize?: Function, onSuccess?: Function, onFail?: Function}) => Promise<*>} 提交函数;opt.serialize 用于提交前转换数据,onSuccess/onFail 为成功/失败回调(默认失败时如为校验错误会弹出提示) + */ +declare function useFormSubmit(code: string, primaryKey: string | number, formSetting?: { + submitDataUri?: string; + submitDataMethod?: string; +}): (form: any, opt?: { + serialize?: Function; + onSuccess?: Function; + onFail?: Function; +}) => Promise; +/** + * 组合 useFormData 与 useFormSubmit:数据拉取到后自动回填表单(否则重置),并返回已绑定 form 的提交函数 + * @param {Object} form rc-field-form 的表单实例 + * @param {string} code 表单编码 + * @param {string|number} primaryKey 记录主键 + * @param {Object} [formSetting] 表单配置(透传给 useFormData/useFormSubmit) + * @returns {(opt?: {serialize?: Function, onSuccess?: Function, onFail?: Function}) => Promise<*>} 已绑定当前 form 的提交函数 + */ +declare function useFormAction(form: any, code: string, primaryKey: string | number, formSetting?: any): (opt?: { + serialize?: Function; + onSuccess?: Function; + onFail?: Function; +}) => Promise; +/** + * 根据 widgetDecorator 表达式动态决定字段实际渲染的控件; + * widgetDecorator 执行结果为 subWidgets 的下标时,切换为对应子控件(合并其 props), + * 同时暴露 setDisabled/setRequired/getDisabled/getRequired 供 widgetDecorator 内部调用来动态调整禁用/必填状态 + * @param {string} itemWidget 默认使用的控件(已归一化的 widget 路径) + * @param {*} widgetDecorator 决定控件切换的表达式/函数,经 useFnRun 执行,返回值作为 subWidgets 下标 + * @param {Array<{widget: string, widgetPrefix?: string, props?: Object}>} [subWidgets=[]] 可切换的候选子控件列表 + * @param {Object} [basicForm={}] 传给 widgetDecorator 执行上下文的表单实例 + * @returns {[string, Object]} `[实际渲染的控件路径, 当前生效的控件 props]` + */ +declare function useWidgetDecorator(itemWidget: string, widgetDecorator: any, subWidgets?: Array<{ + widget: string; + widgetPrefix?: string; + props?: any; +}>, basicForm?: any): [string, any]; +/** + * 把受控的 value/onChange 与 rc-field-form 表单实例双向桥接:外部 value 变化时同步进表单 + * (仅当与内部最近一次变更不同,避免循环),表单内部变化时回调 onChange; + * 同时补全一份兼容 antd Form 的 `__INTERNAL__`/getFieldInstance 等接口(scrollToField/focusField 未实现,仅打印警告) + * @param {Object} config + * @param {Object} [config.value] 外部受控值,变化时会同步到表单 + * @param {(allValues: Object) => void} [config.onChange] 表单值变化时的回调 + * @param {Object} [form=null] 复用的 rc-field-form 表单实例,不传则内部创建 + * @returns {[Object, (changedValues: Object, allValues: Object) => void]} `[增强后的表单实例, 供 Form onValuesChange 使用的处理函数]` + */ +declare function useMergedFormValuesChange({ value, onChange }: { + value?: any; + onChange?: (allValues: any) => void; +}, form?: any): [any, (changedValues: any, allValues: any) => void]; + +/** + * 按 widget 标识异步加载并渲染对应的表单部件,加载完成前不渲染任何内容; + * 加载出错时渲染错误信息文本;支持通过 widgetDecorator/subWidgets 在运行时动态切换实际渲染的子控件(见 useWidgetDecorator) + * @param {Object} props + * @param {string} [props.widget='Input'] 部件标识;以 `@` 或 `blob:` 开头时按原样使用,否则拼接 widgetPrefix 前缀 + * @param {string} [props.widgetPrefix='@pkg/ff/grid-layout-forms'] widget 非绝对标识时使用的前缀 + * @param {*} [props.widgetDecorator] 决定控件切换的表达式/函数,详见 useWidgetDecorator + * @param {Array} [props.subWidgets=[]] widgetDecorator 命中时可切换的候选子控件列表 + * @param {*} [props.basicForm] 表达式求值/字段联动用的外层表单实例 + */ +declare function GridLayoutFormWidget({ widget, widgetPrefix, widgetDecorator, subWidgets, basicForm, ...props }: { + widget?: string; + widgetPrefix?: string; + widgetDecorator?: any; + subWidgets?: Array; + basicForm?: any; +}): undefined; + +/** + * 弹窗表单容器:包裹 GridLayoutForm 并附带保存/取消操作按钮,保存时校验并提交表单, + * 成功后调用 $close 关闭弹窗;常配合 Popup.modal 或 useButton 的 'grid-layout-form' widgetType 使用 + * @param {Object} props + * @param {Object} [props.$setting] 表单配置(透传给 useFormAction 作为 formSetting),okText/cancelText 可自定义按钮文案 + * @param {(result?: *) => void} [props.$close] 关闭弹窗的函数,保存成功或点击取消时调用 + * @param {*} [props.extras] 传给 FFContainer 的额外内容(如头部区域) + * @param {string} [props.code] 表单编码,透传给 useFormAction/GridLayoutForm + * @param {string|number} [props.primaryKey] 记录主键,透传给 useFormAction/GridLayoutForm + */ +declare function GridLayoutFormHelper({ $setting, $close, extras, code, primaryKey, ...props }: { + $setting?: any; + $close?: (result?: any) => void; + extras?: any; + code?: string; + primaryKey?: string | number; +}): React.JSX.Element; + +/** + * 表单容器组件,按 fields 渲染栅格布局字段并托管一个 rc-field-form 表单; + * 支持字段联动(listenChangeFields/listenChangeFieldsFunc)、隐藏字段(hides,内部用 HideField 渲染)、 + * 以及指定 theme 时委托 GridLayoutFramework 渲染主题外壳 + * @param {Object} props + * @param {string} [props.name] 表单字段容器名 + * @param {*} [props.form] 外部传入的 rc-field-form 表单实例,不传时内部自建 + * @param {*} [props.basicForm] 表达式求值/字段联动用的外层表单实例 + * @param {Object} [props.style] 容器行内样式 + * @param {string} [props.className] 容器额外 class 名 + * @param {number} [props.cols=24] 栅格列数 + * @param {number} [props.rowHeight=16] 栅格行高(px) + * @param {[number, number]} [props.itemMargin=[8, 16]] 字段项间距 [横向, 纵向](px) + * @param {[number, number]} [props.containerPadding=[0, 0]] 容器内边距 [纵向, 横向](px) + * @param {Array} [props.fields=[]] 可见字段配置列表(位置、尺寸、部件类型等) + * @param {Array} [props.hides=[]] 隐藏字段配置列表,按 initialValueLanguage 求值后写入对应字段 + * @param {string|number} [props.primaryKey=0] 记录主键,注入为 `__PRIMARY_KEY__` 字段值 + * @param {Object} [props.formProps={}] 注入为 `__PROPS__` 字段值的表单级参数 + * @param {Array} [props.formFields=[]] 额外注入的表单字段(与 formProps/primaryKey 一并作为初始 fields) + * @param {Array} [props.listenChangeFields] 触发联动表达式重新求值的字段列表 + * @param {*} [props.listenChangeFieldsFunc] 字段值变化时执行的联动表达式(经 func.exec 执行) + * @param {(changedValues: Object, allValues: Object) => void} [props.onValuesChange] 表单值变化回调,先于联动表达式执行 + * @param {string} [props.theme] 主题组件标识,指定时通过 GridLayoutFramework 渲染主题外壳 + * @param {Object} [props.themeProps={}] 传给主题组件的额外参数 + * @param {Array} [props.groups=[{key:'default',label:'默认'}]] 字段分组配置,用于主题多分组渲染 + * @param {*} [props.children] 附加渲染在字段项之后的内容 + */ +declare function GridLayoutForm({ name, form: initForm, basicForm, style, className, cols, rowHeight, itemMargin, containerPadding, fields, hides, primaryKey, formProps, formFields, listenChangeFields, listenChangeFieldsFunc, onValuesChange, theme, themeProps, groups, children, ...props }: { + name?: string; + form?: any; + basicForm?: any; + style?: any; + className?: string; + cols?: number; + rowHeight?: number; + itemMargin?: [number, number]; + containerPadding?: [number, number]; + fields?: any[]; + hides?: any[]; + primaryKey?: string | number; + formProps?: any; + formFields?: any[]; + listenChangeFields?: any[]; + listenChangeFieldsFunc?: any; + onValuesChange?: (changedValues: any, allValues: any) => void; + theme?: string; + themeProps?: any; + groups?: any[]; + children?: any; +}): React.JSX.Element; +declare namespace GridLayoutForm { + namespace propTypes { + let fields: PropTypes.Requireable; + let hides: PropTypes.Requireable; + } +} +declare const _default: ({ code, isPreview, ...props }: { + [x: string]: any; + code: any; + isPreview?: boolean; +}) => React.JSX.Element; + +export { GridLayoutForm, GridLayoutFormHelper, GridLayoutFormWidget, _default as default, useFnRun, useFormAction, useFormData, useFormSubmit, useMergedFormValuesChange, useRules, useStructure, useWidgetDecorator }; diff --git a/dist/grid-layout-form.js b/dist/grid-layout-form.js index 9ca9dd3..9f6ffb8 100644 --- a/dist/grid-layout-form.js +++ b/dist/grid-layout-form.js @@ -1,4 +1,4 @@ -import { aa as s, ac as r, ab as u, a9 as o, m as t, ah as m, af as d, ag as i, aj as F, ae as g, ad as c, ai as l } from "./common/main-DsRa-iMx.js"; +import { aa as s, ac as r, ab as u, a9 as o, m as t, ah as m, af as d, ag as i, aj as F, ae as g, ad as c, ai as l } from "./common/main-DahsFEqk.js"; export { s as GridLayoutForm, r as GridLayoutFormHelper, diff --git a/dist/grid-layout-form/utils.d.ts b/dist/grid-layout-form/utils.d.ts new file mode 100644 index 0000000..b04fde1 --- /dev/null +++ b/dist/grid-layout-form/utils.d.ts @@ -0,0 +1,17 @@ +/** + * 在(可能嵌套的)选项列表中按 value 查找选项;先在当前层查找,找不到再递归查找各项的子级(depthKey) + * @param {Array} items 选项列表,每项含 `value` 及可选的子级(depthKey)字段 + * @param {*} value 要查找的选项值 + * @param {string} [depthKey='children'] 子级选项所在的字段名 + * @returns {Object} 匹配到的选项;未找到或 items 为空时返回 `{}` + */ +declare function getOptionItemByValue(items: Array, value: any, depthKey?: string): any; +/** + * 把部件标识归一化为完整路径;以 `@` 或 `blob:` 开头时视为已是绝对标识,原样返回,否则拼接 widgetPrefix 前缀 + * @param {string} [widget='Input'] 部件标识 + * @param {string} [widgetPrefix='@pkg/ff/grid-layout-forms'] widget 非绝对标识时使用的前缀 + * @returns {string} 归一化后的部件路径 + */ +declare function getNormalizeWidget(widget?: string, widgetPrefix?: string): string; + +export { getNormalizeWidget, getOptionItemByValue }; diff --git a/dist/grid-layout-form/utils.js b/dist/grid-layout-form/utils.js index b411e05..90cddc8 100644 --- a/dist/grid-layout-form/utils.js +++ b/dist/grid-layout-form/utils.js @@ -1,5 +1,5 @@ import "lodash"; -import { a as o, g } from "../common/main-DsRa-iMx.js"; +import { a as o, g } from "../common/main-DahsFEqk.js"; export { o as getNormalizeWidget, g as getOptionItemByValue diff --git a/dist/grid-layout.d.ts b/dist/grid-layout.d.ts new file mode 100644 index 0000000..1d7f3da --- /dev/null +++ b/dist/grid-layout.d.ts @@ -0,0 +1,135 @@ +import React from 'react'; + +/** rc-field-form 内部钩子的注册标识 */ +declare const HOOK_MARK: "RC_FORM_INTERNAL_HOOKS"; +/** + * 按布局 code 拉取布局结构定义(字段、主题、栅格设置等),code 变化时重新请求 + * @param {string} code 布局的唯一编码 + * @returns {Object} 布局结构数据,初始为 `{ items: [] }` + */ +declare function useStructure(code: string): any; +/** + * 关联表单字段值,支持初始值表达式求值、watch 联动更新以及经 DataConverter 转换后的展示值 + * @param {string} name 字段名(rc-field-form 的字段路径) + * @param {Object} setting 字段取值相关配置 + * @param {*} [setting.initialValue] 初始值,或语言为 javascript 时的表达式源码 + * @param {string} [setting.initialValueLanguage] 初始值类型,'javascript' 时把 initialValue 当表达式执行 + * @param {*} [setting.convertJs] 用于生成展示值的转换表达式(交给 DataConverter 处理) + * @param {*} [setting.convertJsSetting] convertJs 表达式的附加配置 + * @param {string} [setting.type='string'] 字段值的目标类型,用于类型转换 + * @param {*} [pContext] 表达式里 getFieldValueForBasicForm 取值用的外层表单实例 + * @returns {[*, *]} [经 convertJs 转换后的展示值(未配置时等于原值), 原始字段值] + */ +declare function useField(name: string, { initialValue, initialValueLanguage, convertJs, convertJsSetting, type, }: { + initialValue?: any; + initialValueLanguage?: string; + convertJs?: any; + convertJsSetting?: any; + type?: string; +}, pContext?: any): [any, any]; +/** + * 按 (y, x) 排序将字段列表归一化为渲染项列表(每项已用给定的 ItemWidget 渲染成元素) + * @param {Array} fields 字段配置列表 + * @param {Function} ItemWidget 用于渲染每个字段的组件 + * @param {*} [basicForm] 传给每个字段渲染项的外层表单实例 + * @returns {Array} 已排序并渲染完成的元素列表 + */ +declare function useGridLayoutFields(fields: any[], ItemWidget: Function, basicForm?: any): any[]; +/** + * 执行一段 JS 表达式/函数并跟踪其依赖的表单字段,依赖字段变化时自动重新执行 + * @param {string} fn 要执行的表达式源码,为空时直接返回 initialValue + * @param {*} initialValue 初始值/执行出错时的回退值 + * @param {Object} [params] 传给表达式的额外参数 + * @param {Object} [fns] 传给表达式的额外可调用函数 + * @param {*} [basicForm] 表达式里 getFieldValueForBasicForm 取值用的外层表单实例 + * @param {string} [resultType] 结果值的目标类型,用于类型转换 + * @returns {[*, *]} [执行结果(按 resultType 转换后), 执行出错时的错误对象] + */ +declare function useFnRun(fn: string, initialValue: any, params?: any, fns?: any, basicForm?: any, resultType?: string): [any, any]; + +/** + * 按 widget 标识异步加载并渲染对应的部件组件,加载完成前不渲染任何内容; + * 加载出错时渲染错误信息文本 + * @param {Object} props + * @param {string} [props.widget] 部件标识;以 `@` 或 `blob:` 开头时按原样使用,否则拼接 widgetPrefix 前缀 + * @param {string} [props.widgetPrefix='@pkg/ff/grid-layouts'] widget 非绝对标识时使用的前缀 + * @param {*} [props.basicForm] 表达式求值/字段联动用的外层表单实例 + */ +declare function GridLayoutWidget({ widget, widgetPrefix, basicForm, ...props }: { + widget?: string; + widgetPrefix?: string; + basicForm?: any; +}): undefined; + +/** + * 按 theme 标识异步加载主题外壳组件,并把每个分组(items)渲染成 itemRender 生成的内容后传给主题组件; + * theme 未指定时不渲染,加载出错时渲染错误信息文本 + * @param {Object} props + * @param {string} [props.theme] 主题组件标识,通过 core.getWidgetComponent 加载 + * @param {*} [props.basicForm] 传给主题组件及各分组内容的外层表单实例 + * @param {Array} [props.items=[{key:'default',label:'默认'}]] 分组配置列表 + * @param {Array} [props.fields=[]] 全部布局字段,按分组 key 过滤后分给对应 items 项 + * @param {Function} [props.itemRender] 生成单个分组渲染内容的函数,签名为 (item, fields, children) + * @param {Array} [props.chunks=[]] 额外附加在 items 之后、不参与过滤的分组项 + * @param {*} [props.children] 仅附加给 key 为 'default' 的分组的内容 + * @param {Object} [props.$setting={}] 传给主题组件的基础设置,会与 themeSetting 合并 + */ +declare function GridLayoutFramework({ theme, basicForm, items, fields, itemRender, chunks, children, $setting, ...themeSetting }: { + theme?: string; + basicForm?: any; + items?: any[]; + fields?: any[]; + itemRender?: Function; + chunks?: any[]; + children?: any; + $setting?: any; +}): undefined; + +/** + * 栅格布局容器,按 fields 描述的位置/尺寸渲染各字段部件,并托管一个 rc-field-form 表单; + * 指定 theme 时委托 GridLayoutFramework 渲染主题外壳,否则直接渲染默认分组 + * @param {Object} props + * @param {string} [props.name] 表单字段容器名(即 __LAYOUT_KEY__ 语义,由 GridLayoutHoc 传入) + * @param {*} [props.form] 外部传入的 rc-field-form 表单实例,不传时内部自建 + * @param {*} [props.basicForm] 表达式求值/字段联动用的外层表单实例 + * @param {Object} [props.style] 容器行内样式 + * @param {string} [props.className] 容器额外 class 名 + * @param {number} [props.cols=12] 栅格列数 + * @param {number} [props.rowHeight=21] 栅格行高(px) + * @param {[number, number]} [props.containerPadding=[0, 0]] 容器内边距 [纵向, 横向](px) + * @param {[number, number]} [props.itemMargin=[4, 0]] 字段项间距 [纵向, 横向](px) + * @param {Object} [props.formProps={}] 注入为 `__PROPS__` 字段值的表单级参数 + * @param {Array} [props.formFields=[]] 额外注入的表单字段(与 formProps 一并作为初始 fields) + * @param {Array} [props.fields=[]] 布局字段配置列表(位置、尺寸、部件类型等) + * @param {Object} [props.data] 初始化/回填表单的数据 + * @param {string} [props.theme] 主题组件标识,指定时通过 GridLayoutFramework 渲染主题外壳 + * @param {Object} [props.themeProps={}] 传给主题组件的额外参数 + * @param {Array} [props.groups=[{key:'default',label:'默认'}]] 字段分组配置,用于主题多分组渲染 + * @param {*} [props.children] 附加渲染在字段项之后的内容 + */ +declare function GridLayout({ name, form: initForm, basicForm, style, className, cols, rowHeight, containerPadding, itemMargin, formProps, formFields, fields, data, theme, themeProps, groups, children, ...props }: { + name?: string; + form?: any; + basicForm?: any; + style?: any; + className?: string; + cols?: number; + rowHeight?: number; + containerPadding?: [number, number]; + itemMargin?: [number, number]; + formProps?: any; + formFields?: any[]; + fields?: any[]; + data?: any; + theme?: string; + themeProps?: any; + groups?: any[]; + children?: any; +}): React.JSX.Element; +declare const _default: ({ code, data, ...props }: { + [x: string]: any; + code: any; + data: any; +}) => React.JSX.Element; + +export { GridLayout, GridLayoutFramework, GridLayoutWidget, HOOK_MARK, _default as default, useField, useFnRun, useGridLayoutFields, useStructure }; diff --git a/dist/grid-layout.js b/dist/grid-layout.js index 9a7e07c..b5b735d 100644 --- a/dist/grid-layout.js +++ b/dist/grid-layout.js @@ -1,4 +1,4 @@ -import { h as u, j as e, i as r, H as t, G as d, k as i, m as o, l as G, u as l } from "./common/main-DsRa-iMx.js"; +import { h as u, j as e, i as r, H as t, G as d, k as i, m as o, l as G, u as l } from "./common/main-DahsFEqk.js"; export { u as GridLayout, e as GridLayoutFramework, diff --git a/dist/grid-layout/utils.d.ts b/dist/grid-layout/utils.d.ts new file mode 100644 index 0000000..37d6876 --- /dev/null +++ b/dist/grid-layout/utils.d.ts @@ -0,0 +1,58 @@ +/** + * 将布局字段配置按 (y, x) 排序并渲染为定位好的字段项元素列表 + * @param {Array} [fields=[]] 布局字段配置列表,每项包含 i/x/y/w/h 及 field(可含 boxStyle) + * @param {Function} ItemWidget 用于渲染每个字段内容的组件 + * @param {*} [basicForm] 传给每个字段项的外层表单实例 + * @returns {Array} 已定位、可直接渲染的字段项元素列表 + */ +declare function getNormalizeFields(fields?: any[], ItemWidget: Function, basicForm?: any): any[]; + +/** + * 根据栅格坐标/尺寸及盒模型配置,生成布局字段项的行内样式(以 CSS 自定义属性表达) + * @param {number} x 栅格列坐标 + * @param {number} y 栅格行坐标 + * @param {number} w 栅格宽度(列数) + * @param {number} h 栅格高度(行数) + * @param {Object} [boxStyle={}] 盒模型配置 + * @param {boolean} [boxStyle.autoHeight] 是否按内容自适应高度(不再固定跨行) + * @param {string} [boxStyle.alignItems] 对齐方式,写入 `--grid-layout-box-align-items` + * @param {string} [boxStyle.justifyContent] 主轴对齐方式,写入 `--grid-layout-box-justify-content` + * @param {number} [boxStyle.marginTop] 外边距-上(px) + * @param {number} [boxStyle.marginRight] 外边距-右(px) + * @param {number} [boxStyle.marginBottom] 外边距-下(px) + * @param {number} [boxStyle.marginLeft] 外边距-左(px) + * @param {number} [boxStyle.paddingTop] 内边距-上(px) + * @param {number} [boxStyle.paddingRight] 内边距-右(px) + * @param {number} [boxStyle.paddingBottom] 内边距-下(px) + * @param {number} [boxStyle.paddingLeft] 内边距-左(px) + * @param {number} [height=0] 显式高度(px),传入时覆盖 autoHeight 计算出的 height + * @returns {Object} 可直接用作 React style 的样式对象 + */ +declare function getBoxStyle(x: number, y: number, w: number, h: number, boxStyle?: { + autoHeight?: boolean; + alignItems?: string; + justifyContent?: string; + marginTop?: number; + marginRight?: number; + marginBottom?: number; + marginLeft?: number; + paddingTop?: number; + paddingRight?: number; + paddingBottom?: number; + paddingLeft?: number; +}, height?: number): any; +/** + * 将部件名归一化为完整标识;以 `@` 或 `blob:` 开头时按原样返回,否则拼接 widgetPrefix 前缀 + * @param {string} [widget='Text'] 部件名 + * @param {string} [widgetPrefix='@pkg/ff/grid-layouts'] widget 非绝对标识时使用的前缀 + * @returns {string} 归一化后的部件标识 + */ +declare function getNormalizeWidget(widget?: string, widgetPrefix?: string): string; +/** + * 从 props 中提取所有事件回调(即形如 onXxx 的属性) + * @param {Object} props 任意 props 对象 + * @returns {Object} 仅包含事件回调属性的子集 + */ +declare function getEventProps(props: any): any; + +export { getBoxStyle, getEventProps, getNormalizeFields, getNormalizeWidget }; diff --git a/dist/grid-layout/utils.js b/dist/grid-layout/utils.js index 57370a7..afb42fa 100644 --- a/dist/grid-layout/utils.js +++ b/dist/grid-layout/utils.js @@ -1,4 +1,4 @@ -import { b as a, d as o, e as s, c as g } from "../common/main-DsRa-iMx.js"; +import { b as a, d as o, e as s, c as g } from "../common/main-DahsFEqk.js"; export { a as getBoxStyle, o as getEventProps, diff --git a/dist/hooks.d.ts b/dist/hooks.d.ts new file mode 100644 index 0000000..9b94f3d --- /dev/null +++ b/dist/hooks.d.ts @@ -0,0 +1,60 @@ +export { default as useMergedState } from 'rc-util/lib/hooks/useMergedState'; +export { default as useEvent } from 'rc-util/lib/hooks/useEvent'; + +/** + * 返回一个强制刷新函数;组件卸载后调用无效果 + * @returns {() => void} 调用后触发一次重新渲染 + */ +declare function useUpdate(): () => void; +/** + * 类似 useState,但 setState 支持传入更新完成后的回调 + * @param {*} initialState 初始状态 + * @returns {[*, (newState: *, callback?: (state: *) => void) => void]} [当前状态, 支持回调的 setState] + */ +declare function useStateWithCallback(initialState: any): [any, (newState: any, callback?: (state: any) => void) => void]; +/** + * 依赖做深度比较的 useEffect,deps 引用变化但深度相等时不会重新执行 + * @param {(prevDeps: *) => void} callback 副作用回调,参数为上一次的 deps + * @param {*} deps 依赖值(任意可深度比较的值,不要求是数组) + * @param {(a: *, b: *) => boolean} [compare] 自定义比较函数,默认使用 lodash isEqual + */ +declare function useDeepEqualEffect(callback: (prevDeps: any) => void, deps: any, compare?: (a: any, b: any) => boolean): void; +/** useDeepEqualEffect 的别名 */ +declare function useDeepEffect(callback: (prevDeps: any) => void, deps: any, compare?: (a: any, b: any) => boolean): void; +/** + * 解析表单字段的选项配置,支持静态数组或一段 JavaScript 表达式(动态计算选项,可依赖其他字段的值) + * @param {Array|string} options 静态选项数组,或语言为 javascript 时的表达式源码 + * @param {string} [language] 选项的类型,'javascript' 时把 options 当表达式执行 + * @param {string} [type] 选项 value 的目标类型,用于类型转换(如 'string'/'number') + * @param {*} [form] 关联的 rc-field-form 表单实例,不传时 rc-field-form 会自建一个 + * @param {*} [basicForm] 表达式里 getFieldValueForBasicForm 取值用的外层表单实例 + * @returns {Array} 解析后的选项列表 + */ +declare function useOptions(options: any[] | string, language?: string, type?: string, form?: any, basicForm?: any): any[]; +/** + * 发起 GET 请求并通过 WebSocket 订阅后续更新,数据变化时自动重新拉取 + * @param {string|{url: string, [key: string]: *}} param 请求地址,或包含 url 的请求配置对象 + * @returns {*} 最新一次响应的数据,初始为 undefined + */ +declare function useSubscribeRequest(param: string | { + url: string; + [key: string]: any; +}): any; +/** + * 生成一个用于更新组件 props 的函数;命中 router/query 类型的字段会走路由跳转,其余走本地 state 合并 + * @param {Object} $props props 的类型/来源配置 + * @param {(local: Object) => void} setLocal 合并本地 props 的函数 + * @returns {(patch: Object) => void} 应用一批 props 变更 + */ +declare function useWidgetPropsUpdater($props: any, setLocal: (local: any) => void): (patch: any) => void; +/** + * 解析组件 props 配置(支持路由参数、表达式等来源),并允许外部局部覆盖 + * @param {Object} $props props 的类型/来源配置 + * @param {Object} [data] 表达式求值时可用的上下文数据 + * @param {Object} [fns] 表达式求值时可调用的额外函数 + * @param {Array} [deps] 触发重新解析的额外依赖项 + * @returns {[Object, (patch: Object) => void, Object]} [最终生效的 props, 更新 props 的函数, 被本地覆盖的字段] + */ +declare function useWidgetProps($props: any, data?: any, fns?: any, deps?: any[]): [any, (patch: any) => void, any]; + +export { useDeepEffect, useDeepEqualEffect, useOptions, useStateWithCallback, useSubscribeRequest, useUpdate, useWidgetProps, useWidgetPropsUpdater }; diff --git a/dist/hooks.js b/dist/hooks.js index b991b17..03cb404 100644 --- a/dist/hooks.js +++ b/dist/hooks.js @@ -2,7 +2,7 @@ import "lodash"; import "rc-field-form"; import "react"; import "react-use"; -import { a4 as u, a3 as o, a5 as i, a2 as f, a6 as m, a1 as d, a8 as c, a7 as l } from "./common/main-DsRa-iMx.js"; +import { a4 as u, a3 as o, a5 as i, a2 as f, a6 as m, a1 as d, a8 as c, a7 as l } from "./common/main-DahsFEqk.js"; import { default as b } from "rc-util/lib/hooks/useMergedState"; import { a as x } from "./common/vender-C5RbewOc.js"; export { diff --git a/dist/iconfont.d.ts b/dist/iconfont.d.ts new file mode 100644 index 0000000..bd92267 --- /dev/null +++ b/dist/iconfont.d.ts @@ -0,0 +1,33 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +/** + * 渲染一个 iconfont symbol 图标(依赖 Iconfont.init 注入的 SVG symbol 脚本) + * @param {Object} props + * @param {string} [props.className] 额外的 class 名 + * @param {string} props.type 图标名,对应 svg symbol 的 id + * @param {Object} [props.style] 行内样式 + */ +declare function Iconfont({ className, type, style, ...props }: { + className?: string; + type: string; + style?: any; +}): React.JSX.Element; +declare namespace Iconfont { + export namespace propTypes { + let className: PropTypes.Requireable; + let type: PropTypes.Validator; + let style: PropTypes.Requireable; + } + export { createScriptUrlElements as init }; +} + +/** + * 依次注入 iconfont symbol 的 script 地址(单个 url 只会注入一次); + * 也是 Iconfont.init 挂载的实现,支持传入多个 url 按顺序加载(前一个 load/error 后再加载下一个) + * @param {string[]} [scriptUrls] iconfont symbol 脚本地址列表 + * @param {number} [index] 内部递归用的当前下标 + */ +declare function createScriptUrlElements(scriptUrls?: string[], index?: number): void; + +export { Iconfont as default }; diff --git a/dist/iconfont.js b/dist/iconfont.js index 9a7ef40..0495bab 100644 --- a/dist/iconfont.js +++ b/dist/iconfont.js @@ -2,7 +2,7 @@ import "react/jsx-runtime"; import "react"; import "prop-types"; import "classnames"; -import { ak as a } from "./common/main-DsRa-iMx.js"; +import { ak as a } from "./common/main-DahsFEqk.js"; export { a as default }; diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..194d62a --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,37 @@ +import React from 'react'; + +declare const _default$3: any; + +declare const _default$2: any; + +declare class Cache { + constructor(target: any, fn: any); + get: (...args: any[]) => Promise; + #private; +} + +declare const _default$1: any; + +declare const pipe: any; + +declare const _default: any; + +declare const AppContext: React.Context<{ + user: {}; + initUser: () => void; + initUserComplete: boolean; +}>; +declare const AppGlobalParamsContext: React.Context<{ + set: () => void; + get: () => void; + assign: () => void; + currentRoute: () => void; +}>; + +/** + * 判断是否是 React 组件, 大写字母开头的函数则判断为组件 + */ +declare function isReactComponent(component: any): boolean; +declare function insertStyle(css: any, id: any): any; + +export { AppContext, AppGlobalParamsContext, Cache as cache, _default$1 as configure, _default$3 as default, pipe as func, _default$2 as http, insertStyle, isReactComponent, _default as route }; diff --git a/dist/index.js b/dist/index.js index 82704cc..6f0e26d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,4 +1,4 @@ -import { aE as t, aF as e, aA as o, aB as n, aw as p, aC as r, az as c, ay as f, ax as l, aD as u } from "./common/main-DsRa-iMx.js"; +import { aE as t, aF as e, aA as o, aB as n, aw as p, aC as r, az as c, ay as f, ax as l, aD as u } from "./common/main-DahsFEqk.js"; export { t as AppContext, e as AppGlobalParamsContext, diff --git a/dist/pages.d.ts b/dist/pages.d.ts new file mode 100644 index 0000000..8c1cc54 --- /dev/null +++ b/dist/pages.d.ts @@ -0,0 +1,33 @@ +import React from 'react'; + +/** + * 渲染一个数据列表页(DataListHelper),base62 编码的查询参数会先解码再传下去 + * @param {Object} props + * @param {string} props.component 数据列表编码(listCode) + * @param {Object} [props.$props] props 的类型/来源配置,须解析出 base62params 字段 + */ +declare function DataListPage({ component, $props }: { + component: string; + $props?: any; +}): React.JSX.Element; + +/** + * 按组件名动态加载并渲染一个自定义页面组件,加载失败时显示错误信息,未指定 component 时显示空状态 + * @param {Object} props + * @param {string} [props.component] 要加载的组件名(通过 core.getWidgetComponent 解析) + * @param {Object} [props.$setting] 传给目标组件的 $setting + * @param {Object} [props.$props] 传给目标组件的 props 类型/来源配置(经 useWidgetProps 解析) + */ +declare function CustomPage({ component, $setting, $props }: { + component?: string; + $setting?: any; + $props?: any; +}): React.DetailedReactHTMLElement; + +/** 空页面,渲染 Empty 占位内容 */ +declare function EmptyPage(): React.JSX.Element; + +/** 404 占位页面 */ +declare function NotFoundPage(): string; + +export { CustomPage, DataListPage, EmptyPage, NotFoundPage }; diff --git a/dist/pages.js b/dist/pages.js index 2b3c592..74422bc 100644 --- a/dist/pages.js +++ b/dist/pages.js @@ -1,4 +1,4 @@ -import { L as t, K as e, M as o, N as g } from "./common/main-DsRa-iMx.js"; +import { L as t, K as e, M as o, N as g } from "./common/main-DahsFEqk.js"; export { t as CustomPage, e as DataListPage, diff --git a/dist/res-ws.d.ts b/dist/res-ws.d.ts new file mode 100644 index 0000000..34aa38d --- /dev/null +++ b/dist/res-ws.d.ts @@ -0,0 +1,28 @@ +declare const _default: ResWs; + +/** + * 基于 SharedWorker 的资源状态 WebSocket 单例;多个页面/标签页共用同一条连接, + * 按资源 uuid 把服务端推送的状态变化分发给各自的订阅回调 + */ +declare class ResWs { + /** @type {ResWs} */ + static "__#private@#instance": ResWs; + /** @returns {ResWs} 单例实例 */ + static getInstance: () => ResWs; + /** + * 订阅资源状态变化 + * @param {(data: *) => void} cb 状态变化时的回调,收到服务端推送的原始数据 + * @param {string|string[]} [res] 要订阅的资源 uuid,不传/空数组表示订阅全部('*') + * @returns {() => void} 取消订阅的函数 + */ + subscribe: (cb: (data: any) => void, res?: string | string[]) => () => void; + /** + * 取消订阅 + * @param {Function} cb 订阅时传入的回调 + * @returns {boolean} 是否成功移除 + */ + unsubscribe: (cb: Function) => boolean; + #private; +} + +export { _default as default }; diff --git a/dist/res-ws.js b/dist/res-ws.js index 6b76f9e..6d44070 100644 --- a/dist/res-ws.js +++ b/dist/res-ws.js @@ -1,5 +1,5 @@ import "lodash"; -import { R as a } from "./common/main-DsRa-iMx.js"; +import { R as a } from "./common/main-DahsFEqk.js"; export { a as default }; diff --git a/dist/utils.d.ts b/dist/utils.d.ts new file mode 100644 index 0000000..9c19839 --- /dev/null +++ b/dist/utils.d.ts @@ -0,0 +1,115 @@ +/** + * 把任意值按目标类型做类型转换(json/array/number/integer/float/bool/string 互转) + * @param {*} data 待转换的值 + * @param {string} type 目标类型 + * @returns {*} 转换后的值,没有匹配的转换规则时原样返回 + */ +declare function toPrimitive(data: any, type: string): any; +/** + * 判断值的基础类型,返回 'null'/'array'/'json'/'bool'/'string'/'integer'/'float' 之一 + * @param {*} value 待判断的值 + * @returns {string} 类型名 + */ +declare function getPrimitiveType(value: any): string; +/** + * 按 registerProps 的字段配置(code/field/router/query/string)解析出实际的 props 数据; + * 配置里出现 type: 'code' 时走异步表达式求值,否则走同步解析 + * @param {Object} [registerProps] props 的类型/来源配置,支持嵌套 + * @param {Object} [data] 表达式求值、字段取值时使用的上下文数据 + * @param {Object} [fns] 表达式求值时可调用的额外函数 + * @param {*} [defaultValue] 字段没有取到值时的兜底默认值 + * @returns {Object|Promise} 解析后的 props 数据;含 code 类型字段时返回 Promise + */ +declare function getWidgetPropsData(registerProps?: any, data?: any, fns?: any, defaultValue?: any): any | Promise; +/** + * 递归遍历每个成员做条件判断,成员是 object 或 array 时继续深入遍历 + * @param {*} items 待遍历的值(对象/数组/其他) + * @param {(value: *, key: string|number) => boolean} [func] 判断函数,返回 true 即命中 + * @returns {boolean} 只要有一处命中就返回 true + */ +declare function deepSome(items: any, func?: (value: any, key: string | number) => boolean): boolean; +/** + * 递归替换对象(含嵌套对象/数组)里的 key,不在 keyMap 里的 key 保持不变 + * @param {*} obj 待处理的对象/数组/其他值 + * @param {Object} keyMap 旧 key 到新 key 的映射 + * @returns {*} 替换 key 后的新对象;非对象/数组的值原样返回 + */ +declare function replaceKeys(obj: any, keyMap: { + [x: string]: string; +}): any; +/** + * 生成一个 UUID v4 格式的字符串(非加密安全,仅用于前端本地标识) + * @returns {string} UUID 字符串 + */ +declare function uuid(): string; +/** + * 从 @pkg 风格的包路径里取出包名(路径第 4 段),如 @pkg/owner/category/name/... -> name + * @param {string} pkg 包路径字符串 + * @returns {string} 包名,解析不出时返回空字符串 + */ +declare function getPkgName(pkg: string): string; +/** + * 从 @pkg 风格的包路径里取出分类(路径第 3 段),如 @pkg/owner/category/... -> category + * @param {string} pkg 包路径字符串 + * @returns {string} 分类名,解析不出时返回空字符串 + */ +declare function getPkgCategory(pkg: string): string; +/** + * 从 @pkg 风格的包路径里取出所有者(路径第 2 段),如 @pkg/owner/... -> owner + * @param {string} pkg 包路径字符串 + * @returns {string} 所有者名,解析不出时返回空字符串 + */ +declare function getPkgOwner(pkg: string): string; +/** + * 生成 JSON 的 MurmurHash3 + * @param {Object} obj - JSON 对象 + * @param {number} bits - 输出位数 32 或 128,默认 32 + * @param {"x86"|"x64"|"auto"} algo - 算法版本,默认 auto + * @returns {string} hash 字符串 + */ +declare function hashJSON(obj: any, bits?: number, algo?: "x86" | "x64" | "auto"): string; +/** + * 创建一个 id 生成器;返回的函数把任意一组参数(对象/函数按引用、原始值按值)映射成 + * 形如 "1::2::3" 的可读唯一 key,相同的参数组合总是得到相同的 id + * @returns {(...args: *[]) => string} getId 函数 + */ +declare function makeUniqueIdGenerator(): (...args: any[]) => string; +/** + * 判断 URL 是否包含域名(包括域名、localhost 和 IP 地址) + * @param {string} url - 待检测的 URL 字符串 + * @returns {boolean} 如果包含域名/主机名返回 true,否则返回 false + * + * @example + * hasUrlPrefix('https://www.example.com/path') // true + * hasUrlPrefix('http://example.com') // true + * hasUrlPrefix('//example.com/path') // true + * hasUrlPrefix('example.com/path') // true + * hasUrlPrefix('www.example.com') // true + * hasUrlPrefix('http://localhost:3000') // true + * hasUrlPrefix('http://127.0.0.1:8080') // true + * hasUrlPrefix('http://192.168.1.1') // true + * hasUrlPrefix('/path/to/resource') // false + * hasUrlPrefix('./relative/path') // false + * hasUrlPrefix('../relative/path') // false + */ +declare function hasUrlPrefix(url: string): boolean; +/** + * 为 URL 添加默认前缀(如果没有域名前缀) + * @param {string} url - 待处理的 URL 字符串 + * @param {string} defaultPrefix - 默认前缀,默认为当前域名 + * @returns {string} 处理后的 URL + * + * @example + * getUrlWithPrefix('/path/to/resource') // 'http://current-domain.com/path/to/resource' + * getUrlWithPrefix('/api/data', 'https://api.example.com') // 'https://api.example.com/api/data' + * getUrlWithPrefix('https://example.com/path') // 'https://example.com/path' (不变) + * getUrlWithPrefix('example.com/path') // 'example.com/path' (不变,已有域名) + */ +declare function getUrlWithPrefix(url: string, defaultPrefix?: string): string; +/** + * 生成 UUID v4 字符串,优先用 crypto.randomUUID/getRandomValues,都不支持时降级为 Math.random + * @returns {string} UUID 字符串 + */ +declare function generateUUID(): string; + +export { deepSome, generateUUID, getPkgCategory, getPkgName, getPkgOwner, getPrimitiveType, getUrlWithPrefix, getWidgetPropsData, hasUrlPrefix, hashJSON, makeUniqueIdGenerator, replaceKeys, toPrimitive, uuid }; diff --git a/dist/utils.js b/dist/utils.js index 99724dd..5b39a88 100644 --- a/dist/utils.js +++ b/dist/utils.js @@ -1,5 +1,5 @@ import "lodash"; -import { S as r, a0 as i, W as g, V as o, X as P, P as m, $ as p, Q as U, _ as d, Y as h, Z as k, T as n, O as f, U as l } from "./common/main-DsRa-iMx.js"; +import { S as r, a0 as i, W as g, V as o, X as P, P as m, $ as p, Q as U, _ as d, Y as h, Z as k, T as n, O as f, U as l } from "./common/main-DahsFEqk.js"; import "./common/vender-C5RbewOc.js"; export { r as deepSome, diff --git a/dist/virtual-fs.d.ts b/dist/virtual-fs.d.ts new file mode 100644 index 0000000..12d9dfc --- /dev/null +++ b/dist/virtual-fs.d.ts @@ -0,0 +1,295 @@ +/** + * 把 VirtualFS 里某个路径下的结构递归转换成 antd Tree 组件可用的节点结构 + * (目录排在文件前面,各自按名称排序) + * @param {VirtualFS} vfs - 虚拟文件系统实例 + * @param {string} [pathStr] - 起始路径,默认根目录 + * @param {string} [prefix] - 拼在 key 前面的前缀,用于避免多棵树的 key 冲突 + * @returns {Promise<{title: string, key: string, isLeaf: boolean, children?: Array}|null>} + * 树节点;路径无效/出错时返回 null + */ +declare function toTreePaths(vfs: VirtualFS, pathStr?: string, prefix?: string): Promise<{ + title: string; + key: string; + isLeaf: boolean; + children?: any[]; +} | null>; +/** + * 内存中的虚拟文件系统,提供类似 Node fs 的增删改查 API(stat/dir/readFile/writeFile/mkdir/...), + * 支持工作目录(scope)、变更订阅(subscribe)和文件查找(findFiles) + */ +declare class VirtualFS { + /** + * 创建一个虚拟文件系统实例 + * @param {Object|Object[]|null} [initialStructure] - 初始文件系统结构 + * - 如果是数组:将作为根目录的 children + * - 如果是对象且 name 为 '/':将作为根节点 + * - 如果是对象且 name 不为 '/':将添加到根目录的 children + * - 如果为 null 或 undefined:创建空的文件系统 + * @param {string} [working='/'] - 工作目录路径,默认为根目录 + * + * @example + * // 创建空文件系统 + * const vfs1 = new VirtualFS(); + * + * @example + * // 使用数组初始化 + * const vfs2 = new VirtualFS([ + * { name: 'file.txt', type: 'file', content: 'hello' }, + * { name: 'src', type: 'dir', children: [] } + * ]); + * + * @example + * // 使用根节点对象初始化 + * const vfs3 = new VirtualFS({ + * name: '/', + * type: 'dir', + * children: [{ name: 'file.txt', type: 'file', content: 'hello' }], + * lastModified: Date.now() + * }); + * + * @example + * // 使用子节点对象初始化 + * const vfs4 = new VirtualFS({ + * name: 'src', + * type: 'dir', + * children: [] + * }); + * + * @example + * // 指定工作目录 + * const vfs5 = new VirtualFS(rootNode, '/src'); + */ + constructor(initialStructure?: any | any[] | null, working?: string); + root: any; + /** + * 获取文件/目录的状态信息 + * @param {string} pathStr - 文件或目录路径(相对于工作目录或绝对路径) + * @returns {Promise<{isFile: () => boolean, isDirectory: () => boolean, lastModified: number}>} + * @throws {Error} 路径无效或不存在 + */ + stat(pathStr: string): Promise<{ + isFile: () => boolean; + isDirectory: () => boolean; + lastModified: number; + }>; + /** + * 列出目录下的所有子项名称 + * @param {string} pathStr - 目录路径 + * @returns {Promise} 子项名称数组 + * @throws {Error} 路径无效、不存在或不是目录 + */ + dir(pathStr: string): Promise; + /** + * 读取文件内容 + * @param {string} pathStr - 文件路径 + * @returns {Promise} 文件内容,没有内容时返回空字符串 + * @throws {Error} 路径无效、不存在或是目录 + */ + readFile(pathStr: string): Promise; + /** + * 写入文件内容,文件不存在则创建,存在则覆盖 + * @param {string} pathStr - 文件路径 + * @param {string} content - 文件内容 + * @returns {Promise} + * @throws {Error} 路径无效、父目录不存在或父路径不是目录 + */ + writeFile(pathStr: string, content: string): Promise; + /** + * 创建目录 + * @param {string} pathStr - 目录路径 + * @param {Object} [options] - 选项 + * @param {boolean} [options.recursive] - 是否递归创建缺失的父目录(类似 mkdir -p) + * @returns {Promise} + * @throws {Error} 路径无效、父目录不存在/不是目录,或(非 recursive 时)目录已存在 + */ + mkdir(pathStr: string, options?: { + recursive?: boolean; + }): Promise; + /** + * 删除文件 + * @param {string} pathStr - 文件路径 + * @returns {Promise} + * @throws {Error} 路径无效、不存在或是目录 + */ + unlink(pathStr: string): Promise; + /** + * 删除目录 + * @param {string} pathStr - 目录路径 + * @param {Object} [options] - 选项 + * @param {boolean} [options.recursive] - 目录非空时是否强制删除(类似 rm -rf) + * @returns {Promise} + * @throws {Error} 路径无效、不存在、不是目录,或(非 recursive 时)目录非空 + */ + rmdir(pathStr: string, options?: { + recursive?: boolean; + }): Promise; + /** + * 重命名/移动文件或目录 + * @param {string} oldPath - 原路径 + * @param {string} newPath - 目标路径 + * @returns {Promise} + * @throws {Error} 路径无效、原路径不存在、目标父目录不存在,或目标路径已存在 + */ + rename(oldPath: string, newPath: string): Promise; + /** + * 判断路径是否存在 + * @param {string} pathStr - 文件或目录路径 + * @returns {Promise} 是否存在(路径无效时也返回 false) + */ + exists(pathStr: string): Promise; + /** + * 获取整个文件系统的最后修改时间 + * @returns {number} 时间戳(毫秒) + */ + getLastModified(): number; + /** + * 订阅文件系统变更事件 + * @param {Function} callback - 回调函数,接收事件对象 + * @returns {Function} 取消订阅的函数 + * + * 事件对象格式: + * - action: 'create' | 'update' | 'delete' | 'rename' + * - path: 文件或目录的路径 + * - type: 'file' | 'dir' + * - timestamp: 操作时间戳 + * - oldPath: (仅 rename 事件) 旧路径 + * + * @example + * // 订阅文件系统变更 + * const unsubscribe = vfs.subscribe((event) => { + * console.log(`${event.action} ${event.type}: ${event.path}`); + * // 输出示例: "create file: /src/index.js" + * }); + * + * // 监听特定类型的变更 + * const unsubscribe = vfs.subscribe((event) => { + * if (event.action === 'create' && event.type === 'file') { + * console.log('New file created:', event.path); + * } + * }); + * + * // 取消订阅 + * unsubscribe(); + */ + subscribe(callback: Function): Function; + /** + * 获取当前工作目录 + * @returns {string} 当前工作目录路径 + */ + getWorkingDirectory(): string; + /** + * 打开指定路径的目录,返回一个新的 VirtualFS 实例 + * + * 注意:返回的实例与原实例共享同一个节点树,对新实例的修改会影响原实例 + * + * @param {string} pathStr - 要打开的目录路径,默认为根目录 + * @returns {VirtualFS} 新的 VirtualFS 实例,以指定目录为根(共享引用) + * @throws {Error} 如果路径无效、不存在或不是目录 + * + * @example + * const vfs = new VirtualFS(); + * await vfs.mkdir('/src'); + * await vfs.writeFile('/src/index.js', 'content1'); + * + * const srcVfs = vfs.scope('/src'); + * await srcVfs.writeFile('/index.js', 'content2'); // 修改文件 + * + * // 原实例也会看到修改 + * const content = await vfs.readFile('/src/index.js'); + * console.log(content); // 'content2' + */ + scope(pathStr?: string): VirtualFS; + /** + * 在指定目录下查找匹配的文件 + * @param {string} dirPath - 要搜索的目录路径 + * @param {string|string[]|Function} patterns - 文件名模式,支持精确匹配、glob 通配符或过滤函数 + * @param {Object} options - 选项对象 + * @param {boolean} options.recursive - 是否递归搜索子目录(默认 false) + * @param {boolean|string} options.fullPath - 返回路径的类型(默认 false) + * - false:返回相对路径或文件名 + * - true 或 'working':返回基于工作目录的相对路径(不带前导 /) + * * 例如:'src/index.js', 'utils/helper.js' + * - 'root':返回基于根目录的绝对路径(带前导 /) + * * 例如:'/src/index.js', '/src/utils/helper.js' + * @returns {Promise} 匹配的文件名数组 + * @throws {Error} 如果路径无效、目录不存在或路径不是目录 + * + * 支持的模式类型: + * 1. 精确匹配: 'index.js' - 查找具体的文件名 + * 2. 通配符 *: '*.js' - 匹配任意数量的字符 + * 3. 通配符 ?: 'App.?sx' - 匹配单个字符 + * 4. 大括号展开: 'index.{js,jsx,ts}' - 匹配多个可选值 + * 5. 数组模式: ['*.js', 'App.*', 'package.json'] - 组合多个模式 + * 6. 过滤函数: (filename) => boolean - 自定义过滤逻辑 + * + * 使用示例: + * ```javascript + * // 精确查找单个文件 + * await vfs.findFiles('/src', 'index.js') + * // 返回: ['index.js'] (如果存在) + * + * // 查找多个精确文件 + * await vfs.findFiles('/src', ['index.js', 'App.jsx', 'main.ts']) + * // 返回: ['index.js', 'App.jsx'] (返回存在的文件) + * + * // 使用通配符查找所有 .js 文件 + * await vfs.findFiles('/src', '*.js') + * // 返回: ['index.js', 'main.js', 'utils.js'] + * + * // 使用 ? 匹配单个字符 + * await vfs.findFiles('/src', 'App.?sx') + * // 返回: ['App.jsx', 'App.tsx'] + * + * // 使用大括号展开 + * await vfs.findFiles('/src', 'index.{js,jsx,ts,tsx}') + * // 返回: ['index.js', 'index.jsx'] (返回存在的变体) + * + * // 组合通配符和大括号 + * await vfs.findFiles('/src', '*.{js,jsx}') + * // 返回: ['index.js', 'App.jsx', 'main.js'] + * + * // 混合精确匹配和模式 + * await vfs.findFiles('/src', ['package.json', '*.ts', 'index.{js,jsx}']) + * // 返回所有匹配的文件 + * + * // 使用过滤函数 + * await vfs.findFiles('/src', (filename) => filename.startsWith('test')) + * // 返回: ['test-utils.js', 'test-helpers.js'] + * + * // 使用过滤函数 - 复杂条件 + * await vfs.findFiles('/src', (filename) => { + * return filename.endsWith('.js') && filename.length > 10 + * }) + * // 返回所有长度大于10的 .js 文件 + * + * // 递归搜索所有子目录 + * await vfs.findFiles('/src', '*.js', { recursive: true }) + * // 返回: ['index.js', 'utils/helper.js', 'components/Button.js'] + * + * // 递归搜索 + 过滤函数 + * await vfs.findFiles('/src', (filename) => filename.includes('test'), { recursive: true }) + * // 返回: ['test.js', 'utils/test-helper.js', 'components/Button.test.js'] + * + * // 返回基于工作目录的完整路径 + * await vfs.findFiles('/src', '*.js', { fullPath: true }) + * // 或者 + * await vfs.findFiles('/src', '*.js', { fullPath: 'working' }) + * // 返回: ['src/index.js', 'src/main.js'] (相对路径,不带前导 /) + * + * // 返回基于根目录的完整路径 + * await vfs.findFiles('/src', '*.js', { fullPath: 'root' }) + * // 返回: ['/src/index.js', '/src/main.js'] (绝对路径,带前导 /) + * + * // 递归搜索 + 根目录完整路径 + * await vfs.findFiles('/src', '*.js', { recursive: true, fullPath: 'root' }) + * // 返回: ['/src/index.js', '/src/utils/helper.js', '/src/components/Button.js'] + * ``` + */ + findFiles(dirPath: string, patterns: string | string[] | Function, options?: { + recursive: boolean; + fullPath: boolean | string; + }): Promise; + #private; +} + +export { VirtualFS as default, toTreePaths }; diff --git a/dist/virtual-fs.js b/dist/virtual-fs.js index 05ef93b..04c1aeb 100644 --- a/dist/virtual-fs.js +++ b/dist/virtual-fs.js @@ -1,5 +1,5 @@ import "pathe"; -import { aG as o, aH as r } from "./common/main-DsRa-iMx.js"; +import { aG as o, aH as r } from "./common/main-DahsFEqk.js"; export { o as default, r as toTreePaths diff --git a/package.json b/package.json index 4ad6999..7fe5a16 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,19 @@ { "name": "ff", "private": true, - "version": "0.7.2", + "version": "0.7.3", "author": "www.fsdpf.com", "type": "module", "main": "./dist/index.js", "exports": { - ".": "./dist/index.js", - "./*": "./dist/*" + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./*": { + "types": "./dist/*.d.ts", + "default": "./dist/*.js" + } }, "scripts": { "start": "vite", @@ -63,7 +69,9 @@ "react-router-dom": "6.21.2", "react-use": "^17.6.0", "rollup-plugin-copy": "^3.5.0", + "rollup-plugin-dts": "^6.5.1", "rollup-plugin-terser": "^7.0.2", + "typescript": "^5.5.4", "vite": "^5.2.0", "vite-plugin-mock": "^3.0.2" },