@schemx/vue 1.0.0-next.1 → 1.0.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -44
- package/dist/analyze.html +1 -1
- package/dist/bridge/fieldBridge.d.ts +23 -0
- package/dist/bridge/fieldBridge.d.ts.map +1 -0
- package/dist/bridge/formBridge.d.ts +81 -0
- package/dist/bridge/formBridge.d.ts.map +1 -0
- package/dist/bridge/formFacade.d.ts +65 -0
- package/dist/bridge/formFacade.d.ts.map +1 -0
- package/dist/bridge/helpers.d.ts +31 -0
- package/dist/bridge/helpers.d.ts.map +1 -0
- package/dist/bridge/index.d.ts +11 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/types.d.ts +109 -0
- package/dist/bridge/types.d.ts.map +1 -0
- package/dist/components/Button/index.d.ts +3 -0
- package/dist/components/Button/index.d.ts.map +1 -0
- package/dist/components/Button/index.vue.d.ts +30 -0
- package/dist/components/Button/index.vue.d.ts.map +1 -0
- package/dist/components/Button/types.d.ts +21 -0
- package/dist/components/Button/types.d.ts.map +1 -0
- package/dist/components/FormItem/index.d.ts +1 -1
- package/dist/components/FormItem/index.d.ts.map +1 -1
- package/dist/config/appConfig.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/provideFormContext.d.ts +4 -3
- package/dist/hooks/provideFormContext.d.ts.map +1 -1
- package/dist/hooks/useField.d.ts +3 -29
- package/dist/hooks/useField.d.ts.map +1 -1
- package/dist/hooks/useForm.d.ts +3 -2
- package/dist/hooks/useForm.d.ts.map +1 -1
- package/dist/hooks/useFormSelector.d.ts +38 -0
- package/dist/hooks/useFormSelector.d.ts.map +1 -0
- package/dist/hooks/useViewSchemas.d.ts +23 -3
- package/dist/hooks/useViewSchemas.d.ts.map +1 -1
- package/dist/hooks/useWatch.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +614 -109
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/field.d.ts +1 -1
- package/dist/types/form.d.ts +33 -1
- package/dist/types/form.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,264 @@
|
|
|
1
1
|
import "./style.css";
|
|
2
|
-
import { getCurrentInstance, inject, onScopeDispose, provide,
|
|
2
|
+
import { shallowRef, getCurrentInstance, inject, onScopeDispose, provide, computed, onUnmounted, ref, onMounted, watchEffect, watch, readonly, defineComponent, createVNode, h, createTextVNode, mergeProps, useAttrs, openBlock, createElementBlock, unref, renderSlot, createCommentVNode, createStaticVNode, Fragment, toDisplayString, useSlots, reactive, normalizeClass, normalizeStyle, renderList, createBlock, createSlots, withCtx } from "vue";
|
|
3
3
|
import { createValidationRuleRegistry, mergeSchemxConfig, createForm, createField, createWatch, isViewGroupSchema, isSchemxViewFieldSchema, isSchemxSchemas, defaultSchemxConfigKeys } from "@schemx/core";
|
|
4
4
|
export * from "@schemx/core";
|
|
5
5
|
import classnames from "classnames";
|
|
6
|
+
import { createFormStateAdapter, createRendererRegistry } from "@schemx/core/adapter";
|
|
6
7
|
import { pick } from "es-toolkit";
|
|
7
|
-
|
|
8
|
+
function createVueShallowRef(value) {
|
|
9
|
+
return shallowRef(value);
|
|
10
|
+
}
|
|
11
|
+
function areStringListsEqual(previous, next) {
|
|
12
|
+
return previous.length === next.length && previous.every((value, index) => value === next[index]);
|
|
13
|
+
}
|
|
14
|
+
function getVueFieldBridge(bridge, name) {
|
|
15
|
+
const source = bridge.stateAdapter.field(name);
|
|
16
|
+
const cachedBridge = bridge.fieldBridges.get(source);
|
|
17
|
+
if (cachedBridge) {
|
|
18
|
+
return cachedBridge;
|
|
19
|
+
}
|
|
20
|
+
const snapshot = source.getSnapshot();
|
|
21
|
+
const value = createVueShallowRef(
|
|
22
|
+
snapshot.value
|
|
23
|
+
);
|
|
24
|
+
const errors = createVueShallowRef(snapshot.errors);
|
|
25
|
+
const touched = createVueShallowRef(snapshot.touched);
|
|
26
|
+
const pending = createVueShallowRef(snapshot.pending);
|
|
27
|
+
const updateFieldRefs = () => {
|
|
28
|
+
const nextSnapshot = source.getSnapshot();
|
|
29
|
+
if (!Object.is(value.value, nextSnapshot.value)) {
|
|
30
|
+
value.value = nextSnapshot.value;
|
|
31
|
+
}
|
|
32
|
+
if (!areStringListsEqual(errors.value, nextSnapshot.errors)) {
|
|
33
|
+
errors.value = nextSnapshot.errors;
|
|
34
|
+
}
|
|
35
|
+
if (touched.value !== nextSnapshot.touched) {
|
|
36
|
+
touched.value = nextSnapshot.touched;
|
|
37
|
+
}
|
|
38
|
+
if (pending.value !== nextSnapshot.pending) {
|
|
39
|
+
pending.value = nextSnapshot.pending;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const unsubscribe = source.subscribe(updateFieldRefs);
|
|
43
|
+
const dispose = () => {
|
|
44
|
+
unsubscribe();
|
|
45
|
+
};
|
|
46
|
+
const fieldBridge = {
|
|
47
|
+
source,
|
|
48
|
+
value,
|
|
49
|
+
errors,
|
|
50
|
+
touched,
|
|
51
|
+
pending,
|
|
52
|
+
dispose
|
|
53
|
+
};
|
|
54
|
+
bridge.fieldBridges.set(source, fieldBridge);
|
|
55
|
+
return fieldBridge;
|
|
56
|
+
}
|
|
57
|
+
function createVueFormFacade(form, dependencies) {
|
|
58
|
+
let destroyed = false;
|
|
59
|
+
const getFieldValue = (name) => {
|
|
60
|
+
if (!destroyed) {
|
|
61
|
+
const bridge = dependencies.getFormBridge(form);
|
|
62
|
+
void dependencies.getFieldBridge(bridge, name).value.value;
|
|
63
|
+
}
|
|
64
|
+
return form.getFieldValue(name);
|
|
65
|
+
};
|
|
66
|
+
const getFieldErrors = (name) => {
|
|
67
|
+
if (!destroyed) {
|
|
68
|
+
const bridge = dependencies.getFormBridge(form);
|
|
69
|
+
void dependencies.getFieldBridge(bridge, name).errors.value;
|
|
70
|
+
}
|
|
71
|
+
return form.getFieldErrors(name);
|
|
72
|
+
};
|
|
73
|
+
const isFieldTouched = (name) => {
|
|
74
|
+
if (!destroyed) {
|
|
75
|
+
const bridge = dependencies.getFormBridge(form);
|
|
76
|
+
void dependencies.getFieldBridge(bridge, name).touched.value;
|
|
77
|
+
}
|
|
78
|
+
return form.isFieldTouched(name);
|
|
79
|
+
};
|
|
80
|
+
const isFieldPending = (name) => {
|
|
81
|
+
if (!destroyed) {
|
|
82
|
+
const bridge = dependencies.getFormBridge(form);
|
|
83
|
+
void dependencies.getFieldBridge(bridge, name).pending.value;
|
|
84
|
+
}
|
|
85
|
+
return form.isFieldPending(name);
|
|
86
|
+
};
|
|
87
|
+
const getFieldsValue = (names) => {
|
|
88
|
+
if (!destroyed) {
|
|
89
|
+
const bridge = dependencies.getFormBridge(form);
|
|
90
|
+
if (names === void 0) {
|
|
91
|
+
void bridge.values.value;
|
|
92
|
+
} else {
|
|
93
|
+
for (const name of names) {
|
|
94
|
+
void dependencies.getFieldBridge(bridge, name).value.value;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return form.getFieldsValue(names);
|
|
99
|
+
};
|
|
100
|
+
const getTouchedFields = () => {
|
|
101
|
+
if (!destroyed) {
|
|
102
|
+
const bridge = dependencies.getFormBridge(form);
|
|
103
|
+
void bridge.touchedFields.value;
|
|
104
|
+
}
|
|
105
|
+
return form.getTouchedFields();
|
|
106
|
+
};
|
|
107
|
+
const getPendingFields = () => {
|
|
108
|
+
if (!destroyed) {
|
|
109
|
+
const bridge = dependencies.getFormBridge(form);
|
|
110
|
+
void bridge.pendingFields.value;
|
|
111
|
+
}
|
|
112
|
+
return form.getPendingFields();
|
|
113
|
+
};
|
|
114
|
+
const isLoading = () => {
|
|
115
|
+
if (!destroyed) {
|
|
116
|
+
const bridge = dependencies.getFormBridge(form);
|
|
117
|
+
void bridge.loading.value;
|
|
118
|
+
}
|
|
119
|
+
return form.isLoading();
|
|
120
|
+
};
|
|
121
|
+
const destroy = () => {
|
|
122
|
+
if (destroyed) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
destroyed = true;
|
|
126
|
+
const bridge = dependencies.getCachedFormBridge(form);
|
|
127
|
+
if (bridge) {
|
|
128
|
+
dependencies.disposeFormBridge(bridge);
|
|
129
|
+
}
|
|
130
|
+
form.destroy();
|
|
131
|
+
};
|
|
132
|
+
return {
|
|
133
|
+
...form,
|
|
134
|
+
getFieldValue,
|
|
135
|
+
getFieldErrors,
|
|
136
|
+
isFieldTouched,
|
|
137
|
+
isFieldPending,
|
|
138
|
+
getFieldsValue,
|
|
139
|
+
getTouchedFields,
|
|
140
|
+
getPendingFields,
|
|
141
|
+
isLoading,
|
|
142
|
+
destroy
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const formBridgeCache = /* @__PURE__ */ new WeakMap();
|
|
146
|
+
const formFacadeCache = /* @__PURE__ */ new WeakMap();
|
|
147
|
+
const facadeCoreFormCache = /* @__PURE__ */ new WeakMap();
|
|
148
|
+
function getCoreForm(form) {
|
|
149
|
+
const coreForm = facadeCoreFormCache.get(form);
|
|
150
|
+
return coreForm ?? form;
|
|
151
|
+
}
|
|
152
|
+
function getVueFormBridge(form) {
|
|
153
|
+
const coreForm = getCoreForm(form);
|
|
154
|
+
const cachedBridge = formBridgeCache.get(coreForm);
|
|
155
|
+
if (cachedBridge) {
|
|
156
|
+
return cachedBridge;
|
|
157
|
+
}
|
|
158
|
+
const bridge = createVueFormBridge(coreForm);
|
|
159
|
+
formBridgeCache.set(coreForm, bridge);
|
|
160
|
+
return bridge;
|
|
161
|
+
}
|
|
162
|
+
function getVueFormFacade(form) {
|
|
163
|
+
const coreForm = getCoreForm(form);
|
|
164
|
+
const cachedFacade = formFacadeCache.get(coreForm);
|
|
165
|
+
if (cachedFacade) {
|
|
166
|
+
return cachedFacade;
|
|
167
|
+
}
|
|
168
|
+
const facade = createVueFormFacade(coreForm, {
|
|
169
|
+
getFormBridge: (bridgeForm) => getVueFormBridge(bridgeForm),
|
|
170
|
+
getFieldBridge: (bridge, name) => getVueFieldBridge(bridge, name),
|
|
171
|
+
getCachedFormBridge: (bridgeForm) => {
|
|
172
|
+
const bridge = formBridgeCache.get(bridgeForm);
|
|
173
|
+
return bridge;
|
|
174
|
+
},
|
|
175
|
+
disposeFormBridge: (bridge) => disposeVueFormBridge(bridge)
|
|
176
|
+
});
|
|
177
|
+
formFacadeCache.set(coreForm, facade);
|
|
178
|
+
facadeCoreFormCache.set(facade, coreForm);
|
|
179
|
+
return facade;
|
|
180
|
+
}
|
|
181
|
+
function retainVueFormBridge(bridge) {
|
|
182
|
+
if (bridge.destroyed) {
|
|
183
|
+
return () => {
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
bridge.refCount++;
|
|
187
|
+
let released = false;
|
|
188
|
+
return () => {
|
|
189
|
+
if (released || bridge.destroyed) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
released = true;
|
|
193
|
+
bridge.refCount--;
|
|
194
|
+
if (bridge.refCount === 0) {
|
|
195
|
+
disposeVueFormBridge(bridge);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function disposeVueFormBridge(bridge) {
|
|
200
|
+
if (bridge.destroyed) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
bridge.destroyed = true;
|
|
204
|
+
bridge.refCount = 0;
|
|
205
|
+
bridge.unsubscribe();
|
|
206
|
+
for (const fieldBridge of bridge.fieldBridges.values()) {
|
|
207
|
+
fieldBridge.dispose();
|
|
208
|
+
}
|
|
209
|
+
bridge.fieldBridges.clear();
|
|
210
|
+
bridge.stateAdapter.dispose();
|
|
211
|
+
formBridgeCache.delete(bridge.form);
|
|
212
|
+
}
|
|
213
|
+
function createVueFormBridge(form) {
|
|
214
|
+
const stateAdapter = createFormStateAdapter(form);
|
|
215
|
+
const values = createVueShallowRef(stateAdapter.values.getSnapshot());
|
|
216
|
+
const touchedFields = createVueShallowRef(
|
|
217
|
+
stateAdapter.touchedFields.getSnapshot()
|
|
218
|
+
);
|
|
219
|
+
const pendingFields = createVueShallowRef(
|
|
220
|
+
stateAdapter.pendingFields.getSnapshot()
|
|
221
|
+
);
|
|
222
|
+
const loading = createVueShallowRef(stateAdapter.loading.getSnapshot());
|
|
223
|
+
const fieldBridges = /* @__PURE__ */ new Map();
|
|
224
|
+
const syncValues = () => {
|
|
225
|
+
values.value = stateAdapter.values.getSnapshot();
|
|
226
|
+
};
|
|
227
|
+
const syncTouchedFields = () => {
|
|
228
|
+
touchedFields.value = stateAdapter.touchedFields.getSnapshot();
|
|
229
|
+
};
|
|
230
|
+
const syncPendingFields = () => {
|
|
231
|
+
pendingFields.value = stateAdapter.pendingFields.getSnapshot();
|
|
232
|
+
};
|
|
233
|
+
const syncLoading = () => {
|
|
234
|
+
loading.value = stateAdapter.loading.getSnapshot();
|
|
235
|
+
};
|
|
236
|
+
const unsubscribeValues = stateAdapter.values.subscribe(syncValues);
|
|
237
|
+
const unsubscribeTouchedFields = stateAdapter.touchedFields.subscribe(syncTouchedFields);
|
|
238
|
+
const unsubscribePendingFields = stateAdapter.pendingFields.subscribe(syncPendingFields);
|
|
239
|
+
const unsubscribeLoading = stateAdapter.loading.subscribe(syncLoading);
|
|
240
|
+
const unsubscribe = () => {
|
|
241
|
+
unsubscribeValues();
|
|
242
|
+
unsubscribeTouchedFields();
|
|
243
|
+
unsubscribePendingFields();
|
|
244
|
+
unsubscribeLoading();
|
|
245
|
+
};
|
|
246
|
+
const facade = getVueFormFacade(form);
|
|
247
|
+
const bridge = {
|
|
248
|
+
form,
|
|
249
|
+
stateAdapter,
|
|
250
|
+
values,
|
|
251
|
+
touchedFields,
|
|
252
|
+
pendingFields,
|
|
253
|
+
loading,
|
|
254
|
+
fieldBridges,
|
|
255
|
+
refCount: 0,
|
|
256
|
+
destroyed: false,
|
|
257
|
+
unsubscribe,
|
|
258
|
+
facade
|
|
259
|
+
};
|
|
260
|
+
return bridge;
|
|
261
|
+
}
|
|
8
262
|
const SCHEMX_APP_CONFIG_KEY = Symbol("schemx:app-config");
|
|
9
263
|
const EMPTY_SCHEMX_CONFIG = Object.freeze({
|
|
10
264
|
schemaConfig: Object.freeze({}),
|
|
@@ -15,12 +269,22 @@ function normalizeSchemxAppConfig(config) {
|
|
|
15
269
|
const validatorAdapters = Object.freeze([...config.validatorAdapters ?? []]);
|
|
16
270
|
return Object.freeze({
|
|
17
271
|
schemaConfig,
|
|
272
|
+
rendererProps: normalizeRendererProps(config.rendererProps),
|
|
18
273
|
validatorAdapters,
|
|
19
274
|
defaultRendererType: config.defaultRendererType,
|
|
20
275
|
rendererRegistry: config.rendererRegistry,
|
|
21
276
|
validationRuleRegistry: config.validationRuleRegistry
|
|
22
277
|
});
|
|
23
278
|
}
|
|
279
|
+
function normalizeRendererProps(source) {
|
|
280
|
+
if (source === void 0) {
|
|
281
|
+
return void 0;
|
|
282
|
+
}
|
|
283
|
+
const entries = Object.entries(source).map(([type, props]) => {
|
|
284
|
+
return [type, props === void 0 ? void 0 : Object.freeze({ ...props })];
|
|
285
|
+
});
|
|
286
|
+
return Object.freeze(Object.fromEntries(entries));
|
|
287
|
+
}
|
|
24
288
|
function provideSchemxAppConfig(app, config = {}) {
|
|
25
289
|
const normalizedConfig = normalizeSchemxAppConfig(config);
|
|
26
290
|
app.provide(SCHEMX_APP_CONFIG_KEY, normalizedConfig);
|
|
@@ -36,6 +300,7 @@ const validationRuleRegistry = createValidationRuleRegistry();
|
|
|
36
300
|
function useForm(options = {}) {
|
|
37
301
|
const configuredOptions = mergeSchemxConfig(
|
|
38
302
|
getUseFormSchemxConfig(options),
|
|
303
|
+
// App 安装配置以 Values 存储;在 useForm 边界关联到当前 TValues。
|
|
39
304
|
getSchemxAppConfig(),
|
|
40
305
|
{
|
|
41
306
|
rendererRegistry,
|
|
@@ -47,14 +312,18 @@ function useForm(options = {}) {
|
|
|
47
312
|
...configuredOptions
|
|
48
313
|
};
|
|
49
314
|
const instance = createForm(mergedOptions);
|
|
315
|
+
const form = getVueFormFacade(instance);
|
|
316
|
+
const releaseBridge = retainVueFormBridge(getVueFormBridge(instance));
|
|
50
317
|
onScopeDispose(() => {
|
|
51
|
-
|
|
318
|
+
releaseBridge();
|
|
319
|
+
form.destroy();
|
|
52
320
|
});
|
|
53
|
-
return
|
|
321
|
+
return form;
|
|
54
322
|
}
|
|
55
323
|
function getUseFormSchemxConfig(options) {
|
|
56
324
|
const {
|
|
57
325
|
schemaConfig = {},
|
|
326
|
+
rendererProps = void 0,
|
|
58
327
|
validatorAdapters = [],
|
|
59
328
|
defaultRendererType = void 0,
|
|
60
329
|
rendererRegistry: rendererRegistry2 = void 0,
|
|
@@ -62,6 +331,7 @@ function getUseFormSchemxConfig(options) {
|
|
|
62
331
|
} = options;
|
|
63
332
|
return {
|
|
64
333
|
schemaConfig,
|
|
334
|
+
rendererProps,
|
|
65
335
|
defaultRendererType,
|
|
66
336
|
rendererRegistry: rendererRegistry2,
|
|
67
337
|
validationRuleRegistry: validationRuleRegistry2,
|
|
@@ -70,7 +340,11 @@ function getUseFormSchemxConfig(options) {
|
|
|
70
340
|
}
|
|
71
341
|
const SCHEMX_FORM_INSTANCE_KEY = Symbol("schemx:instance");
|
|
72
342
|
function createFormContext(instance) {
|
|
73
|
-
|
|
343
|
+
const form = getVueFormFacade(instance);
|
|
344
|
+
const releaseBridge = retainVueFormBridge(getVueFormBridge(form));
|
|
345
|
+
provide(SCHEMX_FORM_INSTANCE_KEY, form);
|
|
346
|
+
onScopeDispose(releaseBridge);
|
|
347
|
+
return form;
|
|
74
348
|
}
|
|
75
349
|
function useFormContext() {
|
|
76
350
|
const instance = inject(SCHEMX_FORM_INSTANCE_KEY, null);
|
|
@@ -81,63 +355,37 @@ function useFormContext() {
|
|
|
81
355
|
}
|
|
82
356
|
return instance;
|
|
83
357
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
void fieldValue.value;
|
|
98
|
-
return field.isTouched();
|
|
99
|
-
});
|
|
100
|
-
const pending = computed(() => fieldPending.value);
|
|
101
|
-
const result = {
|
|
358
|
+
function createFieldHook(form, name, fieldBridge) {
|
|
359
|
+
const coreForm = getCoreForm(form);
|
|
360
|
+
const coreField = createField(coreForm, name);
|
|
361
|
+
const errors = computed(() => fieldBridge.errors.value);
|
|
362
|
+
const dirty = computed(() => fieldBridge.touched.value);
|
|
363
|
+
const pending = computed(() => fieldBridge.pending.value);
|
|
364
|
+
const getValue = () => fieldBridge.value.value;
|
|
365
|
+
const getErrors = () => fieldBridge.errors.value;
|
|
366
|
+
const isTouched = () => fieldBridge.touched.value;
|
|
367
|
+
const isPending = () => fieldBridge.pending.value;
|
|
368
|
+
const getValues = () => form.getFieldsValue();
|
|
369
|
+
return {
|
|
370
|
+
...coreField,
|
|
102
371
|
name,
|
|
103
|
-
value:
|
|
372
|
+
value: fieldBridge.value,
|
|
104
373
|
errors,
|
|
105
374
|
dirty,
|
|
106
375
|
pending,
|
|
107
|
-
|
|
108
|
-
|
|
376
|
+
getValue,
|
|
377
|
+
getErrors,
|
|
378
|
+
isTouched,
|
|
379
|
+
isPending,
|
|
380
|
+
getValues
|
|
109
381
|
};
|
|
110
|
-
return { result, dispose };
|
|
111
382
|
}
|
|
112
383
|
const useField = (name) => {
|
|
113
384
|
const form = useFormContext();
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
fieldHookCache.set(form, formCache);
|
|
119
|
-
}
|
|
120
|
-
const cachedEntry = formCache.get(key);
|
|
121
|
-
let activeEntry;
|
|
122
|
-
if (cachedEntry) {
|
|
123
|
-
cachedEntry.refCount++;
|
|
124
|
-
activeEntry = cachedEntry;
|
|
125
|
-
} else {
|
|
126
|
-
const { result, dispose } = createFieldHook(form, name);
|
|
127
|
-
activeEntry = {
|
|
128
|
-
refCount: 1,
|
|
129
|
-
result,
|
|
130
|
-
dispose
|
|
131
|
-
};
|
|
132
|
-
formCache.set(key, activeEntry);
|
|
133
|
-
}
|
|
134
|
-
onUnmounted(() => {
|
|
135
|
-
if (--activeEntry.refCount <= 0) {
|
|
136
|
-
activeEntry.dispose();
|
|
137
|
-
formCache.delete(key);
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
return activeEntry.result;
|
|
385
|
+
const coreForm = getCoreForm(form);
|
|
386
|
+
const formBridge = getVueFormBridge(coreForm);
|
|
387
|
+
const fieldBridge = getVueFieldBridge(formBridge, name);
|
|
388
|
+
return createFieldHook(form, name, fieldBridge);
|
|
141
389
|
};
|
|
142
390
|
const SCHEMX_FORM_FIELD_KEY = Symbol(
|
|
143
391
|
"schemx:field"
|
|
@@ -157,7 +405,7 @@ function useFieldContext() {
|
|
|
157
405
|
function useWatch(nameOrNamesOrCallback, callbackOrOptions, maybeOptions) {
|
|
158
406
|
const form = useFormContext();
|
|
159
407
|
const dispose = createWatch(
|
|
160
|
-
form,
|
|
408
|
+
getCoreForm(form),
|
|
161
409
|
nameOrNamesOrCallback,
|
|
162
410
|
callbackOrOptions,
|
|
163
411
|
maybeOptions
|
|
@@ -301,15 +549,89 @@ function useStableRef(factory) {
|
|
|
301
549
|
});
|
|
302
550
|
return stableRef;
|
|
303
551
|
}
|
|
552
|
+
const viewSchemaBridgeCache = /* @__PURE__ */ new WeakMap();
|
|
304
553
|
function useViewSchemas(form) {
|
|
554
|
+
const bridge = acquireViewSchemaBridge(getCoreForm(form));
|
|
555
|
+
return bridge.viewSchemas;
|
|
556
|
+
}
|
|
557
|
+
function useViewSchema(form, getKey) {
|
|
558
|
+
const bridge = acquireViewSchemaBridge(getCoreForm(form));
|
|
559
|
+
return computed(() => bridge.schemasByKey.value.get(getKey()));
|
|
560
|
+
}
|
|
561
|
+
function createViewSchemaBridge(form) {
|
|
305
562
|
const viewSchemas = shallowRef(
|
|
306
563
|
form.getViewSchemas()
|
|
307
564
|
);
|
|
308
|
-
const
|
|
309
|
-
viewSchemas.value
|
|
565
|
+
const schemasByKey = computed(() => {
|
|
566
|
+
return createViewSchemaIndex(viewSchemas.value);
|
|
567
|
+
});
|
|
568
|
+
const unsubscribe = form.subscribeViewSchemas(
|
|
569
|
+
/**
|
|
570
|
+
* 接收 Core 发布的完整列表并替换共享引用,以保留更新边界。
|
|
571
|
+
*
|
|
572
|
+
* @param nextSchemas - Core 计算出的最新 ViewSchema 列表。
|
|
573
|
+
*/
|
|
574
|
+
(nextSchemas) => {
|
|
575
|
+
viewSchemas.value = nextSchemas;
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
return {
|
|
579
|
+
refCount: 0,
|
|
580
|
+
schemasByKey,
|
|
581
|
+
unsubscribe,
|
|
582
|
+
viewSchemas
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
function acquireViewSchemaBridge(form) {
|
|
586
|
+
const cachedBridge = viewSchemaBridgeCache.get(form);
|
|
587
|
+
const bridge = cachedBridge ?? createViewSchemaBridge(form);
|
|
588
|
+
if (!cachedBridge) {
|
|
589
|
+
viewSchemaBridgeCache.set(form, bridge);
|
|
590
|
+
}
|
|
591
|
+
bridge.refCount++;
|
|
592
|
+
onScopeDispose(() => {
|
|
593
|
+
bridge.refCount--;
|
|
594
|
+
if (bridge.refCount > 0) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
bridge.unsubscribe();
|
|
598
|
+
viewSchemaBridgeCache.delete(form);
|
|
599
|
+
});
|
|
600
|
+
return bridge;
|
|
601
|
+
}
|
|
602
|
+
function createViewSchemaIndex(viewSchemas) {
|
|
603
|
+
const schemasByKey = /* @__PURE__ */ new Map();
|
|
604
|
+
const appendSchemas = (schemas) => {
|
|
605
|
+
for (const schema of schemas) {
|
|
606
|
+
schemasByKey.set(schema.key, schema);
|
|
607
|
+
if (isViewGroupSchema(schema)) {
|
|
608
|
+
appendSchemas(schema.children);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
appendSchemas(viewSchemas);
|
|
613
|
+
return schemasByKey;
|
|
614
|
+
}
|
|
615
|
+
function useFormSelector(form, selector, options = {}) {
|
|
616
|
+
const bridge = getVueFormBridge(getCoreForm(form));
|
|
617
|
+
const releaseBridge = retainVueFormBridge(bridge);
|
|
618
|
+
const selected = shallowRef(selector(bridge.values.value));
|
|
619
|
+
const equals = options.equals ?? Object.is;
|
|
620
|
+
const stop = watch(
|
|
621
|
+
bridge.values,
|
|
622
|
+
(values) => {
|
|
623
|
+
const next = selector(values);
|
|
624
|
+
if (!equals(selected.value, next)) {
|
|
625
|
+
selected.value = next;
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
{ flush: "sync" }
|
|
629
|
+
);
|
|
630
|
+
onScopeDispose(() => {
|
|
631
|
+
stop();
|
|
632
|
+
releaseBridge();
|
|
310
633
|
});
|
|
311
|
-
|
|
312
|
-
return viewSchemas;
|
|
634
|
+
return readonly(selected);
|
|
313
635
|
}
|
|
314
636
|
function isValidTrigger(v) {
|
|
315
637
|
if (v === void 0)
|
|
@@ -582,6 +904,12 @@ const FormItem = /* @__PURE__ */ defineComponent({
|
|
|
582
904
|
required: true
|
|
583
905
|
}
|
|
584
906
|
},
|
|
907
|
+
/**
|
|
908
|
+
* 根据 schema 类型分发字段组或字段项渲染。
|
|
909
|
+
*
|
|
910
|
+
* @param props - 当前组件的 schema 属性。
|
|
911
|
+
* @param slots - Vue setup 上下文提供的插槽集合。
|
|
912
|
+
*/
|
|
585
913
|
setup(props, {
|
|
586
914
|
slots
|
|
587
915
|
}) {
|
|
@@ -607,22 +935,22 @@ const FieldFormItem = /* @__PURE__ */ defineComponent({
|
|
|
607
935
|
required: true
|
|
608
936
|
}
|
|
609
937
|
},
|
|
938
|
+
/**
|
|
939
|
+
* 初始化字段上下文,并组合响应式 schema、校验处理器与插槽渲染器。
|
|
940
|
+
*
|
|
941
|
+
* @param props - 当前字段项的 schema 属性。
|
|
942
|
+
* @param attrs - Vue setup 上下文提供的透传属性。
|
|
943
|
+
* @param slots - Vue setup 上下文提供的插槽集合。
|
|
944
|
+
*/
|
|
610
945
|
setup(props, {
|
|
611
946
|
attrs,
|
|
612
947
|
slots
|
|
613
948
|
}) {
|
|
614
949
|
const form = useFormContext();
|
|
615
|
-
const inputSchema = props.schema;
|
|
616
|
-
const
|
|
617
|
-
const disposeSchemaEffect = form.effect(() => {
|
|
618
|
-
form.getViewSchemas();
|
|
619
|
-
schemaVersion.value++;
|
|
620
|
-
});
|
|
621
|
-
onUnmounted(disposeSchemaEffect);
|
|
950
|
+
const inputSchema = computed(() => props.schema);
|
|
951
|
+
const latestSchema = useViewSchema(form, () => inputSchema.value.key);
|
|
622
952
|
const schemaRef = computed(() => {
|
|
623
|
-
|
|
624
|
-
const latestSchema = form.getViewSchemas().find((viewSchema) => viewSchema.key === inputSchema.key);
|
|
625
|
-
return latestSchema && isSchemxViewFieldSchema(latestSchema) ? latestSchema : inputSchema;
|
|
953
|
+
return latestSchema.value && isSchemxViewFieldSchema(latestSchema.value) ? latestSchema.value : inputSchema.value;
|
|
626
954
|
});
|
|
627
955
|
const formContext = useFormConfigContext();
|
|
628
956
|
const field = useField(schemaRef.value.name);
|
|
@@ -653,28 +981,10 @@ const FieldFormItem = /* @__PURE__ */ defineComponent({
|
|
|
653
981
|
field.setValue(v);
|
|
654
982
|
};
|
|
655
983
|
const componentProps = useStableRef(() => {
|
|
656
|
-
const
|
|
657
|
-
const currentComponentProps = currentSchema.componentProps ?? {};
|
|
658
|
-
const formItemProps = {
|
|
659
|
-
name: currentSchema.name,
|
|
660
|
-
label: currentSchema.label,
|
|
661
|
-
componentType: currentSchema.componentType,
|
|
662
|
-
...currentComponentProps.formItemProps
|
|
663
|
-
};
|
|
984
|
+
const currentComponentProps = schemaRef.value.componentProps ?? {};
|
|
664
985
|
return {
|
|
665
986
|
...currentComponentProps,
|
|
666
987
|
value: field.value.value,
|
|
667
|
-
disabled: currentSchema.disabled,
|
|
668
|
-
readonly: currentSchema.readonly,
|
|
669
|
-
readonlyPlaceholder: currentSchema.readonlyPlaceholder,
|
|
670
|
-
placeholder: currentSchema.placeholder,
|
|
671
|
-
formItemProps: {
|
|
672
|
-
...formItemProps,
|
|
673
|
-
disabled: currentSchema.disabled,
|
|
674
|
-
readonly: currentSchema.readonly,
|
|
675
|
-
readonlyPlaceholder: currentSchema.readonlyPlaceholder,
|
|
676
|
-
placeholder: currentSchema.placeholder
|
|
677
|
-
},
|
|
678
988
|
onChange: handleChange,
|
|
679
989
|
onBlur: handleBlur,
|
|
680
990
|
"onUpdate:value": handleValueUpdate
|
|
@@ -722,6 +1032,65 @@ const FieldFormItem = /* @__PURE__ */ defineComponent({
|
|
|
722
1032
|
}
|
|
723
1033
|
});
|
|
724
1034
|
const FormItem$1 = FormItem;
|
|
1035
|
+
const _hoisted_1$1 = ["aria-busy", "data-loading", "disabled"];
|
|
1036
|
+
const _hoisted_2 = {
|
|
1037
|
+
key: 0,
|
|
1038
|
+
class: "schemx-button__prefix"
|
|
1039
|
+
};
|
|
1040
|
+
const _hoisted_3 = {
|
|
1041
|
+
key: 1,
|
|
1042
|
+
class: "schemx-button__loading",
|
|
1043
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1044
|
+
width: "1em",
|
|
1045
|
+
height: "1em",
|
|
1046
|
+
viewBox: "0 0 24 24",
|
|
1047
|
+
fill: "none",
|
|
1048
|
+
stroke: "currentColor",
|
|
1049
|
+
"stroke-width": "2",
|
|
1050
|
+
"stroke-linecap": "round",
|
|
1051
|
+
"stroke-linejoin": "round"
|
|
1052
|
+
};
|
|
1053
|
+
const _hoisted_4 = {
|
|
1054
|
+
key: 4,
|
|
1055
|
+
class: "schemx-button__suffix"
|
|
1056
|
+
};
|
|
1057
|
+
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
1058
|
+
...{ name: "SchemxButton", inheritAttrs: false },
|
|
1059
|
+
__name: "index",
|
|
1060
|
+
props: {
|
|
1061
|
+
loading: { type: Boolean, default: false },
|
|
1062
|
+
loadingText: { default: void 0 },
|
|
1063
|
+
disabled: { type: Boolean, default: false },
|
|
1064
|
+
size: { default: "medium" }
|
|
1065
|
+
},
|
|
1066
|
+
setup(__props) {
|
|
1067
|
+
const props = __props;
|
|
1068
|
+
const attrs = useAttrs();
|
|
1069
|
+
const isDisabled = computed(() => props.disabled || props.loading);
|
|
1070
|
+
const buttonClass = computed(() => ["schemx-button", `schemx-button--${props.size}`]);
|
|
1071
|
+
return (_ctx, _cache) => {
|
|
1072
|
+
return openBlock(), createElementBlock("button", mergeProps(unref(attrs), {
|
|
1073
|
+
class: buttonClass.value,
|
|
1074
|
+
"aria-busy": props.loading || void 0,
|
|
1075
|
+
"data-loading": props.loading || void 0,
|
|
1076
|
+
disabled: isDisabled.value
|
|
1077
|
+
}), [
|
|
1078
|
+
_ctx.$slots.prefix ? (openBlock(), createElementBlock("span", _hoisted_2, [
|
|
1079
|
+
renderSlot(_ctx.$slots, "prefix")
|
|
1080
|
+
])) : createCommentVNode("", true),
|
|
1081
|
+
props.loading ? (openBlock(), createElementBlock("svg", _hoisted_3, [..._cache[0] || (_cache[0] = [
|
|
1082
|
+
createStaticVNode('<path d="M12 2v4"></path><path d="m16.2 7.8 2.9-2.9"></path><path d="M18 12h4"></path><path d="m16.2 16.2 2.9 2.9"></path><path d="M12 18v4"></path><path d="m4.9 19.1 2.9-2.9"></path><path d="M2 12h4"></path><path d="m4.9 4.9 2.9 2.9"></path>', 8)
|
|
1083
|
+
])])) : createCommentVNode("", true),
|
|
1084
|
+
props.loading && props.loadingText ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
|
|
1085
|
+
createTextVNode(toDisplayString(props.loadingText), 1)
|
|
1086
|
+
], 64)) : renderSlot(_ctx.$slots, "default", {}, void 0, void 0, 3),
|
|
1087
|
+
_ctx.$slots.suffix ? (openBlock(), createElementBlock("span", _hoisted_4, [
|
|
1088
|
+
renderSlot(_ctx.$slots, "suffix")
|
|
1089
|
+
])) : createCommentVNode("", true)
|
|
1090
|
+
], 16, _hoisted_1$1);
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
725
1094
|
function getSectionPosition(list, currentKey) {
|
|
726
1095
|
const currentIndex = list.findIndex((item) => item.key === currentKey);
|
|
727
1096
|
if (currentIndex === -1) {
|
|
@@ -763,6 +1132,10 @@ function hasPositionItemInSection(list, startIndex, step) {
|
|
|
763
1132
|
}
|
|
764
1133
|
return false;
|
|
765
1134
|
}
|
|
1135
|
+
const _hoisted_1 = {
|
|
1136
|
+
key: 0,
|
|
1137
|
+
class: "schemx-actions"
|
|
1138
|
+
};
|
|
766
1139
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
767
1140
|
...{ name: "SchemxForm" },
|
|
768
1141
|
__name: "form",
|
|
@@ -771,8 +1144,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
771
1144
|
initialValues: { default: () => ({}) },
|
|
772
1145
|
modelValue: { default: () => ({}) },
|
|
773
1146
|
form: { default: void 0 },
|
|
1147
|
+
loading: { type: Boolean, default: void 0 },
|
|
1148
|
+
submitter: { type: [Boolean, Object], default: void 0 },
|
|
1149
|
+
resetter: { type: [Boolean, Object], default: void 0 },
|
|
774
1150
|
class: { default: "" },
|
|
775
1151
|
style: { type: [Boolean, null, String, Object, Array], default: () => ({}) },
|
|
1152
|
+
rendererProps: { default: void 0 },
|
|
776
1153
|
validatorAdapters: {},
|
|
777
1154
|
defaultRendererType: {},
|
|
778
1155
|
rendererRegistry: { default: void 0 },
|
|
@@ -780,6 +1157,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
780
1157
|
onRuleError: {},
|
|
781
1158
|
onFinish: { type: Function, default: void 0 },
|
|
782
1159
|
onFinishFailed: { type: Function, default: void 0 },
|
|
1160
|
+
onReset: { type: Function, default: void 0 },
|
|
1161
|
+
onLoadingChange: { type: Function, default: void 0 },
|
|
783
1162
|
onValuesChange: { type: Function, default: void 0 },
|
|
784
1163
|
onFieldsChange: { type: Function, default: void 0 },
|
|
785
1164
|
lifecycleHooks: {},
|
|
@@ -800,64 +1179,150 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
800
1179
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
801
1180
|
const props = __props;
|
|
802
1181
|
const emit = __emit;
|
|
1182
|
+
const slots = useSlots();
|
|
803
1183
|
const pickSchemaConfig = () => {
|
|
804
1184
|
return pick(props, defaultSchemxConfigKeys);
|
|
805
1185
|
};
|
|
806
1186
|
const formSchemaConfig = reactive(pickSchemaConfig());
|
|
807
1187
|
createFormConfigContext({ schemaConfig: formSchemaConfig });
|
|
808
|
-
const
|
|
1188
|
+
const providedForm = props.form ? props.form : useForm({
|
|
809
1189
|
schemas: props.schemas,
|
|
810
1190
|
schemaConfig: pickSchemaConfig(),
|
|
811
1191
|
initialValues: Object.keys(props.modelValue).length > 0 ? props.modelValue : props.initialValues,
|
|
1192
|
+
rendererProps: props.rendererProps,
|
|
812
1193
|
rendererRegistry: props.rendererRegistry,
|
|
813
1194
|
defaultRendererType: props.defaultRendererType,
|
|
814
1195
|
validationRuleRegistry: props.validationRuleRegistry,
|
|
815
1196
|
validatorAdapters: props.validatorAdapters,
|
|
816
|
-
|
|
1197
|
+
/**
|
|
1198
|
+
* 转发提交成功回调。
|
|
1199
|
+
*
|
|
1200
|
+
* @param values - 提交成功时的完整表单快照。
|
|
1201
|
+
*/
|
|
1202
|
+
onFinish: (values) => {
|
|
1203
|
+
var _a;
|
|
1204
|
+
return (_a = props.onFinish) == null ? void 0 : _a.call(props, values);
|
|
1205
|
+
},
|
|
1206
|
+
/**
|
|
1207
|
+
* 转发提交失败回调。
|
|
1208
|
+
*
|
|
1209
|
+
* @param errors - 提交失败时的字段错误集合。
|
|
1210
|
+
*/
|
|
1211
|
+
onFinishFailed: (errors) => {
|
|
1212
|
+
var _a;
|
|
1213
|
+
return (_a = props.onFinishFailed) == null ? void 0 : _a.call(props, errors);
|
|
1214
|
+
},
|
|
1215
|
+
/**
|
|
1216
|
+
* 转发完整表单重置回调。
|
|
1217
|
+
*/
|
|
1218
|
+
onReset: () => {
|
|
817
1219
|
var _a;
|
|
818
|
-
(_a = props.
|
|
1220
|
+
(_a = props.onReset) == null ? void 0 : _a.call(props);
|
|
819
1221
|
},
|
|
820
|
-
|
|
1222
|
+
/**
|
|
1223
|
+
* 转发 Core 发出的提交 loading 状态。
|
|
1224
|
+
*
|
|
1225
|
+
* 外部传入 Form 时不会注入该回调,保持实例的创建期边界。
|
|
1226
|
+
*
|
|
1227
|
+
* @param loading - 当前是否处于提交流程中。
|
|
1228
|
+
*/
|
|
1229
|
+
onLoadingChange: (loading) => {
|
|
821
1230
|
var _a;
|
|
822
|
-
(_a = props.
|
|
1231
|
+
(_a = props.onLoadingChange) == null ? void 0 : _a.call(props, loading);
|
|
823
1232
|
},
|
|
1233
|
+
/**
|
|
1234
|
+
* 转发值变化回调。
|
|
1235
|
+
*
|
|
1236
|
+
* @param changedValues - 本次变更涉及的字段值。
|
|
1237
|
+
* @param latestSnapshot - 变更后的完整表单快照。
|
|
1238
|
+
*/
|
|
824
1239
|
onValuesChange: (changedValues, latestSnapshot) => {
|
|
825
1240
|
var _a;
|
|
826
1241
|
(_a = props.onValuesChange) == null ? void 0 : _a.call(props, changedValues, latestSnapshot);
|
|
827
1242
|
},
|
|
1243
|
+
/**
|
|
1244
|
+
* 转发字段变化回调。
|
|
1245
|
+
*
|
|
1246
|
+
* @param changedPaths - 本次发生变化的字段路径。
|
|
1247
|
+
* @param allPaths - 当前已变更字段路径集合。
|
|
1248
|
+
*/
|
|
828
1249
|
onFieldsChange: (changedPaths, allPaths) => {
|
|
829
1250
|
var _a;
|
|
830
1251
|
(_a = props.onFieldsChange) == null ? void 0 : _a.call(props, changedPaths, allPaths);
|
|
831
1252
|
}
|
|
832
1253
|
});
|
|
833
1254
|
const isExternalForm = props.form !== void 0;
|
|
834
|
-
createFormContext(
|
|
1255
|
+
const formInstance = createFormContext(providedForm);
|
|
1256
|
+
const effectiveLoading = computed(() => props.loading ?? formInstance.isLoading());
|
|
1257
|
+
const normalizeActionConfig = (action) => action === true ? {} : action || {};
|
|
1258
|
+
const submitterConfig = computed(() => normalizeActionConfig(props.submitter));
|
|
1259
|
+
const resetterConfig = computed(() => normalizeActionConfig(props.resetter));
|
|
1260
|
+
const getButtonProps = (config) => {
|
|
1261
|
+
const buttonProps = Object.fromEntries(
|
|
1262
|
+
Object.entries(config.buttonProps ?? {}).filter(
|
|
1263
|
+
([name]) => name !== "type" && name !== "onClick"
|
|
1264
|
+
)
|
|
1265
|
+
);
|
|
1266
|
+
return buttonProps;
|
|
1267
|
+
};
|
|
1268
|
+
const submitterButtonProps = computed(() => getButtonProps(submitterConfig.value));
|
|
1269
|
+
const resetterButtonProps = computed(() => getButtonProps(resetterConfig.value));
|
|
1270
|
+
const isSubmitterVisible = computed(
|
|
1271
|
+
() => props.submitter !== false && (props.submitter !== void 0 || slots.submitter)
|
|
1272
|
+
);
|
|
1273
|
+
const isResetterVisible = computed(
|
|
1274
|
+
() => props.resetter !== false && (props.resetter !== void 0 || slots.resetter)
|
|
1275
|
+
);
|
|
1276
|
+
const isActionsVisible = computed(
|
|
1277
|
+
() => isSubmitterVisible.value || isResetterVisible.value
|
|
1278
|
+
);
|
|
1279
|
+
const fieldSlots = computed(
|
|
1280
|
+
() => Object.fromEntries(
|
|
1281
|
+
Object.entries(slots).filter(
|
|
1282
|
+
([slotName]) => slotName !== "submitter" && slotName !== "resetter"
|
|
1283
|
+
)
|
|
1284
|
+
)
|
|
1285
|
+
);
|
|
1286
|
+
const isSubmitterDisabled = computed(
|
|
1287
|
+
() => effectiveLoading.value || Boolean(submitterButtonProps.value.disabled)
|
|
1288
|
+
);
|
|
1289
|
+
const isResetterDisabled = computed(
|
|
1290
|
+
() => effectiveLoading.value || Boolean(resetterButtonProps.value.disabled)
|
|
1291
|
+
);
|
|
835
1292
|
let syncingFromModel = false;
|
|
836
1293
|
watch(
|
|
837
1294
|
() => props.modelValue,
|
|
838
1295
|
(values) => {
|
|
839
1296
|
syncingFromModel = true;
|
|
840
|
-
|
|
1297
|
+
formInstance.setFieldsValue(values);
|
|
841
1298
|
syncingFromModel = false;
|
|
842
1299
|
},
|
|
843
1300
|
{ deep: true }
|
|
844
1301
|
);
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
1302
|
+
const handleSubmit = () => formInstance.submit();
|
|
1303
|
+
const handleReset = () => {
|
|
1304
|
+
formInstance.reset();
|
|
1305
|
+
};
|
|
1306
|
+
const formValues = useFormSelector(formInstance, (values) => values);
|
|
1307
|
+
watch(
|
|
1308
|
+
formValues,
|
|
1309
|
+
(latestSnapshot) => {
|
|
1310
|
+
if (syncingFromModel)
|
|
1311
|
+
return;
|
|
1312
|
+
emit("update:modelValue", latestSnapshot);
|
|
1313
|
+
},
|
|
1314
|
+
{ flush: "sync" }
|
|
1315
|
+
);
|
|
851
1316
|
watch(
|
|
852
1317
|
() => props.schemas,
|
|
853
1318
|
(schemas) => {
|
|
854
1319
|
if (!isSchemxSchemas(schemas)) {
|
|
855
|
-
|
|
1320
|
+
formInstance.setSchemas(schemas);
|
|
856
1321
|
}
|
|
857
1322
|
},
|
|
858
1323
|
{ deep: false, immediate: !!props.form }
|
|
859
1324
|
);
|
|
860
|
-
const viewSchemas = useViewSchemas(
|
|
1325
|
+
const viewSchemas = useViewSchemas(formInstance);
|
|
861
1326
|
const getFormItemClass = (schema) => {
|
|
862
1327
|
const { isFirst, isLast } = getSectionPosition(
|
|
863
1328
|
viewSchemas.value,
|
|
@@ -872,13 +1337,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
872
1337
|
pickSchemaConfig,
|
|
873
1338
|
(nextSchemaConfig) => {
|
|
874
1339
|
Object.assign(formSchemaConfig, nextSchemaConfig);
|
|
875
|
-
|
|
1340
|
+
formInstance.updateSchemaConfig(nextSchemaConfig);
|
|
876
1341
|
},
|
|
877
1342
|
{ deep: false, immediate: isExternalForm }
|
|
878
1343
|
);
|
|
879
|
-
|
|
880
|
-
...
|
|
881
|
-
|
|
1344
|
+
const exposed = {
|
|
1345
|
+
...formInstance,
|
|
1346
|
+
submit: handleSubmit,
|
|
1347
|
+
reset: handleReset
|
|
1348
|
+
};
|
|
1349
|
+
__expose(exposed);
|
|
882
1350
|
return (_ctx, _cache) => {
|
|
883
1351
|
return openBlock(), createElementBlock("div", {
|
|
884
1352
|
class: normalizeClass(["schemx", props.class]),
|
|
@@ -890,7 +1358,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
890
1358
|
schema,
|
|
891
1359
|
class: normalizeClass(getFormItemClass(schema))
|
|
892
1360
|
}, createSlots({ _: 2 }, [
|
|
893
|
-
renderList(
|
|
1361
|
+
renderList(fieldSlots.value, (_, slotName) => {
|
|
894
1362
|
return {
|
|
895
1363
|
name: slotName,
|
|
896
1364
|
fn: withCtx((slotProps) => [
|
|
@@ -899,7 +1367,42 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
899
1367
|
};
|
|
900
1368
|
})
|
|
901
1369
|
]), 1032, ["schema", "class"]);
|
|
902
|
-
}), 128))
|
|
1370
|
+
}), 128)),
|
|
1371
|
+
isActionsVisible.value ? (openBlock(), createElementBlock("div", _hoisted_1, [
|
|
1372
|
+
isResetterVisible.value && unref(slots).resetter ? renderSlot(_ctx.$slots, "resetter", {
|
|
1373
|
+
form: unref(formInstance),
|
|
1374
|
+
loading: effectiveLoading.value,
|
|
1375
|
+
disabled: isResetterDisabled.value,
|
|
1376
|
+
reset: handleReset
|
|
1377
|
+
}, void 0, void 0, 0) : isResetterVisible.value ? (openBlock(), createBlock(unref(_sfc_main$1), mergeProps({ key: 1 }, resetterButtonProps.value, {
|
|
1378
|
+
class: "schemx-actions-button schemx-actions-button--reset",
|
|
1379
|
+
type: "button",
|
|
1380
|
+
disabled: isResetterDisabled.value,
|
|
1381
|
+
onClick: handleReset
|
|
1382
|
+
}), {
|
|
1383
|
+
default: withCtx(() => [
|
|
1384
|
+
createTextVNode(toDisplayString(resetterConfig.value.text ?? "重置"), 1)
|
|
1385
|
+
]),
|
|
1386
|
+
_: 1
|
|
1387
|
+
}, 16, ["disabled"])) : createCommentVNode("", true),
|
|
1388
|
+
isSubmitterVisible.value && unref(slots).submitter ? renderSlot(_ctx.$slots, "submitter", {
|
|
1389
|
+
form: unref(formInstance),
|
|
1390
|
+
loading: effectiveLoading.value,
|
|
1391
|
+
disabled: isSubmitterDisabled.value,
|
|
1392
|
+
submit: handleSubmit
|
|
1393
|
+
}, void 0, void 0, 2) : isSubmitterVisible.value ? (openBlock(), createBlock(unref(_sfc_main$1), mergeProps({ key: 3 }, submitterButtonProps.value, {
|
|
1394
|
+
class: "schemx-actions-button schemx-actions-button--submit",
|
|
1395
|
+
type: "button",
|
|
1396
|
+
loading: effectiveLoading.value,
|
|
1397
|
+
disabled: isSubmitterDisabled.value,
|
|
1398
|
+
onClick: handleSubmit
|
|
1399
|
+
}), {
|
|
1400
|
+
default: withCtx(() => [
|
|
1401
|
+
createTextVNode(toDisplayString(submitterConfig.value.text ?? "提交"), 1)
|
|
1402
|
+
]),
|
|
1403
|
+
_: 1
|
|
1404
|
+
}, 16, ["loading", "disabled"])) : createCommentVNode("", true)
|
|
1405
|
+
])) : createCommentVNode("", true)
|
|
903
1406
|
], 6);
|
|
904
1407
|
};
|
|
905
1408
|
}
|
|
@@ -957,6 +1460,7 @@ export {
|
|
|
957
1460
|
createFormConfigContext,
|
|
958
1461
|
createFormContext,
|
|
959
1462
|
SchemxFormExport$1 as default,
|
|
1463
|
+
getCoreForm,
|
|
960
1464
|
rendererRegistry,
|
|
961
1465
|
SchemxFormExport$1 as schemxForm,
|
|
962
1466
|
useDictionary,
|
|
@@ -965,6 +1469,7 @@ export {
|
|
|
965
1469
|
useForm,
|
|
966
1470
|
useFormConfigContext,
|
|
967
1471
|
useFormContext,
|
|
1472
|
+
useFormSelector,
|
|
968
1473
|
useStableRef,
|
|
969
1474
|
useViewSchemas,
|
|
970
1475
|
useWatch,
|