@timeax/form-palette 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.scaffold-cache.json +537 -0
- package/package.json +42 -0
- package/src/.scaffold-cache.json +544 -0
- package/src/adapters/axios.ts +117 -0
- package/src/adapters/index.ts +91 -0
- package/src/adapters/inertia.ts +187 -0
- package/src/core/adapter-registry.ts +87 -0
- package/src/core/bound/bind-host.ts +14 -0
- package/src/core/bound/observe-bound-field.ts +172 -0
- package/src/core/bound/wait-for-bound-field.ts +57 -0
- package/src/core/context.ts +23 -0
- package/src/core/core-provider.tsx +818 -0
- package/src/core/core-root.tsx +72 -0
- package/src/core/core-shell.tsx +44 -0
- package/src/core/errors/error-strip.tsx +71 -0
- package/src/core/errors/index.ts +2 -0
- package/src/core/errors/map-error-bag.ts +51 -0
- package/src/core/errors/map-zod.ts +39 -0
- package/src/core/hooks/use-button.ts +220 -0
- package/src/core/hooks/use-core-context.ts +20 -0
- package/src/core/hooks/use-core-utility.ts +0 -0
- package/src/core/hooks/use-core.ts +13 -0
- package/src/core/hooks/use-field.ts +497 -0
- package/src/core/hooks/use-optional-field.ts +28 -0
- package/src/core/index.ts +0 -0
- package/src/core/registry/binder-registry.ts +82 -0
- package/src/core/registry/field-registry.ts +187 -0
- package/src/core/test.tsx +17 -0
- package/src/global.d.ts +14 -0
- package/src/index.ts +68 -0
- package/src/input/index.ts +4 -0
- package/src/input/input-field.tsx +854 -0
- package/src/input/input-layout-graph.ts +230 -0
- package/src/input/input-props.ts +190 -0
- package/src/lib/get-global-countries.ts +87 -0
- package/src/lib/utils.ts +6 -0
- package/src/presets/index.ts +0 -0
- package/src/presets/shadcn-preset.ts +0 -0
- package/src/presets/shadcn-variants/checkbox.tsx +849 -0
- package/src/presets/shadcn-variants/chips.tsx +756 -0
- package/src/presets/shadcn-variants/color.tsx +284 -0
- package/src/presets/shadcn-variants/custom.tsx +227 -0
- package/src/presets/shadcn-variants/date.tsx +796 -0
- package/src/presets/shadcn-variants/file.tsx +764 -0
- package/src/presets/shadcn-variants/keyvalue.tsx +556 -0
- package/src/presets/shadcn-variants/multiselect.tsx +1132 -0
- package/src/presets/shadcn-variants/number.tsx +176 -0
- package/src/presets/shadcn-variants/password.tsx +737 -0
- package/src/presets/shadcn-variants/phone.tsx +628 -0
- package/src/presets/shadcn-variants/radio.tsx +578 -0
- package/src/presets/shadcn-variants/select.tsx +956 -0
- package/src/presets/shadcn-variants/slider.tsx +622 -0
- package/src/presets/shadcn-variants/text.tsx +343 -0
- package/src/presets/shadcn-variants/textarea.tsx +66 -0
- package/src/presets/shadcn-variants/toggle.tsx +218 -0
- package/src/presets/shadcn-variants/treeselect.tsx +784 -0
- package/src/presets/ui/badge.tsx +46 -0
- package/src/presets/ui/button.tsx +60 -0
- package/src/presets/ui/calendar.tsx +214 -0
- package/src/presets/ui/checkbox.tsx +115 -0
- package/src/presets/ui/custom.tsx +0 -0
- package/src/presets/ui/dialog.tsx +141 -0
- package/src/presets/ui/field.tsx +246 -0
- package/src/presets/ui/input-mask.tsx +739 -0
- package/src/presets/ui/input-otp.tsx +77 -0
- package/src/presets/ui/input.tsx +1011 -0
- package/src/presets/ui/label.tsx +22 -0
- package/src/presets/ui/number.tsx +1370 -0
- package/src/presets/ui/popover.tsx +46 -0
- package/src/presets/ui/radio-group.tsx +43 -0
- package/src/presets/ui/scroll-area.tsx +56 -0
- package/src/presets/ui/select.tsx +190 -0
- package/src/presets/ui/separator.tsx +28 -0
- package/src/presets/ui/slider.tsx +61 -0
- package/src/presets/ui/switch.tsx +32 -0
- package/src/presets/ui/textarea.tsx +634 -0
- package/src/presets/ui/time-dropdowns.tsx +350 -0
- package/src/schema/adapter.ts +217 -0
- package/src/schema/core.ts +429 -0
- package/src/schema/field-map.ts +0 -0
- package/src/schema/field.ts +224 -0
- package/src/schema/index.ts +0 -0
- package/src/schema/input-field.ts +260 -0
- package/src/schema/presets.ts +0 -0
- package/src/schema/variant.ts +216 -0
- package/src/variants/core/checkbox.tsx +54 -0
- package/src/variants/core/chips.tsx +22 -0
- package/src/variants/core/color.tsx +16 -0
- package/src/variants/core/custom.tsx +18 -0
- package/src/variants/core/date.tsx +25 -0
- package/src/variants/core/file.tsx +9 -0
- package/src/variants/core/keyvalue.tsx +12 -0
- package/src/variants/core/multiselect.tsx +28 -0
- package/src/variants/core/number.tsx +115 -0
- package/src/variants/core/password.tsx +35 -0
- package/src/variants/core/phone.tsx +16 -0
- package/src/variants/core/radio.tsx +38 -0
- package/src/variants/core/select.tsx +15 -0
- package/src/variants/core/slider.tsx +55 -0
- package/src/variants/core/text.tsx +114 -0
- package/src/variants/core/textarea.tsx +22 -0
- package/src/variants/core/toggle.tsx +50 -0
- package/src/variants/core/treeselect.tsx +11 -0
- package/src/variants/helpers/selection-summary.tsx +236 -0
- package/src/variants/index.ts +75 -0
- package/src/variants/registry.ts +38 -0
- package/src/variants/select-shared.ts +0 -0
- package/src/variants/shared.ts +126 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
// src/schema/core.ts
|
|
2
|
+
// noinspection JSUnusedGlobalSymbols,GrazieInspection
|
|
3
|
+
|
|
4
|
+
import type React from "react";
|
|
5
|
+
import type { z } from "zod";
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
Method,
|
|
9
|
+
AdapterResult,
|
|
10
|
+
AdapterKey,
|
|
11
|
+
AdapterSubmit,
|
|
12
|
+
} from "./adapter";
|
|
13
|
+
import type { ButtonRef, Field } from "./field";
|
|
14
|
+
import { FieldRegistry } from "@/core/registry/field-registry";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generic dictionary type used throughout the core.
|
|
18
|
+
*
|
|
19
|
+
* This matches the legacy Dict<T> from the old types.ts.
|
|
20
|
+
*/
|
|
21
|
+
export type Dict<T = unknown> = Record<string, T>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* If a Zod schema is present, infer the values from that schema;
|
|
25
|
+
* otherwise use the fallback V type. Ensured to be a Dict so it
|
|
26
|
+
* can safely be used as CoreContext's generic argument.
|
|
27
|
+
*/
|
|
28
|
+
export type InferFromSchema<S, V extends Dict> = S extends z.ZodType
|
|
29
|
+
? z.infer<S> & Dict
|
|
30
|
+
: V;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Event object passed to onSubmit, matching the legacy SubmitEvent
|
|
34
|
+
* but kept transport-agnostic. The host decides how route/method/xhr
|
|
35
|
+
* are interpreted and which adapter is used.
|
|
36
|
+
*
|
|
37
|
+
* @template TValues Shape of the outbound data for this submit event.
|
|
38
|
+
*/
|
|
39
|
+
export type SubmitEvent<TValues extends Dict> = {
|
|
40
|
+
/**
|
|
41
|
+
* Prevent the default submit behavior.
|
|
42
|
+
*
|
|
43
|
+
* In practice this prevents the core from continuing with its
|
|
44
|
+
* normal submit/prepare flow.
|
|
45
|
+
*/
|
|
46
|
+
preventDefault(): void;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Mutate the outbound data just before it is used.
|
|
50
|
+
*
|
|
51
|
+
* The callback may return a new data object or mutate in-place.
|
|
52
|
+
*/
|
|
53
|
+
editData(cb: (data: TValues) => TValues | void): void;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Override the route/URL for this submission only.
|
|
57
|
+
*
|
|
58
|
+
* The core itself does not enforce any semantics here; the host
|
|
59
|
+
* is expected to interpret this when wiring submissions.
|
|
60
|
+
*/
|
|
61
|
+
setRoute(route: string): void;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Override the HTTP method for this submission only.
|
|
65
|
+
*/
|
|
66
|
+
setMethod(method: Method): void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The button that triggered this submit, if any.
|
|
70
|
+
*/
|
|
71
|
+
button?: ButtonRef;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The current outbound data snapshot (after any internal merges).
|
|
75
|
+
*/
|
|
76
|
+
readonly formData: TValues;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The core context associated with this submit event.
|
|
80
|
+
*/
|
|
81
|
+
form: CoreContext<TValues>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* If set to false, the core will abort the submit flow after
|
|
85
|
+
* this handler returns.
|
|
86
|
+
*/
|
|
87
|
+
continue: boolean;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Shared base props for the core runtime, matching the spirit of
|
|
92
|
+
* the legacy BaseProps, but transport-agnostic.
|
|
93
|
+
*
|
|
94
|
+
* @template V Shape of the underlying value map (pre-schema).
|
|
95
|
+
* @template S Optional Zod schema type.
|
|
96
|
+
*/
|
|
97
|
+
export type BaseProps<V extends Dict, S extends z.ZodType | undefined> = {
|
|
98
|
+
/**
|
|
99
|
+
* Field names that should be ignored when building diffs or snapshots.
|
|
100
|
+
* Useful for excluding secrets like passwords from logs.
|
|
101
|
+
*/
|
|
102
|
+
exceptions?: string[];
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Whether the core should persist values to the provided valueBag.
|
|
106
|
+
*/
|
|
107
|
+
persist?: boolean;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Optional logical name for the core instance.
|
|
111
|
+
*/
|
|
112
|
+
name?: string;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* If true, a button may be automatically marked as "active" when
|
|
116
|
+
* certain changes occur.
|
|
117
|
+
*/
|
|
118
|
+
activateButtonOnChange?: boolean;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Called whenever a field changes.
|
|
122
|
+
*
|
|
123
|
+
* current is the field that changed; options carries any
|
|
124
|
+
* variant-specific metadata.
|
|
125
|
+
*/
|
|
126
|
+
onChange?(
|
|
127
|
+
form: CoreContext<InferFromSchema<S, V>>,
|
|
128
|
+
current: Field,
|
|
129
|
+
options: Dict
|
|
130
|
+
): void;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Called when the overall values snapshot is considered "updated".
|
|
134
|
+
*/
|
|
135
|
+
onUpdate?(values: InferFromSchema<S, V>): void;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* If true, onChange may run before certain internal updates.
|
|
139
|
+
*/
|
|
140
|
+
changeBefore?: boolean;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Optional ref to the core context instance, for imperative access.
|
|
144
|
+
*/
|
|
145
|
+
formRef?: React.MutableRefObject<CoreContext<InferFromSchema<S, V>> | null>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Initial value bag for hydration / persistence.
|
|
149
|
+
*/
|
|
150
|
+
valueBag?: InferFromSchema<S, V>;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Optional hook used to transform a single value as it is being
|
|
154
|
+
* persisted or fed into the core.
|
|
155
|
+
*/
|
|
156
|
+
valueFeed?: <K extends keyof InferFromSchema<S, V>>(
|
|
157
|
+
name: K,
|
|
158
|
+
value: InferFromSchema<S, V>[K],
|
|
159
|
+
form: CoreContext<InferFromSchema<S, V>>
|
|
160
|
+
) => InferFromSchema<S, V>[K] | undefined;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Called at the end of certain flows (legacy "finish" hook).
|
|
164
|
+
*
|
|
165
|
+
* Receives the core context so you can read values, errors, etc.
|
|
166
|
+
*/
|
|
167
|
+
onFinish?(form: CoreContext<InferFromSchema<S, V>>): void;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Called after the core initializes.
|
|
171
|
+
*/
|
|
172
|
+
init?(form: CoreContext<InferFromSchema<S, V>>): void;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Intercepts the submit event before the core proceeds.
|
|
176
|
+
*
|
|
177
|
+
* You can:
|
|
178
|
+
* - mutate data,
|
|
179
|
+
* - change route/method/xhr flags,
|
|
180
|
+
* - abort by setting e.continue = false.
|
|
181
|
+
*/
|
|
182
|
+
onSubmit?<T extends Dict = InferFromSchema<S, V>>(
|
|
183
|
+
e: SubmitEvent<T>
|
|
184
|
+
): Promise<void> | void;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Optional Zod schema used for validation and value inference.
|
|
188
|
+
*/
|
|
189
|
+
schema?: S;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Public core props, adapter-centric.
|
|
194
|
+
*
|
|
195
|
+
* - The library defines a built-in 'local' adapter flavour.
|
|
196
|
+
* AdapterSubmit<'local'> is `{ data: unknown }`.
|
|
197
|
+
* - Hosts can extend the Adapters interface (schema/adapter.ts) to add
|
|
198
|
+
* their own adapter flavours (axios, inertia, etc.) and then use
|
|
199
|
+
* those keys here.
|
|
200
|
+
*
|
|
201
|
+
* @template V Shape of the underlying value map (pre-schema).
|
|
202
|
+
* @template S Optional Zod schema type.
|
|
203
|
+
* @template K Adapter key; defaults to 'local'.
|
|
204
|
+
*/
|
|
205
|
+
export interface CoreProps<
|
|
206
|
+
V extends Dict,
|
|
207
|
+
S extends z.ZodType | undefined,
|
|
208
|
+
K extends AdapterKey = "local",
|
|
209
|
+
> extends BaseProps<V, S> {
|
|
210
|
+
/**
|
|
211
|
+
* Which adapter flavour this core instance should use.
|
|
212
|
+
*
|
|
213
|
+
* - 'local' (default) → library-defined local submission (no URL/method semantics).
|
|
214
|
+
* - extended keys → host-defined adapters via Adapters augmentation.
|
|
215
|
+
*/
|
|
216
|
+
adapter?: K;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Called after a submission completes. The payload type is derived from
|
|
220
|
+
* the selected adapter key via the adapter registry:
|
|
221
|
+
*
|
|
222
|
+
* AdapterSubmit<'local'> → { data: unknown }
|
|
223
|
+
* AdapterSubmit<'axios'> → host-defined type, etc.
|
|
224
|
+
*/
|
|
225
|
+
onSubmitted?(
|
|
226
|
+
form: CoreContext<InferFromSchema<S, V>>,
|
|
227
|
+
payload: AdapterSubmit<K>,
|
|
228
|
+
resolve?: () => void
|
|
229
|
+
): void | Promise<void>;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Backwards-compatible alias for legacy naming, if you want it.
|
|
234
|
+
*/
|
|
235
|
+
export type FormProps<
|
|
236
|
+
V extends Dict,
|
|
237
|
+
S extends z.ZodType | undefined,
|
|
238
|
+
K extends AdapterKey = "local",
|
|
239
|
+
> = CoreProps<V, S, K>;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Result of a submit operation: values + validity flag.
|
|
243
|
+
*/
|
|
244
|
+
export type ValuesResult<V extends Dict> = { values: V; valid: boolean };
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Query API for fields, similar to DOM helpers but scoped
|
|
248
|
+
* to the current form instance.
|
|
249
|
+
*
|
|
250
|
+
* "id" here refers to the field's groupId.
|
|
251
|
+
*/
|
|
252
|
+
export interface InputStore {
|
|
253
|
+
/** All registered inputs (with at least one identifier). */
|
|
254
|
+
all(): Field[];
|
|
255
|
+
|
|
256
|
+
/** All inputs that have a non-empty name. */
|
|
257
|
+
getAllNamed(): Field[];
|
|
258
|
+
|
|
259
|
+
/** All inputs that have a bindId. */
|
|
260
|
+
getAllBound(): Field[];
|
|
261
|
+
|
|
262
|
+
/** All inputs that have a groupId. */
|
|
263
|
+
getAllGrouped(): Field[];
|
|
264
|
+
|
|
265
|
+
/** First field matching an exact name. */
|
|
266
|
+
getByName(name: string): Field | undefined;
|
|
267
|
+
|
|
268
|
+
/** All fields matching an exact name. */
|
|
269
|
+
getAllByName(name: string): Field[];
|
|
270
|
+
|
|
271
|
+
/** First field with this groupId. */
|
|
272
|
+
getById(id: string): Field | undefined;
|
|
273
|
+
|
|
274
|
+
/** All fields with this groupId. */
|
|
275
|
+
getAllById(id: string): Field[];
|
|
276
|
+
|
|
277
|
+
/** First bound field with this bindId (prefers mounted fields). */
|
|
278
|
+
getByBind(id: string): Field | undefined;
|
|
279
|
+
|
|
280
|
+
/** All fields that share this bindId. */
|
|
281
|
+
getAllByBind(id: string): Field[];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Core runtime context, renamed from the legacy FormContext.
|
|
286
|
+
*
|
|
287
|
+
* @template V Shape of the values object produced by this core instance.
|
|
288
|
+
*/
|
|
289
|
+
export interface CoreContext<V extends Dict> {
|
|
290
|
+
/**
|
|
291
|
+
* Compute the current values snapshot from registered fields.
|
|
292
|
+
*/
|
|
293
|
+
values(): V;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Run validation and return the values + validity flag.
|
|
297
|
+
*/
|
|
298
|
+
submit(): ValuesResult<V>;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Lookup a field by its binding id.
|
|
302
|
+
*/
|
|
303
|
+
getBind(id: string): Field | undefined;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Run validation across fields.
|
|
307
|
+
*
|
|
308
|
+
* @param report If true, fields should update their own error states.
|
|
309
|
+
* @returns true if all fields are valid, false otherwise.
|
|
310
|
+
*/
|
|
311
|
+
validate(report?: boolean): boolean;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Register a new field with the core.
|
|
315
|
+
*/
|
|
316
|
+
addField(field: Field): void;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Generic internal bucket for arbitrary metadata.
|
|
320
|
+
*/
|
|
321
|
+
bucket: Dict;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Set a single field error or map an error bag.
|
|
325
|
+
*/
|
|
326
|
+
error(name: string, msg: string): void;
|
|
327
|
+
error(bag: Record<string, string>): void;
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Re-run button control logic (which button is active/disabled etc.).
|
|
331
|
+
*/
|
|
332
|
+
controlButton(): void;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Prepare an adapter-backed request.
|
|
336
|
+
*
|
|
337
|
+
* This mirrors the legacy prepare method:
|
|
338
|
+
* - Builds a payload from values + extra.
|
|
339
|
+
* - May run validation / beforeSubmit hooks.
|
|
340
|
+
* - Returns an adapter result or undefined if aborted.
|
|
341
|
+
*
|
|
342
|
+
* The concrete adapter wiring is the host's responsibility.
|
|
343
|
+
*/
|
|
344
|
+
prepare(
|
|
345
|
+
type: Method,
|
|
346
|
+
route: string,
|
|
347
|
+
extra?: Partial<V>,
|
|
348
|
+
ignoreForm?: boolean,
|
|
349
|
+
autoErr?: boolean
|
|
350
|
+
): Promise<AdapterResult<any> | undefined>;
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Persist values to a provided data object, optionally transforming
|
|
354
|
+
* values via the feed function.
|
|
355
|
+
*/
|
|
356
|
+
persist(
|
|
357
|
+
data: Partial<V>,
|
|
358
|
+
feed?: (name: string, value: unknown, original: unknown) => unknown
|
|
359
|
+
): void;
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Imperatively set a single value by field name.
|
|
363
|
+
*/
|
|
364
|
+
setValue(name: string, value: unknown): void;
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Kick off a submit flow using optional extra data.
|
|
368
|
+
*/
|
|
369
|
+
go(data?: Partial<V>, ignoreForm?: boolean): void;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Reset specific inputs by name.
|
|
373
|
+
*/
|
|
374
|
+
reset(inputs: string[]): void;
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Register the current active button.
|
|
378
|
+
*/
|
|
379
|
+
set button(v: ButtonRef);
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Force a submit regardless of validation state.
|
|
383
|
+
*/
|
|
384
|
+
forceSubmit(): Promise<void>;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* All registered fields.
|
|
388
|
+
*/
|
|
389
|
+
readonly fields: Field[];
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Effective core props at runtime, excluding internal-only fields.
|
|
393
|
+
*
|
|
394
|
+
* Note: the adapter key parameter is erased here (set to any) because
|
|
395
|
+
* the runtime does not need the specific key for structural typing;
|
|
396
|
+
* hosts can still use more precise generics at the component level.
|
|
397
|
+
*/
|
|
398
|
+
readonly props: Omit<
|
|
399
|
+
CoreProps<V, z.ZodType | undefined, any>,
|
|
400
|
+
"formRef" | "valueBag"
|
|
401
|
+
>;
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Mark a button as active by name.
|
|
405
|
+
*/
|
|
406
|
+
setActiveButton(name: string): void;
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Return uncaught messages (errors that could not be mapped to a field).
|
|
410
|
+
*
|
|
411
|
+
* Typically used by an error strip component.
|
|
412
|
+
*/
|
|
413
|
+
|
|
414
|
+
getUncaught(): readonly string[];
|
|
415
|
+
/**
|
|
416
|
+
* Field-query "DOM" for this form.
|
|
417
|
+
*
|
|
418
|
+
* Example:
|
|
419
|
+
* const email = form.inputs.getByName("email");
|
|
420
|
+
* const phoneFields = form.inputs.getAllById("phone-group");
|
|
421
|
+
* const bound = form.inputs.getByBind("shipping");
|
|
422
|
+
*/
|
|
423
|
+
inputs: Omit<FieldRegistry, "add" | "remove">;
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Checks if the form values have changed
|
|
427
|
+
*/
|
|
428
|
+
isDirty(): boolean
|
|
429
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// src/schema/field.ts
|
|
2
|
+
// noinspection GrazieInspection
|
|
3
|
+
|
|
4
|
+
import type { RefObject } from "react";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Imperative handle for a submit button registered with the core.
|
|
8
|
+
*
|
|
9
|
+
* This mirrors the legacy `ButtonRef` interface, but is aligned with the
|
|
10
|
+
* current CoreProvider implementation:
|
|
11
|
+
*
|
|
12
|
+
* - The core will try `setLoading(v)` / `setDisabled(v)` if available.
|
|
13
|
+
* - Otherwise, it will fall back to setting `loading` / `disabled` props.
|
|
14
|
+
*/
|
|
15
|
+
export interface ButtonRef {
|
|
16
|
+
/**
|
|
17
|
+
* Logical name of the button.
|
|
18
|
+
*
|
|
19
|
+
* Used by the core runtime to track the "active" button
|
|
20
|
+
* and to map behaviours to a specific action.
|
|
21
|
+
*/
|
|
22
|
+
name: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Loading flag. The core may read or assign this directly if
|
|
26
|
+
* no setter is provided.
|
|
27
|
+
*/
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Disabled flag. The core may read or assign this directly if
|
|
32
|
+
* no setter is provided.
|
|
33
|
+
*/
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Optional setter used by the core to toggle loading.
|
|
38
|
+
*/
|
|
39
|
+
setLoading?(v: boolean): void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Optional setter used by the core to toggle disabled state.
|
|
43
|
+
*/
|
|
44
|
+
setDisabled?(v: boolean): void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Runtime representation of a single field registered with the core.
|
|
49
|
+
*
|
|
50
|
+
* This is a direct, type-safe evolution of the legacy `Field` interface
|
|
51
|
+
* from the old `types.ts`, updated to match the new core + binder flow.
|
|
52
|
+
*/
|
|
53
|
+
export interface Field {
|
|
54
|
+
/**
|
|
55
|
+
* Primary field name, used in values, error bags, and schema mapping.
|
|
56
|
+
*
|
|
57
|
+
* May be omitted for purely bound/virtual fields that participate in
|
|
58
|
+
* binder flows but are not directly part of the value bag.
|
|
59
|
+
*/
|
|
60
|
+
name?: string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Internal binding identifier.
|
|
64
|
+
*
|
|
65
|
+
* Used by "bound" helpers (observe-bound-field, wait-for-bound-field)
|
|
66
|
+
* to locate shared/aliased fields without going through the name.
|
|
67
|
+
*/
|
|
68
|
+
bindId?: string;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Optional explicit binding identifier.
|
|
72
|
+
* Use to bind to a specific field in a nested object that has bindId
|
|
73
|
+
*/
|
|
74
|
+
bind?: string;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Ref to the underlying DOM element used for focus/scroll operations.
|
|
78
|
+
*
|
|
79
|
+
* Implementations typically point this at the outer wrapper of the field.
|
|
80
|
+
*/
|
|
81
|
+
ref?: RefObject<HTMLElement> | null;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Whether this field is required.
|
|
85
|
+
*
|
|
86
|
+
* Variant-level and schema-level validation may use this.
|
|
87
|
+
*/
|
|
88
|
+
required?: boolean;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Current error message for the field.
|
|
92
|
+
*
|
|
93
|
+
* Undefined or empty string means "no error".
|
|
94
|
+
*/
|
|
95
|
+
error?: string;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Current value of the field, as seen by the core runtime.
|
|
99
|
+
*
|
|
100
|
+
* For formatted inputs, this may be the formatted representation.
|
|
101
|
+
*/
|
|
102
|
+
value?: unknown;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Initial/default value for the field.
|
|
106
|
+
*
|
|
107
|
+
* This is typically the "un-touched" value coming from props or
|
|
108
|
+
* from a persisted value bag.
|
|
109
|
+
*/
|
|
110
|
+
defaultValue?: unknown;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Original, unformatted value as first seen by the core.
|
|
114
|
+
*
|
|
115
|
+
* This allows callers to compare "what changed" relative to the
|
|
116
|
+
* original snapshot, independent of any display formatting.
|
|
117
|
+
*/
|
|
118
|
+
originalValue?: unknown;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Whether this field is currently performing an async operation
|
|
122
|
+
* (e.g. remote validation).
|
|
123
|
+
*/
|
|
124
|
+
loading?: boolean;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Optional group identifier used to group related fields together
|
|
128
|
+
* (e.g. radio groups, segmented inputs).
|
|
129
|
+
*/
|
|
130
|
+
groupId?: string;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Optional alias for this field.
|
|
134
|
+
*
|
|
135
|
+
* Aliases allow mapping server error bags or schema keys that do
|
|
136
|
+
* not strictly match the `name` property.
|
|
137
|
+
*/
|
|
138
|
+
alias?: string;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Marks this field as the "main" one in a group.
|
|
142
|
+
*
|
|
143
|
+
* Used by some variants/layouts to determine which field drives
|
|
144
|
+
* overall group state.
|
|
145
|
+
*/
|
|
146
|
+
main?: boolean;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* If true, this field will be ignored when building values or
|
|
150
|
+
* running certain validation flows.
|
|
151
|
+
*/
|
|
152
|
+
ignore?: boolean;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Stable unique key (distinct from `name` and `bindId`).
|
|
156
|
+
*
|
|
157
|
+
* Used internally by registries and React lists.
|
|
158
|
+
*/
|
|
159
|
+
key?: string;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Shared key for fields that share their value (e.g. custom views
|
|
163
|
+
* over the same underlying data).
|
|
164
|
+
*
|
|
165
|
+
* This is used by the core when building nested objects, e.g.:
|
|
166
|
+
* shared = "profile", name = "first_name"
|
|
167
|
+
* ⇒ values.profile.first_name
|
|
168
|
+
*/
|
|
169
|
+
shared?: string;
|
|
170
|
+
|
|
171
|
+
// ─────────────────────────────────────────────────────────
|
|
172
|
+
// Behaviour hooks (implemented by InputField / variants)
|
|
173
|
+
// ─────────────────────────────────────────────────────────
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Run validation for this field.
|
|
177
|
+
*
|
|
178
|
+
* @param report If true, the field should update its own error state;
|
|
179
|
+
* if false, it may simply return whether it is valid.
|
|
180
|
+
* @returns `true` if the field is currently valid, `false` otherwise.
|
|
181
|
+
*/
|
|
182
|
+
validate?(report?: boolean): boolean;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Optional hook used by the core or higher-level utilities to retrieve
|
|
186
|
+
* the current value of the field.
|
|
187
|
+
*
|
|
188
|
+
* If omitted, the core will fall back to the `value` property.
|
|
189
|
+
*/
|
|
190
|
+
getValue?(): unknown;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Optional hook used by the core or higher-level utilities to update
|
|
194
|
+
* the current value of the field.
|
|
195
|
+
*
|
|
196
|
+
* If omitted, the core will fall back to mutating the `value` property.
|
|
197
|
+
*/
|
|
198
|
+
setValue?(value: unknown): void;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Optional hook used by the core to reset the field back to its
|
|
202
|
+
* default/original value.
|
|
203
|
+
*/
|
|
204
|
+
reset?(): void;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Optional hook used by the core to set or clear the field error.
|
|
208
|
+
*
|
|
209
|
+
* If omitted, the core will fall back to assigning the `error` property.
|
|
210
|
+
*/
|
|
211
|
+
setError?(message?: string): void;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Optional hook called whenever the field value changes.
|
|
215
|
+
*
|
|
216
|
+
* Used by binder utilities to propagate changes across bound fields.
|
|
217
|
+
*
|
|
218
|
+
* @param value New value.
|
|
219
|
+
* @param old Previous value.
|
|
220
|
+
* @param source Source tag responsible for the change
|
|
221
|
+
* (e.g. "variant", "util", "paste", "programmatic").
|
|
222
|
+
*/
|
|
223
|
+
onChange?(value: unknown, old: unknown, source: string): void;
|
|
224
|
+
}
|
|
File without changes
|