@xbeeant/form-engine-react 0.0.3 → 0.0.4

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.
Files changed (142) hide show
  1. package/dist/cjs/components/FormController.cjs +1 -1
  2. package/dist/cjs/components/NexusField.cjs +1 -1
  3. package/dist/cjs/components/NexusForm.cjs +1 -1
  4. package/dist/cjs/components/form-controller.cjs +1 -0
  5. package/dist/cjs/components/nexus-field.cjs +1 -0
  6. package/dist/cjs/components/nexus-form-provider.cjs +1 -0
  7. package/dist/cjs/components/nexus-form.cjs +1 -0
  8. package/dist/cjs/components/nexus-layout.cjs +1 -0
  9. package/dist/cjs/components/nexus-object.cjs +1 -0
  10. package/dist/cjs/contexts/field-inherit-context.cjs +1 -0
  11. package/dist/cjs/contexts/grid-context.cjs +1 -0
  12. package/dist/cjs/contexts/layout-config-context.cjs +1 -0
  13. package/dist/cjs/contexts/nexus-context.cjs +1 -0
  14. package/dist/cjs/hooks/index.cjs +1 -1
  15. package/dist/cjs/hooks/use-engine.cjs +1 -0
  16. package/dist/cjs/hooks/use-field-state.cjs +1 -0
  17. package/dist/cjs/hooks/use-field-validator.cjs +1 -0
  18. package/dist/cjs/hooks/use-field-value.cjs +1 -0
  19. package/dist/cjs/hooks/use-form-config.cjs +1 -0
  20. package/dist/cjs/hooks/use-form-data.cjs +1 -0
  21. package/dist/cjs/hooks/use-form-submitting.cjs +1 -0
  22. package/dist/cjs/hooks/use-form.cjs +1 -0
  23. package/dist/cjs/hooks/use-nexus-context.cjs +1 -0
  24. package/dist/cjs/hooks/use-watch-all.cjs +1 -0
  25. package/dist/cjs/hooks/use-watch-multiple.cjs +1 -0
  26. package/dist/cjs/hooks/use-watch-state.cjs +1 -0
  27. package/dist/cjs/hooks/use-watch.cjs +1 -0
  28. package/dist/cjs/hooks/useFormData.cjs +1 -1
  29. package/dist/cjs/hooks/useFormSubmitting.cjs +1 -0
  30. package/dist/cjs/index.cjs +1 -1
  31. package/dist/cjs/styles.css +1 -1
  32. package/dist/cjs/utils/omit-nil.cjs +1 -0
  33. package/dist/cjs/utils/omitNil.cjs +1 -0
  34. package/dist/cjs/utils/persist.cjs +1 -0
  35. package/dist/cjs/utils/render-tree-node.cjs +1 -0
  36. package/dist/cjs/utils/resolve-col-span.cjs +1 -0
  37. package/dist/es/components/FormController.d.ts +73 -19
  38. package/dist/es/components/FormController.js +222 -71
  39. package/dist/es/components/NexusField.js +25 -21
  40. package/dist/es/components/NexusForm.d.ts +33 -3
  41. package/dist/es/components/NexusForm.js +143 -96
  42. package/dist/es/components/form-controller.d.ts +129 -0
  43. package/dist/es/components/form-controller.js +310 -0
  44. package/dist/es/components/nexus-field.d.ts +9 -0
  45. package/dist/es/components/nexus-field.js +131 -0
  46. package/dist/es/components/nexus-form-provider.d.ts +12 -0
  47. package/dist/es/components/nexus-form-provider.js +18 -0
  48. package/dist/es/components/nexus-form.d.ts +114 -0
  49. package/dist/es/components/nexus-form.js +174 -0
  50. package/dist/es/components/nexus-layout.d.ts +9 -0
  51. package/dist/es/components/nexus-layout.js +48 -0
  52. package/dist/es/components/nexus-object.d.ts +16 -0
  53. package/dist/es/components/nexus-object.js +64 -0
  54. package/dist/es/contexts/NexusContext.d.ts +2 -0
  55. package/dist/es/contexts/field-inherit-context.d.ts +18 -0
  56. package/dist/es/contexts/field-inherit-context.js +5 -0
  57. package/dist/es/contexts/grid-context.d.ts +5 -0
  58. package/dist/es/contexts/grid-context.js +5 -0
  59. package/dist/es/contexts/layout-config-context.d.ts +4 -0
  60. package/dist/es/contexts/layout-config-context.js +5 -0
  61. package/dist/es/contexts/nexus-context.d.ts +29 -0
  62. package/dist/es/contexts/nexus-context.js +12 -0
  63. package/dist/es/hooks/index.d.ts +12 -11
  64. package/dist/es/hooks/index.js +20 -18
  65. package/dist/es/hooks/use-engine.d.ts +2 -0
  66. package/dist/es/hooks/use-engine.js +8 -0
  67. package/dist/es/hooks/use-field-state.d.ts +7 -0
  68. package/dist/es/hooks/use-field-state.js +13 -0
  69. package/dist/es/hooks/use-field-validator.d.ts +40 -0
  70. package/dist/es/hooks/use-field-validator.js +35 -0
  71. package/dist/es/hooks/use-field-value.d.ts +6 -0
  72. package/dist/es/hooks/use-field-value.js +13 -0
  73. package/dist/es/hooks/use-form-config.d.ts +5 -0
  74. package/dist/es/hooks/use-form-config.js +8 -0
  75. package/dist/es/hooks/use-form-data.d.ts +6 -0
  76. package/dist/es/hooks/use-form-data.js +13 -0
  77. package/dist/es/hooks/use-form-submitting.d.ts +7 -0
  78. package/dist/es/hooks/use-form-submitting.js +11 -0
  79. package/dist/es/hooks/use-form.d.ts +22 -0
  80. package/dist/es/hooks/use-form.js +12 -0
  81. package/dist/es/hooks/use-nexus-context.d.ts +11 -0
  82. package/dist/es/hooks/use-nexus-context.js +12 -0
  83. package/dist/es/hooks/use-watch-all.d.ts +19 -0
  84. package/dist/es/hooks/use-watch-all.js +29 -0
  85. package/dist/es/hooks/use-watch-multiple.d.ts +20 -0
  86. package/dist/es/hooks/use-watch-multiple.js +29 -0
  87. package/dist/es/hooks/use-watch-state.d.ts +18 -0
  88. package/dist/es/hooks/use-watch-state.js +19 -0
  89. package/dist/es/hooks/use-watch.d.ts +25 -0
  90. package/dist/es/hooks/use-watch.js +20 -0
  91. package/dist/es/hooks/useForm.d.ts +11 -4
  92. package/dist/es/hooks/useFormData.js +9 -9
  93. package/dist/es/hooks/useFormSubmitting.d.ts +7 -0
  94. package/dist/es/hooks/useFormSubmitting.js +11 -0
  95. package/dist/es/index.d.ts +26 -24
  96. package/dist/es/index.js +36 -32
  97. package/dist/es/styles.css +1 -1
  98. package/dist/es/utils/omit-nil.d.ts +9 -0
  99. package/dist/es/utils/omit-nil.js +14 -0
  100. package/dist/es/utils/omitNil.d.ts +9 -0
  101. package/dist/es/utils/omitNil.js +14 -0
  102. package/dist/es/utils/persist.d.ts +24 -0
  103. package/dist/es/utils/persist.js +43 -0
  104. package/dist/es/utils/render-tree-node.d.ts +6 -0
  105. package/dist/es/utils/render-tree-node.js +17 -0
  106. package/dist/es/utils/resolve-col-span.d.ts +5 -0
  107. package/dist/es/utils/resolve-col-span.js +9 -0
  108. package/dist/umd/index.css +1 -1
  109. package/dist/umd/index.umd.cjs +1 -1
  110. package/package.json +5 -4
  111. package/src/components/form-controller.ts +584 -0
  112. package/src/components/{NexusField.tsx → nexus-field.tsx} +57 -6
  113. package/src/components/{NexusFormProvider.tsx → nexus-form-provider.tsx} +3 -3
  114. package/src/components/{NexusForm.tsx → nexus-form.tsx} +135 -18
  115. package/src/components/{NexusLayout.tsx → nexus-layout.tsx} +5 -5
  116. package/src/components/{NexusObject.tsx → nexus-object.tsx} +3 -3
  117. package/src/contexts/{NexusContext.ts → nexus-context.ts} +3 -1
  118. package/src/hooks/index.ts +12 -11
  119. package/src/hooks/{useEngine.ts → use-engine.ts} +1 -1
  120. package/src/hooks/{useFieldState.ts → use-field-state.ts} +1 -1
  121. package/src/hooks/{useFieldValidator.ts → use-field-validator.ts} +1 -1
  122. package/src/hooks/{useFieldValue.ts → use-field-value.ts} +1 -1
  123. package/src/hooks/{useFormConfig.ts → use-form-config.ts} +2 -2
  124. package/src/hooks/{useFormData.ts → use-form-data.ts} +4 -4
  125. package/src/hooks/use-form-submitting.ts +16 -0
  126. package/src/hooks/{useForm.ts → use-form.ts} +12 -5
  127. package/src/hooks/{useNexusContext.ts → use-nexus-context.ts} +2 -2
  128. package/src/index.ts +26 -24
  129. package/src/utils/omit-nil.ts +24 -0
  130. package/src/utils/persist.ts +88 -0
  131. package/src/utils/{renderTreeNode.tsx → render-tree-node.tsx} +3 -3
  132. package/src/utils/{resolveColSpan.ts → resolve-col-span.ts} +1 -1
  133. package/dist/cjs/tailwind.css +0 -1
  134. package/dist/es/tailwind.css +0 -1
  135. package/src/components/FormController.ts +0 -278
  136. /package/src/contexts/{FieldInheritContext.ts → field-inherit-context.ts} +0 -0
  137. /package/src/contexts/{GridContext.ts → grid-context.ts} +0 -0
  138. /package/src/contexts/{LayoutConfigContext.ts → layout-config-context.ts} +0 -0
  139. /package/src/hooks/{useWatchAll.ts → use-watch-all.ts} +0 -0
  140. /package/src/hooks/{useWatchMultiple.ts → use-watch-multiple.ts} +0 -0
  141. /package/src/hooks/{useWatchState.ts → use-watch-state.ts} +0 -0
  142. /package/src/hooks/{useWatch.ts → use-watch.ts} +0 -0
@@ -0,0 +1,7 @@
1
+ import { FormController } from '../components/form-controller';
2
+ /**
3
+ * useFormSubmitting — 订阅表单提交中状态(formily submitting 对齐)
4
+ *
5
+ * submit() 全流程(校验 + onFinish)期间返回 true,供提交按钮展示 loading。
6
+ */
7
+ export declare function useFormSubmitting(form: FormController): boolean;
@@ -0,0 +1,11 @@
1
+ import { useSyncExternalStore as i } from "react";
2
+ function u(t) {
3
+ return i(
4
+ (n) => t.onSubmittingChange(n),
5
+ () => t.getSubmitting(),
6
+ () => t.getSubmitting()
7
+ );
8
+ }
9
+ export {
10
+ u as useFormSubmitting
11
+ };
@@ -0,0 +1,22 @@
1
+ import { NexusEngine } from '@xbeeant/form-engine';
2
+ import { FormController } from '../components/form-controller';
3
+ /**
4
+ * useForm — 创建 Form 实例
5
+ *
6
+ * 一个 Form 绑定一个引擎宿主(引擎为独立实体):
7
+ * - 同一 form 引用传给多个 NexusForm → 共享引擎宿主(组件/插件注册共享),
8
+ * 每个 NexusForm 挂载自动获得独立实例(schema/值/订阅互不影响),
9
+ * form 的 API 聚合作用于全部实例
10
+ * - 需要完全独立的表单:各自 useForm()(独立引擎宿主)
11
+ *
12
+ * 支持:
13
+ * - `useForm()`:创建独立实例(引擎宿主内部创建,未注册,不参与跨表单联动)
14
+ * - `useForm(formId)`:创建带 formId 的实例,自动注册到默认表单注册表,
15
+ * 可通过 schema `crossForm` reaction / `engine.linkForm` 与其他表单联动
16
+ * - `useForm(formId, engine)`:复用外部创建的引擎(如 `new NexusEngine({ formId })`),
17
+ * 实现多个 form 共享同一引擎宿主
18
+ *
19
+ * @param formId - 可选,表单实例唯一标识(跨表单联动寻址)
20
+ * @param engine - 可选,外部引擎宿主(缺省内部创建)
21
+ */
22
+ export declare function useForm(formId?: string, engine?: NexusEngine): [FormController];
@@ -0,0 +1,12 @@
1
+ import { NexusEngine as n } from "@xbeeant/form-engine";
2
+ import { useRef as t } from "react";
3
+ import { FormController as u } from "../components/form-controller.js";
4
+ function c(e, o) {
5
+ const r = t(null);
6
+ return r.current || (r.current = new u(
7
+ o ?? (e ? new n({ formId: e }) : void 0)
8
+ )), [r.current];
9
+ }
10
+ export {
11
+ c as useForm
12
+ };
@@ -0,0 +1,11 @@
1
+ import { NexusEngine } from '@xbeeant/form-engine';
2
+ import { FormController } from '../components/form-controller';
3
+ import { NexusFormConfig } from '../components/nexus-form';
4
+ interface NexusContextValue {
5
+ engine: NexusEngine;
6
+ config: NexusFormConfig;
7
+ form: FormController;
8
+ }
9
+ export declare const NexusContext: import('react').Context<NexusContextValue | null>;
10
+ export declare function useNexusContext(): NexusContextValue;
11
+ export {};
@@ -0,0 +1,12 @@
1
+ import { createContext as t, useContext as o } from "react";
2
+ const r = t(null);
3
+ function u() {
4
+ const e = o(r);
5
+ if (!e)
6
+ throw new Error("[NexusField] Must be used within <NexusFormProvider>");
7
+ return e;
8
+ }
9
+ export {
10
+ r as NexusContext,
11
+ u as useNexusContext
12
+ };
@@ -0,0 +1,19 @@
1
+ import { NexusEngine } from '@xbeeant/form-engine';
2
+ /**
3
+ * useWatchAll Hook - 监听整个表单数据变化
4
+ *
5
+ * @param engine - NexusEngine实例
6
+ * @param callback - 变化回调函数
7
+ * @param deep - 是否深度比较值(默认false,仅浅比较)
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // 监听整个表单
12
+ * useWatchAll(engine, (formData) => {
13
+ * console.log('Form data changed:', formData);
14
+ * }, { deep: true });
15
+ * ```
16
+ */
17
+ export declare function useWatchAll(engine: NexusEngine | null, callback: (formData: Record<string, unknown>) => void, options?: {
18
+ deep?: boolean;
19
+ }): Record<string, unknown>;
@@ -0,0 +1,29 @@
1
+ import { useRef as n, useEffect as h } from "react";
2
+ function g(c, i, b) {
3
+ const { deep: l = !1 } = b || {}, t = n({}), e = n({}), u = n(i);
4
+ return u.current = i, h(() => {
5
+ if (!c)
6
+ return;
7
+ const s = c.getFormData();
8
+ t.current = s, e.current = s, u.current(s);
9
+ const d = c.subscribeAll((r) => {
10
+ if (l)
11
+ JSON.stringify(r) !== JSON.stringify(t.current) && (t.current = r, e.current = r, u.current(r));
12
+ else {
13
+ let f = !1;
14
+ for (const o in r)
15
+ if (r[o] !== t.current[o]) {
16
+ f = !0;
17
+ break;
18
+ }
19
+ f && (t.current = r, e.current = r, u.current(r));
20
+ }
21
+ });
22
+ return () => {
23
+ d();
24
+ };
25
+ }, [c, l]), e.current;
26
+ }
27
+ export {
28
+ g as useWatchAll
29
+ };
@@ -0,0 +1,20 @@
1
+ import { NexusEngine } from '@xbeeant/form-engine';
2
+ /**
3
+ * useWatchMultiple Hook - 监听多个字段值变化
4
+ *
5
+ * @param engine - NexusEngine实例
6
+ * @param paths - 字段路径数组
7
+ * @param callback - 变化回调函数
8
+ * @param deep - 是否深度比较值(默认false,仅浅比较)
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * // 监听多个字段
13
+ * const values = useWatchMultiple(engine, ['name', 'email', 'age'], (values) => {
14
+ * console.log('Values changed:', values);
15
+ * }, { deep: true });
16
+ * ```
17
+ */
18
+ export declare function useWatchMultiple(engine: NexusEngine | null, paths: string[], callback: (values: Record<string, unknown>) => void, options?: {
19
+ deep?: boolean;
20
+ }): Record<string, unknown>;
@@ -0,0 +1,29 @@
1
+ import { useRef as s, useEffect as p } from "react";
2
+ function v(r, u, a, R) {
3
+ const { deep: l = !1 } = R || {}, o = s({}), e = s({}), f = s(a);
4
+ f.current = a;
5
+ const i = s(u);
6
+ i.current = u;
7
+ const V = [...u].sort().join(",");
8
+ return p(() => {
9
+ if (!r)
10
+ return;
11
+ const b = i.current, c = {};
12
+ for (const t of b)
13
+ c[t] = r.getFieldValue(t);
14
+ o.current = c, e.current = c, f.current(c);
15
+ const h = b.map(
16
+ (t) => r.subscribe(t, (m) => {
17
+ const n = m.value, d = o.current[t];
18
+ (l ? JSON.stringify(n) !== JSON.stringify(d) : n !== d) && (o.current[t] = n, e.current = { [t]: n }, f.current(e.current));
19
+ })
20
+ );
21
+ return () => {
22
+ for (const t of h)
23
+ t();
24
+ };
25
+ }, [r, l, V]), e.current;
26
+ }
27
+ export {
28
+ v as useWatchMultiple
29
+ };
@@ -0,0 +1,18 @@
1
+ import { FieldState, NexusEngine } from '@xbeeant/form-engine';
2
+ /**
3
+ * useWatchState Hook - 监听单个字段状态变化
4
+ *
5
+ * @param engine - NexusEngine实例
6
+ * @param path - 字段路径
7
+ * @param callback - 状态变化回调函数
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // 监听字段状态(visible/disabled/loading等)
12
+ * const isDisabled = useWatchState(engine, 'email', (state) => {
13
+ * console.log('Disabled:', state.disabled);
14
+ * console.log('Loading:', state.loading);
15
+ * });
16
+ * ```
17
+ */
18
+ export declare function useWatchState(engine: NexusEngine | null, path: string, callback: (state: FieldState) => void): FieldState;
@@ -0,0 +1,19 @@
1
+ import { useRef as n, useEffect as i } from "react";
2
+ function R(r, t, s) {
3
+ const e = n(void 0), u = n(s);
4
+ return u.current = s, i(() => {
5
+ if (!r)
6
+ return;
7
+ const c = r.getFieldState(t);
8
+ e.current = c, c && u.current(c);
9
+ const o = r.subscribe(t, (f) => {
10
+ e.current = f, u.current(f);
11
+ });
12
+ return () => {
13
+ o();
14
+ };
15
+ }, [r, t]), e.current || {};
16
+ }
17
+ export {
18
+ R as useWatchState
19
+ };
@@ -0,0 +1,25 @@
1
+ import { NexusEngine } from '@xbeeant/form-engine';
2
+ /**
3
+ * useWatch Hook - 监听单个字段值变化
4
+ *
5
+ * @param engine - NexusEngine实例
6
+ * @param path - 字段路径
7
+ * @param callback - 变化回调函数
8
+ * @param deep - 是否深度比较值(默认false,仅浅比较)
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * // 监听单个字段
13
+ * const name = useWatch(engine, 'profile.name', (value) => {
14
+ * console.log('Name changed:', value);
15
+ * });
16
+ *
17
+ * // 深度比较对象
18
+ * const profile = useWatch(engine, 'profile', (value) => {
19
+ * console.log('Profile changed:', value);
20
+ * }, { deep: true });
21
+ * ```
22
+ */
23
+ export declare function useWatch(engine: NexusEngine | null, path: string, callback: (value: unknown) => void, options?: {
24
+ deep?: boolean;
25
+ }): unknown;
@@ -0,0 +1,20 @@
1
+ import { useRef as f, useEffect as d } from "react";
2
+ function J(e, c, o, i) {
3
+ const { deep: n = !1 } = i || {}, r = f(void 0), s = f(o);
4
+ return s.current = o, d(() => {
5
+ if (!e)
6
+ return;
7
+ const t = e.getFieldValue(c);
8
+ r.current === void 0 && (r.current = t), (n ? JSON.stringify(t) !== JSON.stringify(r.current) : t !== r.current) && (r.current = t, s.current(t));
9
+ const l = e.subscribe(c, (a) => {
10
+ const u = a.value;
11
+ (n ? JSON.stringify(u) !== JSON.stringify(r.current) : u !== r.current) && (r.current = u, s.current(u));
12
+ });
13
+ return () => {
14
+ l();
15
+ };
16
+ }, [e, c, n]), r.current;
17
+ }
18
+ export {
19
+ J as useWatch
20
+ };
@@ -3,13 +3,20 @@ import { FormController } from '../components/FormController';
3
3
  /**
4
4
  * useForm — 创建 Form 实例
5
5
  *
6
- * 支持一个页面挂载多个表单实例:
7
- * - `useForm()`:独立实例(未注册,不参与跨表单联动)
6
+ * 一个 Form 绑定一个引擎宿主(引擎为独立实体):
7
+ * - 同一 form 引用传给多个 NexusForm → 共享引擎宿主(组件/插件注册共享),
8
+ * 每个 NexusForm 挂载自动获得独立实例(schema/值/订阅互不影响),
9
+ * form 的 API 聚合作用于全部实例
10
+ * - 需要完全独立的表单:各自 useForm()(独立引擎宿主)
11
+ *
12
+ * 支持:
13
+ * - `useForm()`:创建独立实例(引擎宿主内部创建,未注册,不参与跨表单联动)
8
14
  * - `useForm(formId)`:创建带 formId 的实例,自动注册到默认表单注册表,
9
15
  * 可通过 schema `crossForm` reaction / `engine.linkForm` 与其他表单联动
10
- * - `useForm(formId, engine)`:复用外部创建的引擎(如 `new NexusEngine({ formId })`)
16
+ * - `useForm(formId, engine)`:复用外部创建的引擎(如 `new NexusEngine({ formId })`),
17
+ * 实现多个 form 共享同一引擎宿主
11
18
  *
12
19
  * @param formId - 可选,表单实例唯一标识(跨表单联动寻址)
13
- * @param engine - 可选,外部引擎实例(缺省内部创建)
20
+ * @param engine - 可选,外部引擎宿主(缺省内部创建)
14
21
  */
15
22
  export declare function useForm(formId?: string, engine?: NexusEngine): [FormController];
@@ -1,13 +1,13 @@
1
- import { useSyncExternalStore as o, useMemo as n } from "react";
2
- import { useEngine as r } from "./useEngine.js";
3
- function i() {
4
- const e = r(), t = o(
5
- e.subscribeStore,
6
- e.getSnapshot,
7
- e.getSnapshot
1
+ import { useSyncExternalStore as n, useMemo as r } from "react";
2
+ import { useEngine as s } from "./useEngine.js";
3
+ function m() {
4
+ const e = s(), t = n(
5
+ (o) => e.subscribeStore(o),
6
+ () => e.getSnapshot(),
7
+ () => e.getSnapshot()
8
8
  );
9
- return n(() => e.getFormData(), [e, t]);
9
+ return r(() => e.getFormData(), [e, t]);
10
10
  }
11
11
  export {
12
- i as useFormData
12
+ m as useFormData
13
13
  };
@@ -0,0 +1,7 @@
1
+ import { FormController } from '../components/FormController';
2
+ /**
3
+ * useFormSubmitting — 订阅表单提交中状态(formily submitting 对齐)
4
+ *
5
+ * submit() 全流程(校验 + onFinish)期间返回 true,供提交按钮展示 loading。
6
+ */
7
+ export declare function useFormSubmitting(form: FormController): boolean;
@@ -0,0 +1,11 @@
1
+ import { useSyncExternalStore as i } from "react";
2
+ function u(t) {
3
+ return i(
4
+ (n) => t.onSubmittingChange(n),
5
+ () => t.getSubmitting(),
6
+ () => t.getSubmitting()
7
+ );
8
+ }
9
+ export {
10
+ u as useFormSubmitting
11
+ };
@@ -1,24 +1,26 @@
1
- export { FormController } from './components/FormController';
2
- export { NexusField } from './components/NexusField';
3
- export type { NexusFormConfig } from './components/NexusForm';
4
- export { NexusForm } from './components/NexusForm';
5
- export { NexusFormProvider } from './components/NexusFormProvider';
6
- export { NexusLayout } from './components/NexusLayout';
7
- export { NexusObject } from './components/NexusObject';
8
- export type { FieldInheritValue } from './contexts/FieldInheritContext';
9
- export { FieldInheritContext } from './contexts/FieldInheritContext';
10
- export type { GridContextValue } from './contexts/GridContext';
11
- export { GridContext } from './contexts/GridContext';
12
- export type { LayoutConfigContextValue } from './contexts/LayoutConfigContext';
13
- export { LayoutConfigContext } from './contexts/LayoutConfigContext';
14
- export { useEngine } from './hooks/useEngine';
15
- export { useFieldState } from './hooks/useFieldState';
16
- export { useFieldValidator } from './hooks/useFieldValidator';
17
- export { useFieldValue } from './hooks/useFieldValue';
18
- export { useForm } from './hooks/useForm';
19
- export { useFormConfig } from './hooks/useFormConfig';
20
- export { useFormData } from './hooks/useFormData';
21
- export { useWatch } from './hooks/useWatch';
22
- export { useWatchAll } from './hooks/useWatchAll';
23
- export { useWatchMultiple } from './hooks/useWatchMultiple';
24
- export { useWatchState } from './hooks/useWatchState';
1
+ export { FormController } from './components/form-controller';
2
+ export { NexusField } from './components/nexus-field';
3
+ export type { NexusFormConfig, NexusFormProps } from './components/nexus-form';
4
+ export { NexusForm } from './components/nexus-form';
5
+ export { NexusFormProvider } from './components/nexus-form-provider';
6
+ export { NexusLayout } from './components/nexus-layout';
7
+ export { NexusObject } from './components/nexus-object';
8
+ export type { FieldInheritValue } from './contexts/field-inherit-context';
9
+ export { FieldInheritContext } from './contexts/field-inherit-context';
10
+ export type { GridContextValue } from './contexts/grid-context';
11
+ export { GridContext } from './contexts/grid-context';
12
+ export type { LayoutConfigContextValue } from './contexts/layout-config-context';
13
+ export { LayoutConfigContext } from './contexts/layout-config-context';
14
+ export { NexusContext } from './contexts/nexus-context';
15
+ export { useEngine } from './hooks/use-engine';
16
+ export { useFieldState } from './hooks/use-field-state';
17
+ export { useFieldValidator } from './hooks/use-field-validator';
18
+ export { useFieldValue } from './hooks/use-field-value';
19
+ export { useForm } from './hooks/use-form';
20
+ export { useFormConfig } from './hooks/use-form-config';
21
+ export { useFormData } from './hooks/use-form-data';
22
+ export { useFormSubmitting } from './hooks/use-form-submitting';
23
+ export { useWatch } from './hooks/use-watch';
24
+ export { useWatchAll } from './hooks/use-watch-all';
25
+ export { useWatchMultiple } from './hooks/use-watch-multiple';
26
+ export { useWatchState } from './hooks/use-watch-state';
package/dist/es/index.js CHANGED
@@ -1,43 +1,47 @@
1
1
  import './styles.css';/* empty css */
2
- import { FormController as t } from "./components/FormController.js";
3
- import { NexusField as m } from "./components/NexusField.js";
4
- import { NexusForm as p } from "./components/NexusForm.js";
5
- import { NexusFormProvider as s } from "./components/NexusFormProvider.js";
6
- import { NexusLayout as a } from "./components/NexusLayout.js";
7
- import { NexusObject as F } from "./components/NexusObject.js";
8
- import { FieldInheritContext as d } from "./contexts/FieldInheritContext.js";
9
- import { GridContext as c } from "./contexts/GridContext.js";
10
- import { LayoutConfigContext as N } from "./contexts/LayoutConfigContext.js";
11
- import { useEngine as g } from "./hooks/useEngine.js";
12
- import { useFieldState as L } from "./hooks/useFieldState.js";
13
- import { useFieldValidator as V } from "./hooks/useFieldValidator.js";
14
- import { useFieldValue as j } from "./hooks/useFieldValue.js";
15
- import { useForm as A } from "./hooks/useForm.js";
16
- import { useFormConfig as E } from "./hooks/useFormConfig.js";
17
- import { useFormData as I } from "./hooks/useFormData.js";
18
- import { useWatch as O } from "./hooks/useWatch.js";
19
- import { useWatchAll as k } from "./hooks/useWatchAll.js";
20
- import { useWatchMultiple as w } from "./hooks/useWatchMultiple.js";
21
- import { useWatchState as B } from "./hooks/useWatchState.js";
2
+ import { FormController as t } from "./components/form-controller.js";
3
+ import { NexusField as m } from "./components/nexus-field.js";
4
+ import { NexusForm as p } from "./components/nexus-form.js";
5
+ import { NexusFormProvider as s } from "./components/nexus-form-provider.js";
6
+ import { NexusLayout as a } from "./components/nexus-layout.js";
7
+ import { NexusObject as F } from "./components/nexus-object.js";
8
+ import { FieldInheritContext as d } from "./contexts/field-inherit-context.js";
9
+ import { GridContext as N } from "./contexts/grid-context.js";
10
+ import { LayoutConfigContext as h } from "./contexts/layout-config-context.js";
11
+ import { NexusContext as W } from "./contexts/nexus-context.js";
12
+ import { useEngine as b } from "./hooks/use-engine.js";
13
+ import { useFieldState as L } from "./hooks/use-field-state.js";
14
+ import { useFieldValidator as j } from "./hooks/use-field-validator.js";
15
+ import { useFieldValue as A } from "./hooks/use-field-value.js";
16
+ import { useForm as E } from "./hooks/use-form.js";
17
+ import { useFormConfig as I } from "./hooks/use-form-config.js";
18
+ import { useFormData as O } from "./hooks/use-form-data.js";
19
+ import { useFormSubmitting as k } from "./hooks/use-form-submitting.js";
20
+ import { useWatch as w } from "./hooks/use-watch.js";
21
+ import { useWatchAll as B } from "./hooks/use-watch-all.js";
22
+ import { useWatchMultiple as J } from "./hooks/use-watch-multiple.js";
23
+ import { useWatchState as Q } from "./hooks/use-watch-state.js";
22
24
  export {
23
25
  d as FieldInheritContext,
24
26
  t as FormController,
25
- c as GridContext,
26
- N as LayoutConfigContext,
27
+ N as GridContext,
28
+ h as LayoutConfigContext,
29
+ W as NexusContext,
27
30
  m as NexusField,
28
31
  p as NexusForm,
29
32
  s as NexusFormProvider,
30
33
  a as NexusLayout,
31
34
  F as NexusObject,
32
- g as useEngine,
35
+ b as useEngine,
33
36
  L as useFieldState,
34
- V as useFieldValidator,
35
- j as useFieldValue,
36
- A as useForm,
37
- E as useFormConfig,
38
- I as useFormData,
39
- O as useWatch,
40
- k as useWatchAll,
41
- w as useWatchMultiple,
42
- B as useWatchState
37
+ j as useFieldValidator,
38
+ A as useFieldValue,
39
+ E as useForm,
40
+ I as useFormConfig,
41
+ O as useFormData,
42
+ k as useFormSubmitting,
43
+ w as useWatch,
44
+ B as useWatchAll,
45
+ J as useWatchMultiple,
46
+ Q as useWatchState
43
47
  };
@@ -1 +1 @@
1
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}:root,:host{--color-red-500:oklch(63.7% .237 25.331);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-bold:700;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}.visible{visibility:visible}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.rotate-0{rotate:0deg}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.gap-1{gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-0{padding:0}.align-middle{vertical-align:middle}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-red-500{color:var(--color-red-500)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.select-none{-webkit-user-select:none;user-select:none}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
1
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}:root,:host{--color-red-500:oklch(63.7% .237 25.331);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-bold:700;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}.visible{visibility:visible}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.rotate-0{rotate:0deg}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.gap-1{gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-0{padding:0}.align-middle{vertical-align:middle}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-red-500{color:var(--color-red-500)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.select-none{-webkit-user-select:none;user-select:none}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * omitNilDeep — 递归移除空值(undefined / null / '')
3
+ *
4
+ * ProForm omitNil 对齐:提交/取值时过滤掉未填写的空值字段。
5
+ * - 对象:移除值为空的键(递归处理嵌套对象)
6
+ * - 数组:逐项递归处理(保留数组结构与长度)
7
+ * - 0 / false / NaN 等非空值保留
8
+ */
9
+ export declare function omitNilDeep(value: unknown): unknown;
@@ -0,0 +1,14 @@
1
+ function i(t) {
2
+ if (Array.isArray(t))
3
+ return t.map((r) => i(r));
4
+ if (t !== null && typeof t == "object") {
5
+ const r = {};
6
+ for (const [o, n] of Object.entries(t))
7
+ n == null || n === "" || (r[o] = i(n));
8
+ return r;
9
+ }
10
+ return t;
11
+ }
12
+ export {
13
+ i as omitNilDeep
14
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * omitNilDeep — 递归移除空值(undefined / null / '')
3
+ *
4
+ * ProForm omitNil 对齐:提交/取值时过滤掉未填写的空值字段。
5
+ * - 对象:移除值为空的键(递归处理嵌套对象)
6
+ * - 数组:逐项递归处理(保留数组结构与长度)
7
+ * - 0 / false / NaN 等非空值保留
8
+ */
9
+ export declare function omitNilDeep(value: unknown): unknown;
@@ -0,0 +1,14 @@
1
+ function i(t) {
2
+ if (Array.isArray(t))
3
+ return t.map((r) => i(r));
4
+ if (t !== null && typeof t == "object") {
5
+ const r = {};
6
+ for (const [o, n] of Object.entries(t))
7
+ n == null || n === "" || (r[o] = i(n));
8
+ return r;
9
+ }
10
+ return t;
11
+ }
12
+ export {
13
+ i as omitNilDeep
14
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * 表单草稿持久化(NexusForm persist 选项实现)
3
+ *
4
+ * 将表单数据自动保存到 Web Storage(localStorage / sessionStorage),
5
+ * 下次挂载时自动恢复为初始值(草稿续填)。
6
+ *
7
+ * 约束:
8
+ * - 所有存储访问均 try/catch 包裹(SSR 无 window / Safari 隐私模式抛错)
9
+ * - 存储键为完整路径前缀,避免多表单实例冲突
10
+ * - 提交成功后默认清除草稿(clearOnSubmit: false 可关闭)
11
+ */
12
+ export interface PersistOptions {
13
+ /** 存储键(必填,多表单实例需唯一) */
14
+ key: string;
15
+ /** 存储介质,默认 localStorage */
16
+ storage?: 'localStorage' | 'sessionStorage';
17
+ /** 保存防抖毫秒数,默认 300 */
18
+ debounce?: number;
19
+ /** 提交成功后清除草稿,默认 true */
20
+ clearOnSubmit?: boolean;
21
+ }
22
+ export declare function loadPersisted(options: PersistOptions): Record<string, unknown> | undefined;
23
+ export declare function savePersisted(options: PersistOptions, data: Record<string, unknown>): void;
24
+ export declare function clearPersisted(options: PersistOptions): void;
@@ -0,0 +1,43 @@
1
+ function s(t) {
2
+ if (!(typeof window > "u"))
3
+ try {
4
+ const e = t === "sessionStorage" ? window.sessionStorage : window.localStorage;
5
+ return e.setItem("__nexus_persist_probe__", "1"), e.removeItem("__nexus_persist_probe__"), e;
6
+ } catch {
7
+ return;
8
+ }
9
+ }
10
+ function n(t) {
11
+ const e = s(t.storage);
12
+ if (e)
13
+ try {
14
+ const r = e.getItem(t.key);
15
+ if (!r)
16
+ return;
17
+ const o = JSON.parse(r);
18
+ return typeof o == "object" && o !== null ? o : void 0;
19
+ } catch {
20
+ return;
21
+ }
22
+ }
23
+ function i(t, e) {
24
+ const r = s(t.storage);
25
+ if (r)
26
+ try {
27
+ r.setItem(t.key, JSON.stringify(e));
28
+ } catch {
29
+ }
30
+ }
31
+ function a(t) {
32
+ const e = s(t.storage);
33
+ if (e)
34
+ try {
35
+ e.removeItem(t.key);
36
+ } catch {
37
+ }
38
+ }
39
+ export {
40
+ a as clearPersisted,
41
+ n as loadPersisted,
42
+ i as savePersisted
43
+ };
@@ -0,0 +1,6 @@
1
+ import { RenderTreeNode } from '@xbeeant/form-engine';
2
+ import { ReactElement } from 'react';
3
+ /**
4
+ * renderTreeNode — 递归渲染
5
+ */
6
+ export declare function renderTreeNode(node: RenderTreeNode, index: number): ReactElement;
@@ -0,0 +1,17 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import { NexusField as e } from "../components/nexus-field.js";
3
+ import { NexusLayout as u } from "../components/nexus-layout.js";
4
+ import { NexusObject as y } from "../components/nexus-object.js";
5
+ function p(t, a) {
6
+ return t.type === "field" ? /* @__PURE__ */ r(
7
+ e,
8
+ {
9
+ dataPath: t.dataPath,
10
+ layoutKey: t.layoutKey
11
+ },
12
+ t.layoutKey || t.dataPath
13
+ ) : t.type === "object" ? /* @__PURE__ */ r(y, { node: t }, `object-${t.layoutKey}-${a}`) : /* @__PURE__ */ r(u, { node: t }, `layout-${t.type}-${a}`);
14
+ }
15
+ export {
16
+ p as renderTreeNode
17
+ };