@lobehub/ui 5.55.0 → 5.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/es/EditableText/ControlInput.mjs +2 -2
  2. package/es/EditableText/ControlInput.mjs.map +1 -1
  3. package/es/SearchBar/SearchBar.mjs +2 -2
  4. package/es/SearchBar/SearchBar.mjs.map +1 -1
  5. package/es/base-ui/Checkbox/Checkbox.d.mts +6 -2
  6. package/es/base-ui/Checkbox/Checkbox.mjs +2 -1
  7. package/es/base-ui/Checkbox/Checkbox.mjs.map +1 -1
  8. package/es/base-ui/Checkbox/CheckboxGroup.mjs +2 -2
  9. package/es/base-ui/Checkbox/CheckboxGroup.mjs.map +1 -1
  10. package/es/base-ui/Checkbox/index.d.mts +2 -2
  11. package/es/base-ui/ColorPicker/ColorPicker.mjs +4 -4
  12. package/es/base-ui/ColorPicker/ColorPicker.mjs.map +1 -1
  13. package/es/base-ui/DatePicker/style.mjs +1 -0
  14. package/es/base-ui/DatePicker/style.mjs.map +1 -1
  15. package/es/base-ui/Form/components/FormGroup.mjs +13 -5
  16. package/es/base-ui/Form/components/FormGroup.mjs.map +1 -1
  17. package/es/base-ui/Form/index.d.mts +3 -0
  18. package/es/base-ui/Form/index.mjs +3 -0
  19. package/es/base-ui/Form/index.mjs.map +1 -1
  20. package/es/base-ui/Form/style.mjs +32 -6
  21. package/es/base-ui/Form/style.mjs.map +1 -1
  22. package/es/base-ui/FormKit/Field.d.mts +9 -0
  23. package/es/base-ui/FormKit/Field.mjs +167 -0
  24. package/es/base-ui/FormKit/Field.mjs.map +1 -0
  25. package/es/base-ui/FormKit/Form.mjs +96 -0
  26. package/es/base-ui/FormKit/Form.mjs.map +1 -0
  27. package/es/base-ui/FormKit/List.d.mts +34 -0
  28. package/es/base-ui/FormKit/List.mjs +102 -0
  29. package/es/base-ui/FormKit/List.mjs.map +1 -0
  30. package/es/base-ui/FormKit/SubmitFooter.d.mts +6 -0
  31. package/es/base-ui/FormKit/SubmitFooter.mjs +36 -0
  32. package/es/base-ui/FormKit/SubmitFooter.mjs.map +1 -0
  33. package/es/base-ui/FormKit/binding.mjs +23 -0
  34. package/es/base-ui/FormKit/binding.mjs.map +1 -0
  35. package/es/base-ui/FormKit/context.d.mts +7 -0
  36. package/es/base-ui/FormKit/context.mjs +14 -0
  37. package/es/base-ui/FormKit/context.mjs.map +1 -0
  38. package/es/base-ui/FormKit/engine/tanstack.mjs +293 -0
  39. package/es/base-ui/FormKit/engine/tanstack.mjs.map +1 -0
  40. package/es/base-ui/FormKit/engine/types.d.mts +6 -0
  41. package/es/base-ui/FormKit/index.d.mts +31 -0
  42. package/es/base-ui/FormKit/index.mjs +28 -0
  43. package/es/base-ui/FormKit/index.mjs.map +1 -0
  44. package/es/base-ui/FormKit/instance.mjs +67 -0
  45. package/es/base-ui/FormKit/instance.mjs.map +1 -0
  46. package/es/base-ui/FormKit/schema.d.mts +33 -0
  47. package/es/base-ui/FormKit/schema.mjs +23 -0
  48. package/es/base-ui/FormKit/schema.mjs.map +1 -0
  49. package/es/base-ui/FormKit/style.mjs +119 -0
  50. package/es/base-ui/FormKit/style.mjs.map +1 -0
  51. package/es/base-ui/FormKit/type.d.mts +122 -0
  52. package/es/base-ui/FormKit/useForm.d.mts +10 -0
  53. package/es/base-ui/FormKit/useForm.mjs +54 -0
  54. package/es/base-ui/FormKit/useForm.mjs.map +1 -0
  55. package/es/base-ui/FormKit/useStoreSelector.mjs +25 -0
  56. package/es/base-ui/FormKit/useStoreSelector.mjs.map +1 -0
  57. package/es/base-ui/FormKit/useWatch.d.mts +7 -0
  58. package/es/base-ui/FormKit/useWatch.mjs +12 -0
  59. package/es/base-ui/FormKit/useWatch.mjs.map +1 -0
  60. package/es/base-ui/Input/Input.d.mts +6 -2
  61. package/es/base-ui/Input/Input.mjs +2 -1
  62. package/es/base-ui/Input/Input.mjs.map +1 -1
  63. package/es/base-ui/Input/InputNumber.d.mts +6 -2
  64. package/es/base-ui/Input/InputNumber.mjs +13 -6
  65. package/es/base-ui/Input/InputNumber.mjs.map +1 -1
  66. package/es/base-ui/Input/InputPassword.d.mts +6 -2
  67. package/es/base-ui/Input/InputPassword.mjs +4 -3
  68. package/es/base-ui/Input/InputPassword.mjs.map +1 -1
  69. package/es/base-ui/Input/TextArea.d.mts +6 -2
  70. package/es/base-ui/Input/TextArea.mjs +2 -1
  71. package/es/base-ui/Input/TextArea.mjs.map +1 -1
  72. package/es/base-ui/Input/index.d.mts +5 -5
  73. package/es/base-ui/Input/style.d.mts +4 -1
  74. package/es/base-ui/Input/style.mjs +21 -8
  75. package/es/base-ui/Input/style.mjs.map +1 -1
  76. package/es/base-ui/Modal/Modal.mjs +4 -8
  77. package/es/base-ui/Modal/Modal.mjs.map +1 -1
  78. package/es/base-ui/Slider/SliderWithInput.mjs +2 -2
  79. package/es/base-ui/Slider/SliderWithInput.mjs.map +1 -1
  80. package/es/base-ui/Switch/Switch.mjs +2 -2
  81. package/es/base-ui/Switch/Switch.mjs.map +1 -1
  82. package/es/base-ui/Text/style.d.mts +1 -1
  83. package/es/base-ui/Tree/TreeNode.mjs +2 -2
  84. package/es/base-ui/Tree/TreeNode.mjs.map +1 -1
  85. package/es/base-ui/index.d.mts +8 -8
  86. package/es/base-ui/index.mjs +6 -6
  87. package/es/chat/ChatInputArea/components/ChatInputAreaInner.mjs +2 -2
  88. package/es/chat/ChatInputArea/components/ChatInputAreaInner.mjs.map +1 -1
  89. package/es/chat/MessageInput/MessageInput.mjs +2 -2
  90. package/es/chat/MessageInput/MessageInput.mjs.map +1 -1
  91. package/es/chat/MessageModal/MessageModal.mjs +2 -2
  92. package/es/chat/MessageModal/MessageModal.mjs.map +1 -1
  93. package/es/eslint/index.d.mts +27 -3
  94. package/es/eslint/index.mjs +40 -2
  95. package/es/eslint/index.mjs.map +1 -1
  96. package/es/eslint/noInlineFormSchema.mjs +44 -0
  97. package/es/eslint/noInlineFormSchema.mjs.map +1 -0
  98. package/es/i18n/resources/en/form.d.mts +4 -0
  99. package/es/i18n/resources/en/form.mjs +4 -0
  100. package/es/i18n/resources/en/form.mjs.map +1 -1
  101. package/es/i18n/resources/zhCn/form.d.mts +4 -0
  102. package/es/i18n/resources/zhCn/form.mjs +4 -0
  103. package/es/i18n/resources/zhCn/form.mjs.map +1 -1
  104. package/es/node_modules/.pnpm/@eslint_core@0.17.0/node_modules/@eslint/core/dist/esm/types.d.mts +1139 -0
  105. package/es/node_modules/.pnpm/@types_estree@1.0.9/node_modules/@types/estree/index.d.mts +528 -0
  106. package/es/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.mts +201 -0
  107. package/es/node_modules/.pnpm/eslint@9.39.5_jiti@2.6.1_supports-color@10.2.2/node_modules/eslint/lib/types/index.d.mts +962 -0
  108. package/package.json +6 -1
@@ -0,0 +1,293 @@
1
+ import isEqual from "fast-deep-equal";
2
+ import { FormApi, getBy, setBy } from "@tanstack/form-core";
3
+ //#region src/base-ui/FormKit/engine/tanstack.ts
4
+ const toEnginePath = (path) => path.replaceAll(/\.(\d+)(?=\.|$)/g, "[$1]");
5
+ const isSameOrNested = (a, b) => a === b || a.startsWith(`${b}.`) || b.startsWith(`${a}.`);
6
+ const isUnder = (path, root) => path === root || path.startsWith(`${root}.`);
7
+ const createTanstackEngine = (initialValues) => {
8
+ const form = new FormApi({ defaultValues: initialValues });
9
+ const fields = /* @__PURE__ */ new Map();
10
+ const fieldErrors = /* @__PURE__ */ new Map();
11
+ const formErrors = /* @__PURE__ */ new Map();
12
+ const serverErrors = /* @__PURE__ */ new Map();
13
+ const validating = /* @__PURE__ */ new Set();
14
+ const touched = /* @__PURE__ */ new Set();
15
+ const listeners = /* @__PURE__ */ new Set();
16
+ const valueListeners = /* @__PURE__ */ new Set();
17
+ const snapshots = /* @__PURE__ */ new Map();
18
+ let formValidator;
19
+ let baseline = initialValues;
20
+ let dirtyCache;
21
+ let inflightSubmit;
22
+ let submitting = false;
23
+ let submitCount = 0;
24
+ let status = {
25
+ dirty: false,
26
+ submitCount: 0,
27
+ submitting: false
28
+ };
29
+ const notify = () => {
30
+ for (const listener of listeners) listener();
31
+ };
32
+ const storeSubscription = form.store.subscribe(notify);
33
+ const getValue = (path) => form.getFieldValue(toEnginePath(path));
34
+ const getValues = () => form.state.values;
35
+ const isTouched = (path) => {
36
+ for (const entry of touched) if (isSameOrNested(entry, path)) return true;
37
+ return false;
38
+ };
39
+ const errorOf = (path) => serverErrors.get(path) ?? fieldErrors.get(path) ?? formErrors.get(path);
40
+ const getField = (path) => {
41
+ const next = {
42
+ error: errorOf(path),
43
+ touched: isTouched(path),
44
+ validating: validating.has(path),
45
+ value: getValue(path)
46
+ };
47
+ const prev = snapshots.get(path);
48
+ if (prev && prev.error === next.error && prev.touched === next.touched && prev.validating === next.validating && Object.is(prev.value, next.value)) return prev;
49
+ snapshots.set(path, next);
50
+ return next;
51
+ };
52
+ const getStatus = () => {
53
+ const values = getValues();
54
+ if (dirtyCache?.values !== values || dirtyCache.baseline !== baseline) dirtyCache = {
55
+ baseline,
56
+ dirty: !isEqual(values, baseline),
57
+ values
58
+ };
59
+ const { dirty } = dirtyCache;
60
+ if (status.dirty !== dirty || status.submitting !== submitting || status.submitCount !== submitCount) status = {
61
+ dirty,
62
+ submitCount,
63
+ submitting
64
+ };
65
+ return status;
66
+ };
67
+ const shouldValidate = (path, trigger) => {
68
+ const mode = fields.get(path)?.registration.validateOn ?? "auto";
69
+ if (trigger === "submit") return true;
70
+ if (mode === "change") return true;
71
+ if (mode === "blur") return trigger === "blur";
72
+ if (mode === "submit") return false;
73
+ return trigger === "blur" || errorOf(path) !== void 0;
74
+ };
75
+ const setOrDelete = (map, path, error) => {
76
+ if (error === void 0) map.delete(path);
77
+ else map.set(path, error);
78
+ };
79
+ const runField = (path, withFormValidator) => {
80
+ const runtime = fields.get(path);
81
+ if (!runtime) return Promise.resolve();
82
+ runtime.token += 1;
83
+ const token = runtime.token;
84
+ const { validate } = runtime.registration;
85
+ if (!validate && !(withFormValidator && formValidator)) return Promise.resolve();
86
+ validating.add(path);
87
+ notify();
88
+ return (async () => {
89
+ const values = getValues();
90
+ const [fieldError, formResult] = await Promise.all([validate?.(getValue(path), values), withFormValidator ? formValidator?.(values) : void 0]);
91
+ if (runtime.token !== token || fields.get(path) !== runtime) return;
92
+ setOrDelete(fieldErrors, path, fieldError);
93
+ if (withFormValidator) setOrDelete(formErrors, path, formResult?.[path]);
94
+ validating.delete(path);
95
+ notify();
96
+ })();
97
+ };
98
+ const schedule = (path, trigger) => {
99
+ const runtime = fields.get(path);
100
+ if (!runtime || !shouldValidate(path, trigger)) return;
101
+ clearTimeout(runtime.timer);
102
+ const debounceMs = runtime.registration.debounceMs ?? 0;
103
+ if (trigger === "change" && debounceMs > 0) {
104
+ runtime.token += 1;
105
+ runtime.timer = setTimeout(() => void runField(path, true), debounceMs);
106
+ return;
107
+ }
108
+ runField(path, true);
109
+ };
110
+ const clearErrorsUnder = (path, inclusive = false) => {
111
+ for (const map of [
112
+ fieldErrors,
113
+ formErrors,
114
+ serverErrors
115
+ ]) for (const key of map.keys()) if (inclusive ? isUnder(key, path) : key.startsWith(`${path}.`)) map.delete(key);
116
+ };
117
+ const resetTo = (values) => {
118
+ clearRuntimeState();
119
+ baseline = values;
120
+ form.reset(values);
121
+ notify();
122
+ };
123
+ const emitValueChange = (path, source) => {
124
+ for (const listener of valueListeners) listener({
125
+ path,
126
+ source
127
+ });
128
+ };
129
+ const afterUserChange = (path) => {
130
+ touched.add(path);
131
+ serverErrors.delete(path);
132
+ schedule(path, "change");
133
+ for (const [other, runtime] of fields) if (other !== path && runtime.registration.deps?.includes(path) && isTouched(other)) runField(other, true);
134
+ notify();
135
+ };
136
+ const validate = async (paths) => {
137
+ const values = getValues();
138
+ const formResult = (formValidator ? await formValidator(values) : void 0) ?? {};
139
+ const targets = paths ?? [.../* @__PURE__ */ new Set([...fields.keys(), ...Object.keys(formResult)])];
140
+ await Promise.all(targets.map((path) => runField(path, false)));
141
+ for (const path of targets) setOrDelete(formErrors, path, formResult[path]);
142
+ notify();
143
+ const errors = {};
144
+ for (const path of targets) {
145
+ const error = errorOf(path);
146
+ if (error !== void 0) errors[path] = error;
147
+ }
148
+ return {
149
+ errors,
150
+ valid: Object.keys(errors).length === 0
151
+ };
152
+ };
153
+ const clearRuntimeState = () => {
154
+ for (const runtime of fields.values()) {
155
+ clearTimeout(runtime.timer);
156
+ runtime.token += 1;
157
+ }
158
+ fieldErrors.clear();
159
+ formErrors.clear();
160
+ serverErrors.clear();
161
+ validating.clear();
162
+ touched.clear();
163
+ };
164
+ const runSubmit = async (onSubmit) => {
165
+ submitCount += 1;
166
+ serverErrors.clear();
167
+ for (const path of fields.keys()) touched.add(path);
168
+ let values;
169
+ let result;
170
+ do {
171
+ values = getValues();
172
+ result = await validate();
173
+ } while (values !== getValues());
174
+ if (!result.valid) {
175
+ notify();
176
+ return result;
177
+ }
178
+ submitting = true;
179
+ notify();
180
+ try {
181
+ await onSubmit?.(values);
182
+ if (serverErrors.size > 0) return {
183
+ errors: Object.fromEntries(serverErrors),
184
+ valid: false
185
+ };
186
+ resetTo(getValues());
187
+ } finally {
188
+ submitting = false;
189
+ notify();
190
+ }
191
+ return result;
192
+ };
193
+ return {
194
+ blurField: (path) => {
195
+ touched.add(path);
196
+ schedule(path, "blur");
197
+ notify();
198
+ },
199
+ destroy: () => {
200
+ for (const runtime of fields.values()) clearTimeout(runtime.timer);
201
+ storeSubscription.unsubscribe();
202
+ listeners.clear();
203
+ valueListeners.clear();
204
+ },
205
+ getField,
206
+ getStatus,
207
+ getValue,
208
+ getValues,
209
+ isTouched,
210
+ moveItem: (path, from, to) => {
211
+ form.moveFieldValues(toEnginePath(path), from, to);
212
+ touched.add(path);
213
+ clearErrorsUnder(path);
214
+ emitValueChange(path, "user");
215
+ notify();
216
+ },
217
+ onValueChange: (listener) => {
218
+ valueListeners.add(listener);
219
+ return () => valueListeners.delete(listener);
220
+ },
221
+ pushItem: (path, item) => {
222
+ form.pushFieldValue(toEnginePath(path), item);
223
+ touched.add(path);
224
+ emitValueChange(path, "user");
225
+ notify();
226
+ },
227
+ registerField: (path, registration) => {
228
+ const runtime = {
229
+ registration,
230
+ token: 0
231
+ };
232
+ fields.set(path, runtime);
233
+ return () => {
234
+ if (fields.get(path) !== runtime) return;
235
+ clearTimeout(runtime.timer);
236
+ fields.delete(path);
237
+ fieldErrors.delete(path);
238
+ validating.delete(path);
239
+ snapshots.delete(path);
240
+ notify();
241
+ };
242
+ },
243
+ removeItem: (path, index) => {
244
+ form.removeFieldValue(toEnginePath(path), index);
245
+ touched.add(path);
246
+ clearErrorsUnder(path);
247
+ emitValueChange(path, "user");
248
+ notify();
249
+ },
250
+ reset: (values) => resetTo(values ?? baseline),
251
+ resetField: (path) => {
252
+ for (const [key, runtime] of fields) {
253
+ if (!isUnder(key, path)) continue;
254
+ clearTimeout(runtime.timer);
255
+ runtime.token += 1;
256
+ validating.delete(key);
257
+ }
258
+ for (const entry of touched) if (isUnder(entry, path)) touched.delete(entry);
259
+ clearErrorsUnder(path, true);
260
+ form.setFieldValue(toEnginePath(path), getBy(baseline, toEnginePath(path)), { dontUpdateMeta: true });
261
+ emitValueChange(path, "api");
262
+ notify();
263
+ },
264
+ setErrors: (errors) => {
265
+ for (const [path, error] of Object.entries(errors)) setOrDelete(serverErrors, path, error);
266
+ notify();
267
+ },
268
+ setFormValidator: (validator) => {
269
+ formValidator = validator;
270
+ },
271
+ setValue: (path, value, source) => {
272
+ form.setFieldValue(toEnginePath(path), value, { dontUpdateMeta: true });
273
+ if (source === "api") baseline = setBy(baseline, toEnginePath(path), () => value);
274
+ emitValueChange(path, source);
275
+ if (source === "user") afterUserChange(path);
276
+ },
277
+ submit: (onSubmit) => {
278
+ inflightSubmit ??= runSubmit(onSubmit).finally(() => {
279
+ inflightSubmit = void 0;
280
+ });
281
+ return inflightSubmit;
282
+ },
283
+ subscribe: (listener) => {
284
+ listeners.add(listener);
285
+ return () => listeners.delete(listener);
286
+ },
287
+ validate
288
+ };
289
+ };
290
+ //#endregion
291
+ export { createTanstackEngine };
292
+
293
+ //# sourceMappingURL=tanstack.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tanstack.mjs","names":[],"sources":["../../../../src/base-ui/FormKit/engine/tanstack.ts"],"sourcesContent":["import { FormApi, getBy, setBy } from '@tanstack/form-core';\nimport isEqual from 'fast-deep-equal';\n\nimport type {\n ChangeSource,\n CreateEngine,\n FieldRegistration,\n FieldSnapshot,\n FormEngine,\n FormStatus,\n FormValidator,\n ValidateResult,\n ValidateTrigger,\n ValueChange,\n} from './types';\n\nconst toEnginePath = (path: string) => path.replaceAll(/\\.(\\d+)(?=\\.|$)/g, '[$1]');\n\nconst isSameOrNested = (a: string, b: string) =>\n a === b || a.startsWith(`${b}.`) || b.startsWith(`${a}.`);\n\nconst isUnder = (path: string, root: string) => path === root || path.startsWith(`${root}.`);\n\ninterface FieldRuntime {\n registration: FieldRegistration;\n timer?: ReturnType<typeof setTimeout>;\n token: number;\n}\n\nexport const createTanstackEngine: CreateEngine = (initialValues) => {\n const form = new FormApi({ defaultValues: initialValues });\n\n const fields = new Map<string, FieldRuntime>();\n const fieldErrors = new Map<string, string>();\n const formErrors = new Map<string, string>();\n const serverErrors = new Map<string, string>();\n const validating = new Set<string>();\n const touched = new Set<string>();\n const listeners = new Set<() => void>();\n const valueListeners = new Set<(change: ValueChange) => void>();\n const snapshots = new Map<string, FieldSnapshot>();\n\n let formValidator: FormValidator | undefined;\n let baseline = initialValues;\n let dirtyCache: { baseline: unknown; dirty: boolean; values: unknown } | undefined;\n let inflightSubmit: Promise<ValidateResult> | undefined;\n let submitting = false;\n let submitCount = 0;\n let status: FormStatus = { dirty: false, submitCount: 0, submitting: false };\n\n const notify = () => {\n for (const listener of listeners) listener();\n };\n const storeSubscription = form.store.subscribe(notify);\n\n const getValue = (path: string) => form.getFieldValue(toEnginePath(path) as never) as unknown;\n const getValues = () => form.state.values as Record<string, unknown>;\n const isTouched = (path: string) => {\n for (const entry of touched) if (isSameOrNested(entry, path)) return true;\n return false;\n };\n const errorOf = (path: string) =>\n serverErrors.get(path) ?? fieldErrors.get(path) ?? formErrors.get(path);\n\n const getField = (path: string): FieldSnapshot => {\n const next: FieldSnapshot = {\n error: errorOf(path),\n touched: isTouched(path),\n validating: validating.has(path),\n value: getValue(path),\n };\n const prev = snapshots.get(path);\n if (\n prev &&\n prev.error === next.error &&\n prev.touched === next.touched &&\n prev.validating === next.validating &&\n Object.is(prev.value, next.value)\n )\n return prev;\n snapshots.set(path, next);\n return next;\n };\n\n const getStatus = (): FormStatus => {\n const values = getValues();\n if (dirtyCache?.values !== values || dirtyCache.baseline !== baseline)\n dirtyCache = { baseline, dirty: !isEqual(values, baseline), values };\n const { dirty } = dirtyCache;\n if (\n status.dirty !== dirty ||\n status.submitting !== submitting ||\n status.submitCount !== submitCount\n )\n status = { dirty, submitCount, submitting };\n return status;\n };\n\n const shouldValidate = (path: string, trigger: ValidateTrigger) => {\n const mode = fields.get(path)?.registration.validateOn ?? 'auto';\n if (trigger === 'submit') return true;\n if (mode === 'change') return true;\n if (mode === 'blur') return trigger === 'blur';\n if (mode === 'submit') return false;\n return trigger === 'blur' || errorOf(path) !== undefined;\n };\n\n const setOrDelete = (map: Map<string, string>, path: string, error: string | undefined) => {\n if (error === undefined) map.delete(path);\n else map.set(path, error);\n };\n\n const runField = (path: string, withFormValidator: boolean): Promise<void> => {\n const runtime = fields.get(path);\n if (!runtime) return Promise.resolve();\n runtime.token += 1;\n const token = runtime.token;\n const { validate } = runtime.registration;\n if (!validate && !(withFormValidator && formValidator)) return Promise.resolve();\n\n validating.add(path);\n notify();\n return (async () => {\n const values = getValues();\n const [fieldError, formResult] = await Promise.all([\n validate?.(getValue(path), values),\n withFormValidator ? formValidator?.(values) : undefined,\n ]);\n if (runtime.token !== token || fields.get(path) !== runtime) return;\n setOrDelete(fieldErrors, path, fieldError);\n if (withFormValidator) setOrDelete(formErrors, path, formResult?.[path]);\n validating.delete(path);\n notify();\n })();\n };\n\n const schedule = (path: string, trigger: ValidateTrigger) => {\n const runtime = fields.get(path);\n if (!runtime || !shouldValidate(path, trigger)) return;\n clearTimeout(runtime.timer);\n const debounceMs = runtime.registration.debounceMs ?? 0;\n if (trigger === 'change' && debounceMs > 0) {\n runtime.token += 1;\n runtime.timer = setTimeout(() => void runField(path, true), debounceMs);\n return;\n }\n void runField(path, true);\n };\n\n const clearErrorsUnder = (path: string, inclusive = false) => {\n for (const map of [fieldErrors, formErrors, serverErrors])\n for (const key of map.keys())\n if (inclusive ? isUnder(key, path) : key.startsWith(`${path}.`)) map.delete(key);\n };\n\n const resetTo = (values: Record<string, unknown>) => {\n clearRuntimeState();\n baseline = values;\n form.reset(values);\n notify();\n };\n\n const emitValueChange = (path: string, source: ChangeSource) => {\n for (const listener of valueListeners) listener({ path, source });\n };\n\n const afterUserChange = (path: string) => {\n touched.add(path);\n serverErrors.delete(path);\n schedule(path, 'change');\n for (const [other, runtime] of fields) {\n if (other !== path && runtime.registration.deps?.includes(path) && isTouched(other))\n void runField(other, true);\n }\n notify();\n };\n\n const validate = async (paths?: string[]): Promise<ValidateResult> => {\n const values = getValues();\n const formResult = (formValidator ? await formValidator(values) : undefined) ?? {};\n const targets = paths ?? [...new Set([...fields.keys(), ...Object.keys(formResult)])];\n await Promise.all(targets.map((path) => runField(path, false)));\n for (const path of targets) setOrDelete(formErrors, path, formResult[path]);\n notify();\n const errors: Record<string, string> = {};\n for (const path of targets) {\n const error = errorOf(path);\n if (error !== undefined) errors[path] = error;\n }\n return { errors, valid: Object.keys(errors).length === 0 };\n };\n\n const clearRuntimeState = () => {\n for (const runtime of fields.values()) {\n clearTimeout(runtime.timer);\n runtime.token += 1;\n }\n fieldErrors.clear();\n formErrors.clear();\n serverErrors.clear();\n validating.clear();\n touched.clear();\n };\n\n const runSubmit = async (onSubmit?: (values: Record<string, unknown>) => unknown) => {\n submitCount += 1;\n serverErrors.clear();\n for (const path of fields.keys()) touched.add(path);\n let values: Record<string, unknown>;\n let result: ValidateResult;\n do {\n values = getValues();\n result = await validate();\n // Async validators must finish against unchanged values before submission.\n } while (values !== getValues());\n if (!result.valid) {\n notify();\n return result;\n }\n submitting = true;\n notify();\n try {\n await onSubmit?.(values);\n if (serverErrors.size > 0) return { errors: Object.fromEntries(serverErrors), valid: false };\n resetTo(getValues());\n } finally {\n submitting = false;\n notify();\n }\n return result;\n };\n\n const engine: FormEngine = {\n blurField: (path) => {\n touched.add(path);\n schedule(path, 'blur');\n notify();\n },\n destroy: () => {\n for (const runtime of fields.values()) clearTimeout(runtime.timer);\n storeSubscription.unsubscribe();\n listeners.clear();\n valueListeners.clear();\n },\n getField,\n getStatus,\n getValue,\n getValues,\n isTouched,\n moveItem: (path, from, to) => {\n form.moveFieldValues(toEnginePath(path) as never, from, to);\n touched.add(path);\n clearErrorsUnder(path);\n emitValueChange(path, 'user');\n notify();\n },\n onValueChange: (listener) => {\n valueListeners.add(listener);\n return () => valueListeners.delete(listener);\n },\n pushItem: (path, item) => {\n form.pushFieldValue(toEnginePath(path) as never, item as never);\n touched.add(path);\n emitValueChange(path, 'user');\n notify();\n },\n registerField: (path, registration) => {\n const runtime: FieldRuntime = { registration, token: 0 };\n fields.set(path, runtime);\n return () => {\n if (fields.get(path) !== runtime) return;\n clearTimeout(runtime.timer);\n fields.delete(path);\n fieldErrors.delete(path);\n validating.delete(path);\n snapshots.delete(path);\n notify();\n };\n },\n removeItem: (path, index) => {\n void form.removeFieldValue(toEnginePath(path) as never, index);\n touched.add(path);\n clearErrorsUnder(path);\n emitValueChange(path, 'user');\n notify();\n },\n reset: (values) => resetTo(values ?? baseline),\n resetField: (path) => {\n for (const [key, runtime] of fields) {\n if (!isUnder(key, path)) continue;\n clearTimeout(runtime.timer);\n runtime.token += 1;\n validating.delete(key);\n }\n for (const entry of touched) if (isUnder(entry, path)) touched.delete(entry);\n clearErrorsUnder(path, true);\n form.setFieldValue(toEnginePath(path) as never, getBy(baseline, toEnginePath(path)), {\n dontUpdateMeta: true,\n });\n emitValueChange(path, 'api');\n notify();\n },\n setErrors: (errors) => {\n for (const [path, error] of Object.entries(errors)) setOrDelete(serverErrors, path, error);\n notify();\n },\n setFormValidator: (validator) => {\n formValidator = validator;\n },\n setValue: (path, value, source) => {\n form.setFieldValue(toEnginePath(path) as never, value as never, { dontUpdateMeta: true });\n if (source === 'api') baseline = setBy(baseline, toEnginePath(path), () => value);\n emitValueChange(path, source);\n if (source === 'user') afterUserChange(path);\n },\n submit: (onSubmit) => {\n inflightSubmit ??= runSubmit(onSubmit).finally(() => {\n inflightSubmit = undefined;\n });\n return inflightSubmit;\n },\n subscribe: (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n validate,\n };\n\n return engine;\n};\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ //#region src/base-ui/FormKit/engine/types.d.ts
2
+ type ValidateTrigger = 'change' | 'blur' | 'submit';
3
+ type ValidateOn = 'auto' | ValidateTrigger;
4
+ //#endregion
5
+ export { ValidateOn, ValidateTrigger };
6
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1,31 @@
1
+ import { FlexBasicProps } from "../../Flex/type.mjs";
2
+ import "../../index.mjs";
3
+ import { FormDividerProps, FormFlatGroupProps, FormGroupProps, FormSubmitFooterProps, FormTitleProps } from "../Form/type.mjs";
4
+ import { FieldValidate, StandardSchema } from "./schema.mjs";
5
+ import { DeepPartial, FieldBinding, FieldPath, FieldPathValue, FieldRenderProps, FormFieldProps, FormGroupItem, FormInstance, FormProps, FormValidateResult, FormValues, SetValueOptions, UseFormOptions } from "./type.mjs";
6
+ import "../index.mjs";
7
+ import FormList, { FormListColumn, FormListField, FormListProps, FormListRenderProps } from "./List.mjs";
8
+ import _default from "./Field.mjs";
9
+ import SubmitFooter from "./SubmitFooter.mjs";
10
+ import { useFormInstance } from "./context.mjs";
11
+ import { useForm } from "./useForm.mjs";
12
+ import { useWatch } from "./useWatch.mjs";
13
+ //#region src/base-ui/FormKit/index.d.ts
14
+ declare const Form: {
15
+ <T extends FormValues>({ activeKey, children, className, classNames, collapsible, defaultActiveKey, footer, form, gap, itemMinWidth, items, itemsType, layout, onCollapse, ref, style, styles: customStyles, variant, ...rest }: FormProps<T>): import("react").JSX.Element;
16
+ displayName: string;
17
+ } & {
18
+ Divider: import("react").FC<FormDividerProps>;
19
+ Field: (<T extends FormValues = FormValues>(props: FormFieldProps<T>) => import("react").ReactNode) & {
20
+ displayName?: string;
21
+ };
22
+ FlatGroup: import("react").NamedExoticComponent<FormFlatGroupProps>;
23
+ Footer: import("react").FC<FlexBasicProps>;
24
+ Group: import("react").NamedExoticComponent<FormGroupProps>;
25
+ List: import("react").NamedExoticComponent<FormListProps>;
26
+ SubmitFooter: import("react").NamedExoticComponent<FormSubmitFooterProps>;
27
+ Title: import("react").FC<FormTitleProps>;
28
+ };
29
+ //#endregion
30
+ export { type DeepPartial, type FieldBinding, type FieldPath, type FieldPathValue, type FieldRenderProps, type FieldValidate, Form, Form as default, _default as FormField, type FormFieldProps, type FormGroupItem, type FormInstance, FormList, type FormListColumn, type FormListField, type FormListProps, type FormListRenderProps, type FormProps, SubmitFooter as FormSubmitFooter, type FormValidateResult, type FormValues, type SetValueOptions, type StandardSchema, type UseFormOptions, useForm, useFormInstance, useWatch };
31
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import FormDivider from "../Form/components/FormDivider.mjs";
3
+ import FormTitle from "../Form/components/FormTitle.mjs";
4
+ import FormFlatGroup from "../Form/components/FormFlatGroup.mjs";
5
+ import FormFooter from "../Form/components/FormFooter.mjs";
6
+ import FormGroup from "../Form/components/FormGroup.mjs";
7
+ import { useFormInstance } from "./context.mjs";
8
+ import FormField from "./Field.mjs";
9
+ import Form$1 from "./Form.mjs";
10
+ import FormList from "./List.mjs";
11
+ import SubmitFooter from "./SubmitFooter.mjs";
12
+ import { useForm } from "./useForm.mjs";
13
+ import { useWatch } from "./useWatch.mjs";
14
+ //#region src/base-ui/FormKit/index.ts
15
+ const Form = Object.assign(Form$1, {
16
+ Divider: FormDivider,
17
+ Field: FormField,
18
+ FlatGroup: FormFlatGroup,
19
+ Footer: FormFooter,
20
+ Group: FormGroup,
21
+ List: FormList,
22
+ SubmitFooter,
23
+ Title: FormTitle
24
+ });
25
+ //#endregion
26
+ export { Form, Form as default, FormField, FormList, SubmitFooter as FormSubmitFooter, useForm, useFormInstance, useWatch };
27
+
28
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["FormParent","FormSubmitFooter"],"sources":["../../../src/base-ui/FormKit/index.ts"],"sourcesContent":["'use client';\n\nimport FormDivider from '../Form/components/FormDivider';\nimport FormFlatGroup from '../Form/components/FormFlatGroup';\nimport FormFooter from '../Form/components/FormFooter';\nimport FormGroup from '../Form/components/FormGroup';\nimport FormTitle from '../Form/components/FormTitle';\nimport FormField from './Field';\nimport FormParent from './Form';\nimport FormList from './List';\nimport FormSubmitFooter from './SubmitFooter';\n\nexport const Form = Object.assign(FormParent, {\n Divider: FormDivider,\n Field: FormField,\n FlatGroup: FormFlatGroup,\n Footer: FormFooter,\n Group: FormGroup,\n List: FormList,\n SubmitFooter: FormSubmitFooter,\n Title: FormTitle,\n});\n\nexport { useFormInstance } from './context';\nexport type { FormListColumn, FormListField, FormListProps, FormListRenderProps } from './List';\nexport type {\n DeepPartial,\n FieldBinding,\n FieldPath,\n FieldPathValue,\n FieldRenderProps,\n FieldValidate,\n FormFieldProps,\n FormGroupItem,\n FormInstance,\n FormProps,\n FormValidateResult,\n FormValues,\n SetValueOptions,\n StandardSchema,\n UseFormOptions,\n} from './type';\nexport { useForm } from './useForm';\nexport { useWatch } from './useWatch';\nexport { FormField, FormList, FormSubmitFooter };\n\nexport default Form;\n"],"mappings":";;;;;;;;;;;;;;AAYA,MAAa,OAAO,OAAO,OAAOA,QAAY;CAC5C,SAAS;CACT,OAAO;CACP,WAAW;CACX,QAAQ;CACR,OAAO;CACP,MAAM;CACQC;CACd,OAAO;AACT,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { createTanstackEngine } from "./engine/tanstack.mjs";
2
+ import { schemaToFormValidator } from "./schema.mjs";
3
+ //#region src/base-ui/FormKit/instance.ts
4
+ const internals = /* @__PURE__ */ new WeakMap();
5
+ const getInternals = (form) => {
6
+ const found = internals.get(form);
7
+ if (!found) throw new Error("[@lobehub/ui/base-ui/form] form was not created by useForm");
8
+ return found;
9
+ };
10
+ const isPlainObject = (value) => {
11
+ if (typeof value !== "object" || value === null) return false;
12
+ const proto = Object.getPrototypeOf(value);
13
+ return proto === Object.prototype || proto === null;
14
+ };
15
+ const leafPaths = (value, prefix = "") => {
16
+ if (!isPlainObject(value) || prefix && Object.keys(value).length === 0) return prefix ? [prefix] : [];
17
+ return Object.entries(value).flatMap(([key, child]) => leafPaths(child, prefix ? `${prefix}.${key}` : key));
18
+ };
19
+ const getIn = (value, path) => path.split(".").reduce((acc, key) => acc == null ? void 0 : acc[key], value);
20
+ const setIn = (target, path, value) => {
21
+ const keys = path.split(".");
22
+ let cursor = target;
23
+ keys.slice(0, -1).forEach((key) => {
24
+ if (!isPlainObject(cursor[key])) cursor[key] = {};
25
+ cursor = cursor[key];
26
+ });
27
+ cursor[keys.at(-1)] = value;
28
+ };
29
+ const createFormInstance = ({ initialValues, schema, validateOn }) => {
30
+ const engine = createTanstackEngine(initialValues);
31
+ if (schema) engine.setFormValidator(schemaToFormValidator(schema));
32
+ const source = (options) => options?.asUser ? "user" : "api";
33
+ const form = {
34
+ getValue: ((name) => engine.getValue(name)),
35
+ getValues: () => engine.getValues(),
36
+ isDirty: () => engine.getStatus().dirty,
37
+ isTouched: (name) => engine.isTouched(name),
38
+ reset: (values) => engine.reset(values),
39
+ resetField: (name) => engine.resetField(name),
40
+ setErrors: (errors) => engine.setErrors(errors),
41
+ setSchema: (next) => engine.setFormValidator(next ? schemaToFormValidator(next) : void 0),
42
+ setValue: ((name, value, options) => engine.setValue(name, value, source(options))),
43
+ setValues: (values, options) => {
44
+ for (const path of leafPaths(values)) engine.setValue(path, getIn(values, path), source(options));
45
+ },
46
+ submit: () => engine.submit((values) => internals.get(form)?.onSubmit?.(values)),
47
+ subscribe: (selector, callback) => {
48
+ let selected = selector(engine.getValues());
49
+ return engine.subscribe(() => {
50
+ const next = selector(engine.getValues());
51
+ if (Object.is(next, selected)) return;
52
+ selected = next;
53
+ callback(next);
54
+ });
55
+ },
56
+ validate: (names) => engine.validate(names)
57
+ };
58
+ internals.set(form, {
59
+ engine,
60
+ validateOn
61
+ });
62
+ return form;
63
+ };
64
+ //#endregion
65
+ export { createFormInstance, getIn, getInternals, leafPaths, setIn };
66
+
67
+ //# sourceMappingURL=instance.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance.mjs","names":[],"sources":["../../../src/base-ui/FormKit/instance.ts"],"sourcesContent":["import { createTanstackEngine } from './engine/tanstack';\nimport type { FormEngine, ValidateOn } from './engine/types';\nimport { schemaToFormValidator } from './schema';\nimport type { FormInstance, FormValues } from './type';\n\ninterface InstanceInternals {\n engine: FormEngine;\n onSubmit?: (values: FormValues) => unknown;\n validateOn: ValidateOn;\n}\n\nconst internals = new WeakMap<object, InstanceInternals>();\n\nexport const getInternals = (form: object): InstanceInternals => {\n const found = internals.get(form);\n if (!found) throw new Error('[@lobehub/ui/base-ui/form] form was not created by useForm');\n return found;\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\nexport const leafPaths = (value: unknown, prefix = ''): string[] => {\n if (!isPlainObject(value) || (prefix && Object.keys(value).length === 0))\n return prefix ? [prefix] : [];\n return Object.entries(value).flatMap(([key, child]) =>\n leafPaths(child, prefix ? `${prefix}.${key}` : key),\n );\n};\n\nexport const getIn = (value: unknown, path: string): unknown =>\n path\n .split('.')\n .reduce<unknown>((acc, key) => (acc == null ? undefined : (acc as any)[key]), value);\n\nexport const setIn = (target: Record<string, unknown>, path: string, value: unknown) => {\n const keys = path.split('.');\n let cursor: Record<string, unknown> = target;\n keys.slice(0, -1).forEach((key) => {\n if (!isPlainObject(cursor[key])) cursor[key] = {};\n cursor = cursor[key] as Record<string, unknown>;\n });\n cursor[keys.at(-1)!] = value;\n};\n\ninterface CreateOptions {\n initialValues: FormValues;\n schema?: Parameters<typeof schemaToFormValidator>[0];\n validateOn: ValidateOn;\n}\n\nexport const createFormInstance = <T extends FormValues>({\n initialValues,\n schema,\n validateOn,\n}: CreateOptions): FormInstance<T> => {\n const engine = createTanstackEngine(initialValues);\n if (schema) engine.setFormValidator(schemaToFormValidator(schema));\n const source = (options?: { asUser?: boolean }) => (options?.asUser ? 'user' : 'api');\n\n const form: FormInstance<T> = {\n getValue: ((name: string) => engine.getValue(name)) as FormInstance<T>['getValue'],\n getValues: () => engine.getValues() as T,\n isDirty: () => engine.getStatus().dirty,\n isTouched: (name) => engine.isTouched(name),\n reset: (values) => engine.reset(values),\n resetField: (name) => engine.resetField(name),\n setErrors: (errors) => engine.setErrors(errors as Record<string, string | undefined>),\n setSchema: (next) => engine.setFormValidator(next ? schemaToFormValidator(next) : undefined),\n setValue: ((name: string, value: unknown, options?: { asUser?: boolean }) =>\n engine.setValue(name, value, source(options))) as FormInstance<T>['setValue'],\n setValues: (values, options) => {\n for (const path of leafPaths(values))\n engine.setValue(path, getIn(values, path), source(options));\n },\n submit: () =>\n engine.submit((values) => internals.get(form)?.onSubmit?.(values)) as ReturnType<\n FormInstance<T>['submit']\n >,\n subscribe: (selector, callback) => {\n let selected = selector(engine.getValues() as T);\n return engine.subscribe(() => {\n const next = selector(engine.getValues() as T);\n if (Object.is(next, selected)) return;\n selected = next;\n callback(next);\n });\n },\n validate: (names) => engine.validate(names) as ReturnType<FormInstance<T>['validate']>,\n };\n\n internals.set(form, { engine, validateOn });\n return form;\n};\n"],"mappings":";;;AAWA,MAAM,4BAAY,IAAI,QAAmC;AAEzD,MAAa,gBAAgB,SAAoC;CAC/D,MAAM,QAAQ,UAAU,IAAI,IAAI;CAChC,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,4DAA4D;CACxF,OAAO;AACT;AAEA,MAAM,iBAAiB,UAAqD;CAC1E,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,QAAQ,OAAO,eAAe,KAAK;CACzC,OAAO,UAAU,OAAO,aAAa,UAAU;AACjD;AAEA,MAAa,aAAa,OAAgB,SAAS,OAAiB;CAClE,IAAI,CAAC,cAAc,KAAK,KAAM,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GACpE,OAAO,SAAS,CAAC,MAAM,IAAI,CAAC;CAC9B,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,WAC1C,UAAU,OAAO,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,CACpD;AACF;AAEA,MAAa,SAAS,OAAgB,SACpC,KACG,MAAM,GAAG,CAAC,CACV,QAAiB,KAAK,QAAS,OAAO,OAAO,KAAA,IAAa,IAAY,MAAO,KAAK;AAEvF,MAAa,SAAS,QAAiC,MAAc,UAAmB;CACtF,MAAM,OAAO,KAAK,MAAM,GAAG;CAC3B,IAAI,SAAkC;CACtC,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,SAAS,QAAQ;EACjC,IAAI,CAAC,cAAc,OAAO,IAAI,GAAG,OAAO,OAAO,CAAC;EAChD,SAAS,OAAO;CAClB,CAAC;CACD,OAAO,KAAK,GAAG,EAAE,KAAM;AACzB;AAQA,MAAa,sBAA4C,EACvD,eACA,QACA,iBACoC;CACpC,MAAM,SAAS,qBAAqB,aAAa;CACjD,IAAI,QAAQ,OAAO,iBAAiB,sBAAsB,MAAM,CAAC;CACjE,MAAM,UAAU,YAAoC,SAAS,SAAS,SAAS;CAE/E,MAAM,OAAwB;EAC5B,YAAY,SAAiB,OAAO,SAAS,IAAI;EACjD,iBAAiB,OAAO,UAAU;EAClC,eAAe,OAAO,UAAU,CAAC,CAAC;EAClC,YAAY,SAAS,OAAO,UAAU,IAAI;EAC1C,QAAQ,WAAW,OAAO,MAAM,MAAM;EACtC,aAAa,SAAS,OAAO,WAAW,IAAI;EAC5C,YAAY,WAAW,OAAO,UAAU,MAA4C;EACpF,YAAY,SAAS,OAAO,iBAAiB,OAAO,sBAAsB,IAAI,IAAI,KAAA,CAAS;EAC3F,YAAY,MAAc,OAAgB,YACxC,OAAO,SAAS,MAAM,OAAO,OAAO,OAAO,CAAC;EAC9C,YAAY,QAAQ,YAAY;GAC9B,KAAK,MAAM,QAAQ,UAAU,MAAM,GACjC,OAAO,SAAS,MAAM,MAAM,QAAQ,IAAI,GAAG,OAAO,OAAO,CAAC;EAC9D;EACA,cACE,OAAO,QAAQ,WAAW,UAAU,IAAI,IAAI,CAAC,EAAE,WAAW,MAAM,CAAC;EAGnE,YAAY,UAAU,aAAa;GACjC,IAAI,WAAW,SAAS,OAAO,UAAU,CAAM;GAC/C,OAAO,OAAO,gBAAgB;IAC5B,MAAM,OAAO,SAAS,OAAO,UAAU,CAAM;IAC7C,IAAI,OAAO,GAAG,MAAM,QAAQ,GAAG;IAC/B,WAAW;IACX,SAAS,IAAI;GACf,CAAC;EACH;EACA,WAAW,UAAU,OAAO,SAAS,KAAK;CAC5C;CAEA,UAAU,IAAI,MAAM;EAAE;EAAQ;CAAW,CAAC;CAC1C,OAAO;AACT"}
@@ -0,0 +1,33 @@
1
+ //#region src/base-ui/FormKit/schema.d.ts
2
+ interface StandardSchemaIssue {
3
+ message: string;
4
+ path?: ReadonlyArray<PropertyKey | {
5
+ key: PropertyKey;
6
+ }>;
7
+ }
8
+ interface StandardSchema<Input = unknown, Output = Input> {
9
+ readonly '~standard': {
10
+ readonly types?: {
11
+ readonly input: Input;
12
+ readonly output: Output;
13
+ };
14
+ readonly validate: (value: unknown) => {
15
+ readonly issues?: undefined;
16
+ readonly value: Output;
17
+ } | {
18
+ readonly issues: ReadonlyArray<StandardSchemaIssue>;
19
+ } | Promise<{
20
+ readonly issues?: undefined;
21
+ readonly value: Output;
22
+ } | {
23
+ readonly issues: ReadonlyArray<StandardSchemaIssue>;
24
+ }>;
25
+ readonly vendor: string;
26
+ readonly version: 1;
27
+ };
28
+ }
29
+ type InferSchemaInput<S> = S extends StandardSchema<infer I, any> ? I : never;
30
+ type FieldValidate = StandardSchema | ((value: any, values: any) => string | undefined | Promise<string | undefined>);
31
+ //#endregion
32
+ export { FieldValidate, InferSchemaInput, StandardSchema, StandardSchemaIssue };
33
+ //# sourceMappingURL=schema.d.mts.map
@@ -0,0 +1,23 @@
1
+ //#region src/base-ui/FormKit/schema.ts
2
+ const isStandardSchema = (value) => typeof value === "object" && value !== null && "~standard" in value;
3
+ const issuePath = (issue) => (issue.path ?? []).map((segment) => String(typeof segment === "object" ? segment.key : segment)).join(".");
4
+ const schemaToFormValidator = (schema) => async (values) => {
5
+ const result = await schema["~standard"].validate(values);
6
+ if (!result.issues) return void 0;
7
+ const errors = {};
8
+ for (const issue of result.issues) {
9
+ const path = issuePath(issue);
10
+ if (errors[path] === void 0) errors[path] = issue.message;
11
+ }
12
+ return errors;
13
+ };
14
+ const toFieldValidator = (validate) => {
15
+ if (!isStandardSchema(validate)) return validate;
16
+ return async (value) => {
17
+ return (await validate["~standard"].validate(value)).issues?.[0]?.message;
18
+ };
19
+ };
20
+ //#endregion
21
+ export { isStandardSchema, schemaToFormValidator, toFieldValidator };
22
+
23
+ //# sourceMappingURL=schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.mjs","names":[],"sources":["../../../src/base-ui/FormKit/schema.ts"],"sourcesContent":["import type { FieldValidator, FormValidator } from './engine/types';\n\nexport interface StandardSchemaIssue {\n message: string;\n path?: ReadonlyArray<PropertyKey | { key: PropertyKey }>;\n}\n\nexport interface StandardSchema<Input = unknown, Output = Input> {\n readonly '~standard': {\n readonly types?: { readonly input: Input; readonly output: Output };\n readonly validate: (\n value: unknown,\n ) =>\n | { readonly issues?: undefined; readonly value: Output }\n | { readonly issues: ReadonlyArray<StandardSchemaIssue> }\n | Promise<\n | { readonly issues?: undefined; readonly value: Output }\n | { readonly issues: ReadonlyArray<StandardSchemaIssue> }\n >;\n readonly vendor: string;\n readonly version: 1;\n };\n}\n\nexport type InferSchemaInput<S> = S extends StandardSchema<infer I, any> ? I : never;\n\nexport type FieldValidate =\n StandardSchema | ((value: any, values: any) => string | undefined | Promise<string | undefined>);\n\nexport const isStandardSchema = (value: unknown): value is StandardSchema =>\n typeof value === 'object' && value !== null && '~standard' in value;\n\nconst issuePath = (issue: StandardSchemaIssue) =>\n (issue.path ?? [])\n .map((segment) => String(typeof segment === 'object' ? segment.key : segment))\n .join('.');\n\nexport const schemaToFormValidator =\n (schema: StandardSchema): FormValidator =>\n async (values) => {\n const result = await schema['~standard'].validate(values);\n if (!result.issues) return undefined;\n const errors: Record<string, string> = {};\n for (const issue of result.issues) {\n const path = issuePath(issue);\n if (errors[path] === undefined) errors[path] = issue.message;\n }\n return errors;\n };\n\nexport const toFieldValidator = (validate: FieldValidate): FieldValidator => {\n if (!isStandardSchema(validate)) return validate;\n return async (value) => {\n const result = await validate['~standard'].validate(value);\n return result.issues?.[0]?.message;\n };\n};\n"],"mappings":";AA6BA,MAAa,oBAAoB,UAC/B,OAAO,UAAU,YAAY,UAAU,QAAQ,eAAe;AAEhE,MAAM,aAAa,WAChB,MAAM,QAAQ,CAAC,EAAA,CACb,KAAK,YAAY,OAAO,OAAO,YAAY,WAAW,QAAQ,MAAM,OAAO,CAAC,CAAC,CAC7E,KAAK,GAAG;AAEb,MAAa,yBACV,WACD,OAAO,WAAW;CAChB,MAAM,SAAS,MAAM,OAAO,YAAY,CAAC,SAAS,MAAM;CACxD,IAAI,CAAC,OAAO,QAAQ,OAAO,KAAA;CAC3B,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,OAAO,UAAU,KAAK;EAC5B,IAAI,OAAO,UAAU,KAAA,GAAW,OAAO,QAAQ,MAAM;CACvD;CACA,OAAO;AACT;AAEF,MAAa,oBAAoB,aAA4C;CAC3E,IAAI,CAAC,iBAAiB,QAAQ,GAAG,OAAO;CACxC,OAAO,OAAO,UAAU;EAEtB,QAAO,MADc,SAAS,YAAY,CAAC,SAAS,KAAK,EAAA,CAC3C,SAAS,EAAE,EAAE;CAC7B;AACF"}