jsonisch 0.1.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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +218 -0
- package/dist/form-ref-BEri3JKv.js +1123 -0
- package/dist/form-ref-D_xHSaqL.d.ts +994 -0
- package/dist/handle-submit-CD3WY9gW.js +208 -0
- package/dist/handle-submit-Dk7QW3_q.d.ts +34 -0
- package/dist/index.d.ts +724 -0
- package/dist/index.js +1521 -0
- package/dist/plugin/index.d.ts +188 -0
- package/dist/plugin/index.js +4 -0
- package/dist/plugin-BCsAE8RK.d.ts +612 -0
- package/dist/plugin-Qka-vaO1.js +1545 -0
- package/dist/react/index.d.ts +476 -0
- package/dist/react/index.js +456 -0
- package/docs/decode-fork.md +24 -0
- package/docs/plugin-lifecycle.md +44 -0
- package/docs/rerender-history.md +61 -0
- package/docs/wire-shapes.md +70 -0
- package/package.json +87 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { C as FieldErrors, G as JsonSchema, K as Path, M as ControlKind, S as FieldElement, a as InternalFormStore, i as FormValidator, r as FormConfig } from "../form-ref-D_xHSaqL.js";
|
|
2
|
+
import { t as SubmitHandler } from "../handle-submit-Dk7QW3_q.js";
|
|
3
|
+
import { ComponentType, FormHTMLAttributes, ReactElement, ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/react/types.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The public form store returned by `useForm`/`useAppForm`: an immutable
|
|
9
|
+
* snapshot whose identity changes when any observed form-level value
|
|
10
|
+
* changes — reactivity rides on the object, not on property reads, so it
|
|
11
|
+
* composes with React Compiler memoization. The internal store is
|
|
12
|
+
* reachable for the methods layer — every method accepts this wrapper
|
|
13
|
+
* directly.
|
|
14
|
+
*/
|
|
15
|
+
interface FormStore {
|
|
16
|
+
/**
|
|
17
|
+
* The internal form store (the methods layer unwraps it).
|
|
18
|
+
*/
|
|
19
|
+
readonly internal: InternalFormStore;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the form is currently submitting.
|
|
22
|
+
*/
|
|
23
|
+
readonly isSubmitting: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the form has been submitted.
|
|
26
|
+
*/
|
|
27
|
+
readonly isSubmitted: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Whether the form is currently validating.
|
|
30
|
+
*/
|
|
31
|
+
readonly isValidating: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Whether any field in the form has been touched.
|
|
34
|
+
*/
|
|
35
|
+
readonly isTouched: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Whether any field in the form has been edited.
|
|
38
|
+
*/
|
|
39
|
+
readonly isEdited: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether any field in the form differs from its start input.
|
|
42
|
+
*/
|
|
43
|
+
readonly isDirty: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Whether no field in the form has errors.
|
|
46
|
+
*/
|
|
47
|
+
readonly isValid: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* The form-level (root) errors. Use `getDeepErrors` for all field errors.
|
|
50
|
+
*/
|
|
51
|
+
readonly errors: FieldErrors;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The props a field store provides for binding a DOM element.
|
|
55
|
+
*/
|
|
56
|
+
interface FieldElementProps {
|
|
57
|
+
/**
|
|
58
|
+
* The name attribute of the field element.
|
|
59
|
+
*/
|
|
60
|
+
readonly name: string;
|
|
61
|
+
/**
|
|
62
|
+
* Whether to autofocus the element (set while the field has errors).
|
|
63
|
+
*/
|
|
64
|
+
readonly autoFocus: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* The ref callback registering the element on the field store.
|
|
67
|
+
*/
|
|
68
|
+
readonly ref: (element: FieldElement | null) => void;
|
|
69
|
+
/**
|
|
70
|
+
* The focus handler (marks the field touched). Takes no arguments so it
|
|
71
|
+
* assigns to any element's focus handler type.
|
|
72
|
+
*/
|
|
73
|
+
readonly onFocus: () => void;
|
|
74
|
+
/**
|
|
75
|
+
* The blur handler (triggers blur-mode validation). Takes no arguments so
|
|
76
|
+
* it assigns to any element's blur handler type.
|
|
77
|
+
*/
|
|
78
|
+
readonly onBlur: () => void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The plugin-contributed members of `FieldStore` — an empty marker each
|
|
82
|
+
* plugin merges its `fieldSnapshot` keys into via `declare module`
|
|
83
|
+
* augmentation IN ITS OWN FILE (fastify's decorate pattern), so widgets
|
|
84
|
+
* type-check flat members (`field.mode`, `field.setEntryMode(...)`) with
|
|
85
|
+
* no generics anywhere and ownership stays greppable. The react adapter
|
|
86
|
+
* itself knows no plugin's vocabulary; the runtime twin of this contract
|
|
87
|
+
* is `dispatchFieldSnapshot`'s collision throw.
|
|
88
|
+
*/
|
|
89
|
+
interface FieldStoreSlots {}
|
|
90
|
+
/**
|
|
91
|
+
* The public field store returned by `useField`: an immutable snapshot —
|
|
92
|
+
* a new object identity whenever any observed value changes, stable
|
|
93
|
+
* otherwise. Widgets are plain controlled components that render `input`
|
|
94
|
+
* and call `onChange` with the new value; no signal hook, no directive.
|
|
95
|
+
* Plugin-contributed members ride `FieldStoreSlots`.
|
|
96
|
+
*/
|
|
97
|
+
interface FieldStore extends FieldStoreSlots {
|
|
98
|
+
/**
|
|
99
|
+
* The path to the field within the form.
|
|
100
|
+
*/
|
|
101
|
+
readonly path: Path;
|
|
102
|
+
/**
|
|
103
|
+
* The property name of the field (last path segment).
|
|
104
|
+
*/
|
|
105
|
+
readonly name: string;
|
|
106
|
+
/**
|
|
107
|
+
* The JSON-Schema node of the field (title, enum options, formats, …).
|
|
108
|
+
*/
|
|
109
|
+
readonly schema: JsonSchema;
|
|
110
|
+
/**
|
|
111
|
+
* The widget kind the field renders as (resolved at walk time).
|
|
112
|
+
*/
|
|
113
|
+
readonly control: ControlKind;
|
|
114
|
+
/**
|
|
115
|
+
* The current input value of the field.
|
|
116
|
+
*/
|
|
117
|
+
readonly input: unknown;
|
|
118
|
+
/**
|
|
119
|
+
* The current error messages of the field.
|
|
120
|
+
*/
|
|
121
|
+
readonly errors: FieldErrors;
|
|
122
|
+
/**
|
|
123
|
+
* Whether the field (or a descendant) has been touched.
|
|
124
|
+
*/
|
|
125
|
+
readonly isTouched: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Whether the field (or a descendant) has been edited.
|
|
128
|
+
*/
|
|
129
|
+
readonly isEdited: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Whether the field (or a descendant) differs from its start input.
|
|
132
|
+
*/
|
|
133
|
+
readonly isDirty: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Whether the field and its descendants have no errors.
|
|
136
|
+
*/
|
|
137
|
+
readonly isValid: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Whether the field currently renders: `false` for a `hidden` control or
|
|
140
|
+
* while a conditional-visibility rule (`visibleWhen`) is unsatisfied.
|
|
141
|
+
* Registry dispatch skips invisible fields; headless layouts decide
|
|
142
|
+
* themselves. A hidden field keeps its state, dirtiness, and place in
|
|
143
|
+
* the payload.
|
|
144
|
+
*/
|
|
145
|
+
readonly visible: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Sets the field input (controlled-component change handler).
|
|
148
|
+
*/
|
|
149
|
+
readonly onChange: (value: unknown) => void;
|
|
150
|
+
/**
|
|
151
|
+
* The props to spread onto the field element.
|
|
152
|
+
*/
|
|
153
|
+
readonly props: FieldElementProps;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The public field array store returned by `useFieldArray`.
|
|
157
|
+
*/
|
|
158
|
+
interface FieldArrayStore {
|
|
159
|
+
/**
|
|
160
|
+
* The path to the array field within the form.
|
|
161
|
+
*/
|
|
162
|
+
readonly path: Path;
|
|
163
|
+
/**
|
|
164
|
+
* The stable item IDs, one per row — use them as React keys so state
|
|
165
|
+
* follows its row across reorders.
|
|
166
|
+
*/
|
|
167
|
+
readonly items: string[];
|
|
168
|
+
/**
|
|
169
|
+
* The current error messages of the array field itself.
|
|
170
|
+
*/
|
|
171
|
+
readonly errors: FieldErrors;
|
|
172
|
+
/**
|
|
173
|
+
* Whether the array (or a descendant) has been touched.
|
|
174
|
+
*/
|
|
175
|
+
readonly isTouched: boolean;
|
|
176
|
+
/**
|
|
177
|
+
* Whether the array (or a descendant) has been edited.
|
|
178
|
+
*/
|
|
179
|
+
readonly isEdited: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Whether the array (or a descendant) differs from its start input.
|
|
182
|
+
*/
|
|
183
|
+
readonly isDirty: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Whether the array and its descendants have no errors.
|
|
186
|
+
*/
|
|
187
|
+
readonly isValid: boolean;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The props every registry widget receives.
|
|
191
|
+
*/
|
|
192
|
+
interface WidgetProps {
|
|
193
|
+
/**
|
|
194
|
+
* The field store the widget renders.
|
|
195
|
+
*/
|
|
196
|
+
readonly field: FieldStore;
|
|
197
|
+
/**
|
|
198
|
+
* The form store the field belongs to.
|
|
199
|
+
*/
|
|
200
|
+
readonly form: FormStore;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* The configuration of `createFormHook`: the registry mapping widget kinds
|
|
204
|
+
* to components, plus the injected validator compiler.
|
|
205
|
+
*/
|
|
206
|
+
interface FormHookConfig {
|
|
207
|
+
/**
|
|
208
|
+
* The widget registry, keyed by `ControlKind`. A kind without an entry
|
|
209
|
+
* renders the `fallback`.
|
|
210
|
+
*/
|
|
211
|
+
readonly widgets: Partial<Record<ControlKind, ComponentType<WidgetProps>>>;
|
|
212
|
+
/**
|
|
213
|
+
* The widget rendered for a kind without a registry entry. Without one, a
|
|
214
|
+
* built-in placeholder names the unsupported kind visibly.
|
|
215
|
+
*/
|
|
216
|
+
readonly fallback?: ComponentType<WidgetProps> | undefined;
|
|
217
|
+
/**
|
|
218
|
+
* Compiles the injected validator for a schema, called ONCE per form
|
|
219
|
+
* (memoized by `useAppForm`). Omit for forms without enforcement.
|
|
220
|
+
*/
|
|
221
|
+
readonly validate?: ((schema: JsonSchema) => FormValidator) | undefined;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The configuration of `useAppForm`: the store config minus the validator,
|
|
225
|
+
* which the hook compiles itself via the registry's `validate`.
|
|
226
|
+
*/
|
|
227
|
+
type UseAppFormConfig = Omit<FormConfig, "validator">;
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/react/components.d.ts
|
|
230
|
+
/**
|
|
231
|
+
* Props of the headless `Form` component.
|
|
232
|
+
*/
|
|
233
|
+
interface FormProps extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "noValidate"> {
|
|
234
|
+
/**
|
|
235
|
+
* The form store instance.
|
|
236
|
+
*/
|
|
237
|
+
readonly of: FormStore;
|
|
238
|
+
/**
|
|
239
|
+
* The submit handler called with the validated output when validation
|
|
240
|
+
* succeeds.
|
|
241
|
+
*/
|
|
242
|
+
readonly onSubmit: SubmitHandler;
|
|
243
|
+
/**
|
|
244
|
+
* The form contents.
|
|
245
|
+
*/
|
|
246
|
+
readonly children?: ReactNode;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Headless form component: a native `<form noValidate>` wired to
|
|
250
|
+
* `handleSubmit` — an invalid submit blocks the handler and focuses the
|
|
251
|
+
* first erroring field. The registry-aware `Form` from `createFormHook`
|
|
252
|
+
* builds on this and adds whole-form auto-rendering.
|
|
253
|
+
*
|
|
254
|
+
* @param props The form component props.
|
|
255
|
+
*
|
|
256
|
+
* @returns A native form element.
|
|
257
|
+
*/
|
|
258
|
+
declare function Form({
|
|
259
|
+
of,
|
|
260
|
+
onSubmit,
|
|
261
|
+
...other
|
|
262
|
+
}: FormProps): ReactElement;
|
|
263
|
+
/**
|
|
264
|
+
* Props of the headless `Field` component.
|
|
265
|
+
*/
|
|
266
|
+
interface FieldProps {
|
|
267
|
+
/**
|
|
268
|
+
* The form store the field belongs to.
|
|
269
|
+
*/
|
|
270
|
+
readonly of: FormStore;
|
|
271
|
+
/**
|
|
272
|
+
* The path to the field.
|
|
273
|
+
*/
|
|
274
|
+
readonly path: Path;
|
|
275
|
+
/**
|
|
276
|
+
* The render function receiving the field store.
|
|
277
|
+
*/
|
|
278
|
+
readonly children: (field: FieldStore) => ReactNode;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Headless field component — the escape hatch for custom layouts: takes a
|
|
282
|
+
* form store and a path, and calls the render function with the reactive
|
|
283
|
+
* field store.
|
|
284
|
+
*
|
|
285
|
+
* @param props The field component props.
|
|
286
|
+
*
|
|
287
|
+
* @returns The rendered field UI.
|
|
288
|
+
*/
|
|
289
|
+
declare function Field({
|
|
290
|
+
of,
|
|
291
|
+
path,
|
|
292
|
+
children
|
|
293
|
+
}: FieldProps): ReactNode;
|
|
294
|
+
/**
|
|
295
|
+
* Props of the headless `FieldArray` component.
|
|
296
|
+
*/
|
|
297
|
+
interface FieldArrayProps {
|
|
298
|
+
/**
|
|
299
|
+
* The form store the array field belongs to.
|
|
300
|
+
*/
|
|
301
|
+
readonly of: FormStore;
|
|
302
|
+
/**
|
|
303
|
+
* The path to the array field.
|
|
304
|
+
*/
|
|
305
|
+
readonly path: Path;
|
|
306
|
+
/**
|
|
307
|
+
* The render function receiving the field array store.
|
|
308
|
+
*/
|
|
309
|
+
readonly children: (fieldArray: FieldArrayStore) => ReactNode;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Headless field array component: calls the render function with the
|
|
313
|
+
* reactive field array store (stable item IDs for React keys).
|
|
314
|
+
*
|
|
315
|
+
* @param props The field array component props.
|
|
316
|
+
*
|
|
317
|
+
* @returns The rendered field array UI.
|
|
318
|
+
*/
|
|
319
|
+
declare function FieldArray({
|
|
320
|
+
of,
|
|
321
|
+
path,
|
|
322
|
+
children
|
|
323
|
+
}: FieldArrayProps): ReactNode;
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/react/create-form-hook.d.ts
|
|
326
|
+
/**
|
|
327
|
+
* Props of the registry-aware `Field` component returned by
|
|
328
|
+
* `createFormHook`.
|
|
329
|
+
*/
|
|
330
|
+
interface AppFieldProps {
|
|
331
|
+
/**
|
|
332
|
+
* The form store the field belongs to.
|
|
333
|
+
*/
|
|
334
|
+
readonly of: FormStore;
|
|
335
|
+
/**
|
|
336
|
+
* The path to the field.
|
|
337
|
+
*/
|
|
338
|
+
readonly path: Path;
|
|
339
|
+
/**
|
|
340
|
+
* Optional render function for a custom layout (headless mode). Without
|
|
341
|
+
* it the field renders its registry widget.
|
|
342
|
+
*/
|
|
343
|
+
readonly children?: ((field: FieldStore) => ReactNode) | undefined;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* The bound form API returned by `createFormHook`.
|
|
347
|
+
*/
|
|
348
|
+
interface FormHook {
|
|
349
|
+
/**
|
|
350
|
+
* Creates a form store, compiling the injected validator once for the
|
|
351
|
+
* form's schema.
|
|
352
|
+
*/
|
|
353
|
+
readonly useAppForm: (config: UseAppFormConfig) => FormStore;
|
|
354
|
+
/**
|
|
355
|
+
* The form component. Without children it renders the WHOLE form from
|
|
356
|
+
* the schema via the widget registry — no hand-written field components.
|
|
357
|
+
*/
|
|
358
|
+
readonly Form: (props: FormProps) => ReactElement;
|
|
359
|
+
/**
|
|
360
|
+
* The field component: registry-dispatched without children, headless
|
|
361
|
+
* with a render function.
|
|
362
|
+
*/
|
|
363
|
+
readonly Field: (props: AppFieldProps) => ReactNode;
|
|
364
|
+
/**
|
|
365
|
+
* The auto-rendered field list (every non-hidden root field through its
|
|
366
|
+
* registry widget). `Form` renders it when given no children; use it
|
|
367
|
+
* directly to compose auto fields with custom chrome (e.g. a footer).
|
|
368
|
+
*/
|
|
369
|
+
readonly Fields: (props: {
|
|
370
|
+
readonly of: FormStore;
|
|
371
|
+
}) => ReactElement;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Creates the app's form API around a widget registry (the TanStack
|
|
375
|
+
* `createFormHook` borrow): widgets are registered ONCE at module level,
|
|
376
|
+
* and every form derives its fields from the schema through them.
|
|
377
|
+
*
|
|
378
|
+
* @param config The registry and injected validator compiler.
|
|
379
|
+
*
|
|
380
|
+
* @returns The bound `useAppForm`, `Form` and `Field`.
|
|
381
|
+
*/
|
|
382
|
+
declare function createFormHook(config: FormHookConfig): FormHook;
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region src/react/use-field.d.ts
|
|
385
|
+
/**
|
|
386
|
+
* Creates a reactive field store for the field at the given path. Widgets
|
|
387
|
+
* are controlled components: render `field.input`, call
|
|
388
|
+
* `field.onChange(value)`, and spread `field.props` onto the DOM element so
|
|
389
|
+
* focus/blur validation modes and focus-on-error work.
|
|
390
|
+
*
|
|
391
|
+
* The returned store is an immutable SNAPSHOT: its identity changes when
|
|
392
|
+
* any observed value changes and is stable otherwise, so it composes with
|
|
393
|
+
* React Compiler memoization instead of fighting it (the LOS-567/LOS-602
|
|
394
|
+
* rewrite). Callbacks and DOM plumbing keep a stable identity for the
|
|
395
|
+
* field's lifetime.
|
|
396
|
+
*
|
|
397
|
+
* @param form The form store the field belongs to.
|
|
398
|
+
* @param path The path to the field.
|
|
399
|
+
*
|
|
400
|
+
* @returns The field store snapshot.
|
|
401
|
+
*/
|
|
402
|
+
declare function useField(form: FormStore, path: Path): FieldStore;
|
|
403
|
+
//#endregion
|
|
404
|
+
//#region src/react/use-field-array.d.ts
|
|
405
|
+
/**
|
|
406
|
+
* Creates a reactive field array store for the array field at the given
|
|
407
|
+
* path. Render one row per `items` entry and use the item ID as the React
|
|
408
|
+
* key so row state and DOM follow their row across reorders.
|
|
409
|
+
*
|
|
410
|
+
* The returned store is an immutable SNAPSHOT (see `useField` for the
|
|
411
|
+
* model).
|
|
412
|
+
*
|
|
413
|
+
* @param form The form store the array field belongs to.
|
|
414
|
+
* @param path The path to the array field.
|
|
415
|
+
*
|
|
416
|
+
* @returns The field array store snapshot.
|
|
417
|
+
*/
|
|
418
|
+
declare function useFieldArray(form: FormStore, path: Path): FieldArrayStore;
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region src/react/use-form.d.ts
|
|
421
|
+
/**
|
|
422
|
+
* Creates a reactive form store from a form configuration. The store is
|
|
423
|
+
* created once for the component's lifetime — config changes after mount
|
|
424
|
+
* are ignored (`applyBaseline` rebases on a fresh server record; `reset`
|
|
425
|
+
* with a new `initialInput` discards in-flight edits with it).
|
|
426
|
+
*
|
|
427
|
+
* The returned store is an immutable SNAPSHOT over the stable `internal`
|
|
428
|
+
* store: its identity changes when any observed form-level value changes
|
|
429
|
+
* (see `useField` for the model).
|
|
430
|
+
*
|
|
431
|
+
* @param config The form configuration.
|
|
432
|
+
*
|
|
433
|
+
* @returns The form store snapshot.
|
|
434
|
+
*/
|
|
435
|
+
declare function useForm(config: FormConfig): FormStore;
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/react/use-signal-snapshot.d.ts
|
|
438
|
+
/**
|
|
439
|
+
* Value-level equality for snapshot objects: top-level keys compared with
|
|
440
|
+
* `Object.is`, with ONE extra level for plain arrays and plain objects —
|
|
441
|
+
* computed results (a `DerivedState`, an errors array) are rebuilt with a
|
|
442
|
+
* fresh identity on every recompute, and without the value compare every
|
|
443
|
+
* notification would produce a render even when nothing visible changed.
|
|
444
|
+
* Deeper nesting falls back to "not equal" (re-render), never the other
|
|
445
|
+
* way — a false negative costs one render, a false positive would cost a
|
|
446
|
+
* stale UI.
|
|
447
|
+
*/
|
|
448
|
+
declare function snapshotEqual(a: unknown, b: unknown): boolean;
|
|
449
|
+
/**
|
|
450
|
+
* Subscribes the component to exactly the signals `compute` reads and
|
|
451
|
+
* returns the computed snapshot. THE reactive primitive of the react
|
|
452
|
+
* adapter — every jsonisch hook reads through it, and it is the public
|
|
453
|
+
* escape hatch for a component that needs a narrower subscription than
|
|
454
|
+
* `useField` provides.
|
|
455
|
+
*
|
|
456
|
+
* React-Compiler-safe by construction: the tracked reads happen inside a
|
|
457
|
+
* closure the library invokes — the compiler can only elide expressions
|
|
458
|
+
* whose call sites it memoized, never a call made from a hook's internals —
|
|
459
|
+
* and the returned snapshot is an immutable value whose identity changes
|
|
460
|
+
* when any observed value changes, so compiler memo caches keyed on it
|
|
461
|
+
* invalidate correctly instead of freezing.
|
|
462
|
+
*
|
|
463
|
+
* `useMemo` semantics apply to `deps`: the compute closure is captured when
|
|
464
|
+
* `deps` change, so everything it reads must be a signal (tracked) or
|
|
465
|
+
* listed in `deps` (recreates the store). `isEqual` gates re-renders by
|
|
466
|
+
* value; it defaults to `snapshotEqual`.
|
|
467
|
+
*
|
|
468
|
+
* @param compute The tracked read producing the snapshot.
|
|
469
|
+
* @param deps The non-signal inputs of `compute` (useMemo contract).
|
|
470
|
+
* @param isEqual The snapshot equality gate.
|
|
471
|
+
*
|
|
472
|
+
* @returns The current snapshot.
|
|
473
|
+
*/
|
|
474
|
+
declare function useSignalSnapshot<T>(compute: () => T, deps: readonly unknown[], isEqual?: (a: T, b: T) => boolean): T;
|
|
475
|
+
//#endregion
|
|
476
|
+
export { type AppFieldProps, Field, FieldArray, type FieldArrayProps, type FieldArrayStore, type FieldElementProps, type FieldProps, type FieldStore, type FieldStoreSlots, Form, type FormHook, type FormHookConfig, type FormProps, type FormStore, type UseAppFormConfig, type WidgetProps, createFormHook, snapshotEqual, useField, useFieldArray, useForm, useSignalSnapshot };
|