@xbeeant/form-engine-react 0.0.2 → 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.
- package/dist/cjs/components/FormController.cjs +1 -1
- package/dist/cjs/components/NexusField.cjs +1 -1
- package/dist/cjs/components/NexusForm.cjs +1 -1
- package/dist/cjs/components/form-controller.cjs +1 -0
- package/dist/cjs/components/nexus-field.cjs +1 -0
- package/dist/cjs/components/nexus-form-provider.cjs +1 -0
- package/dist/cjs/components/nexus-form.cjs +1 -0
- package/dist/cjs/components/nexus-layout.cjs +1 -0
- package/dist/cjs/components/nexus-object.cjs +1 -0
- package/dist/cjs/contexts/field-inherit-context.cjs +1 -0
- package/dist/cjs/contexts/grid-context.cjs +1 -0
- package/dist/cjs/contexts/layout-config-context.cjs +1 -0
- package/dist/cjs/contexts/nexus-context.cjs +1 -0
- package/dist/cjs/hooks/index.cjs +1 -1
- package/dist/cjs/hooks/use-engine.cjs +1 -0
- package/dist/cjs/hooks/use-field-state.cjs +1 -0
- package/dist/cjs/hooks/use-field-validator.cjs +1 -0
- package/dist/cjs/hooks/use-field-value.cjs +1 -0
- package/dist/cjs/hooks/use-form-config.cjs +1 -0
- package/dist/cjs/hooks/use-form-data.cjs +1 -0
- package/dist/cjs/hooks/use-form-submitting.cjs +1 -0
- package/dist/cjs/hooks/use-form.cjs +1 -0
- package/dist/cjs/hooks/use-nexus-context.cjs +1 -0
- package/dist/cjs/hooks/use-watch-all.cjs +1 -0
- package/dist/cjs/hooks/use-watch-multiple.cjs +1 -0
- package/dist/cjs/hooks/use-watch-state.cjs +1 -0
- package/dist/cjs/hooks/use-watch.cjs +1 -0
- package/dist/cjs/hooks/useForm.cjs +1 -1
- package/dist/cjs/hooks/useFormData.cjs +1 -1
- package/dist/cjs/hooks/useFormSubmitting.cjs +1 -0
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/styles.css +1 -0
- package/dist/cjs/utils/omit-nil.cjs +1 -0
- package/dist/cjs/utils/omitNil.cjs +1 -0
- package/dist/cjs/utils/persist.cjs +1 -0
- package/dist/cjs/utils/render-tree-node.cjs +1 -0
- package/dist/cjs/utils/resolve-col-span.cjs +1 -0
- package/dist/es/components/FormController.d.ts +76 -18
- package/dist/es/components/FormController.js +227 -70
- package/dist/es/components/NexusField.js +63 -60
- package/dist/es/components/NexusForm.d.ts +40 -3
- package/dist/es/components/NexusForm.js +143 -89
- package/dist/es/components/form-controller.d.ts +129 -0
- package/dist/es/components/form-controller.js +310 -0
- package/dist/es/components/nexus-field.d.ts +9 -0
- package/dist/es/components/nexus-field.js +131 -0
- package/dist/es/components/nexus-form-provider.d.ts +12 -0
- package/dist/es/components/nexus-form-provider.js +18 -0
- package/dist/es/components/nexus-form.d.ts +114 -0
- package/dist/es/components/nexus-form.js +174 -0
- package/dist/es/components/nexus-layout.d.ts +9 -0
- package/dist/es/components/nexus-layout.js +48 -0
- package/dist/es/components/nexus-object.d.ts +16 -0
- package/dist/es/components/nexus-object.js +64 -0
- package/dist/es/contexts/NexusContext.d.ts +2 -0
- package/dist/es/contexts/field-inherit-context.d.ts +18 -0
- package/dist/es/contexts/field-inherit-context.js +5 -0
- package/dist/es/contexts/grid-context.d.ts +5 -0
- package/dist/es/contexts/grid-context.js +5 -0
- package/dist/es/contexts/layout-config-context.d.ts +4 -0
- package/dist/es/contexts/layout-config-context.js +5 -0
- package/dist/es/contexts/nexus-context.d.ts +29 -0
- package/dist/es/contexts/nexus-context.js +12 -0
- package/dist/es/hooks/index.d.ts +12 -11
- package/dist/es/hooks/index.js +20 -18
- package/dist/es/hooks/use-engine.d.ts +2 -0
- package/dist/es/hooks/use-engine.js +8 -0
- package/dist/es/hooks/use-field-state.d.ts +7 -0
- package/dist/es/hooks/use-field-state.js +13 -0
- package/dist/es/hooks/use-field-validator.d.ts +40 -0
- package/dist/es/hooks/use-field-validator.js +35 -0
- package/dist/es/hooks/use-field-value.d.ts +6 -0
- package/dist/es/hooks/use-field-value.js +13 -0
- package/dist/es/hooks/use-form-config.d.ts +5 -0
- package/dist/es/hooks/use-form-config.js +8 -0
- package/dist/es/hooks/use-form-data.d.ts +6 -0
- package/dist/es/hooks/use-form-data.js +13 -0
- package/dist/es/hooks/use-form-submitting.d.ts +7 -0
- package/dist/es/hooks/use-form-submitting.js +11 -0
- package/dist/es/hooks/use-form.d.ts +22 -0
- package/dist/es/hooks/use-form.js +12 -0
- package/dist/es/hooks/use-nexus-context.d.ts +11 -0
- package/dist/es/hooks/use-nexus-context.js +12 -0
- package/dist/es/hooks/use-watch-all.d.ts +19 -0
- package/dist/es/hooks/use-watch-all.js +29 -0
- package/dist/es/hooks/use-watch-multiple.d.ts +20 -0
- package/dist/es/hooks/use-watch-multiple.js +29 -0
- package/dist/es/hooks/use-watch-state.d.ts +18 -0
- package/dist/es/hooks/use-watch-state.js +19 -0
- package/dist/es/hooks/use-watch.d.ts +25 -0
- package/dist/es/hooks/use-watch.js +20 -0
- package/dist/es/hooks/useForm.d.ts +17 -1
- package/dist/es/hooks/useForm.js +9 -6
- package/dist/es/hooks/useFormData.js +9 -9
- package/dist/es/hooks/useFormSubmitting.d.ts +7 -0
- package/dist/es/hooks/useFormSubmitting.js +11 -0
- package/dist/es/index.d.ts +26 -24
- package/dist/es/index.js +43 -38
- package/dist/es/styles.css +1 -0
- package/dist/es/utils/omit-nil.d.ts +9 -0
- package/dist/es/utils/omit-nil.js +14 -0
- package/dist/es/utils/omitNil.d.ts +9 -0
- package/dist/es/utils/omitNil.js +14 -0
- package/dist/es/utils/persist.d.ts +24 -0
- package/dist/es/utils/persist.js +43 -0
- package/dist/es/utils/render-tree-node.d.ts +6 -0
- package/dist/es/utils/render-tree-node.js +17 -0
- package/dist/es/utils/resolve-col-span.d.ts +5 -0
- package/dist/es/utils/resolve-col-span.js +9 -0
- package/dist/umd/index.css +1 -0
- package/dist/umd/index.umd.cjs +1 -1
- package/package.json +5 -4
- package/src/components/form-controller.ts +584 -0
- package/src/components/{NexusField.tsx → nexus-field.tsx} +108 -31
- package/src/components/{NexusFormProvider.tsx → nexus-form-provider.tsx} +3 -3
- package/src/components/{NexusForm.tsx → nexus-form.tsx} +159 -18
- package/src/components/{NexusLayout.tsx → nexus-layout.tsx} +5 -5
- package/src/components/{NexusObject.tsx → nexus-object.tsx} +3 -3
- package/src/contexts/{NexusContext.ts → nexus-context.ts} +3 -1
- package/src/hooks/index.ts +12 -11
- package/src/hooks/{useEngine.ts → use-engine.ts} +1 -1
- package/src/hooks/{useFieldState.ts → use-field-state.ts} +1 -1
- package/src/hooks/{useFieldValidator.ts → use-field-validator.ts} +1 -1
- package/src/hooks/{useFieldValue.ts → use-field-value.ts} +1 -1
- package/src/hooks/{useFormConfig.ts → use-form-config.ts} +2 -2
- package/src/hooks/{useFormData.ts → use-form-data.ts} +4 -4
- package/src/hooks/use-form-submitting.ts +16 -0
- package/src/hooks/use-form.ts +36 -0
- package/src/hooks/{useNexusContext.ts → use-nexus-context.ts} +2 -2
- package/src/index.ts +28 -24
- package/src/styles.css +6 -0
- package/src/utils/omit-nil.ts +24 -0
- package/src/utils/persist.ts +88 -0
- package/src/utils/{renderTreeNode.tsx → render-tree-node.tsx} +3 -3
- package/src/utils/{resolveColSpan.ts → resolve-col-span.ts} +1 -1
- package/src/vite-env.d.ts +1 -0
- package/src/components/FormController.ts +0 -271
- package/src/hooks/useForm.ts +0 -15
- /package/src/contexts/{FieldInheritContext.ts → field-inherit-context.ts} +0 -0
- /package/src/contexts/{GridContext.ts → grid-context.ts} +0 -0
- /package/src/contexts/{LayoutConfigContext.ts → layout-config-context.ts} +0 -0
- /package/src/hooks/{useWatchAll.ts → use-watch-all.ts} +0 -0
- /package/src/hooks/{useWatchMultiple.ts → use-watch-multiple.ts} +0 -0
- /package/src/hooks/{useWatchState.ts → use-watch-state.ts} +0 -0
- /package/src/hooks/{useWatch.ts → use-watch.ts} +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { jsx as S, jsxs as A } from "react/jsx-runtime";
|
|
2
|
+
import { useId as de, useMemo as f, useRef as i, useEffect as u, useSyncExternalStore as fe, useCallback as B } from "react";
|
|
3
|
+
import "../contexts/nexus-context.js";
|
|
4
|
+
import "@xbeeant/form-engine";
|
|
5
|
+
import { useFormSubmitting as pe } from "../hooks/use-form-submitting.js";
|
|
6
|
+
import { loadPersisted as be, savePersisted as ge, clearPersisted as ye } from "../utils/persist.js";
|
|
7
|
+
import { renderTreeNode as me } from "../utils/render-tree-node.js";
|
|
8
|
+
import { NexusFormProvider as Re } from "./nexus-form-provider.js";
|
|
9
|
+
function T() {
|
|
10
|
+
}
|
|
11
|
+
function je({
|
|
12
|
+
form: o,
|
|
13
|
+
schema: n,
|
|
14
|
+
initialValues: G,
|
|
15
|
+
widgets: p,
|
|
16
|
+
layouts: b,
|
|
17
|
+
fieldWrapper: g,
|
|
18
|
+
onFinish: J,
|
|
19
|
+
onFinishFailed: Q,
|
|
20
|
+
onMount: x,
|
|
21
|
+
footer: y = !1,
|
|
22
|
+
className: U,
|
|
23
|
+
style: X,
|
|
24
|
+
children: Y,
|
|
25
|
+
labelCol: m,
|
|
26
|
+
labelWidth: Z,
|
|
27
|
+
colon: H,
|
|
28
|
+
label: ee,
|
|
29
|
+
displayType: te,
|
|
30
|
+
readOnly: C,
|
|
31
|
+
column: ne,
|
|
32
|
+
watch: v,
|
|
33
|
+
onValuesChange: L,
|
|
34
|
+
removeHiddenData: h = !0,
|
|
35
|
+
omitNil: j = !1,
|
|
36
|
+
locale: re,
|
|
37
|
+
persist: c
|
|
38
|
+
}) {
|
|
39
|
+
const l = de(), e = f(
|
|
40
|
+
() => o._useInstance(l),
|
|
41
|
+
[o, l]
|
|
42
|
+
), k = i(null), a = i(c);
|
|
43
|
+
a.current = c;
|
|
44
|
+
const E = te ?? n?.displayType ?? "row", I = ee ?? n?.label ?? !0, N = H ?? n?.colon, s = Z ?? n?.labelWidth, O = C ?? n?.readOnly ?? !1, d = ne ?? n?.column, P = re ?? n?.locale ?? e.getLocale();
|
|
45
|
+
u(() => {
|
|
46
|
+
p && e.registerWidgets(p), g && e.registerFieldWrapper(g), b && e.registerLayouts(b);
|
|
47
|
+
}, [e, p, b, g]);
|
|
48
|
+
const _ = i(!0), oe = i(G);
|
|
49
|
+
u(() => {
|
|
50
|
+
if (n)
|
|
51
|
+
if (_.current) {
|
|
52
|
+
const t = a.current ? be(a.current) : void 0;
|
|
53
|
+
e.init(n, t ?? oe.current), _.current = !1;
|
|
54
|
+
} else
|
|
55
|
+
e.init(n, e.getFormData());
|
|
56
|
+
}, [e, n]);
|
|
57
|
+
const $ = c ? `${c.storage ?? "localStorage"}:${c.key}` : null;
|
|
58
|
+
u(() => {
|
|
59
|
+
const t = $ ? a.current : void 0;
|
|
60
|
+
if (!t)
|
|
61
|
+
return;
|
|
62
|
+
let r = null;
|
|
63
|
+
const F = t.debounce ?? 300, ae = e.subscribeStore(() => {
|
|
64
|
+
r && clearTimeout(r), r = setTimeout(() => {
|
|
65
|
+
ge(t, e.getFormData());
|
|
66
|
+
}, F);
|
|
67
|
+
});
|
|
68
|
+
return () => {
|
|
69
|
+
r && clearTimeout(r), ae();
|
|
70
|
+
};
|
|
71
|
+
}, [e, $]);
|
|
72
|
+
const D = i(x);
|
|
73
|
+
D.current = x;
|
|
74
|
+
const V = i(!1), W = !n || typeof n == "object" && Object.keys(n).length === 0;
|
|
75
|
+
u(() => {
|
|
76
|
+
V.current || W || (V.current = !0, D.current?.());
|
|
77
|
+
}, [W]);
|
|
78
|
+
const M = i(T), K = i(T);
|
|
79
|
+
M.current = (t) => {
|
|
80
|
+
const r = a.current;
|
|
81
|
+
return r && r.clearOnSubmit !== !1 && ye(r), J?.(t);
|
|
82
|
+
}, K.current = Q ?? T, u(() => {
|
|
83
|
+
o._bind(
|
|
84
|
+
l,
|
|
85
|
+
k.current,
|
|
86
|
+
() => M.current,
|
|
87
|
+
() => K.current
|
|
88
|
+
);
|
|
89
|
+
}, [o, l]);
|
|
90
|
+
const q = i(L);
|
|
91
|
+
q.current = L, u(() => {
|
|
92
|
+
o._syncConfig(l, {
|
|
93
|
+
removeHiddenData: h,
|
|
94
|
+
omitNil: j,
|
|
95
|
+
watch: v,
|
|
96
|
+
onValuesChange: (t, r, F) => q.current?.(t, r, F)
|
|
97
|
+
});
|
|
98
|
+
}, [o, l, h, j, v]);
|
|
99
|
+
const ie = fe(
|
|
100
|
+
(t) => e.subscribeRender(t),
|
|
101
|
+
() => e.getRenderSnapshot(),
|
|
102
|
+
() => e.getRenderSnapshot()
|
|
103
|
+
), se = f(() => e.getRenderTree(), [e, ie]), le = B(
|
|
104
|
+
async (t) => {
|
|
105
|
+
t.preventDefault(), await o.submit();
|
|
106
|
+
},
|
|
107
|
+
[o]
|
|
108
|
+
), ue = B(() => {
|
|
109
|
+
o.resetFields();
|
|
110
|
+
}, [o]), w = pe(o);
|
|
111
|
+
let R = null;
|
|
112
|
+
y === !0 ? R = /* @__PURE__ */ A("div", { className: "mt-4", children: [
|
|
113
|
+
/* @__PURE__ */ S("button", { type: "submit", disabled: w, children: w ? "提交中..." : "提交" }),
|
|
114
|
+
" ",
|
|
115
|
+
/* @__PURE__ */ S("button", { type: "button", onClick: ue, children: "重置" })
|
|
116
|
+
] }) : y && (R = y);
|
|
117
|
+
const z = f(() => {
|
|
118
|
+
if (m)
|
|
119
|
+
return m;
|
|
120
|
+
if (s)
|
|
121
|
+
return {
|
|
122
|
+
style: {
|
|
123
|
+
width: typeof s == "number" ? `${s}px` : s
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}, [m, s]), ce = f(
|
|
127
|
+
() => ({
|
|
128
|
+
labelCol: z,
|
|
129
|
+
labelWidth: s,
|
|
130
|
+
colon: N,
|
|
131
|
+
label: I,
|
|
132
|
+
displayType: E,
|
|
133
|
+
readOnly: O,
|
|
134
|
+
column: d,
|
|
135
|
+
locale: P
|
|
136
|
+
}),
|
|
137
|
+
[
|
|
138
|
+
z,
|
|
139
|
+
s,
|
|
140
|
+
N,
|
|
141
|
+
I,
|
|
142
|
+
E,
|
|
143
|
+
O,
|
|
144
|
+
d,
|
|
145
|
+
P
|
|
146
|
+
]
|
|
147
|
+
);
|
|
148
|
+
return /* @__PURE__ */ S(Re, { engine: e, config: ce, form: o, children: /* @__PURE__ */ A(
|
|
149
|
+
"form",
|
|
150
|
+
{
|
|
151
|
+
ref: k,
|
|
152
|
+
onSubmit: le,
|
|
153
|
+
className: U,
|
|
154
|
+
style: {
|
|
155
|
+
...X,
|
|
156
|
+
// 当配置了 column 时,使用 CSS Grid 布局
|
|
157
|
+
...d && d > 1 ? {
|
|
158
|
+
display: "grid",
|
|
159
|
+
gridTemplateColumns: `repeat(${d}, 1fr)`,
|
|
160
|
+
gap: "0 16px"
|
|
161
|
+
} : {}
|
|
162
|
+
},
|
|
163
|
+
noValidate: !0,
|
|
164
|
+
children: [
|
|
165
|
+
se.map((t, r) => me(t, r)),
|
|
166
|
+
!C && R,
|
|
167
|
+
Y
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
) });
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
je as NexusForm
|
|
174
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as e, jsxs as u } from "react/jsx-runtime";
|
|
2
|
+
import { useContext as y, useMemo as f } from "react";
|
|
3
|
+
import { GridContext as h } from "../contexts/grid-context.js";
|
|
4
|
+
import { LayoutConfigContext as p } from "../contexts/layout-config-context.js";
|
|
5
|
+
import { useNexusContext as v } from "../contexts/nexus-context.js";
|
|
6
|
+
import { renderTreeNode as x } from "../utils/render-tree-node.js";
|
|
7
|
+
import { resolveColSpan as C } from "../utils/resolve-col-span.js";
|
|
8
|
+
function O({ node: t }) {
|
|
9
|
+
const { engine: n } = v(), r = n.getLayout(t.type), i = t.children.map(
|
|
10
|
+
(c, d) => x(c, d)
|
|
11
|
+
), a = y(h), l = C(t.props.colSpan, a), o = {
|
|
12
|
+
...l ? { gridColumn: `span ${l}` } : {},
|
|
13
|
+
...t.props.width ? { width: t.props.width, flexShrink: 0 } : {}
|
|
14
|
+
}, s = f(
|
|
15
|
+
() => ({ removeHidden: t.props.removeHidden }),
|
|
16
|
+
[t.props.removeHidden]
|
|
17
|
+
);
|
|
18
|
+
if (!r)
|
|
19
|
+
return /* @__PURE__ */ e(p.Provider, { value: s, children: /* @__PURE__ */ u(
|
|
20
|
+
"div",
|
|
21
|
+
{
|
|
22
|
+
"data-nexus-layout": t.type,
|
|
23
|
+
className: "mb-4",
|
|
24
|
+
style: Object.keys(o).length > 0 ? o : void 0,
|
|
25
|
+
children: [
|
|
26
|
+
t.title && /* @__PURE__ */ e("div", { className: "mb-2 font-bold", children: t.title }),
|
|
27
|
+
i
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
) });
|
|
31
|
+
const {
|
|
32
|
+
displayType: g,
|
|
33
|
+
labelWidth: w,
|
|
34
|
+
colSpan: b,
|
|
35
|
+
width: S,
|
|
36
|
+
...m
|
|
37
|
+
} = t.props;
|
|
38
|
+
return /* @__PURE__ */ e(p.Provider, { value: s, children: /* @__PURE__ */ e(
|
|
39
|
+
"div",
|
|
40
|
+
{
|
|
41
|
+
style: Object.keys(o).length > 0 ? o : void 0,
|
|
42
|
+
children: /* @__PURE__ */ e(r, { ...m, node: t, title: t.title, children: i })
|
|
43
|
+
}
|
|
44
|
+
) });
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
O as NexusLayout
|
|
48
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RenderObjectNode } from '@xbeeant/form-engine';
|
|
2
|
+
interface NexusObjectProps {
|
|
3
|
+
node: RenderObjectNode;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* NexusObject — 数据对象容器(可折叠,支持 disabled/hidden/readOnly 属性配置)
|
|
7
|
+
*
|
|
8
|
+
* 点击 title 折叠/展开 children。
|
|
9
|
+
* 折叠时仅以 display:none 隐藏 children,并不销毁(字段状态与订阅保持存活)。
|
|
10
|
+
*
|
|
11
|
+
* 属性继承:容器自身(Schema 布尔值 / 表达式 / setFieldState)配置的
|
|
12
|
+
* disabled / readOnly / hidden 会经 FieldInheritContext 下发给子树,
|
|
13
|
+
* 子树中的字段继承对应状态(disabled/readOnly 仅父级激活时生效)。
|
|
14
|
+
*/
|
|
15
|
+
export declare function NexusObject({ node }: NexusObjectProps): import("react").JSX.Element;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as r, jsxs as u } from "react/jsx-runtime";
|
|
2
|
+
import { useContext as g, useSyncExternalStore as v, useState as x } from "react";
|
|
3
|
+
import { FieldInheritContext as h } from "../contexts/field-inherit-context.js";
|
|
4
|
+
import { useNexusContext as y } from "../contexts/nexus-context.js";
|
|
5
|
+
import { renderTreeNode as C } from "../utils/render-tree-node.js";
|
|
6
|
+
function O({ node: e }) {
|
|
7
|
+
const { engine: i, config: a } = y(), s = g(h);
|
|
8
|
+
v(
|
|
9
|
+
(t) => i.subscribeField(e.dataPath, t),
|
|
10
|
+
() => i.getFieldVersion(e.dataPath),
|
|
11
|
+
() => i.getFieldVersion(e.dataPath)
|
|
12
|
+
);
|
|
13
|
+
const n = i.getFieldState(e.dataPath), [o, m] = x(!1), l = (a.column ?? 1) > 1, d = l ? { gridTemplateColumns: `repeat(${a.column}, 1fr)` } : {}, c = {
|
|
14
|
+
disabled: s.disabled ?? (n?.disabled === !0 ? !0 : void 0),
|
|
15
|
+
readOnly: s.readOnly ?? (n?.readOnly === !0 ? !0 : void 0),
|
|
16
|
+
visible: s.visible === !1 || n?.visible === !1 ? !1 : void 0
|
|
17
|
+
}, p = c.visible === !1, b = () => m((t) => !t);
|
|
18
|
+
return /* @__PURE__ */ r(h.Provider, { value: c, children: /* @__PURE__ */ u(
|
|
19
|
+
"div",
|
|
20
|
+
{
|
|
21
|
+
"data-nexus-object": e.dataPath,
|
|
22
|
+
className: `mb-4 ${p ? "hidden" : ""}`,
|
|
23
|
+
children: [
|
|
24
|
+
e.title && /* @__PURE__ */ u(
|
|
25
|
+
"div",
|
|
26
|
+
{
|
|
27
|
+
onClick: b,
|
|
28
|
+
className: "flex gap-1 mb-2 cursor-pointer select-none border-none bg-transparent p-0 font-bold",
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ r(
|
|
31
|
+
"svg",
|
|
32
|
+
{
|
|
33
|
+
width: "12",
|
|
34
|
+
height: "12",
|
|
35
|
+
viewBox: "0 0 24 24",
|
|
36
|
+
fill: "none",
|
|
37
|
+
stroke: "currentColor",
|
|
38
|
+
strokeWidth: "2",
|
|
39
|
+
strokeLinecap: "round",
|
|
40
|
+
strokeLinejoin: "round",
|
|
41
|
+
className: `align-middle transition-transform duration-200 ease-in-out ${o ? "rotate-0" : "rotate-90"}`,
|
|
42
|
+
"aria-hidden": "true",
|
|
43
|
+
children: /* @__PURE__ */ r("polyline", { points: "9 18 15 12 9 6" })
|
|
44
|
+
}
|
|
45
|
+
),
|
|
46
|
+
e.title
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ r(
|
|
51
|
+
"div",
|
|
52
|
+
{
|
|
53
|
+
className: `${l ? "grid gap-x-4" : ""} ${o ? "hidden" : ""}`,
|
|
54
|
+
style: Object.keys(d).length > 0 ? d : void 0,
|
|
55
|
+
children: e.children.map((t, f) => C(t, f))
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
) });
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
O as NexusObject
|
|
64
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 字段继承上下文 — 数据对象容器(NexusObject)向下游字段下发继承属性
|
|
3
|
+
*
|
|
4
|
+
* 语义:
|
|
5
|
+
* - 仅「激活」状态被下发:disabled/readOnly 只在父容器显式启用时
|
|
6
|
+
* 携带 true(父级未设置时上下文不存在该键),子字段自行合并
|
|
7
|
+
* - visible 为 false 表示祖先对象容器隐藏,子树整体不可见
|
|
8
|
+
* - 合并优先级:祖先(已激活) > 字段自身状态 > 默认值
|
|
9
|
+
*/
|
|
10
|
+
export interface FieldInheritValue {
|
|
11
|
+
/** 祖先对象容器禁用(仅 true 存在) */
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
/** 祖先对象容器只读(仅 true 存在) */
|
|
14
|
+
readOnly?: boolean;
|
|
15
|
+
/** 祖先对象容器隐藏 → 子树不可见(false 存在时子树全部隐藏) */
|
|
16
|
+
visible?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const FieldInheritContext: import('react').Context<FieldInheritValue>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { NexusEngine } from '@xbeeant/form-engine';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { FormController } from '../components/form-controller';
|
|
4
|
+
export interface NexusFormConfig {
|
|
5
|
+
/** label 列配置(由 ui 层 Form.Item 消费) */
|
|
6
|
+
labelCol?: Record<string, unknown>;
|
|
7
|
+
/** label 宽度(px 或 %),快捷方式 — 映射到 labelCol.style.width */
|
|
8
|
+
labelWidth?: number | string;
|
|
9
|
+
/** 是否显示冒号 */
|
|
10
|
+
colon?: boolean | ReactNode;
|
|
11
|
+
/** 是否显示 label(默认 true) */
|
|
12
|
+
label?: boolean;
|
|
13
|
+
/** 表单布局方向 */
|
|
14
|
+
displayType?: 'row' | 'column' | 'inline';
|
|
15
|
+
/** 整个表单只读,所有字段以文本展示 */
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
/** 表单每行显示多少列 */
|
|
18
|
+
column?: number;
|
|
19
|
+
/** 表单语言标识(如 'zh-CN' / 'en-US',ui 层消费:antd locale + 内置文案) */
|
|
20
|
+
locale?: string;
|
|
21
|
+
}
|
|
22
|
+
interface NexusContextValue {
|
|
23
|
+
engine: NexusEngine;
|
|
24
|
+
config: NexusFormConfig;
|
|
25
|
+
form: FormController;
|
|
26
|
+
}
|
|
27
|
+
export declare const NexusContext: import('react').Context<NexusContextValue | null>;
|
|
28
|
+
export declare function useNexusContext(): NexusContextValue;
|
|
29
|
+
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
|
+
};
|
package/dist/es/hooks/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
export { useEngine } from './
|
|
2
|
-
export { useFieldState } from './
|
|
3
|
-
export { useFieldValidator } from './
|
|
4
|
-
export { useFieldValue } from './
|
|
5
|
-
export { useForm } from './
|
|
6
|
-
export { useFormConfig } from './
|
|
7
|
-
export { useFormData } from './
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
1
|
+
export { useEngine } from './use-engine';
|
|
2
|
+
export { useFieldState } from './use-field-state';
|
|
3
|
+
export { useFieldValidator } from './use-field-validator';
|
|
4
|
+
export { useFieldValue } from './use-field-value';
|
|
5
|
+
export { useForm } from './use-form';
|
|
6
|
+
export { useFormConfig } from './use-form-config';
|
|
7
|
+
export { useFormData } from './use-form-data';
|
|
8
|
+
export { useFormSubmitting } from './use-form-submitting';
|
|
9
|
+
export { useWatch } from './use-watch';
|
|
10
|
+
export { useWatchAll } from './use-watch-all';
|
|
11
|
+
export { useWatchMultiple } from './use-watch-multiple';
|
|
12
|
+
export { useWatchState } from './use-watch-state';
|
package/dist/es/hooks/index.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import { useEngine as r } from "./
|
|
2
|
-
import { useFieldState as m } from "./
|
|
3
|
-
import { useFieldValidator as f } from "./
|
|
4
|
-
import { useFieldValue as
|
|
5
|
-
import { useForm as
|
|
6
|
-
import { useFormConfig as
|
|
7
|
-
import { useFormData as c } from "./
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
1
|
+
import { useEngine as r } from "./use-engine.js";
|
|
2
|
+
import { useFieldState as m } from "./use-field-state.js";
|
|
3
|
+
import { useFieldValidator as f } from "./use-field-validator.js";
|
|
4
|
+
import { useFieldValue as s } from "./use-field-value.js";
|
|
5
|
+
import { useForm as a } from "./use-form.js";
|
|
6
|
+
import { useFormConfig as l } from "./use-form-config.js";
|
|
7
|
+
import { useFormData as c } from "./use-form-data.js";
|
|
8
|
+
import { useFormSubmitting as h } from "./use-form-submitting.js";
|
|
9
|
+
import { useWatch as W } from "./use-watch.js";
|
|
10
|
+
import { useWatchAll as S } from "./use-watch-all.js";
|
|
11
|
+
import { useWatchMultiple as b } from "./use-watch-multiple.js";
|
|
12
|
+
import { useWatchState as C } from "./use-watch-state.js";
|
|
12
13
|
export {
|
|
13
14
|
r as useEngine,
|
|
14
15
|
m as useFieldState,
|
|
15
16
|
f as useFieldValidator,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
s as useFieldValue,
|
|
18
|
+
a as useForm,
|
|
19
|
+
l as useFormConfig,
|
|
19
20
|
c as useFormData,
|
|
20
|
-
h as
|
|
21
|
-
|
|
22
|
-
S as
|
|
23
|
-
|
|
21
|
+
h as useFormSubmitting,
|
|
22
|
+
W as useWatch,
|
|
23
|
+
S as useWatchAll,
|
|
24
|
+
b as useWatchMultiple,
|
|
25
|
+
C as useWatchState
|
|
24
26
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useSyncExternalStore as r } from "react";
|
|
2
|
+
import { useNexusContext as n } from "../contexts/nexus-context.js";
|
|
3
|
+
function u(e) {
|
|
4
|
+
const { engine: t } = n();
|
|
5
|
+
return r(
|
|
6
|
+
(i) => t.subscribeField(e, i),
|
|
7
|
+
() => t.getFieldVersion(e),
|
|
8
|
+
() => t.getFieldVersion(e)
|
|
9
|
+
), t.getFieldState(e);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
u as useFieldState
|
|
13
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { NexusFormInstance } from '@xbeeant/form-engine';
|
|
2
|
+
export type FieldValidator = (value: unknown, formData: Record<string, unknown>) => string[] | Promise<string[]>;
|
|
3
|
+
export interface UseFieldValidatorOptions {
|
|
4
|
+
/**
|
|
5
|
+
* 依赖字段路径列表。这些字段变化时自动对目标字段重校验,
|
|
6
|
+
* 实现「组件内注册的跨字段校验」与依赖字段的实时联动
|
|
7
|
+
* (等价于 schema 中 validate 表达式的依赖图联动)。
|
|
8
|
+
*/
|
|
9
|
+
dependsOn?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* 校验器闭包依赖的组件 state(useEffect 语义)。
|
|
12
|
+
* 任意依赖值变化时,校验器会重新注册,新闭包捕获最新的组件 state,
|
|
13
|
+
* 保证校验逻辑读到的是当前渲染的 state,而不是注册时刻的陈旧值。
|
|
14
|
+
*
|
|
15
|
+
* 用法:
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const [strict, setStrict] = useState(false);
|
|
18
|
+
* useFieldValidator(form, dataPath, (val, formData) => {
|
|
19
|
+
* if (strict && val && val !== formData.password) { ... }
|
|
20
|
+
* }, { deps: [strict] });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
deps?: ReadonlyArray<unknown>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 在 widget 组件内注册字段校验规则
|
|
27
|
+
*
|
|
28
|
+
* - 挂载时调用 form.registerValidator(path, validator)
|
|
29
|
+
* - 卸载时调用 form.unregisterValidator 清理,避免校验器累积
|
|
30
|
+
* - validator 通过 ref 持有最新闭包;deps 变化时 effect 重跑,
|
|
31
|
+
* 重新注册捕获最新组件 state 的新闭包(useEffect 语义),
|
|
32
|
+
* 校验逻辑总能读到当前渲染的组件 state
|
|
33
|
+
* - 传入 dependsOn 时,订阅依赖字段变化并实时重校验目标字段
|
|
34
|
+
*
|
|
35
|
+
* @param form - 表单实例(widget 的 props.form)
|
|
36
|
+
* @param path - 字段路径(widget 的 props.dataPath)
|
|
37
|
+
* @param validator - 校验函数,返回错误消息数组(空数组 = 通过)
|
|
38
|
+
* @param options - 配置(dependsOn 依赖字段联动 / deps 闭包依赖的组件 state)
|
|
39
|
+
*/
|
|
40
|
+
export declare function useFieldValidator(form: NexusFormInstance | undefined, path: string | undefined, validator: FieldValidator, options?: UseFieldValidatorOptions): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useRef as o, useEffect as f } from "react";
|
|
2
|
+
import { useNexusContext as b } from "../contexts/nexus-context.js";
|
|
3
|
+
function R(r, e, c, s) {
|
|
4
|
+
const { engine: i } = b(), d = o(c);
|
|
5
|
+
d.current = c;
|
|
6
|
+
const t = o(s?.dependsOn);
|
|
7
|
+
t.current = s?.dependsOn;
|
|
8
|
+
const l = s?.deps;
|
|
9
|
+
f(() => {
|
|
10
|
+
if (!r || !e)
|
|
11
|
+
return;
|
|
12
|
+
const n = d.current;
|
|
13
|
+
return r.registerValidator(e, n), () => {
|
|
14
|
+
r.unregisterValidator(e, n);
|
|
15
|
+
};
|
|
16
|
+
}, [r, e, ...l ?? []]), f(() => {
|
|
17
|
+
if (!e || !t.current || t.current.length === 0)
|
|
18
|
+
return;
|
|
19
|
+
const n = i;
|
|
20
|
+
if (!n)
|
|
21
|
+
return;
|
|
22
|
+
const g = e, a = t.current.map(
|
|
23
|
+
(u) => n.subscribeField(u, () => {
|
|
24
|
+
r?.revalidateField(g);
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
return () => {
|
|
28
|
+
for (const u of a)
|
|
29
|
+
u();
|
|
30
|
+
};
|
|
31
|
+
}, [i, r, e]);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
R as useFieldValidator
|
|
35
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useSyncExternalStore as r } from "react";
|
|
2
|
+
import { useEngine as o } from "./use-engine.js";
|
|
3
|
+
function t(e) {
|
|
4
|
+
const i = o();
|
|
5
|
+
return r(
|
|
6
|
+
(n) => i.subscribeField(e, n),
|
|
7
|
+
() => i.getFieldVersion(e),
|
|
8
|
+
() => i.getFieldVersion(e)
|
|
9
|
+
), i.getFieldValue(e);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
t as useFieldValue
|
|
13
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useSyncExternalStore as n, useMemo as r } from "react";
|
|
2
|
+
import { useEngine as s } from "./use-engine.js";
|
|
3
|
+
function m() {
|
|
4
|
+
const e = s(), t = n(
|
|
5
|
+
(o) => e.subscribeStore(o),
|
|
6
|
+
() => e.getSnapshot(),
|
|
7
|
+
() => e.getSnapshot()
|
|
8
|
+
);
|
|
9
|
+
return r(() => e.getFormData(), [e, t]);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
m as useFormData
|
|
13
|
+
};
|