@xbeeant/form-engine-designer 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,121 +1,128 @@
1
- import { jsx as b, jsxs as L } from "react/jsx-runtime";
2
- import { useRef as l, useEffect as o, useSyncExternalStore as Q, useMemo as y, useCallback as W } from "react";
3
- import { renderTreeNode as U } from "../utils/renderTreeNode.js";
4
- import { NexusFormProvider as X } from "./NexusFormProvider.js";
1
+ import { jsx as b, jsxs as k } from "react/jsx-runtime";
2
+ import { useRef as i, useEffect as l, useSyncExternalStore as Z, useMemo as y, useCallback as O } from "react";
3
+ import { renderTreeNode as H } from "../utils/renderTreeNode.js";
4
+ import { NexusFormProvider as ee } from "./NexusFormProvider.js";
5
5
  function s() {
6
6
  }
7
- function ne({
8
- form: n,
9
- schema: t,
10
- initialValues: _,
7
+ function oe({
8
+ form: t,
9
+ schema: e,
10
+ initialValues: D,
11
11
  widgets: u,
12
12
  layouts: c,
13
- onFinish: j,
14
- onFinishFailed: k,
15
- footer: a = !1,
16
- className: D,
17
- style: O,
18
- children: V,
19
- labelCol: f,
20
- labelWidth: $,
21
- colon: I,
22
- label: M,
23
- displayType: P,
24
- readOnly: g,
25
- column: q,
13
+ onFinish: M,
14
+ onFinishFailed: V,
15
+ onMount: g,
16
+ footer: f = !1,
17
+ className: $,
18
+ style: I,
19
+ children: P,
20
+ labelCol: a,
21
+ labelWidth: q,
22
+ colon: w,
23
+ label: z,
24
+ displayType: A,
25
+ readOnly: R,
26
+ column: B,
26
27
  watch: m,
27
- removeHiddenData: R = !0
28
+ removeHiddenData: F = !0
28
29
  }) {
29
- const e = n._getEngine(), x = l(null), F = P ?? t?.displayType ?? "row", C = M ?? t?.label ?? !0, S = I ?? t?.colon, r = $ ?? t?.labelWidth, T = g ?? t?.readOnly ?? !1, i = q ?? t?.column;
30
- o(() => {
31
- u && e.registerWidgets(u), c && e.registerLayouts(c);
32
- }, [e, u, c]);
33
- const h = l(!0), w = l(_);
34
- o(() => {
35
- t && (h.current ? (e.init(t, w.current), h.current = !1) : e.init(t, e.getFormData()));
36
- }, [e, t]);
37
- const N = l(s), v = l(s);
38
- N.current = j ?? s, v.current = k ?? s, o(() => {
39
- n._bind(
30
+ const n = t._getEngine(), x = i(null), S = A ?? e?.displayType ?? "row", C = z ?? e?.label ?? !0, T = w ?? e?.colon, r = q ?? e?.labelWidth, E = R ?? e?.readOnly ?? !1, o = B ?? e?.column;
31
+ l(() => {
32
+ u && n.registerWidgets(u), c && n.registerLayouts(c);
33
+ }, [n, u, c]);
34
+ const N = i(!0), G = i(D);
35
+ l(() => {
36
+ e && (N.current ? (n.init(e, G.current), N.current = !1) : n.init(e, n.getFormData()));
37
+ }, [n, e]);
38
+ const h = i(g);
39
+ h.current = g;
40
+ const j = i(!1), v = !e || typeof e == "object" && Object.keys(e).length === 0;
41
+ l(() => {
42
+ j.current || v || (j.current = !0, h.current?.());
43
+ }, [v]);
44
+ const L = i(s), W = i(s);
45
+ L.current = M ?? s, W.current = V ?? s, l(() => {
46
+ t._bind(
40
47
  x.current,
41
- () => N.current,
42
- () => v.current
48
+ () => L.current,
49
+ () => W.current
43
50
  );
44
- }, [n]), o(() => {
45
- n._syncConfig({ removeHiddenData: R, watch: m });
46
- }, [n, R, m]);
47
- const z = Q(
48
- e.subscribeStore,
49
- e.getSnapshot,
50
- e.getSnapshot
51
- ), A = y(() => e.getRenderTree(), [e, z]), B = W(
51
+ }, [t]), l(() => {
52
+ t._syncConfig({ removeHiddenData: F, watch: m });
53
+ }, [t, F, m]);
54
+ const J = Z(
55
+ n.subscribeStore,
56
+ n.getSnapshot,
57
+ n.getSnapshot
58
+ ), K = y(() => n.getRenderTree(), [n, J]), Q = O(
52
59
  async (p) => {
53
- p.preventDefault(), await n.submit();
60
+ p.preventDefault(), await t.submit();
54
61
  },
55
- [n]
56
- ), G = W(() => {
57
- n.resetFields();
58
- }, [n]);
62
+ [t]
63
+ ), U = O(() => {
64
+ t.resetFields();
65
+ }, [t]);
59
66
  let d = null;
60
- a === !0 ? d = /* @__PURE__ */ L("div", { className: "mt-4", children: [
67
+ f === !0 ? d = /* @__PURE__ */ k("div", { className: "mt-4", children: [
61
68
  /* @__PURE__ */ b("button", { type: "submit", children: "提交" }),
62
69
  " ",
63
- /* @__PURE__ */ b("button", { type: "button", onClick: G, children: "重置" })
64
- ] }) : a && (d = a);
65
- const E = y(() => {
66
- if (f)
67
- return f;
70
+ /* @__PURE__ */ b("button", { type: "button", onClick: U, children: "重置" })
71
+ ] }) : f && (d = f);
72
+ const _ = y(() => {
73
+ if (a)
74
+ return a;
68
75
  if (r)
69
76
  return {
70
77
  style: {
71
78
  width: typeof r == "number" ? `${r}px` : r
72
79
  }
73
80
  };
74
- }, [f, r]), J = y(
81
+ }, [a, r]), X = y(
75
82
  () => ({
76
- labelCol: E,
83
+ labelCol: _,
77
84
  labelWidth: r,
78
- colon: S,
85
+ colon: T,
79
86
  label: C,
80
- displayType: F,
81
- readOnly: T,
82
- column: i
87
+ displayType: S,
88
+ readOnly: E,
89
+ column: o
83
90
  }),
84
91
  [
85
- E,
92
+ _,
86
93
  r,
87
- S,
88
- C,
89
- F,
90
94
  T,
91
- i
95
+ C,
96
+ S,
97
+ E,
98
+ o
92
99
  ]
93
100
  );
94
- return /* @__PURE__ */ b(X, { engine: e, config: J, form: n, children: /* @__PURE__ */ L(
101
+ return /* @__PURE__ */ b(ee, { engine: n, config: X, form: t, children: /* @__PURE__ */ k(
95
102
  "form",
96
103
  {
97
104
  ref: x,
98
- onSubmit: B,
99
- className: D,
105
+ onSubmit: Q,
106
+ className: $,
100
107
  style: {
101
- ...O,
108
+ ...I,
102
109
  // 当配置了 column 时,使用 CSS Grid 布局
103
- ...i && i > 1 ? {
110
+ ...o && o > 1 ? {
104
111
  display: "grid",
105
- gridTemplateColumns: `repeat(${i}, 1fr)`,
112
+ gridTemplateColumns: `repeat(${o}, 1fr)`,
106
113
  gap: "0 16px"
107
114
  } : {}
108
115
  },
109
116
  noValidate: !0,
110
117
  children: [
111
- A.map((p, K) => U(p, K)),
112
- !g && d,
113
- V
118
+ K.map((p, Y) => H(p, Y)),
119
+ !R && d,
120
+ P
114
121
  ]
115
122
  }
116
123
  ) });
117
124
  }
118
125
  export {
119
- ne as NexusForm
126
+ oe as NexusForm
120
127
  };
121
128
  //# sourceMappingURL=NexusForm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NexusForm.js","sources":["../../../../../../react/src/components/NexusForm.tsx"],"sourcesContent":["import type { NexusSchema } from '@xbeeant/form-engine';\nimport type { CSSProperties, ReactNode, SubmitEvent } from 'react';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nimport { renderTreeNode } from '../utils/renderTreeNode';\nimport type { FormController } from './FormController';\nimport { NexusFormProvider } from './NexusFormProvider';\n\n// ────────────────────────────────────────────────────────────────────────────\n// Form 布局配置\n// ────────────────────────────────────────────────────────────────────────────\n\nexport interface NexusFormConfig {\n /** label 列配置(由 ui 层 Form.Item 消费) */\n labelCol?: Record<string, unknown>;\n /** label 宽度(px 或 %),快捷方式 — 映射到 labelCol.style.width */\n labelWidth?: number | string;\n /** 是否显示冒号 */\n colon?: boolean | ReactNode;\n /** 是否显示 label(默认 true) */\n label?: boolean;\n /** 表单布局方向 */\n displayType?: 'row' | 'column' | 'inline';\n /** 整个表单只读,所有字段以文本展示 */\n readOnly?: boolean;\n /** 表单每行显示多少列 */\n column?: number;\n}\n\nexport interface NexusFormProps {\n /** Form 实例,由 useForm() 创建 */\n form: FormController;\n /** Schema 定义 */\n schema?: NexusSchema;\n /** 初始值 */\n initialValues?: Record<string, unknown>;\n /** 额外注册的 widget(与已注册的合并) */\n widgets?: Record<string, (props: any) => ReactNode>;\n /** 额外注册的 layout */\n layouts?: Record<string, (props: any) => ReactNode>;\n /** 提交成功回调 */\n onFinish?: (formData: Record<string, unknown>) => void | Promise<void>;\n /** 校验失败回调 */\n onFinishFailed?: (errors: Map<string, string[]>) => void;\n /** 是否显示默认 footer(提交/重置按钮),或自定义 footer */\n footer?: boolean | ReactNode;\n /** 自定义类名 */\n className?: string;\n /** 自定义样式 */\n style?: CSSProperties;\n /** 子节点 */\n children?: ReactNode;\n /**\n * 表单值变化监听\n * - key 为字段路径(如 'username'),值为回调函数\n * - 使用 '#' 作为 key 可监听所有字段变化\n * - 回调参数为 (value, allValues);全局('#')监听额外提供第三参 changedPath,\n * 即本次实际变更的字段路径(用于区分「未触碰的默认空值」与「用户主动清空」)\n */\n watch?: {\n [path: string]: (\n value: unknown,\n allValues: Record<string, unknown>,\n changedPath?: string,\n ) => void;\n };\n /**\n * 提交时是否移除 hidden 字段数据,默认 true\n * - true: submit/getValues 不包含 hidden 字段\n * - false: submit/getValues 包含所有字段(含 hidden)\n */\n removeHiddenData?: boolean;\n\n // ── 表单布局配置 ──────────────────────────────────────────────────────\n /** label 列配置(由 ui 层 Form.Item 消费) */\n labelCol?: Record<string, unknown>;\n /** label 宽度(px 或 %),快捷方式 — 映射到 labelCol.style.width */\n labelWidth?: number | string;\n /** 是否显示冒号 */\n colon?: boolean | ReactNode;\n /** 是否显示 label(默认 true) */\n label?: boolean;\n /** 表单布局方向:'row' = horizontal, 'column' = vertical, 'inline' = inline */\n displayType?: 'row' | 'column' | 'inline';\n /** 整个表单只读,所有字段以文本展示 */\n readOnly?: boolean;\n /** 表单每行显示多少列 */\n column?: number;\n}\n\nfunction noop() {}\n\n/**\n * NexusForm — 顶层表单组件\n */\nexport function NexusForm({\n form,\n schema,\n initialValues,\n widgets,\n layouts,\n onFinish,\n onFinishFailed,\n footer = false,\n className,\n style,\n children,\n labelCol,\n labelWidth,\n colon,\n label,\n displayType,\n readOnly,\n column,\n watch,\n removeHiddenData = true,\n}: NexusFormProps) {\n const engine = form._getEngine();\n const formElRef = useRef<HTMLFormElement | null>(null);\n\n // Schema 顶层配置作为默认值,props 优先级更高\n const finalDisplayType = displayType ?? schema?.displayType ?? 'row';\n const finalLabel = label ?? schema?.label ?? true;\n const finalColon = colon ?? schema?.colon;\n const finalLabelWidth = labelWidth ?? schema?.labelWidth;\n const finalReadOnly = readOnly ?? schema?.readOnly ?? false;\n const finalColumn = column ?? schema?.column;\n\n // 注册额外 widgets / layouts(仅首次或引用变化时)\n useEffect(() => {\n if (widgets) {\n engine.registerWidgets(widgets);\n }\n if (layouts) {\n engine.registerLayouts(layouts);\n }\n }, [engine, widgets, layouts]);\n\n // schema 变化时重新初始化\n // 注意:initialValues 仅在首次挂载时使用,避免每次渲染都 re-init 导致\n // 已有的 errors / 用户输入被重置。后续需要更新值请使用 form.setValues()。\n const isFirstInitRef = useRef(true);\n const initialValuesRef = useRef(initialValues);\n useEffect(() => {\n if (!schema) {\n return;\n }\n if (isFirstInitRef.current) {\n engine.init(schema, initialValuesRef.current);\n isFirstInitRef.current = false;\n } else {\n // schema 变化:保留当前已填数据,而非重置为 initialValues\n engine.init(schema, engine.getFormData());\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [engine, schema]);\n\n // 绑定 form controller\n // 使用 ref 持有 onFinish / onFinishFailed,避免每次 re-render 都造成绑定逻辑重复执行\n const onFinishRef =\n useRef<(data: Record<string, unknown>) => void | Promise<void>>(noop);\n const onFinishFailedRef =\n useRef<(errors: Map<string, string[]>) => void>(noop);\n onFinishRef.current = onFinish ?? noop;\n onFinishFailedRef.current = onFinishFailed ?? noop;\n\n // 只在挂载时绑定一次:传入「稳定的 getter」,让 FormController 在 submit 时读取最新回调\n useEffect(() => {\n form._bind(\n formElRef.current,\n () => onFinishRef.current,\n () => onFinishFailedRef.current,\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [form]);\n\n // watch / removeHiddenData 变化时单独同步(不重置其他绑定)\n useEffect(() => {\n form._syncConfig({ removeHiddenData, watch });\n }, [form, removeHiddenData, watch]);\n\n const _version = useSyncExternalStore(\n engine.subscribeStore,\n engine.getSnapshot,\n engine.getSnapshot,\n );\n // 依赖 _version:engine.init() / setSchema() 会 bump version,\n // 需要在此后重新读取 renderTree(首次渲染时 engine 尚未 init,renderTree 为空)\n // biome-ignore lint/correctness/useExhaustiveDependencies: _version 是 renderTree 失效信号(engine 内部状态,静态分析不可见)\n const renderTree = useMemo(() => engine.getRenderTree(), [engine, _version]);\n\n const handleSubmit = useCallback(\n async (e: SubmitEvent) => {\n e.preventDefault();\n await form.submit();\n },\n [form],\n );\n\n const handleReset = useCallback(() => {\n form.resetFields();\n }, [form]);\n\n // footer 渲染\n let footerNode: ReactNode = null;\n if (footer === true) {\n footerNode = (\n <div className='mt-4'>\n <button type='submit'>提交</button>{' '}\n <button type='button' onClick={handleReset}>\n 重置\n </button>\n </div>\n );\n } else if (footer) {\n footerNode = footer;\n }\n\n // labelCol: 合并 labelWidth 快捷方式\n const mergedLabelCol = useMemo(() => {\n if (labelCol) {\n return labelCol;\n }\n if (finalLabelWidth) {\n return {\n style: {\n width:\n typeof finalLabelWidth === 'number'\n ? `${finalLabelWidth}px`\n : finalLabelWidth,\n },\n };\n }\n return undefined;\n }, [labelCol, finalLabelWidth]);\n\n // NexusFormConfig 传递给 Context(由 ui 层消费,自行实现布局)\n const formConfig = useMemo<NexusFormConfig>(\n () => ({\n labelCol: mergedLabelCol,\n labelWidth: finalLabelWidth,\n colon: finalColon,\n label: finalLabel,\n displayType: finalDisplayType,\n readOnly: finalReadOnly,\n column: finalColumn,\n }),\n [\n mergedLabelCol,\n finalLabelWidth,\n finalColon,\n finalLabel,\n finalDisplayType,\n finalReadOnly,\n finalColumn,\n ],\n );\n\n return (\n <NexusFormProvider engine={engine} config={formConfig} form={form}>\n <form\n ref={formElRef}\n onSubmit={handleSubmit}\n className={className}\n style={{\n ...style,\n // 当配置了 column 时,使用 CSS Grid 布局\n ...(finalColumn && finalColumn > 1\n ? {\n display: 'grid',\n gridTemplateColumns: `repeat(${finalColumn}, 1fr)`,\n gap: '0 16px',\n }\n : {}),\n }}\n noValidate\n >\n {renderTree.map((node, index) => renderTreeNode(node, index))}\n {!readOnly && footerNode}\n {children}\n </form>\n </NexusFormProvider>\n );\n}\n"],"names":["noop","NexusForm","form","schema","initialValues","widgets","layouts","onFinish","onFinishFailed","footer","className","style","children","labelCol","labelWidth","colon","label","displayType","readOnly","column","watch","removeHiddenData","engine","formElRef","useRef","finalDisplayType","finalLabel","finalColon","finalLabelWidth","finalReadOnly","finalColumn","useEffect","isFirstInitRef","initialValuesRef","onFinishRef","onFinishFailedRef","_version","useSyncExternalStore","renderTree","useMemo","handleSubmit","useCallback","e","handleReset","footerNode","jsxs","jsx","mergedLabelCol","formConfig","NexusFormProvider","node","index","renderTreeNode"],"mappings":"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"}
1
+ {"version":3,"file":"NexusForm.js","sources":["../../../../../../react/src/components/NexusForm.tsx"],"sourcesContent":["import type { NexusSchema } from '@xbeeant/form-engine';\nimport type { CSSProperties, ReactNode, SubmitEvent } from 'react';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nimport { renderTreeNode } from '../utils/renderTreeNode';\nimport type { FormController } from './FormController';\nimport { NexusFormProvider } from './NexusFormProvider';\n\n// ────────────────────────────────────────────────────────────────────────────\n// Form 布局配置\n// ────────────────────────────────────────────────────────────────────────────\n\nexport interface NexusFormConfig {\n /** label 列配置(由 ui 层 Form.Item 消费) */\n labelCol?: Record<string, unknown>;\n /** label 宽度(px 或 %),快捷方式 — 映射到 labelCol.style.width */\n labelWidth?: number | string;\n /** 是否显示冒号 */\n colon?: boolean | ReactNode;\n /** 是否显示 label(默认 true) */\n label?: boolean;\n /** 表单布局方向 */\n displayType?: 'row' | 'column' | 'inline';\n /** 整个表单只读,所有字段以文本展示 */\n readOnly?: boolean;\n /** 表单每行显示多少列 */\n column?: number;\n}\n\nexport interface NexusFormProps {\n /** Form 实例,由 useForm() 创建 */\n form: FormController;\n /** Schema 定义 */\n schema?: NexusSchema;\n /** 初始值 */\n initialValues?: Record<string, unknown>;\n /** 额外注册的 widget(与已注册的合并) */\n widgets?: Record<string, (props: any) => ReactNode>;\n /** 额外注册的 layout */\n layouts?: Record<string, (props: any) => ReactNode>;\n /** 提交成功回调 */\n onFinish?: (formData: Record<string, unknown>) => void | Promise<void>;\n /** 校验失败回调 */\n onFinishFailed?: (errors: Map<string, string[]>) => void;\n /**\n * 表单首次加载回调:非空 schema 首次传入并完成渲染后执行一次\n * - undefined / null / {}(无 properties)均视为「空」schema,不触发\n * - schema 由空变为非空时,于首个非空渲染提交后触发\n * - 后续 schema 变更不重复触发\n */\n onMount?: () => void;\n /** 是否显示默认 footer(提交/重置按钮),或自定义 footer */\n footer?: boolean | ReactNode;\n /** 自定义类名 */\n className?: string;\n /** 自定义样式 */\n style?: CSSProperties;\n /** 子节点 */\n children?: ReactNode;\n /**\n * 表单值变化监听\n * - key 为字段路径(如 'username'),值为回调函数\n * - 使用 '#' 作为 key 可监听所有字段变化\n * - 回调参数为 (value, allValues);全局('#')监听额外提供第三参 changedPath,\n * 即本次实际变更的字段路径(用于区分「未触碰的默认空值」与「用户主动清空」)\n */\n watch?: {\n [path: string]: (\n value: unknown,\n allValues: Record<string, unknown>,\n changedPath?: string,\n ) => void;\n };\n /**\n * 提交时是否移除 hidden 字段数据,默认 true\n * - true: submit/getValues 不包含 hidden 字段\n * - false: submit/getValues 包含所有字段(含 hidden)\n */\n removeHiddenData?: boolean;\n\n // ── 表单布局配置 ──────────────────────────────────────────────────────\n /** label 列配置(由 ui 层 Form.Item 消费) */\n labelCol?: Record<string, unknown>;\n /** label 宽度(px 或 %),快捷方式 — 映射到 labelCol.style.width */\n labelWidth?: number | string;\n /** 是否显示冒号 */\n colon?: boolean | ReactNode;\n /** 是否显示 label(默认 true) */\n label?: boolean;\n /** 表单布局方向:'row' = horizontal, 'column' = vertical, 'inline' = inline */\n displayType?: 'row' | 'column' | 'inline';\n /** 整个表单只读,所有字段以文本展示 */\n readOnly?: boolean;\n /** 表单每行显示多少列 */\n column?: number;\n}\n\nfunction noop() {}\n\n/**\n * NexusForm — 顶层表单组件\n */\nexport function NexusForm({\n form,\n schema,\n initialValues,\n widgets,\n layouts,\n onFinish,\n onFinishFailed,\n onMount,\n footer = false,\n className,\n style,\n children,\n labelCol,\n labelWidth,\n colon,\n label,\n displayType,\n readOnly,\n column,\n watch,\n removeHiddenData = true,\n}: NexusFormProps) {\n const engine = form._getEngine();\n const formElRef = useRef<HTMLFormElement | null>(null);\n\n // Schema 顶层配置作为默认值,props 优先级更高\n const finalDisplayType = displayType ?? schema?.displayType ?? 'row';\n const finalLabel = label ?? schema?.label ?? true;\n const finalColon = colon ?? schema?.colon;\n const finalLabelWidth = labelWidth ?? schema?.labelWidth;\n const finalReadOnly = readOnly ?? schema?.readOnly ?? false;\n const finalColumn = column ?? schema?.column;\n\n // 注册额外 widgets / layouts(仅首次或引用变化时)\n useEffect(() => {\n if (widgets) {\n engine.registerWidgets(widgets);\n }\n if (layouts) {\n engine.registerLayouts(layouts);\n }\n }, [engine, widgets, layouts]);\n\n // schema 变化时重新初始化\n // 注意:initialValues 仅在首次挂载时使用,避免每次渲染都 re-init 导致\n // 已有的 errors / 用户输入被重置。后续需要更新值请使用 form.setValues()。\n const isFirstInitRef = useRef(true);\n const initialValuesRef = useRef(initialValues);\n useEffect(() => {\n if (!schema) {\n return;\n }\n if (isFirstInitRef.current) {\n engine.init(schema, initialValuesRef.current);\n isFirstInitRef.current = false;\n } else {\n // schema 变化:保留当前已填数据,而非重置为 initialValues\n engine.init(schema, engine.getFormData());\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [engine, schema]);\n\n // onMount:首次传入「非空」schema 并完成渲染后执行一次\n // undefined / null / {}(无任何键)均视为空 schema,不触发;\n // schema 由空变为非空时,于首个非空渲染提交(useEffect)后触发。\n const onMountRef = useRef(onMount);\n onMountRef.current = onMount;\n const onMountFiredRef = useRef(false);\n const isSchemaEmpty =\n !schema || (typeof schema === 'object' && Object.keys(schema).length === 0);\n useEffect(() => {\n if (onMountFiredRef.current || isSchemaEmpty) {\n return;\n }\n onMountFiredRef.current = true;\n onMountRef.current?.();\n }, [isSchemaEmpty]);\n\n // 绑定 form controller\n // 使用 ref 持有 onFinish / onFinishFailed,避免每次 re-render 都造成绑定逻辑重复执行\n const onFinishRef =\n useRef<(data: Record<string, unknown>) => void | Promise<void>>(noop);\n const onFinishFailedRef =\n useRef<(errors: Map<string, string[]>) => void>(noop);\n onFinishRef.current = onFinish ?? noop;\n onFinishFailedRef.current = onFinishFailed ?? noop;\n\n // 只在挂载时绑定一次:传入「稳定的 getter」,让 FormController 在 submit 时读取最新回调\n useEffect(() => {\n form._bind(\n formElRef.current,\n () => onFinishRef.current,\n () => onFinishFailedRef.current,\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [form]);\n\n // watch / removeHiddenData 变化时单独同步(不重置其他绑定)\n useEffect(() => {\n form._syncConfig({ removeHiddenData, watch });\n }, [form, removeHiddenData, watch]);\n\n const _version = useSyncExternalStore(\n engine.subscribeStore,\n engine.getSnapshot,\n engine.getSnapshot,\n );\n // 依赖 _version:engine.init() / setSchema() 会 bump version,\n // 需要在此后重新读取 renderTree(首次渲染时 engine 尚未 init,renderTree 为空)\n // biome-ignore lint/correctness/useExhaustiveDependencies: _version 是 renderTree 失效信号(engine 内部状态,静态分析不可见)\n const renderTree = useMemo(() => engine.getRenderTree(), [engine, _version]);\n\n const handleSubmit = useCallback(\n async (e: SubmitEvent) => {\n e.preventDefault();\n await form.submit();\n },\n [form],\n );\n\n const handleReset = useCallback(() => {\n form.resetFields();\n }, [form]);\n\n // footer 渲染\n let footerNode: ReactNode = null;\n if (footer === true) {\n footerNode = (\n <div className='mt-4'>\n <button type='submit'>提交</button>{' '}\n <button type='button' onClick={handleReset}>\n 重置\n </button>\n </div>\n );\n } else if (footer) {\n footerNode = footer;\n }\n\n // labelCol: 合并 labelWidth 快捷方式\n const mergedLabelCol = useMemo(() => {\n if (labelCol) {\n return labelCol;\n }\n if (finalLabelWidth) {\n return {\n style: {\n width:\n typeof finalLabelWidth === 'number'\n ? `${finalLabelWidth}px`\n : finalLabelWidth,\n },\n };\n }\n return undefined;\n }, [labelCol, finalLabelWidth]);\n\n // NexusFormConfig 传递给 Context(由 ui 层消费,自行实现布局)\n const formConfig = useMemo<NexusFormConfig>(\n () => ({\n labelCol: mergedLabelCol,\n labelWidth: finalLabelWidth,\n colon: finalColon,\n label: finalLabel,\n displayType: finalDisplayType,\n readOnly: finalReadOnly,\n column: finalColumn,\n }),\n [\n mergedLabelCol,\n finalLabelWidth,\n finalColon,\n finalLabel,\n finalDisplayType,\n finalReadOnly,\n finalColumn,\n ],\n );\n\n return (\n <NexusFormProvider engine={engine} config={formConfig} form={form}>\n <form\n ref={formElRef}\n onSubmit={handleSubmit}\n className={className}\n style={{\n ...style,\n // 当配置了 column 时,使用 CSS Grid 布局\n ...(finalColumn && finalColumn > 1\n ? {\n display: 'grid',\n gridTemplateColumns: `repeat(${finalColumn}, 1fr)`,\n gap: '0 16px',\n }\n : {}),\n }}\n noValidate\n >\n {renderTree.map((node, index) => renderTreeNode(node, index))}\n {!readOnly && footerNode}\n {children}\n </form>\n </NexusFormProvider>\n );\n}\n"],"names":["noop","NexusForm","form","schema","initialValues","widgets","layouts","onFinish","onFinishFailed","onMount","footer","className","style","children","labelCol","labelWidth","colon","label","displayType","readOnly","column","watch","removeHiddenData","engine","formElRef","useRef","finalDisplayType","finalLabel","finalColon","finalLabelWidth","finalReadOnly","finalColumn","useEffect","isFirstInitRef","initialValuesRef","onMountRef","onMountFiredRef","isSchemaEmpty","onFinishRef","onFinishFailedRef","_version","useSyncExternalStore","renderTree","useMemo","handleSubmit","useCallback","e","handleReset","footerNode","jsxs","jsx","mergedLabelCol","formConfig","NexusFormProvider","node","index","renderTreeNode"],"mappings":"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"}
@@ -1,10 +1,13 @@
1
- import { useRef as e } from "react";
2
- import { FormController as n } from "../components/FormController.js";
3
- function f(o) {
4
- const r = e(null);
5
- return r.current || (r.current = new n(o)), [r.current];
1
+ import "@xbeeant/form-engine";
2
+ import { useRef as o } from "react";
3
+ import { FormController as e } from "../components/FormController.js";
4
+ function i(n, t) {
5
+ const r = o(null);
6
+ return r.current || (r.current = new e(
7
+ void 0
8
+ )), [r.current];
6
9
  }
7
10
  export {
8
- f as useForm
11
+ i as useForm
9
12
  };
10
13
  //# sourceMappingURL=useForm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useForm.js","sources":["../../../../../../react/src/hooks/useForm.ts"],"sourcesContent":["import type { NexusEngine } from '@xbeeant/form-engine';\nimport { useRef } from 'react';\n\nimport { FormController } from '../components/FormController';\n\n/**\n * useForm — 创建 Form 实例\n */\nexport function useForm(engine?: NexusEngine): [FormController] {\n const formRef = useRef<FormController | null>(null);\n if (!formRef.current) {\n formRef.current = new FormController(engine);\n }\n return [formRef.current];\n}\n"],"names":["useForm","engine","formRef","useRef","FormController"],"mappings":";;AAQO,SAASA,EAAQC,GAAwC;AAC9D,QAAMC,IAAUC,EAA8B,IAAI;AAClD,SAAKD,EAAQ,YACXA,EAAQ,UAAU,IAAIE,EAAeH,CAAM,IAEtC,CAACC,EAAQ,OAAO;AACzB;"}
1
+ {"version":3,"file":"useForm.js","sources":["../../../../../../react/src/hooks/useForm.ts"],"sourcesContent":["import { NexusEngine } from '@xbeeant/form-engine';\nimport { useRef } from 'react';\n\nimport { FormController } from '../components/FormController';\n\n/**\n * useForm — 创建 Form 实例\n *\n * 支持一个页面挂载多个表单实例:\n * - `useForm()`:独立实例(未注册,不参与跨表单联动)\n * - `useForm(formId)`:创建带 formId 的实例,自动注册到默认表单注册表,\n * 可通过 schema `crossForm` reaction / `engine.linkForm` 与其他表单联动\n * - `useForm(formId, engine)`:复用外部创建的引擎(如 `new NexusEngine({ formId })`)\n *\n * @param formId - 可选,表单实例唯一标识(跨表单联动寻址)\n * @param engine - 可选,外部引擎实例(缺省内部创建)\n */\nexport function useForm(\n formId?: string,\n engine?: NexusEngine,\n): [FormController] {\n const formRef = useRef<FormController | null>(null);\n if (!formRef.current) {\n formRef.current = new FormController(\n engine ?? (formId ? new NexusEngine({ formId }) : undefined),\n );\n }\n return [formRef.current];\n}\n"],"names":["useForm","formId","engine","formRef","useRef","FormController"],"mappings":";;;AAiBO,SAASA,EACdC,GACAC,GACkB;AAClB,QAAMC,IAAUC,EAA8B,IAAI;AAClD,SAAKD,EAAQ,YACXA,EAAQ,UAAU,IAAIE;AAAA,IAC8B;AAAA,EAAA,IAG/C,CAACF,EAAQ,OAAO;AACzB;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xbeeant/form-engine-designer",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
@@ -53,10 +53,11 @@
53
53
  }
54
54
  },
55
55
  "dependencies": {
56
- "@xbeeant/form-engine": "^0.0.1",
57
- "@xbeeant/form-engine-ui": "^0.0.1"
56
+ "@xbeeant/form-engine": "^0.0.3",
57
+ "@xbeeant/form-engine-ui": "^0.0.3"
58
58
  },
59
59
  "devDependencies": {
60
60
  "vitest": "^4.1.10"
61
- }
61
+ },
62
+ "gitHead": "32282a81ac6acd1c5b26ccf081504b9da53e07de"
62
63
  }
package/src/catalog.ts CHANGED
@@ -226,6 +226,7 @@ export const widgetCatalog: CatalogItem[] = [
226
226
  type: 'string',
227
227
  widget: 'voidTitle',
228
228
  title: '标题文字',
229
+ label: false,
229
230
  }),
230
231
  },
231
232
  {
@@ -1 +0,0 @@
1
- .drop-indicator-line:before{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:3px;background:#1677ff;border-radius:2px;box-shadow:0 0 8px #1677ff99;animation:nexus-drop-pulse 1.2s ease-in-out infinite}@keyframes nexus-drop-pulse{0%,to{opacity:1}50%{opacity:.5}}.nexus-resize-handle{position:absolute;top:0;bottom:0;width:5px;cursor:col-resize;z-index:10;background:transparent;transition:background .15s}.nexus-resize-handle:after{content:"";position:absolute;top:0;bottom:0;left:50%;transform:translate(-50%);width:1px;background:#e8e8e8;transition:background .15s,width .15s}.nexus-resize-handle:hover,.nexus-resize-handle.nexus-resize-active{background:#1677ff14}.nexus-resize-handle:hover:after,.nexus-resize-handle.nexus-resize-active:after{width:4px;background:#1677ff;border-radius:2px}.nexus-panel-toggle{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:1px solid #e8e8e8;border-radius:999px;background:#fff;color:#999;cursor:pointer;box-shadow:0 1px 2px #0000000a;transition:color .15s,border-color .15s,background .15s,box-shadow .15s}.nexus-panel-toggle:hover{color:#1677ff;border-color:#1677ff;background:#f0f7ff;box-shadow:0 2px 6px #1677ff26}.nexus-palette-search.ant-input-affix-wrapper{border-radius:8px;background:#fff;box-shadow:0 1px 2px #00000008}.nexus-palette-collapse{background:transparent;border:none}.nexus-palette-collapse>.ant-collapse-item{margin-bottom:8px;overflow:hidden;border:1px solid #f0f0f0;border-radius:10px;background:#fff}.nexus-palette-collapse>.ant-collapse-item:last-child{margin-bottom:0}.nexus-palette-collapse>.ant-collapse-item>.ant-collapse-header{padding:9px 10px;font-size:13px;font-weight:600;color:#333;align-items:center;background:#fff;transition:background .15s}.nexus-palette-collapse>.ant-collapse-item>.ant-collapse-header:hover{background:#fafbfc}.nexus-palette-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{font-size:10px;color:#999}.nexus-palette-collapse>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding:8px 0 4px}.nexus-key-input.ant-input{border-radius:6px}.nexus-property-body .ant-collapse{background:transparent;border:none}.nexus-property-body .ant-collapse>.ant-collapse-item{margin-bottom:8px;overflow:hidden;border:1px solid #f0f0f0;border-radius:8px;background:#fff}.nexus-property-body .ant-collapse>.ant-collapse-item:last-child{margin-bottom:0}.nexus-property-body .ant-collapse>.ant-collapse-item>.ant-collapse-header{padding:8px 10px;font-size:12px;font-weight:600;color:#333;align-items:center}.nexus-property-body .ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{font-size:10px;color:#999}.nexus-property-body .ant-collapse>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding:8px 10px 4px}
@@ -1,188 +0,0 @@
1
- import { NexusEngine as h } from "@xbeeant/form-engine";
2
- import { describe as s, it as n, expect as t } from "/Users/amybee/Codes/xbeeant/nexus-form-engine/node_modules/.bun/vitest@4.1.10+0a9a94c82e2ce81a/node_modules/vitest/dist/index.js";
3
- import { diffPropertyPatch as l, updateNodeWithNesting as r, addChildToSchema as m, flattenNodeForPropertyEditor as y, extractFormLevelConfig as c, collectDataFieldOptions as u } from "./schemaUtils.js";
4
- const p = {
5
- type: "string",
6
- widget: "radio",
7
- title: "单选",
8
- enum: ["a", "b"],
9
- enumNames: ["选项A", "选项B"]
10
- };
11
- s("diffPropertyPatch", () => {
12
- n("filters out empty-string defaults for untouched fields", () => {
13
- const e = l({
14
- title: "单选",
15
- options: [
16
- { value: "a", label: "选项A" },
17
- { value: "b", label: "选项B" }
18
- ]
19
- }, {
20
- title: "单选",
21
- description: "",
22
- placeholder: "",
23
- default: "",
24
- disabled: "",
25
- readOnly: "",
26
- hidden: "",
27
- required: "",
28
- pattern: "",
29
- bind: "",
30
- dependencies: "",
31
- options: [
32
- { value: "a", label: "选项A" },
33
- { value: "b", label: "选项B" }
34
- ]
35
- });
36
- t(e).toEqual({});
37
- }), n("keeps genuinely changed values", () => {
38
- const a = { title: "单选", options: [{ value: "a", label: "A" }] }, i = {
39
- title: "新标题",
40
- options: [
41
- { value: "a", label: "A" },
42
- { value: "b", label: "B" }
43
- ]
44
- }, e = l(a, i);
45
- t(e).toEqual(i);
46
- }), n("empty string is treated as unassigned and never written to schema", () => {
47
- const e = l({ title: "单选", description: "说明", bind: "user.name" }, { title: "单选", description: "", bind: "" });
48
- t(e).toEqual({});
49
- }), n("user-cleared field is written back as undefined for deletion", () => {
50
- const o = l({ title: "单选", variant: "outlined", description: "说明" }, { title: "单选", variant: "", description: "" }, /* @__PURE__ */ new Set(["variant"]));
51
- t(o).toEqual({ variant: void 0 });
52
- }), n("untouched empty fields stay skipped even with changedFields set", () => {
53
- const o = l({ title: "单选" }, { title: "单选", description: "", placeholder: "" }, /* @__PURE__ */ new Set(["title"]));
54
- t(o).toEqual({});
55
- });
56
- });
57
- s("updateNodeWithNesting deletion semantics", () => {
58
- n("cleared UI prop is removed from node.props instead of written as undefined", () => {
59
- const e = r({
60
- type: "object",
61
- properties: {
62
- card: {
63
- type: "card",
64
- title: "卡片",
65
- props: { variant: "outlined", hoverable: !0 },
66
- properties: {}
67
- }
68
- }
69
- }, ["card"], {
70
- variant: void 0
71
- }).properties.card;
72
- t(e.props.variant).toBeUndefined(), t("variant" in e.props).toBe(!1), t(e.props.hoverable).toBe(!0);
73
- }), n("cleared schema-level key is removed from the node", () => {
74
- const a = {
75
- type: "object",
76
- properties: {
77
- gender: { ...p, bind: "user.gender" }
78
- }
79
- }, e = r(a, ["gender"], { bind: void 0 }).properties.gender;
80
- t(e.bind).toBeUndefined(), t("bind" in e).toBe(!1), t(e.title).toBe("单选");
81
- }), n("widget display format is written into node.props (antd passthrough)", () => {
82
- const e = r({
83
- type: "object",
84
- properties: {
85
- birthday: { type: "string", widget: "date", title: "出生日期" }
86
- }
87
- }, ["birthday"], {
88
- format: "YYYY/MM/DD"
89
- }).properties.birthday;
90
- t(e.format).toBeUndefined(), t("format" in e).toBe(!1), t(e.props.format).toBe("YYYY/MM/DD");
91
- });
92
- });
93
- s("designer full property-panel patch", () => {
94
- n("empty defaults are not written, radio key preserved in formData", () => {
95
- let a = { type: "object", properties: {} };
96
- a = m(a, [], "gender", p);
97
- const i = y(
98
- a.properties.gender
99
- ), o = l(i, {
100
- title: "单选",
101
- description: "",
102
- placeholder: "",
103
- default: "",
104
- extra: "",
105
- disabled: "",
106
- readOnly: "",
107
- readOnlyWidget: "",
108
- hidden: "",
109
- width: "",
110
- options: [
111
- { value: "a", label: "选项A" },
112
- { value: "b", label: "选项B" }
113
- ],
114
- optionType: "",
115
- buttonStyle: "",
116
- required: "",
117
- pattern: "",
118
- validate: "",
119
- bind: "",
120
- dependencies: ""
121
- });
122
- t(o.bind).toBeUndefined(), a = r(a, ["gender"], o);
123
- const d = new h();
124
- d.init(a), d.setFieldValue("gender", "a"), t(d.getFormData()).toEqual({ gender: "a" });
125
- });
126
- });
127
- s("extractFormLevelConfig", () => {
128
- n("only extracts top-level form config keys, not the whole schema", () => {
129
- const e = c(
130
- {
131
- type: "object",
132
- displayType: "row",
133
- colon: !0,
134
- properties: { gender: p }
135
- },
136
- [
137
- "displayType",
138
- "labelWidth",
139
- "colon",
140
- "label",
141
- "readOnly",
142
- "column"
143
- ]
144
- );
145
- t(e).toEqual({ displayType: "row", colon: !0 }), t("properties" in e).toBe(!1), t("type" in e).toBe(!1);
146
- }), n("omits form-level keys that are not set on the schema", () => {
147
- const i = c(
148
- { type: "object", properties: {} },
149
- ["labelWidth", "column"]
150
- );
151
- t(i).toEqual({});
152
- });
153
- });
154
- s("collectDataFieldOptions", () => {
155
- n("labels options with field title, values with path key", () => {
156
- const i = u({
157
- properties: {
158
- user: {
159
- type: "object",
160
- properties: {
161
- name: { type: "string", title: "姓名" },
162
- gender: { type: "string", widget: "radio", title: "性别" }
163
- }
164
- },
165
- tags: {
166
- type: "array",
167
- widget: "list",
168
- items: { type: "string", widget: "input", title: "标签项" }
169
- }
170
- }
171
- });
172
- t(i).toEqual([
173
- { value: "user.name", label: "姓名" },
174
- { value: "user.gender", label: "性别" },
175
- { value: "tags", label: "tags" },
176
- { value: "tags[0]", label: "标签项" }
177
- ]);
178
- }), n("falls back to key when title is missing", () => {
179
- t(u({
180
- properties: {
181
- birthday: { type: "string", widget: "date" }
182
- }
183
- })).toEqual([
184
- { value: "birthday", label: "birthday" }
185
- ]);
186
- });
187
- });
188
- //# sourceMappingURL=schemaUtils.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemaUtils.test.js","sources":["../../src/schemaUtils.test.ts"],"sourcesContent":["import type { NexusSchema, SchemaNode } from '@xbeeant/form-engine';\nimport { NexusEngine } from '@xbeeant/form-engine';\nimport { describe, expect, it } from 'vitest';\nimport {\n addChildToSchema,\n collectDataFieldOptions,\n diffPropertyPatch,\n extractFormLevelConfig,\n flattenNodeForPropertyEditor,\n updateNodeWithNesting,\n} from './schemaUtils';\n\nconst radioNode: SchemaNode = {\n type: 'string',\n widget: 'radio',\n title: '单选',\n enum: ['a', 'b'],\n enumNames: ['选项A', '选项B'],\n};\n\ndescribe('diffPropertyPatch', () => {\n it('filters out empty-string defaults for untouched fields', () => {\n const initial = {\n title: '单选',\n options: [\n { value: 'a', label: '选项A' },\n { value: 'b', label: '选项B' },\n ],\n };\n const allValues = {\n title: '单选',\n description: '',\n placeholder: '',\n default: '',\n disabled: '',\n readOnly: '',\n hidden: '',\n required: '',\n pattern: '',\n bind: '',\n dependencies: '',\n options: [\n { value: 'a', label: '选项A' },\n { value: 'b', label: '选项B' },\n ],\n };\n const patch = diffPropertyPatch(initial, allValues);\n expect(patch).toEqual({});\n });\n\n it('keeps genuinely changed values', () => {\n const initial = { title: '单选', options: [{ value: 'a', label: 'A' }] };\n const allValues = {\n title: '新标题',\n options: [\n { value: 'a', label: 'A' },\n { value: 'b', label: 'B' },\n ],\n };\n const patch = diffPropertyPatch(initial, allValues);\n expect(patch).toEqual(allValues);\n });\n\n it('empty string is treated as unassigned and never written to schema', () => {\n const initial = { title: '单选', description: '说明', bind: 'user.name' };\n const allValues = { title: '单选', description: '', bind: '' };\n const patch = diffPropertyPatch(initial, allValues);\n expect(patch).toEqual({});\n });\n\n it('user-cleared field is written back as undefined for deletion', () => {\n const initial = { title: '单选', variant: 'outlined', description: '说明' };\n const allValues = { title: '单选', variant: '', description: '' };\n const changed = new Set(['variant']);\n const patch = diffPropertyPatch(initial, allValues, changed);\n expect(patch).toEqual({ variant: undefined });\n });\n\n it('untouched empty fields stay skipped even with changedFields set', () => {\n const initial = { title: '单选' };\n const allValues = { title: '单选', description: '', placeholder: '' };\n const changed = new Set(['title']);\n const patch = diffPropertyPatch(initial, allValues, changed);\n expect(patch).toEqual({});\n });\n});\n\ndescribe('updateNodeWithNesting deletion semantics', () => {\n it('cleared UI prop is removed from node.props instead of written as undefined', () => {\n const schema: NexusSchema = {\n type: 'object',\n properties: {\n card: {\n type: 'card',\n title: '卡片',\n props: { variant: 'outlined', hoverable: true },\n properties: {},\n },\n },\n };\n const next = updateNodeWithNesting(schema, ['card'], {\n variant: undefined,\n });\n const node = next.properties.card as Record<string, unknown>;\n expect((node.props as Record<string, unknown>).variant).toBeUndefined();\n expect('variant' in (node.props as Record<string, unknown>)).toBe(false);\n expect((node.props as Record<string, unknown>).hoverable).toBe(true);\n });\n\n it('cleared schema-level key is removed from the node', () => {\n const schema: NexusSchema = {\n type: 'object',\n properties: {\n gender: { ...radioNode, bind: 'user.gender' },\n },\n };\n const next = updateNodeWithNesting(schema, ['gender'], { bind: undefined });\n const node = next.properties.gender as Record<string, unknown>;\n expect(node.bind).toBeUndefined();\n expect('bind' in node).toBe(false);\n expect(node.title).toBe('单选');\n });\n\n it('widget display format is written into node.props (antd passthrough)', () => {\n // date 等控件的 format 是显示格式,必须走 props 通道才能被 widget 消费;\n // 顶层 node.format 保留给 JSON Schema 校验语义(email/url)\n const schema: NexusSchema = {\n type: 'object',\n properties: {\n birthday: { type: 'string', widget: 'date', title: '出生日期' },\n },\n };\n const next = updateNodeWithNesting(schema, ['birthday'], {\n format: 'YYYY/MM/DD',\n });\n const node = next.properties.birthday as Record<string, unknown>;\n expect(node.format).toBeUndefined();\n expect('format' in node).toBe(false);\n expect((node.props as Record<string, unknown>).format).toBe('YYYY/MM/DD');\n });\n});\n\ndescribe('designer full property-panel patch', () => {\n it('empty defaults are not written, radio key preserved in formData', () => {\n let schema: NexusSchema = { type: 'object', properties: {} };\n schema = addChildToSchema(schema, [], 'gender', radioNode);\n\n // simulate property form allValues (includes empty-string defaults) + diff filter\n const initial = flattenNodeForPropertyEditor(\n schema.properties.gender as never,\n );\n const allValues = {\n title: '单选',\n description: '',\n placeholder: '',\n default: '',\n extra: '',\n disabled: '',\n readOnly: '',\n readOnlyWidget: '',\n hidden: '',\n width: '',\n options: [\n { value: 'a', label: '选项A' },\n { value: 'b', label: '选项B' },\n ],\n optionType: '',\n buttonStyle: '',\n required: '',\n pattern: '',\n validate: '',\n bind: '',\n dependencies: '',\n };\n const patch = diffPropertyPatch(initial, allValues);\n expect(patch.bind).toBeUndefined();\n\n schema = updateNodeWithNesting(schema, ['gender'], patch);\n\n const engine = new NexusEngine();\n engine.init(schema);\n engine.setFieldValue('gender', 'a');\n expect(engine.getFormData()).toEqual({ gender: 'a' });\n });\n});\n\ndescribe('extractFormLevelConfig', () => {\n it('only extracts top-level form config keys, not the whole schema', () => {\n const schema: NexusSchema = {\n type: 'object',\n displayType: 'row',\n colon: true,\n properties: { gender: radioNode },\n };\n const keys = [\n 'displayType',\n 'labelWidth',\n 'colon',\n 'label',\n 'readOnly',\n 'column',\n ];\n const config = extractFormLevelConfig(\n schema as unknown as Record<string, unknown>,\n keys,\n );\n expect(config).toEqual({ displayType: 'row', colon: true });\n expect('properties' in config).toBe(false);\n expect('type' in config).toBe(false);\n });\n\n it('omits form-level keys that are not set on the schema', () => {\n const schema: NexusSchema = { type: 'object', properties: {} };\n const config = extractFormLevelConfig(\n schema as unknown as Record<string, unknown>,\n ['labelWidth', 'column'],\n );\n expect(config).toEqual({});\n });\n});\n\ndescribe('collectDataFieldOptions', () => {\n it('labels options with field title, values with path key', () => {\n const schema: NexusSchema = {\n type: 'object',\n properties: {\n user: {\n type: 'object',\n properties: {\n name: { type: 'string', title: '姓名' },\n gender: { type: 'string', widget: 'radio', title: '性别' },\n },\n },\n tags: {\n type: 'array',\n widget: 'list',\n items: { type: 'string', widget: 'input', title: '标签项' },\n },\n },\n };\n const options = collectDataFieldOptions(schema);\n expect(options).toEqual([\n { value: 'user.name', label: '姓名' },\n { value: 'user.gender', label: '性别' },\n { value: 'tags', label: 'tags' },\n { value: 'tags[0]', label: '标签项' },\n ]);\n });\n\n it('falls back to key when title is missing', () => {\n const schema: NexusSchema = {\n type: 'object',\n properties: {\n birthday: { type: 'string', widget: 'date' },\n },\n };\n expect(collectDataFieldOptions(schema)).toEqual([\n { value: 'birthday', label: 'birthday' },\n ]);\n });\n});\n"],"names":["radioNode","describe","it","patch","diffPropertyPatch","expect","initial","allValues","node","updateNodeWithNesting","schema","addChildToSchema","flattenNodeForPropertyEditor","engine","NexusEngine","config","extractFormLevelConfig","options","collectDataFieldOptions"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
-
2
- //# sourceMappingURL=vite-env.d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite-env.d.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}