react-formesh 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -0
- package/dist/array.cjs +4 -0
- package/dist/array.cjs.map +1 -0
- package/dist/array.d.cts +2 -0
- package/dist/array.d.ts +2 -0
- package/dist/array.js +3 -0
- package/dist/array.js.map +1 -0
- package/dist/field-CLlwd7BC.d.ts +134 -0
- package/dist/field-DvWKUaTD.d.cts +134 -0
- package/dist/file.cjs +4 -0
- package/dist/file.cjs.map +1 -0
- package/dist/file.d.cts +2 -0
- package/dist/file.d.ts +2 -0
- package/dist/file.js +3 -0
- package/dist/file.js.map +1 -0
- package/dist/index.cjs +431 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +209 -0
- package/dist/index.d.ts +209 -0
- package/dist/index.js +419 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +487 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +144 -0
- package/dist/react.d.ts +144 -0
- package/dist/react.js +482 -0
- package/dist/react.js.map +1 -0
- package/dist/validation-gIT3Xn9h.d.cts +125 -0
- package/dist/validation-gIT3Xn9h.d.ts +125 -0
- package/dist/validators.cjs +99 -0
- package/dist/validators.cjs.map +1 -0
- package/dist/validators.d.cts +20 -0
- package/dist/validators.d.ts +20 -0
- package/dist/validators.js +89 -0
- package/dist/validators.js.map +1 -0
- package/package.json +70 -0
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { F as FormValues, b as ValidationResult, c as ValidationSchema, W as WatchListener } from './validation-gIT3Xn9h.cjs';
|
|
2
|
+
import { F as FieldOptions, R as RegisteredField, S as SyncTarget, D as DebouncedSync } from './field-DvWKUaTD.cjs';
|
|
3
|
+
|
|
4
|
+
interface UseFormOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Scopes this hook instance to a slice of the store (e.g. "employeeInfo"),
|
|
7
|
+
* mirroring how independent sections of a multi-section ERP form each own
|
|
8
|
+
* a key on the parent object. Omit to work with the whole store.
|
|
9
|
+
*/
|
|
10
|
+
section?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Validation schema (Phase 2): per-field rules keyed by scope-relative
|
|
13
|
+
* dot-path, and/or form-level validators receiving the whole values
|
|
14
|
+
* object in scope (for cross-field rules like date ranges and budget
|
|
15
|
+
* caps). Omit for no validation (`errors` stays `{}`, `isValid` stays
|
|
16
|
+
* `true`).
|
|
17
|
+
*/
|
|
18
|
+
validation?: ValidationSchema;
|
|
19
|
+
}
|
|
20
|
+
interface FormApi<TValues extends FormValues = FormValues> {
|
|
21
|
+
/** Current values in scope (whole store, or just this section). */
|
|
22
|
+
values: TValues;
|
|
23
|
+
/** Which field paths (relative to scope) have been blurred at least once. */
|
|
24
|
+
touched: Record<string, boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Whether values in scope differ from their value when this hook instance
|
|
27
|
+
* first observed them. See the in-source note on `initialRef` below for
|
|
28
|
+
* the exact semantics.
|
|
29
|
+
*/
|
|
30
|
+
isDirty: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Validation errors for the current values in scope, keyed by
|
|
33
|
+
* scope-relative field path. Recomputed on every values change against
|
|
34
|
+
* `options.validation` — and because validation runs over the values this
|
|
35
|
+
* hook renders from, a DebouncedSync target yields per-keystroke errors
|
|
36
|
+
* from its read-through values, not only after the debounced commit.
|
|
37
|
+
* All paths are exposed regardless of touched state; gate display with
|
|
38
|
+
* `touched` if you only want to show errors after a field was blurred.
|
|
39
|
+
*/
|
|
40
|
+
errors: Record<string, string>;
|
|
41
|
+
/** Whether `errors` is currently empty. Always `true` without a schema. */
|
|
42
|
+
isValid: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Runs the validation schema against the target's CURRENT values (re-read
|
|
45
|
+
* live, not the render snapshot) and returns the full result — for
|
|
46
|
+
* submit-time checks or manual revalidation. Same computation
|
|
47
|
+
* `errors`/`isValid` already reflect.
|
|
48
|
+
*/
|
|
49
|
+
validate: () => ValidationResult;
|
|
50
|
+
getValue: (path: string) => unknown;
|
|
51
|
+
setValue: (path: string, value: unknown) => void;
|
|
52
|
+
setValues: (partial: Partial<TValues>) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Produces a `{ name, value, onChange, onBlur }` prop bag for a field,
|
|
55
|
+
* normalizing whatever the input hands back via `onChange`. This is the
|
|
56
|
+
* direct replacement for a hand-written `handleFieldChange` per component.
|
|
57
|
+
*/
|
|
58
|
+
registerField: <TValue = unknown>(path: string, options?: FieldOptions<TValue>) => RegisteredField<TValue>;
|
|
59
|
+
/** Resets values in scope back to baseline and clears touched state. */
|
|
60
|
+
reset: () => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* React binding over the shared structural target surface — a FormStore, a
|
|
64
|
+
* FormSection, or a DebouncedSync wrapper (all satisfy `SyncTarget`
|
|
65
|
+
* structurally; that is what makes debounced buffering compose straight
|
|
66
|
+
* into this hook).
|
|
67
|
+
*
|
|
68
|
+
* Subscribes via `useSyncExternalStore`, so this component re-renders on
|
|
69
|
+
* any change within its scope (whole store, a section slice, or the sync
|
|
70
|
+
* wrapper's read-through values). This
|
|
71
|
+
* is the "whole-section" usage pattern — the direct replacement for a
|
|
72
|
+
* component's local `useState` + manual sync-to-parent — where one
|
|
73
|
+
* component renders many fields together, same as most existing ERP form
|
|
74
|
+
* sections do today.
|
|
75
|
+
*
|
|
76
|
+
* For genuinely fine-grained, single-field re-render isolation (a separate
|
|
77
|
+
* component per field), see `useFormField` instead — this hook intentionally
|
|
78
|
+
* re-renders on any change in scope, matching how these forms are already
|
|
79
|
+
* structured, rather than forcing a per-field-component rewrite to adopt it.
|
|
80
|
+
*/
|
|
81
|
+
declare function useForm<TValues extends FormValues = FormValues>(target: SyncTarget<FormValues>, options?: UseFormOptions): FormApi<TValues>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Subscribes a component to exactly one field path.
|
|
85
|
+
*
|
|
86
|
+
* The target may be a FormStore, a FormSection, or a DebouncedSync wrapper
|
|
87
|
+
* — anything satisfying the shared structural SyncTarget surface, which is
|
|
88
|
+
* what lets debounced buffering compose into per-field subscriptions.
|
|
89
|
+
*
|
|
90
|
+
* The subscribe callback here ignores the changed-paths list and always
|
|
91
|
+
* asks React to re-check — but `useSyncExternalStore` only actually
|
|
92
|
+
* re-renders the component when `getSnapshot()`'s return value differs
|
|
93
|
+
* (via `Object.is`) from the last one. Because the store only clones
|
|
94
|
+
* objects along the path that changed (see `setAtPath`), an update to an
|
|
95
|
+
* unrelated field leaves this field's value referentially identical, so
|
|
96
|
+
* React bails out without rendering.
|
|
97
|
+
*
|
|
98
|
+
* This is the primitive to reach for when a form is large enough that
|
|
99
|
+
* isolating re-renders per field (rather than per section, via `useForm`)
|
|
100
|
+
* actually matters — e.g. a field array with hundreds of rows.
|
|
101
|
+
*/
|
|
102
|
+
declare function useFormField<TValue = unknown>(target: SyncTarget, path: string, options?: FieldOptions<TValue>): RegisteredField<TValue>;
|
|
103
|
+
|
|
104
|
+
interface UseDebouncedSyncOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Milliseconds to wait after the last buffered write before committing to
|
|
107
|
+
* the target. Defaults to 300ms.
|
|
108
|
+
*/
|
|
109
|
+
delay?: number;
|
|
110
|
+
/**
|
|
111
|
+
* What happens to buffered-but-uncommitted writes when the component
|
|
112
|
+
* unmounts. Defaults to `true` (flush) so the last keystrokes before a
|
|
113
|
+
* navigation are never lost — the exact failure mode debounced sync
|
|
114
|
+
* would otherwise introduce. Set to `false` (cancel) when unmounting
|
|
115
|
+
* means "abandon this edit" rather than "the form went away".
|
|
116
|
+
*/
|
|
117
|
+
flushOnUnmount?: boolean;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* React binding over `createDebouncedSync`. The wrapper is memoized on
|
|
121
|
+
* `[target, delay]`, so passing it to `useForm`/`useFormField` (it exposes
|
|
122
|
+
* the same read/write/subscribe surface they expect) or rendering from its
|
|
123
|
+
* read-through values stays referentially stable across re-renders.
|
|
124
|
+
*/
|
|
125
|
+
declare function useDebouncedSync<TValues extends FormValues = FormValues>(target: SyncTarget<TValues>, options?: UseDebouncedSyncOptions): DebouncedSync<TValues>;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Runs `listener(value, previousValue)` whenever the value at `path`
|
|
129
|
+
* actually changes (deep equality). This is the React entry to the store's
|
|
130
|
+
* `watch` primitive — the primitive derived fields (`qty × price =
|
|
131
|
+
* lineTotal`) and cascading selects (`Country` change clears `City`) are
|
|
132
|
+
* built on.
|
|
133
|
+
*
|
|
134
|
+
* The listener identity may change every render (it usually closes over
|
|
135
|
+
* props/state); the effect only re-subscribes when `target` or `path`
|
|
136
|
+
* changes, and always invokes the latest listener via a ref — so handlers
|
|
137
|
+
* never see stale closures, and no subscription churn happens per render.
|
|
138
|
+
*
|
|
139
|
+
* The listener does not fire on mount. Initial derivations belong in
|
|
140
|
+
* render (read the value directly) or in the code that sets up the form.
|
|
141
|
+
*/
|
|
142
|
+
declare function useWatch(target: SyncTarget, path: string, listener: WatchListener): void;
|
|
143
|
+
|
|
144
|
+
export { type FormApi, type UseDebouncedSyncOptions, type UseFormOptions, useDebouncedSync, useForm, useFormField, useWatch };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { F as FormValues, b as ValidationResult, c as ValidationSchema, W as WatchListener } from './validation-gIT3Xn9h.js';
|
|
2
|
+
import { F as FieldOptions, R as RegisteredField, S as SyncTarget, D as DebouncedSync } from './field-CLlwd7BC.js';
|
|
3
|
+
|
|
4
|
+
interface UseFormOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Scopes this hook instance to a slice of the store (e.g. "employeeInfo"),
|
|
7
|
+
* mirroring how independent sections of a multi-section ERP form each own
|
|
8
|
+
* a key on the parent object. Omit to work with the whole store.
|
|
9
|
+
*/
|
|
10
|
+
section?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Validation schema (Phase 2): per-field rules keyed by scope-relative
|
|
13
|
+
* dot-path, and/or form-level validators receiving the whole values
|
|
14
|
+
* object in scope (for cross-field rules like date ranges and budget
|
|
15
|
+
* caps). Omit for no validation (`errors` stays `{}`, `isValid` stays
|
|
16
|
+
* `true`).
|
|
17
|
+
*/
|
|
18
|
+
validation?: ValidationSchema;
|
|
19
|
+
}
|
|
20
|
+
interface FormApi<TValues extends FormValues = FormValues> {
|
|
21
|
+
/** Current values in scope (whole store, or just this section). */
|
|
22
|
+
values: TValues;
|
|
23
|
+
/** Which field paths (relative to scope) have been blurred at least once. */
|
|
24
|
+
touched: Record<string, boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Whether values in scope differ from their value when this hook instance
|
|
27
|
+
* first observed them. See the in-source note on `initialRef` below for
|
|
28
|
+
* the exact semantics.
|
|
29
|
+
*/
|
|
30
|
+
isDirty: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Validation errors for the current values in scope, keyed by
|
|
33
|
+
* scope-relative field path. Recomputed on every values change against
|
|
34
|
+
* `options.validation` — and because validation runs over the values this
|
|
35
|
+
* hook renders from, a DebouncedSync target yields per-keystroke errors
|
|
36
|
+
* from its read-through values, not only after the debounced commit.
|
|
37
|
+
* All paths are exposed regardless of touched state; gate display with
|
|
38
|
+
* `touched` if you only want to show errors after a field was blurred.
|
|
39
|
+
*/
|
|
40
|
+
errors: Record<string, string>;
|
|
41
|
+
/** Whether `errors` is currently empty. Always `true` without a schema. */
|
|
42
|
+
isValid: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Runs the validation schema against the target's CURRENT values (re-read
|
|
45
|
+
* live, not the render snapshot) and returns the full result — for
|
|
46
|
+
* submit-time checks or manual revalidation. Same computation
|
|
47
|
+
* `errors`/`isValid` already reflect.
|
|
48
|
+
*/
|
|
49
|
+
validate: () => ValidationResult;
|
|
50
|
+
getValue: (path: string) => unknown;
|
|
51
|
+
setValue: (path: string, value: unknown) => void;
|
|
52
|
+
setValues: (partial: Partial<TValues>) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Produces a `{ name, value, onChange, onBlur }` prop bag for a field,
|
|
55
|
+
* normalizing whatever the input hands back via `onChange`. This is the
|
|
56
|
+
* direct replacement for a hand-written `handleFieldChange` per component.
|
|
57
|
+
*/
|
|
58
|
+
registerField: <TValue = unknown>(path: string, options?: FieldOptions<TValue>) => RegisteredField<TValue>;
|
|
59
|
+
/** Resets values in scope back to baseline and clears touched state. */
|
|
60
|
+
reset: () => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* React binding over the shared structural target surface — a FormStore, a
|
|
64
|
+
* FormSection, or a DebouncedSync wrapper (all satisfy `SyncTarget`
|
|
65
|
+
* structurally; that is what makes debounced buffering compose straight
|
|
66
|
+
* into this hook).
|
|
67
|
+
*
|
|
68
|
+
* Subscribes via `useSyncExternalStore`, so this component re-renders on
|
|
69
|
+
* any change within its scope (whole store, a section slice, or the sync
|
|
70
|
+
* wrapper's read-through values). This
|
|
71
|
+
* is the "whole-section" usage pattern — the direct replacement for a
|
|
72
|
+
* component's local `useState` + manual sync-to-parent — where one
|
|
73
|
+
* component renders many fields together, same as most existing ERP form
|
|
74
|
+
* sections do today.
|
|
75
|
+
*
|
|
76
|
+
* For genuinely fine-grained, single-field re-render isolation (a separate
|
|
77
|
+
* component per field), see `useFormField` instead — this hook intentionally
|
|
78
|
+
* re-renders on any change in scope, matching how these forms are already
|
|
79
|
+
* structured, rather than forcing a per-field-component rewrite to adopt it.
|
|
80
|
+
*/
|
|
81
|
+
declare function useForm<TValues extends FormValues = FormValues>(target: SyncTarget<FormValues>, options?: UseFormOptions): FormApi<TValues>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Subscribes a component to exactly one field path.
|
|
85
|
+
*
|
|
86
|
+
* The target may be a FormStore, a FormSection, or a DebouncedSync wrapper
|
|
87
|
+
* — anything satisfying the shared structural SyncTarget surface, which is
|
|
88
|
+
* what lets debounced buffering compose into per-field subscriptions.
|
|
89
|
+
*
|
|
90
|
+
* The subscribe callback here ignores the changed-paths list and always
|
|
91
|
+
* asks React to re-check — but `useSyncExternalStore` only actually
|
|
92
|
+
* re-renders the component when `getSnapshot()`'s return value differs
|
|
93
|
+
* (via `Object.is`) from the last one. Because the store only clones
|
|
94
|
+
* objects along the path that changed (see `setAtPath`), an update to an
|
|
95
|
+
* unrelated field leaves this field's value referentially identical, so
|
|
96
|
+
* React bails out without rendering.
|
|
97
|
+
*
|
|
98
|
+
* This is the primitive to reach for when a form is large enough that
|
|
99
|
+
* isolating re-renders per field (rather than per section, via `useForm`)
|
|
100
|
+
* actually matters — e.g. a field array with hundreds of rows.
|
|
101
|
+
*/
|
|
102
|
+
declare function useFormField<TValue = unknown>(target: SyncTarget, path: string, options?: FieldOptions<TValue>): RegisteredField<TValue>;
|
|
103
|
+
|
|
104
|
+
interface UseDebouncedSyncOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Milliseconds to wait after the last buffered write before committing to
|
|
107
|
+
* the target. Defaults to 300ms.
|
|
108
|
+
*/
|
|
109
|
+
delay?: number;
|
|
110
|
+
/**
|
|
111
|
+
* What happens to buffered-but-uncommitted writes when the component
|
|
112
|
+
* unmounts. Defaults to `true` (flush) so the last keystrokes before a
|
|
113
|
+
* navigation are never lost — the exact failure mode debounced sync
|
|
114
|
+
* would otherwise introduce. Set to `false` (cancel) when unmounting
|
|
115
|
+
* means "abandon this edit" rather than "the form went away".
|
|
116
|
+
*/
|
|
117
|
+
flushOnUnmount?: boolean;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* React binding over `createDebouncedSync`. The wrapper is memoized on
|
|
121
|
+
* `[target, delay]`, so passing it to `useForm`/`useFormField` (it exposes
|
|
122
|
+
* the same read/write/subscribe surface they expect) or rendering from its
|
|
123
|
+
* read-through values stays referentially stable across re-renders.
|
|
124
|
+
*/
|
|
125
|
+
declare function useDebouncedSync<TValues extends FormValues = FormValues>(target: SyncTarget<TValues>, options?: UseDebouncedSyncOptions): DebouncedSync<TValues>;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Runs `listener(value, previousValue)` whenever the value at `path`
|
|
129
|
+
* actually changes (deep equality). This is the React entry to the store's
|
|
130
|
+
* `watch` primitive — the primitive derived fields (`qty × price =
|
|
131
|
+
* lineTotal`) and cascading selects (`Country` change clears `City`) are
|
|
132
|
+
* built on.
|
|
133
|
+
*
|
|
134
|
+
* The listener identity may change every render (it usually closes over
|
|
135
|
+
* props/state); the effect only re-subscribes when `target` or `path`
|
|
136
|
+
* changes, and always invokes the latest listener via a ref — so handlers
|
|
137
|
+
* never see stale closures, and no subscription churn happens per render.
|
|
138
|
+
*
|
|
139
|
+
* The listener does not fire on mount. Initial derivations belong in
|
|
140
|
+
* render (read the value directly) or in the code that sets up the form.
|
|
141
|
+
*/
|
|
142
|
+
declare function useWatch(target: SyncTarget, path: string, listener: WatchListener): void;
|
|
143
|
+
|
|
144
|
+
export { type FormApi, type UseDebouncedSyncOptions, type UseFormOptions, useDebouncedSync, useForm, useFormField, useWatch };
|