@xbeeant/form-engine-react 0.0.1
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.
- package/README.md +69 -0
- package/dist/cjs/components/FormController.cjs +1 -0
- package/dist/cjs/components/NexusField.cjs +1 -0
- package/dist/cjs/components/NexusForm.cjs +1 -0
- package/dist/cjs/components/NexusFormProvider.cjs +1 -0
- package/dist/cjs/components/NexusLayout.cjs +1 -0
- package/dist/cjs/components/NexusObject.cjs +1 -0
- package/dist/cjs/contexts/FieldInheritContext.cjs +1 -0
- package/dist/cjs/contexts/GridContext.cjs +1 -0
- package/dist/cjs/contexts/LayoutConfigContext.cjs +1 -0
- package/dist/cjs/contexts/NexusContext.cjs +1 -0
- package/dist/cjs/hooks/index.cjs +1 -0
- package/dist/cjs/hooks/useEngine.cjs +1 -0
- package/dist/cjs/hooks/useFieldState.cjs +1 -0
- package/dist/cjs/hooks/useFieldValidator.cjs +1 -0
- package/dist/cjs/hooks/useFieldValue.cjs +1 -0
- package/dist/cjs/hooks/useForm.cjs +1 -0
- package/dist/cjs/hooks/useFormConfig.cjs +1 -0
- package/dist/cjs/hooks/useFormData.cjs +1 -0
- package/dist/cjs/hooks/useNexusContext.cjs +1 -0
- package/dist/cjs/hooks/useWatch.cjs +1 -0
- package/dist/cjs/hooks/useWatchAll.cjs +1 -0
- package/dist/cjs/hooks/useWatchMultiple.cjs +1 -0
- package/dist/cjs/hooks/useWatchState.cjs +1 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/utils/renderTreeNode.cjs +1 -0
- package/dist/cjs/utils/resolveColSpan.cjs +1 -0
- package/dist/es/components/FormController.d.ts +71 -0
- package/dist/es/components/FormController.js +153 -0
- package/dist/es/components/NexusField.d.ts +9 -0
- package/dist/es/components/NexusField.js +98 -0
- package/dist/es/components/NexusForm.d.ts +77 -0
- package/dist/es/components/NexusForm.js +120 -0
- package/dist/es/components/NexusFormProvider.d.ts +12 -0
- package/dist/es/components/NexusFormProvider.js +18 -0
- package/dist/es/components/NexusLayout.d.ts +9 -0
- package/dist/es/components/NexusLayout.js +48 -0
- package/dist/es/components/NexusObject.d.ts +16 -0
- package/dist/es/components/NexusObject.js +64 -0
- package/dist/es/contexts/FieldInheritContext.d.ts +18 -0
- package/dist/es/contexts/FieldInheritContext.js +5 -0
- package/dist/es/contexts/GridContext.d.ts +5 -0
- package/dist/es/contexts/GridContext.js +5 -0
- package/dist/es/contexts/LayoutConfigContext.d.ts +4 -0
- package/dist/es/contexts/LayoutConfigContext.js +5 -0
- package/dist/es/contexts/NexusContext.d.ts +27 -0
- package/dist/es/contexts/NexusContext.js +12 -0
- package/dist/es/hooks/index.d.ts +11 -0
- package/dist/es/hooks/index.js +24 -0
- package/dist/es/hooks/useEngine.d.ts +2 -0
- package/dist/es/hooks/useEngine.js +8 -0
- package/dist/es/hooks/useFieldState.d.ts +7 -0
- package/dist/es/hooks/useFieldState.js +13 -0
- package/dist/es/hooks/useFieldValidator.d.ts +40 -0
- package/dist/es/hooks/useFieldValidator.js +35 -0
- package/dist/es/hooks/useFieldValue.d.ts +6 -0
- package/dist/es/hooks/useFieldValue.js +13 -0
- package/dist/es/hooks/useForm.d.ts +6 -0
- package/dist/es/hooks/useForm.js +9 -0
- package/dist/es/hooks/useFormConfig.d.ts +5 -0
- package/dist/es/hooks/useFormConfig.js +8 -0
- package/dist/es/hooks/useFormData.d.ts +6 -0
- package/dist/es/hooks/useFormData.js +13 -0
- package/dist/es/hooks/useNexusContext.d.ts +11 -0
- package/dist/es/hooks/useNexusContext.js +12 -0
- package/dist/es/hooks/useWatch.d.ts +25 -0
- package/dist/es/hooks/useWatch.js +20 -0
- package/dist/es/hooks/useWatchAll.d.ts +19 -0
- package/dist/es/hooks/useWatchAll.js +29 -0
- package/dist/es/hooks/useWatchMultiple.d.ts +20 -0
- package/dist/es/hooks/useWatchMultiple.js +29 -0
- package/dist/es/hooks/useWatchState.d.ts +18 -0
- package/dist/es/hooks/useWatchState.js +19 -0
- package/dist/es/index.d.ts +24 -0
- package/dist/es/index.js +42 -0
- package/dist/es/utils/renderTreeNode.d.ts +6 -0
- package/dist/es/utils/renderTreeNode.js +17 -0
- package/dist/es/utils/resolveColSpan.d.ts +5 -0
- package/dist/es/utils/resolveColSpan.js +9 -0
- package/dist/umd/index.umd.cjs +1 -0
- package/package.json +75 -0
- package/src/components/FormController.ts +271 -0
- package/src/components/NexusField.tsx +182 -0
- package/src/components/NexusForm.tsx +290 -0
- package/src/components/NexusFormProvider.tsx +28 -0
- package/src/components/NexusLayout.tsx +81 -0
- package/src/components/NexusObject.tsx +93 -0
- package/src/contexts/FieldInheritContext.ts +21 -0
- package/src/contexts/GridContext.ts +8 -0
- package/src/contexts/LayoutConfigContext.ts +6 -0
- package/src/contexts/NexusContext.ts +41 -0
- package/src/hooks/index.ts +11 -0
- package/src/hooks/useEngine.ts +8 -0
- package/src/hooks/useFieldState.ts +21 -0
- package/src/hooks/useFieldValidator.ts +123 -0
- package/src/hooks/useFieldValue.ts +20 -0
- package/src/hooks/useForm.ts +15 -0
- package/src/hooks/useFormConfig.ts +10 -0
- package/src/hooks/useFormData.ts +20 -0
- package/src/hooks/useNexusContext.ts +24 -0
- package/src/hooks/useWatch.ts +83 -0
- package/src/hooks/useWatchAll.ts +77 -0
- package/src/hooks/useWatchMultiple.ts +86 -0
- package/src/hooks/useWatchState.ts +54 -0
- package/src/index.ts +30 -0
- package/src/utils/renderTreeNode.tsx +30 -0
- package/src/utils/resolveColSpan.ts +18 -0
|
@@ -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
|
+
};
|
|
@@ -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,24 @@
|
|
|
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';
|
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { FormController as r } from "./components/FormController.js";
|
|
2
|
+
import { NexusField as x } from "./components/NexusField.js";
|
|
3
|
+
import { NexusForm as f } from "./components/NexusForm.js";
|
|
4
|
+
import { NexusFormProvider as u } from "./components/NexusFormProvider.js";
|
|
5
|
+
import { NexusLayout as a } from "./components/NexusLayout.js";
|
|
6
|
+
import { NexusObject as l } from "./components/NexusObject.js";
|
|
7
|
+
import { FieldInheritContext as n } from "./contexts/FieldInheritContext.js";
|
|
8
|
+
import { GridContext as C } from "./contexts/GridContext.js";
|
|
9
|
+
import { LayoutConfigContext as h } from "./contexts/LayoutConfigContext.js";
|
|
10
|
+
import { useEngine as W } from "./hooks/useEngine.js";
|
|
11
|
+
import { useFieldState as y } from "./hooks/useFieldState.js";
|
|
12
|
+
import { useFieldValidator as S } from "./hooks/useFieldValidator.js";
|
|
13
|
+
import { useFieldValue as b } from "./hooks/useFieldValue.js";
|
|
14
|
+
import { useForm as v } from "./hooks/useForm.js";
|
|
15
|
+
import { useFormConfig as D } from "./hooks/useFormConfig.js";
|
|
16
|
+
import { useFormData as G } from "./hooks/useFormData.js";
|
|
17
|
+
import { useWatch as M } from "./hooks/useWatch.js";
|
|
18
|
+
import { useWatchAll as P } from "./hooks/useWatchAll.js";
|
|
19
|
+
import { useWatchMultiple as q } from "./hooks/useWatchMultiple.js";
|
|
20
|
+
import { useWatchState as z } from "./hooks/useWatchState.js";
|
|
21
|
+
export {
|
|
22
|
+
n as FieldInheritContext,
|
|
23
|
+
r as FormController,
|
|
24
|
+
C as GridContext,
|
|
25
|
+
h as LayoutConfigContext,
|
|
26
|
+
x as NexusField,
|
|
27
|
+
f as NexusForm,
|
|
28
|
+
u as NexusFormProvider,
|
|
29
|
+
a as NexusLayout,
|
|
30
|
+
l as NexusObject,
|
|
31
|
+
W as useEngine,
|
|
32
|
+
y as useFieldState,
|
|
33
|
+
S as useFieldValidator,
|
|
34
|
+
b as useFieldValue,
|
|
35
|
+
v as useForm,
|
|
36
|
+
D as useFormConfig,
|
|
37
|
+
G as useFormData,
|
|
38
|
+
M as useWatch,
|
|
39
|
+
P as useWatchAll,
|
|
40
|
+
q as useWatchMultiple,
|
|
41
|
+
z as useWatchState
|
|
42
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { NexusField as e } from "../components/NexusField.js";
|
|
3
|
+
import { NexusLayout as u } from "../components/NexusLayout.js";
|
|
4
|
+
import { NexusObject as y } from "../components/NexusObject.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
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(a,N){typeof exports=="object"&&typeof module<"u"?N(exports,require("@xbeeant/form-engine"),require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","@xbeeant/form-engine","react/jsx-runtime","react"],N):(a=typeof globalThis<"u"?globalThis:a||self,N(a.NexusFormEngineReact={},a.formEngine,a.jsxRuntime,a.react))})(this,(function(a,N,c,s){"use strict";class P{engine;formElementRef;getOnFinish;getOnFinishFailed;removeHiddenData=!0;watchers=new Map;globalWatcher=null;constructor(t){this.engine=t??new N.NexusEngine,this.engine.hasPlugin("async-validator")||this.engine.use(new N.AsyncValidatorPlugin(this.engine)),this.formElementRef={current:null},this.getOnFinish=()=>()=>{},this.getOnFinishFailed=()=>()=>{}}_bind(t,i,r){this.formElementRef.current=t,this.getOnFinish=i,this.getOnFinishFailed=r,this.engine.registerOnFieldValueChange((l,n)=>this._onFieldValueChange(l,n))}_syncConfig(t){if(t.removeHiddenData!==void 0&&(this.removeHiddenData=t.removeHiddenData),t.watch){this.watchers.clear(),this.globalWatcher=null;for(const[i,r]of Object.entries(t.watch))i==="#"?this.globalWatcher=r:this.watchers.set(i,r)}}_onFieldValueChange(t,i){const r=this.engine.getFormData(),l=this.removeHiddenData?r:this.engine.getAllFormData();this.globalWatcher&&this.globalWatcher(l,l,t);const n=this.watchers.get(t);n&&n(i,l)}_getEngine(){return this.engine}async submit(){const t=await this.engine.validate();if(t.size>0){this.focusFirstError(t),this.getOnFinishFailed()?.(t);return}const i=this.removeHiddenData?this.engine.getFormData():this.engine.getAllFormData();await this.getOnFinish()?.(i)}focusFirstError(t){const i=this.formElementRef.current;if(!i||t.size===0)return;const r=new Set(t.keys());requestAnimationFrame(()=>{const n=i.querySelectorAll("[data-nexus-field]");for(const o of Array.from(n)){const u=o.getAttribute("data-nexus-field");if(!u||!r.has(u))continue;o.scrollIntoView({behavior:"smooth",block:"center"}),o.querySelector('input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')?.focus();return}})}resetFields(){this.engine.reset()}setErrorFields(t){this.engine.setErrorFields(t)}setValues(t){this.engine.setFieldValues(t)}setValueByPath(t,i){this.engine.setFieldValue(t,i)}setSchemaByPath(t,i){this.engine.setSchemaByPath(t,i)}setSchema(t){this.engine.setSchema(t)}getValues(t){return this.engine.getFormData(t)}getHiddenValues(){return this.engine.getHiddenValues()}getAllValues(){return this.engine.getAllFormData()}getValueByPath(t){return this.engine.getFieldValue(t)}registerValidator(t,i){this.engine.registerFieldValidator(t,i)}unregisterValidator(t,i){this.engine.unregisterFieldValidator(t,i)}revalidateField(t){this.engine.validateField(t,{trigger:"change"})}getSchema(){return this.engine.getSchema()}removeErrorField(t){this.engine.removeErrorField(t)}scrollToPath(t){this.formElementRef.current?.querySelector(`[data-nexus-field="${t}"]`)?.scrollIntoView({behavior:"smooth",block:"center"})}getFieldError(t){return this.engine.getFieldError(t)}getFieldsError(){return this.engine.getFieldsError()}validateFields(t){return this.engine.validate(t)}getFieldState(t){return this.engine.getFieldState(t)}}const R=s.createContext({}),M=s.createContext(null),k=s.createContext({}),H=s.createContext(null);function S(){const e=s.useContext(H);if(!e)throw new Error("[NexusField] Must be used within <NexusFormProvider>");return e}function q(e,t){if(e!==void 0)return e;if(t&&t.column>0)return Math.max(1,Math.round(t.column/24))}function J({dataPath:e,layoutKey:t}){const{engine:i,config:r,form:l}=S();s.useSyncExternalStore(y=>i.subscribeField(e,y),()=>i.getFieldVersion(e),()=>i.getFieldVersion(e));const n=i.getFieldState(e),o=s.useContext(M),u=s.useContext(k),g=s.useContext(R),f=s.useCallback(y=>{i.setFieldValue(e,y)},[i,e]),b=s.useCallback(y=>{y.currentTarget.contains(y.relatedTarget)||i.validateField(e,{trigger:"blur"})},[i,e]),d=s.useMemo(()=>n?.meta.enum?n.meta.enum.map((y,E)=>({value:y,label:n.meta.enumNames?.[E]??String(y)})):n?.props.options,[n?.meta.enum,n?.meta.enumNames,n?.props.options]),F=s.useMemo(()=>{const y={};if(n?.reactions){for(const E of n.reactions)if(E.dependencies)for(const p of E.dependencies)y[p]=i.getFieldValue(p)}return y},[n?.reactions,i]);if(!n)return i.getSnapshot()>0&&console.warn(`[NexusField] Field not found: ${e}`),null;if(g.visible===!1||!n.visible)return u.removeHidden===!0?null:c.jsx("div",{className:"hidden","data-nexus-hidden":e});const h=r.readOnly||g.readOnly===!0||n.readOnly,C=g.disabled===!0||n.disabled,v=h&&!!n.meta.readOnlyWidget,x=v?n.meta.readOnlyWidget:n.meta.widget;let V=i.getWidget(x);if(!V&&v&&(V=i.getWidget(n.meta.widget)),!V)return c.jsxs("div",{className:"text-xs text-red-500","data-nexus-field":e,children:['⚠️ Widget "',n.meta.widget,'" 未注册 (path: ',e,")"]});const j=n.meta.displayType??r.displayType,D=n.meta.labelWidth??r.labelWidth,m=n.meta.column??r.column,O=q(n.meta.colSpan,o),w={...n.meta.width?{width:n.meta.width,flexShrink:0}:{},...O?{gridColumn:`span ${O}`}:{}};return c.jsx("div",{"data-nexus-field":e,onBlur:b,style:Object.keys(w).length>0?w:void 0,children:c.jsx(V,{dataPath:e,path:e,value:n.value,onChange:f,disabled:C,readOnly:h,loading:n.loading,required:n.required,title:n.meta.title,description:n.meta.description,placeholder:n.meta.placeholder,label:n.meta.label,options:d,errors:n.errors,extra:n.meta.extra,displayType:j,labelWidth:D,column:m,form:l,dependValues:F,items:n.meta.items,...n.props},t)})}function B({node:e}){const{engine:t}=S(),i=t.getLayout(e.type),r=e.children.map((h,C)=>$(h,C)),l=s.useContext(M),n=q(e.props.colSpan,l),o={...n?{gridColumn:`span ${n}`}:{},...e.props.width?{width:e.props.width,flexShrink:0}:{}},u=s.useMemo(()=>({removeHidden:e.props.removeHidden}),[e.props.removeHidden]);if(!i)return c.jsx(k.Provider,{value:u,children:c.jsxs("div",{"data-nexus-layout":e.type,className:"mb-4",style:Object.keys(o).length>0?o:void 0,children:[e.title&&c.jsx("div",{className:"mb-2 font-bold",children:e.title}),r]})});const{displayType:g,labelWidth:f,colSpan:b,width:d,...F}=e.props;return c.jsx(k.Provider,{value:u,children:c.jsx("div",{style:Object.keys(o).length>0?o:void 0,children:c.jsx(i,{...F,node:e,title:e.title,children:r})})})}function I({node:e}){const{engine:t,config:i}=S(),r=s.useContext(R);s.useSyncExternalStore(F=>t.subscribeField(e.dataPath,F),()=>t.getFieldVersion(e.dataPath),()=>t.getFieldVersion(e.dataPath));const l=t.getFieldState(e.dataPath),[n,o]=s.useState(!1),u=(i.column??1)>1,g=u?{gridTemplateColumns:`repeat(${i.column}, 1fr)`}:{},f={disabled:r.disabled??(l?.disabled===!0?!0:void 0),readOnly:r.readOnly??(l?.readOnly===!0?!0:void 0),visible:r.visible===!1||l?.visible===!1?!1:void 0},b=f.visible===!1,d=()=>o(F=>!F);return c.jsx(R.Provider,{value:f,children:c.jsxs("div",{"data-nexus-object":e.dataPath,className:`mb-4 ${b?"hidden":""}`,children:[e.title&&c.jsxs("div",{onClick:d,className:"flex gap-1 mb-2 cursor-pointer select-none border-none bg-transparent p-0 font-bold",children:[c.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:`align-middle transition-transform duration-200 ease-in-out ${n?"rotate-0":"rotate-90"}`,"aria-hidden":"true",children:c.jsx("polyline",{points:"9 18 15 12 9 6"})}),e.title]}),c.jsx("div",{className:`${u?"grid gap-x-4":""} ${n?"hidden":""}`,style:Object.keys(g).length>0?g:void 0,children:e.children.map((F,h)=>$(F,h))})]})})}function $(e,t){return e.type==="field"?c.jsx(J,{dataPath:e.dataPath,layoutKey:e.layoutKey},e.layoutKey||e.dataPath):e.type==="object"?c.jsx(I,{node:e},`object-${e.layoutKey}-${t}`):c.jsx(B,{node:e},`layout-${e.type}-${t}`)}function K({engine:e,config:t,form:i,children:r}){const l=s.useMemo(()=>({engine:e,config:t,form:i}),[e,t,i]);return c.jsx(H.Provider,{value:l,children:r})}function T(){}function Y({form:e,schema:t,initialValues:i,widgets:r,layouts:l,onFinish:n,onFinishFailed:o,footer:u=!1,className:g,style:f,children:b,labelCol:d,labelWidth:F,colon:h,label:C,displayType:v,readOnly:x,column:V,watch:j,removeHiddenData:D=!0}){const m=e._getEngine(),O=s.useRef(null),w=v??t?.displayType??"row",y=C??t?.label??!0,E=h??t?.colon,p=F??t?.labelWidth,G=x??t?.readOnly??!1,W=V??t?.column;s.useEffect(()=>{r&&m.registerWidgets(r),l&&m.registerLayouts(l)},[m,r,l]);const z=s.useRef(!0),ae=s.useRef(i);s.useEffect(()=>{t&&(z.current?(m.init(t,ae.current),z.current=!1):m.init(t,m.getFormData()))},[m,t]);const U=s.useRef(T),Q=s.useRef(T);U.current=n??T,Q.current=o??T,s.useEffect(()=>{e._bind(O.current,()=>U.current,()=>Q.current)},[e]),s.useEffect(()=>{e._syncConfig({removeHiddenData:D,watch:j})},[e,D,j]);const ce=s.useSyncExternalStore(m.subscribeStore,m.getSnapshot,m.getSnapshot),de=s.useMemo(()=>m.getRenderTree(),[m,ce]),fe=s.useCallback(async A=>{A.preventDefault(),await e.submit()},[e]),ge=s.useCallback(()=>{e.resetFields()},[e]);let L=null;u===!0?L=c.jsxs("div",{className:"mt-4",children:[c.jsx("button",{type:"submit",children:"提交"})," ",c.jsx("button",{type:"button",onClick:ge,children:"重置"})]}):u&&(L=u);const X=s.useMemo(()=>{if(d)return d;if(p)return{style:{width:typeof p=="number"?`${p}px`:p}}},[d,p]),he=s.useMemo(()=>({labelCol:X,labelWidth:p,colon:E,label:y,displayType:w,readOnly:G,column:W}),[X,p,E,y,w,G,W]);return c.jsx(K,{engine:m,config:he,form:e,children:c.jsxs("form",{ref:O,onSubmit:fe,className:g,style:{...f,...W&&W>1?{display:"grid",gridTemplateColumns:`repeat(${W}, 1fr)`,gap:"0 16px"}:{}},noValidate:!0,children:[de.map((A,be)=>$(A,be)),!x&&L,b]})})}function _(){const{engine:e}=S();return e}function Z(e){const{engine:t}=S();return s.useSyncExternalStore(i=>t.subscribeField(e,i),()=>t.getFieldVersion(e),()=>t.getFieldVersion(e)),t.getFieldState(e)}function ee(e,t,i,r){const{engine:l}=S(),n=s.useRef(i);n.current=i;const o=s.useRef(r?.dependsOn);o.current=r?.dependsOn;const u=r?.deps;s.useEffect(()=>{if(!e||!t)return;const g=n.current;return e.registerValidator(t,g),()=>{e.unregisterValidator(t,g)}},[e,t,...u??[]]),s.useEffect(()=>{if(!t||!o.current||o.current.length===0)return;const g=l;if(!g)return;const f=t,b=o.current.map(d=>g.subscribeField(d,()=>{e?.revalidateField(f)}));return()=>{for(const d of b)d()}},[l,e,t])}function te(e){const t=_();return s.useSyncExternalStore(i=>t.subscribeField(e,i),()=>t.getFieldVersion(e),()=>t.getFieldVersion(e)),t.getFieldValue(e)}function ne(e){const t=s.useRef(null);return t.current||(t.current=new P(e)),[t.current]}function ie(){const{config:e}=S();return e}function se(){const e=_(),t=s.useSyncExternalStore(e.subscribeStore,e.getSnapshot,e.getSnapshot);return s.useMemo(()=>e.getFormData(),[e,t])}function re(e,t,i,r){const{deep:l=!1}=r||{},n=s.useRef(void 0),o=s.useRef(i);return o.current=i,s.useEffect(()=>{if(!e)return;const u=e.getFieldValue(t);n.current===void 0&&(n.current=u),(l?JSON.stringify(u)!==JSON.stringify(n.current):u!==n.current)&&(n.current=u,o.current(u));const f=e.subscribe(t,b=>{const d=b.value;(l?JSON.stringify(d)!==JSON.stringify(n.current):d!==n.current)&&(n.current=d,o.current(d))});return()=>{f()}},[e,t,l]),n.current}function le(e,t,i){const{deep:r=!1}=i||{},l=s.useRef({}),n=s.useRef({}),o=s.useRef(t);return o.current=t,s.useEffect(()=>{if(!e)return;const u=e.getFormData();l.current=u,n.current=u,o.current(u);const g=e.subscribeAll(f=>{if(r)JSON.stringify(f)!==JSON.stringify(l.current)&&(l.current=f,n.current=f,o.current(f));else{let b=!1;for(const d in f)if(f[d]!==l.current[d]){b=!0;break}b&&(l.current=f,n.current=f,o.current(f))}});return()=>{g()}},[e,r]),n.current}function oe(e,t,i,r){const{deep:l=!1}=r||{},n=s.useRef({}),o=s.useRef({}),u=s.useRef(i);u.current=i;const g=s.useRef(t);g.current=t;const f=[...t].sort().join(",");return s.useEffect(()=>{if(!e)return;const b=g.current,d={};for(const h of b)d[h]=e.getFieldValue(h);n.current=d,o.current=d,u.current(d);const F=b.map(h=>e.subscribe(h,C=>{const v=C.value,x=n.current[h];(l?JSON.stringify(v)!==JSON.stringify(x):v!==x)&&(n.current[h]=v,o.current={[h]:v},u.current(o.current))}));return()=>{for(const h of F)h()}},[e,l,f]),o.current}function ue(e,t,i){const r=s.useRef(void 0),l=s.useRef(i);return l.current=i,s.useEffect(()=>{if(!e)return;const n=e.getFieldState(t);r.current=n,n&&l.current(n);const o=e.subscribe(t,u=>{r.current=u,l.current(u)});return()=>{o()}},[e,t]),r.current||{}}a.FieldInheritContext=R,a.FormController=P,a.GridContext=M,a.LayoutConfigContext=k,a.NexusField=J,a.NexusForm=Y,a.NexusFormProvider=K,a.NexusLayout=B,a.NexusObject=I,a.useEngine=_,a.useFieldState=Z,a.useFieldValidator=ee,a.useFieldValue=te,a.useForm=ne,a.useFormConfig=ie,a.useFormData=se,a.useWatch=re,a.useWatchAll=le,a.useWatchMultiple=oe,a.useWatchState=ue,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xbeeant/form-engine-react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public",
|
|
6
|
+
"registry": "https://registry.npmjs.org/"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/es/index.js",
|
|
10
|
+
"module": "./dist/es/index.js",
|
|
11
|
+
"types": "./dist/es/index.d.ts",
|
|
12
|
+
"unpkg": "./dist/umd/index.umd.cjs",
|
|
13
|
+
"jsdelivr": "./dist/umd/index.umd.cjs",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/es/index.d.ts",
|
|
17
|
+
"import": "./dist/es/index.js",
|
|
18
|
+
"require": "./dist/cjs/index.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./components/*": {
|
|
21
|
+
"types": "./dist/es/components/*.d.ts",
|
|
22
|
+
"import": "./dist/es/components/*.js",
|
|
23
|
+
"require": "./dist/cjs/components/*.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./hooks/*": {
|
|
26
|
+
"types": "./dist/es/hooks/*.d.ts",
|
|
27
|
+
"import": "./dist/es/hooks/*.js",
|
|
28
|
+
"require": "./dist/cjs/hooks/*.cjs"
|
|
29
|
+
},
|
|
30
|
+
"./contexts/*": {
|
|
31
|
+
"types": "./dist/es/contexts/*.d.ts",
|
|
32
|
+
"import": "./dist/es/contexts/*.js",
|
|
33
|
+
"require": "./dist/cjs/contexts/*.cjs"
|
|
34
|
+
},
|
|
35
|
+
"./utils/*": {
|
|
36
|
+
"types": "./dist/es/utils/*.d.ts",
|
|
37
|
+
"import": "./dist/es/utils/*.js",
|
|
38
|
+
"require": "./dist/cjs/utils/*.cjs"
|
|
39
|
+
},
|
|
40
|
+
"./package.json": "./package.json"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"src",
|
|
45
|
+
"README.md",
|
|
46
|
+
"!**/*.map"
|
|
47
|
+
],
|
|
48
|
+
"sideEffects": [
|
|
49
|
+
"**/*.css"
|
|
50
|
+
],
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "npm run build:es && npm run build:cjs && npm run build:umd",
|
|
53
|
+
"prepublishOnly": "npm run build",
|
|
54
|
+
"build:es": "tsc -b && vite build -f es",
|
|
55
|
+
"build:cjs": "vite build -f cjs",
|
|
56
|
+
"build:umd": "vite build -f umd",
|
|
57
|
+
"lint": "biome check .",
|
|
58
|
+
"lint:fix": "biome check --write ."
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"react": ">=18.0.0",
|
|
62
|
+
"react-dom": ">=18.0.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependenciesMeta": {
|
|
65
|
+
"react": {
|
|
66
|
+
"optional": false
|
|
67
|
+
},
|
|
68
|
+
"react-dom": {
|
|
69
|
+
"optional": false
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"@xbeeant/form-engine": "^0.0.1"
|
|
74
|
+
}
|
|
75
|
+
}
|