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