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.
@@ -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 };
@@ -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 };