@neutro/form 0.0.5 → 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/dist/adapters/angular.cjs +24 -6
- package/dist/adapters/angular.d.cts +163 -19
- package/dist/adapters/angular.d.ts +163 -19
- package/dist/adapters/angular.js +25 -7
- package/dist/adapters/react.cjs +5 -1
- package/dist/adapters/react.d.cts +86 -5
- package/dist/adapters/react.d.ts +86 -5
- package/dist/adapters/react.js +6 -2
- package/dist/adapters/solid.cjs +12 -3
- package/dist/adapters/solid.d.cts +161 -16
- package/dist/adapters/solid.d.ts +161 -16
- package/dist/adapters/solid.js +12 -3
- package/dist/adapters/svelte.cjs +18 -9
- package/dist/adapters/svelte.d.cts +161 -17
- package/dist/adapters/svelte.d.ts +161 -17
- package/dist/adapters/svelte.js +18 -9
- package/dist/adapters/vue.cjs +15 -4
- package/dist/adapters/vue.d.cts +161 -17
- package/dist/adapters/vue.d.ts +161 -17
- package/dist/adapters/vue.js +23 -5
- package/dist/chunk-FDAQJJJ7.js +657 -0
- package/dist/core.cjs +510 -425
- package/dist/core.d.cts +94 -7
- package/dist/core.d.ts +94 -7
- package/dist/core.js +24 -569
- package/dist/devtools.cjs +244 -0
- package/dist/devtools.d.cts +141 -0
- package/dist/devtools.d.ts +141 -0
- package/dist/devtools.js +217 -0
- package/dist/testing.cjs +667 -0
- package/dist/testing.d.cts +254 -0
- package/dist/testing.d.ts +254 -0
- package/dist/testing.js +39 -0
- package/package.json +25 -7
package/dist/adapters/react.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
type Primitive = string | number | boolean | null | undefined | Date | File;
|
|
6
6
|
type Prev = [never, 0, 1, 2, 3, 4, 5, ...any[]];
|
|
7
|
-
type PathImpl<T, K extends keyof T, Depth extends number = 5> = [Depth] extends [never] ? never : K extends string ? T[K] extends Primitive ? K : T[K] extends Array<infer U> ? K | `${K}.${number}` | (U extends object ? `${K}.${number}.${PathImpl<U, keyof U, Prev[Depth]>}` : never) : T[K] extends object ? K | `${K}.${PathImpl<T[K]
|
|
7
|
+
type PathImpl<T, K extends keyof T, Depth extends number = 5> = [Depth] extends [never] ? never : K extends string ? T[K] extends Primitive ? K : T[K] extends Array<infer U> ? K | `${K}.${number}` | (U extends object ? `${K}.${number}.${PathImpl<U, keyof U, Prev[Depth]>}` : never) : NonNullable<T[K]> extends object ? K | `${K}.${PathImpl<NonNullable<T[K]>, keyof NonNullable<T[K]>, Prev[Depth]>}` : K : never;
|
|
8
8
|
type Path<T> = PathImpl<T, keyof T> & string;
|
|
9
9
|
type _GetPathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? _GetPathValue<NonNullable<T[K]>, Rest> : T extends readonly any[] ? _GetPathValue<NonNullable<T[number]>, Rest> : unknown : P extends keyof T ? T[P] : T extends readonly any[] ? T[number] : unknown;
|
|
10
10
|
type GetPathValue<T, P extends string> = _GetPathValue<T, P>;
|
|
@@ -17,19 +17,90 @@ interface FormState<T> {
|
|
|
17
17
|
isValidating: boolean;
|
|
18
18
|
}
|
|
19
19
|
type FormSubscriber<T> = (state: FormState<T>) => void;
|
|
20
|
-
type PathSubscriber = (value:
|
|
20
|
+
type PathSubscriber<V = any> = (value: V, fieldState: {
|
|
21
21
|
error?: string;
|
|
22
22
|
touched?: boolean;
|
|
23
23
|
dirty?: boolean;
|
|
24
24
|
}) => void;
|
|
25
|
+
type ValidationMode = 'onChange' | 'onBlur' | 'onTouched' | 'onSubmitOnly';
|
|
26
|
+
type FormAction = {
|
|
27
|
+
type: 'SET';
|
|
28
|
+
path: string;
|
|
29
|
+
value: unknown;
|
|
30
|
+
options?: {
|
|
31
|
+
touch?: boolean;
|
|
32
|
+
validate?: boolean;
|
|
33
|
+
};
|
|
34
|
+
} | {
|
|
35
|
+
type: 'VALIDATE';
|
|
36
|
+
paths?: string[];
|
|
37
|
+
} | {
|
|
38
|
+
type: 'SUBMIT';
|
|
39
|
+
} | {
|
|
40
|
+
type: 'RESET';
|
|
41
|
+
newValues?: unknown;
|
|
42
|
+
} | {
|
|
43
|
+
type: 'SET_ERRORS';
|
|
44
|
+
errors: Record<string, string>;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'CONNECT';
|
|
47
|
+
path: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'DISCONNECT';
|
|
50
|
+
path: string;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'BLUR';
|
|
53
|
+
path: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'BATCH_START';
|
|
56
|
+
} | {
|
|
57
|
+
type: 'BATCH_END';
|
|
58
|
+
} | {
|
|
59
|
+
type: 'ARRAY_APPEND';
|
|
60
|
+
path: string;
|
|
61
|
+
item: unknown;
|
|
62
|
+
} | {
|
|
63
|
+
type: 'ARRAY_INSERT';
|
|
64
|
+
path: string;
|
|
65
|
+
index: number;
|
|
66
|
+
item: unknown;
|
|
67
|
+
} | {
|
|
68
|
+
type: 'ARRAY_REMOVE';
|
|
69
|
+
path: string;
|
|
70
|
+
index: number;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'ARRAY_MOVE';
|
|
73
|
+
path: string;
|
|
74
|
+
from: number;
|
|
75
|
+
to: number;
|
|
76
|
+
} | {
|
|
77
|
+
type: 'ARRAY_SWAP';
|
|
78
|
+
path: string;
|
|
79
|
+
i: number;
|
|
80
|
+
j: number;
|
|
81
|
+
} | {
|
|
82
|
+
type: 'CLEAR_ERRORS';
|
|
83
|
+
};
|
|
84
|
+
interface AriaPropsOptions {
|
|
85
|
+
required?: boolean;
|
|
86
|
+
errorId?: string;
|
|
87
|
+
}
|
|
88
|
+
interface AriaProps {
|
|
89
|
+
'aria-invalid': 'true' | 'false';
|
|
90
|
+
'aria-describedby': string | undefined;
|
|
91
|
+
'aria-required': true | undefined;
|
|
92
|
+
}
|
|
25
93
|
interface ConnectOptions {
|
|
26
94
|
persist?: boolean;
|
|
27
95
|
format?: (val: string) => string;
|
|
96
|
+
validateOn?: ValidationMode;
|
|
28
97
|
}
|
|
29
98
|
interface FormInstance<T extends object> {
|
|
30
99
|
subscribe: (fn: FormSubscriber<T>) => () => void;
|
|
31
|
-
subscribeToPath
|
|
32
|
-
|
|
100
|
+
subscribeToPath<P extends Path<T>>(path: P, fn: PathSubscriber<GetPathValue<T, P>>): () => void;
|
|
101
|
+
subscribeToPath(path: string, fn: PathSubscriber): () => void;
|
|
102
|
+
get<P extends Path<T>>(path: P): GetPathValue<T, P>;
|
|
103
|
+
get(path: string | string[]): any;
|
|
33
104
|
set: (path: Path<T> | string | string[], val: any, options?: {
|
|
34
105
|
touch?: boolean;
|
|
35
106
|
validate?: boolean;
|
|
@@ -40,6 +111,7 @@ interface FormInstance<T extends object> {
|
|
|
40
111
|
handleSubmit: (onValid: (payload: Partial<T>) => void | Promise<void>, onInvalid?: (errors: Record<string, string>) => void) => (e?: Event) => void;
|
|
41
112
|
getState: () => FormState<T>;
|
|
42
113
|
getPayload: () => Partial<T>;
|
|
114
|
+
getAriaProps: (path: Path<T> | string, options?: AriaPropsOptions) => AriaProps;
|
|
43
115
|
batch: (fn: () => void) => void;
|
|
44
116
|
arrayAppend: (path: Path<T> | string | string[], item: any) => void;
|
|
45
117
|
arrayInsert: (path: Path<T> | string | string[], index: number, item: any) => void;
|
|
@@ -49,9 +121,18 @@ interface FormInstance<T extends object> {
|
|
|
49
121
|
reset: (newValues?: T) => void;
|
|
50
122
|
getConnectedCount: () => number;
|
|
51
123
|
destroy: () => void;
|
|
124
|
+
setErrors: (errors: Record<Path<T> | (string & {}), string>) => void;
|
|
125
|
+
clearErrors: () => void;
|
|
126
|
+
/**
|
|
127
|
+
* Returns the effective ValidationMode for a field. Useful for debugging
|
|
128
|
+
* validation timing; framework adapters should rely on this only in custom
|
|
129
|
+
* event handlers, not in render logic.
|
|
130
|
+
*/
|
|
131
|
+
getFieldMode: (path: string) => ValidationMode;
|
|
132
|
+
_subscribeToActions: (fn: (action: FormAction, state: FormState<T>) => void) => () => void;
|
|
52
133
|
}
|
|
53
134
|
|
|
54
|
-
declare function useForm<T extends object>(form: FormInstance<T>): FormState<T> & Omit<FormInstance<T>, 'subscribe' | 'getState'>;
|
|
135
|
+
declare function useForm<T extends object>(form: FormInstance<T>): FormState<T> & Omit<FormInstance<T>, 'subscribe' | 'getState' | '_subscribeToActions'>;
|
|
55
136
|
declare function useFormPath<T extends object, P extends Path<T>>(form: FormInstance<T>, path: P): GetPathValue<T, P>;
|
|
56
137
|
declare function useFormConnect(form: any): (path: string, options?: any) => (el: HTMLElement | null) => void;
|
|
57
138
|
|
package/dist/adapters/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ../adapters/react/dist/index.js
|
|
2
|
-
import {
|
|
2
|
+
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
3
3
|
function useForm(form) {
|
|
4
4
|
const state = useSyncExternalStore(form.subscribe, form.getState, form.getState);
|
|
5
5
|
return {
|
|
@@ -14,13 +14,17 @@ function useForm(form) {
|
|
|
14
14
|
subscribeToPath: form.subscribeToPath,
|
|
15
15
|
validate: form.validate,
|
|
16
16
|
getPayload: form.getPayload,
|
|
17
|
+
getAriaProps: form.getAriaProps,
|
|
18
|
+
getFieldMode: form.getFieldMode,
|
|
17
19
|
getConnectedCount: form.getConnectedCount,
|
|
18
20
|
destroy: form.destroy,
|
|
19
21
|
arrayAppend: form.arrayAppend,
|
|
20
22
|
arrayInsert: form.arrayInsert,
|
|
21
23
|
arrayRemove: form.arrayRemove,
|
|
22
24
|
arrayMove: form.arrayMove,
|
|
23
|
-
arraySwap: form.arraySwap
|
|
25
|
+
arraySwap: form.arraySwap,
|
|
26
|
+
setErrors: form.setErrors,
|
|
27
|
+
clearErrors: form.clearErrors
|
|
24
28
|
};
|
|
25
29
|
}
|
|
26
30
|
function useFormPath(form, path) {
|
package/dist/adapters/solid.cjs
CHANGED
|
@@ -44,18 +44,27 @@ function useSolidForm(form) {
|
|
|
44
44
|
handleSubmit: form.handleSubmit,
|
|
45
45
|
reset: form.reset,
|
|
46
46
|
batch: form.batch,
|
|
47
|
+
validate: form.validate,
|
|
48
|
+
subscribeToPath: form.subscribeToPath,
|
|
49
|
+
getPayload: form.getPayload,
|
|
50
|
+
getAriaProps: form.getAriaProps,
|
|
51
|
+
getFieldMode: form.getFieldMode,
|
|
52
|
+
getConnectedCount: form.getConnectedCount,
|
|
53
|
+
destroy: form.destroy,
|
|
47
54
|
arrayAppend: form.arrayAppend,
|
|
48
55
|
arrayInsert: form.arrayInsert,
|
|
49
56
|
arrayRemove: form.arrayRemove,
|
|
50
57
|
arrayMove: form.arrayMove,
|
|
51
|
-
arraySwap: form.arraySwap
|
|
58
|
+
arraySwap: form.arraySwap,
|
|
59
|
+
setErrors: form.setErrors,
|
|
60
|
+
clearErrors: form.clearErrors
|
|
52
61
|
}
|
|
53
62
|
];
|
|
54
63
|
}
|
|
55
64
|
function useSolidFormPath(form, path) {
|
|
56
|
-
const [value, setValue] = (0, import_solid_js.createSignal)(form.get(path
|
|
65
|
+
const [value, setValue] = (0, import_solid_js.createSignal)(form.get(path));
|
|
57
66
|
const [fieldState, setFieldState] = (0, import_solid_js.createSignal)(null);
|
|
58
|
-
const unsubscribe = form.subscribeToPath(path
|
|
67
|
+
const unsubscribe = form.subscribeToPath(path, (v, fs) => {
|
|
59
68
|
setValue(() => v);
|
|
60
69
|
setFieldState(() => fs);
|
|
61
70
|
});
|
|
@@ -1,20 +1,165 @@
|
|
|
1
1
|
import * as solid_js from 'solid-js';
|
|
2
|
+
import { Store } from 'solid-js/store';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @neutro/form-core
|
|
6
|
+
* High-Performance, Zero-Dependency, Framework-Agnostic Reactive Form Engine.
|
|
7
|
+
*/
|
|
8
|
+
type Primitive = string | number | boolean | null | undefined | Date | File;
|
|
9
|
+
type Prev = [never, 0, 1, 2, 3, 4, 5, ...any[]];
|
|
10
|
+
type PathImpl<T, K extends keyof T, Depth extends number = 5> = [Depth] extends [never] ? never : K extends string ? T[K] extends Primitive ? K : T[K] extends Array<infer U> ? K | `${K}.${number}` | (U extends object ? `${K}.${number}.${PathImpl<U, keyof U, Prev[Depth]>}` : never) : NonNullable<T[K]> extends object ? K | `${K}.${PathImpl<NonNullable<T[K]>, keyof NonNullable<T[K]>, Prev[Depth]>}` : K : never;
|
|
11
|
+
type Path<T> = PathImpl<T, keyof T> & string;
|
|
12
|
+
type _GetPathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? _GetPathValue<NonNullable<T[K]>, Rest> : T extends readonly any[] ? _GetPathValue<NonNullable<T[number]>, Rest> : unknown : P extends keyof T ? T[P] : T extends readonly any[] ? T[number] : unknown;
|
|
13
|
+
type GetPathValue<T, P extends string> = _GetPathValue<T, P>;
|
|
14
|
+
interface FormState<T> {
|
|
15
|
+
values: T;
|
|
16
|
+
errors: Record<string, string>;
|
|
17
|
+
touched: Record<string, boolean>;
|
|
18
|
+
dirty: Record<string, boolean>;
|
|
19
|
+
isSubmitting: boolean;
|
|
20
|
+
isValidating: boolean;
|
|
21
|
+
}
|
|
22
|
+
type FormSubscriber<T> = (state: FormState<T>) => void;
|
|
23
|
+
type PathSubscriber<V = any> = (value: V, fieldState: {
|
|
24
|
+
error?: string;
|
|
25
|
+
touched?: boolean;
|
|
26
|
+
dirty?: boolean;
|
|
27
|
+
}) => void;
|
|
28
|
+
type ValidationMode = 'onChange' | 'onBlur' | 'onTouched' | 'onSubmitOnly';
|
|
29
|
+
type FormAction = {
|
|
30
|
+
type: 'SET';
|
|
31
|
+
path: string;
|
|
32
|
+
value: unknown;
|
|
33
|
+
options?: {
|
|
34
|
+
touch?: boolean;
|
|
35
|
+
validate?: boolean;
|
|
36
|
+
};
|
|
37
|
+
} | {
|
|
38
|
+
type: 'VALIDATE';
|
|
39
|
+
paths?: string[];
|
|
40
|
+
} | {
|
|
41
|
+
type: 'SUBMIT';
|
|
42
|
+
} | {
|
|
43
|
+
type: 'RESET';
|
|
44
|
+
newValues?: unknown;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'SET_ERRORS';
|
|
47
|
+
errors: Record<string, string>;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'CONNECT';
|
|
50
|
+
path: string;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'DISCONNECT';
|
|
53
|
+
path: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'BLUR';
|
|
56
|
+
path: string;
|
|
57
|
+
} | {
|
|
58
|
+
type: 'BATCH_START';
|
|
59
|
+
} | {
|
|
60
|
+
type: 'BATCH_END';
|
|
61
|
+
} | {
|
|
62
|
+
type: 'ARRAY_APPEND';
|
|
63
|
+
path: string;
|
|
64
|
+
item: unknown;
|
|
65
|
+
} | {
|
|
66
|
+
type: 'ARRAY_INSERT';
|
|
67
|
+
path: string;
|
|
68
|
+
index: number;
|
|
69
|
+
item: unknown;
|
|
70
|
+
} | {
|
|
71
|
+
type: 'ARRAY_REMOVE';
|
|
72
|
+
path: string;
|
|
73
|
+
index: number;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'ARRAY_MOVE';
|
|
76
|
+
path: string;
|
|
77
|
+
from: number;
|
|
78
|
+
to: number;
|
|
79
|
+
} | {
|
|
80
|
+
type: 'ARRAY_SWAP';
|
|
81
|
+
path: string;
|
|
82
|
+
i: number;
|
|
83
|
+
j: number;
|
|
84
|
+
} | {
|
|
85
|
+
type: 'CLEAR_ERRORS';
|
|
86
|
+
};
|
|
87
|
+
interface AriaPropsOptions {
|
|
88
|
+
required?: boolean;
|
|
89
|
+
errorId?: string;
|
|
90
|
+
}
|
|
91
|
+
interface AriaProps {
|
|
92
|
+
'aria-invalid': 'true' | 'false';
|
|
93
|
+
'aria-describedby': string | undefined;
|
|
94
|
+
'aria-required': true | undefined;
|
|
95
|
+
}
|
|
96
|
+
interface ConnectOptions {
|
|
97
|
+
persist?: boolean;
|
|
98
|
+
format?: (val: string) => string;
|
|
99
|
+
validateOn?: ValidationMode;
|
|
100
|
+
}
|
|
101
|
+
interface FormInstance<T extends object> {
|
|
102
|
+
subscribe: (fn: FormSubscriber<T>) => () => void;
|
|
103
|
+
subscribeToPath<P extends Path<T>>(path: P, fn: PathSubscriber<GetPathValue<T, P>>): () => void;
|
|
104
|
+
subscribeToPath(path: string, fn: PathSubscriber): () => void;
|
|
105
|
+
get<P extends Path<T>>(path: P): GetPathValue<T, P>;
|
|
106
|
+
get(path: string | string[]): any;
|
|
107
|
+
set: (path: Path<T> | string | string[], val: any, options?: {
|
|
108
|
+
touch?: boolean;
|
|
109
|
+
validate?: boolean;
|
|
110
|
+
}) => void;
|
|
111
|
+
validate: (scopePaths?: Path<T>[] | string[] | string[][]) => Promise<boolean>;
|
|
112
|
+
connect: (path: Path<T> | string, el: HTMLElement, options?: ConnectOptions) => () => void;
|
|
113
|
+
submit: (onValid: (payload: Partial<T>) => void | Promise<void>) => Promise<boolean>;
|
|
114
|
+
handleSubmit: (onValid: (payload: Partial<T>) => void | Promise<void>, onInvalid?: (errors: Record<string, string>) => void) => (e?: Event) => void;
|
|
115
|
+
getState: () => FormState<T>;
|
|
116
|
+
getPayload: () => Partial<T>;
|
|
117
|
+
getAriaProps: (path: Path<T> | string, options?: AriaPropsOptions) => AriaProps;
|
|
118
|
+
batch: (fn: () => void) => void;
|
|
119
|
+
arrayAppend: (path: Path<T> | string | string[], item: any) => void;
|
|
120
|
+
arrayInsert: (path: Path<T> | string | string[], index: number, item: any) => void;
|
|
121
|
+
arrayRemove: (path: Path<T> | string | string[], index: number) => void;
|
|
122
|
+
arrayMove: (path: Path<T> | string | string[], fromIndex: number, toIndex: number) => void;
|
|
123
|
+
arraySwap: (path: Path<T> | string | string[], indexA: number, indexB: number) => void;
|
|
124
|
+
reset: (newValues?: T) => void;
|
|
125
|
+
getConnectedCount: () => number;
|
|
126
|
+
destroy: () => void;
|
|
127
|
+
setErrors: (errors: Record<Path<T> | (string & {}), string>) => void;
|
|
128
|
+
clearErrors: () => void;
|
|
129
|
+
/**
|
|
130
|
+
* Returns the effective ValidationMode for a field. Useful for debugging
|
|
131
|
+
* validation timing; framework adapters should rely on this only in custom
|
|
132
|
+
* event handlers, not in render logic.
|
|
133
|
+
*/
|
|
134
|
+
getFieldMode: (path: string) => ValidationMode;
|
|
135
|
+
_subscribeToActions: (fn: (action: FormAction, state: FormState<T>) => void) => () => void;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface SolidFormActions<T extends object> {
|
|
139
|
+
get: FormInstance<T>['get'];
|
|
140
|
+
set: FormInstance<T>['set'];
|
|
141
|
+
connect: FormInstance<T>['connect'];
|
|
142
|
+
submit: FormInstance<T>['submit'];
|
|
143
|
+
handleSubmit: FormInstance<T>['handleSubmit'];
|
|
144
|
+
reset: FormInstance<T>['reset'];
|
|
145
|
+
batch: FormInstance<T>['batch'];
|
|
146
|
+
validate: FormInstance<T>['validate'];
|
|
147
|
+
subscribeToPath: FormInstance<T>['subscribeToPath'];
|
|
148
|
+
getPayload: FormInstance<T>['getPayload'];
|
|
149
|
+
getAriaProps: FormInstance<T>['getAriaProps'];
|
|
150
|
+
getFieldMode: FormInstance<T>['getFieldMode'];
|
|
151
|
+
getConnectedCount: FormInstance<T>['getConnectedCount'];
|
|
152
|
+
destroy: FormInstance<T>['destroy'];
|
|
153
|
+
arrayAppend: FormInstance<T>['arrayAppend'];
|
|
154
|
+
arrayInsert: FormInstance<T>['arrayInsert'];
|
|
155
|
+
arrayRemove: FormInstance<T>['arrayRemove'];
|
|
156
|
+
arrayMove: FormInstance<T>['arrayMove'];
|
|
157
|
+
arraySwap: FormInstance<T>['arraySwap'];
|
|
158
|
+
setErrors: FormInstance<T>['setErrors'];
|
|
159
|
+
clearErrors: FormInstance<T>['clearErrors'];
|
|
160
|
+
}
|
|
161
|
+
declare function useSolidForm<T extends object>(form: FormInstance<T>): [Store<FormState<T>>, SolidFormActions<T>];
|
|
162
|
+
declare function useSolidFormPath<T extends object>(form: FormInstance<T>, path: string): {
|
|
18
163
|
value: solid_js.Accessor<unknown>;
|
|
19
164
|
fieldState: solid_js.Accessor<{
|
|
20
165
|
error?: string;
|
|
@@ -23,4 +168,4 @@ declare function useSolidFormPath(form: any, path: () => string): {
|
|
|
23
168
|
} | null>;
|
|
24
169
|
};
|
|
25
170
|
|
|
26
|
-
export { useSolidForm, useSolidFormPath };
|
|
171
|
+
export { type SolidFormActions, useSolidForm, useSolidFormPath };
|
package/dist/adapters/solid.d.ts
CHANGED
|
@@ -1,20 +1,165 @@
|
|
|
1
1
|
import * as solid_js from 'solid-js';
|
|
2
|
+
import { Store } from 'solid-js/store';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @neutro/form-core
|
|
6
|
+
* High-Performance, Zero-Dependency, Framework-Agnostic Reactive Form Engine.
|
|
7
|
+
*/
|
|
8
|
+
type Primitive = string | number | boolean | null | undefined | Date | File;
|
|
9
|
+
type Prev = [never, 0, 1, 2, 3, 4, 5, ...any[]];
|
|
10
|
+
type PathImpl<T, K extends keyof T, Depth extends number = 5> = [Depth] extends [never] ? never : K extends string ? T[K] extends Primitive ? K : T[K] extends Array<infer U> ? K | `${K}.${number}` | (U extends object ? `${K}.${number}.${PathImpl<U, keyof U, Prev[Depth]>}` : never) : NonNullable<T[K]> extends object ? K | `${K}.${PathImpl<NonNullable<T[K]>, keyof NonNullable<T[K]>, Prev[Depth]>}` : K : never;
|
|
11
|
+
type Path<T> = PathImpl<T, keyof T> & string;
|
|
12
|
+
type _GetPathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? _GetPathValue<NonNullable<T[K]>, Rest> : T extends readonly any[] ? _GetPathValue<NonNullable<T[number]>, Rest> : unknown : P extends keyof T ? T[P] : T extends readonly any[] ? T[number] : unknown;
|
|
13
|
+
type GetPathValue<T, P extends string> = _GetPathValue<T, P>;
|
|
14
|
+
interface FormState<T> {
|
|
15
|
+
values: T;
|
|
16
|
+
errors: Record<string, string>;
|
|
17
|
+
touched: Record<string, boolean>;
|
|
18
|
+
dirty: Record<string, boolean>;
|
|
19
|
+
isSubmitting: boolean;
|
|
20
|
+
isValidating: boolean;
|
|
21
|
+
}
|
|
22
|
+
type FormSubscriber<T> = (state: FormState<T>) => void;
|
|
23
|
+
type PathSubscriber<V = any> = (value: V, fieldState: {
|
|
24
|
+
error?: string;
|
|
25
|
+
touched?: boolean;
|
|
26
|
+
dirty?: boolean;
|
|
27
|
+
}) => void;
|
|
28
|
+
type ValidationMode = 'onChange' | 'onBlur' | 'onTouched' | 'onSubmitOnly';
|
|
29
|
+
type FormAction = {
|
|
30
|
+
type: 'SET';
|
|
31
|
+
path: string;
|
|
32
|
+
value: unknown;
|
|
33
|
+
options?: {
|
|
34
|
+
touch?: boolean;
|
|
35
|
+
validate?: boolean;
|
|
36
|
+
};
|
|
37
|
+
} | {
|
|
38
|
+
type: 'VALIDATE';
|
|
39
|
+
paths?: string[];
|
|
40
|
+
} | {
|
|
41
|
+
type: 'SUBMIT';
|
|
42
|
+
} | {
|
|
43
|
+
type: 'RESET';
|
|
44
|
+
newValues?: unknown;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'SET_ERRORS';
|
|
47
|
+
errors: Record<string, string>;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'CONNECT';
|
|
50
|
+
path: string;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'DISCONNECT';
|
|
53
|
+
path: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'BLUR';
|
|
56
|
+
path: string;
|
|
57
|
+
} | {
|
|
58
|
+
type: 'BATCH_START';
|
|
59
|
+
} | {
|
|
60
|
+
type: 'BATCH_END';
|
|
61
|
+
} | {
|
|
62
|
+
type: 'ARRAY_APPEND';
|
|
63
|
+
path: string;
|
|
64
|
+
item: unknown;
|
|
65
|
+
} | {
|
|
66
|
+
type: 'ARRAY_INSERT';
|
|
67
|
+
path: string;
|
|
68
|
+
index: number;
|
|
69
|
+
item: unknown;
|
|
70
|
+
} | {
|
|
71
|
+
type: 'ARRAY_REMOVE';
|
|
72
|
+
path: string;
|
|
73
|
+
index: number;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'ARRAY_MOVE';
|
|
76
|
+
path: string;
|
|
77
|
+
from: number;
|
|
78
|
+
to: number;
|
|
79
|
+
} | {
|
|
80
|
+
type: 'ARRAY_SWAP';
|
|
81
|
+
path: string;
|
|
82
|
+
i: number;
|
|
83
|
+
j: number;
|
|
84
|
+
} | {
|
|
85
|
+
type: 'CLEAR_ERRORS';
|
|
86
|
+
};
|
|
87
|
+
interface AriaPropsOptions {
|
|
88
|
+
required?: boolean;
|
|
89
|
+
errorId?: string;
|
|
90
|
+
}
|
|
91
|
+
interface AriaProps {
|
|
92
|
+
'aria-invalid': 'true' | 'false';
|
|
93
|
+
'aria-describedby': string | undefined;
|
|
94
|
+
'aria-required': true | undefined;
|
|
95
|
+
}
|
|
96
|
+
interface ConnectOptions {
|
|
97
|
+
persist?: boolean;
|
|
98
|
+
format?: (val: string) => string;
|
|
99
|
+
validateOn?: ValidationMode;
|
|
100
|
+
}
|
|
101
|
+
interface FormInstance<T extends object> {
|
|
102
|
+
subscribe: (fn: FormSubscriber<T>) => () => void;
|
|
103
|
+
subscribeToPath<P extends Path<T>>(path: P, fn: PathSubscriber<GetPathValue<T, P>>): () => void;
|
|
104
|
+
subscribeToPath(path: string, fn: PathSubscriber): () => void;
|
|
105
|
+
get<P extends Path<T>>(path: P): GetPathValue<T, P>;
|
|
106
|
+
get(path: string | string[]): any;
|
|
107
|
+
set: (path: Path<T> | string | string[], val: any, options?: {
|
|
108
|
+
touch?: boolean;
|
|
109
|
+
validate?: boolean;
|
|
110
|
+
}) => void;
|
|
111
|
+
validate: (scopePaths?: Path<T>[] | string[] | string[][]) => Promise<boolean>;
|
|
112
|
+
connect: (path: Path<T> | string, el: HTMLElement, options?: ConnectOptions) => () => void;
|
|
113
|
+
submit: (onValid: (payload: Partial<T>) => void | Promise<void>) => Promise<boolean>;
|
|
114
|
+
handleSubmit: (onValid: (payload: Partial<T>) => void | Promise<void>, onInvalid?: (errors: Record<string, string>) => void) => (e?: Event) => void;
|
|
115
|
+
getState: () => FormState<T>;
|
|
116
|
+
getPayload: () => Partial<T>;
|
|
117
|
+
getAriaProps: (path: Path<T> | string, options?: AriaPropsOptions) => AriaProps;
|
|
118
|
+
batch: (fn: () => void) => void;
|
|
119
|
+
arrayAppend: (path: Path<T> | string | string[], item: any) => void;
|
|
120
|
+
arrayInsert: (path: Path<T> | string | string[], index: number, item: any) => void;
|
|
121
|
+
arrayRemove: (path: Path<T> | string | string[], index: number) => void;
|
|
122
|
+
arrayMove: (path: Path<T> | string | string[], fromIndex: number, toIndex: number) => void;
|
|
123
|
+
arraySwap: (path: Path<T> | string | string[], indexA: number, indexB: number) => void;
|
|
124
|
+
reset: (newValues?: T) => void;
|
|
125
|
+
getConnectedCount: () => number;
|
|
126
|
+
destroy: () => void;
|
|
127
|
+
setErrors: (errors: Record<Path<T> | (string & {}), string>) => void;
|
|
128
|
+
clearErrors: () => void;
|
|
129
|
+
/**
|
|
130
|
+
* Returns the effective ValidationMode for a field. Useful for debugging
|
|
131
|
+
* validation timing; framework adapters should rely on this only in custom
|
|
132
|
+
* event handlers, not in render logic.
|
|
133
|
+
*/
|
|
134
|
+
getFieldMode: (path: string) => ValidationMode;
|
|
135
|
+
_subscribeToActions: (fn: (action: FormAction, state: FormState<T>) => void) => () => void;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface SolidFormActions<T extends object> {
|
|
139
|
+
get: FormInstance<T>['get'];
|
|
140
|
+
set: FormInstance<T>['set'];
|
|
141
|
+
connect: FormInstance<T>['connect'];
|
|
142
|
+
submit: FormInstance<T>['submit'];
|
|
143
|
+
handleSubmit: FormInstance<T>['handleSubmit'];
|
|
144
|
+
reset: FormInstance<T>['reset'];
|
|
145
|
+
batch: FormInstance<T>['batch'];
|
|
146
|
+
validate: FormInstance<T>['validate'];
|
|
147
|
+
subscribeToPath: FormInstance<T>['subscribeToPath'];
|
|
148
|
+
getPayload: FormInstance<T>['getPayload'];
|
|
149
|
+
getAriaProps: FormInstance<T>['getAriaProps'];
|
|
150
|
+
getFieldMode: FormInstance<T>['getFieldMode'];
|
|
151
|
+
getConnectedCount: FormInstance<T>['getConnectedCount'];
|
|
152
|
+
destroy: FormInstance<T>['destroy'];
|
|
153
|
+
arrayAppend: FormInstance<T>['arrayAppend'];
|
|
154
|
+
arrayInsert: FormInstance<T>['arrayInsert'];
|
|
155
|
+
arrayRemove: FormInstance<T>['arrayRemove'];
|
|
156
|
+
arrayMove: FormInstance<T>['arrayMove'];
|
|
157
|
+
arraySwap: FormInstance<T>['arraySwap'];
|
|
158
|
+
setErrors: FormInstance<T>['setErrors'];
|
|
159
|
+
clearErrors: FormInstance<T>['clearErrors'];
|
|
160
|
+
}
|
|
161
|
+
declare function useSolidForm<T extends object>(form: FormInstance<T>): [Store<FormState<T>>, SolidFormActions<T>];
|
|
162
|
+
declare function useSolidFormPath<T extends object>(form: FormInstance<T>, path: string): {
|
|
18
163
|
value: solid_js.Accessor<unknown>;
|
|
19
164
|
fieldState: solid_js.Accessor<{
|
|
20
165
|
error?: string;
|
|
@@ -23,4 +168,4 @@ declare function useSolidFormPath(form: any, path: () => string): {
|
|
|
23
168
|
} | null>;
|
|
24
169
|
};
|
|
25
170
|
|
|
26
|
-
export { useSolidForm, useSolidFormPath };
|
|
171
|
+
export { type SolidFormActions, useSolidForm, useSolidFormPath };
|
package/dist/adapters/solid.js
CHANGED
|
@@ -17,18 +17,27 @@ function useSolidForm(form) {
|
|
|
17
17
|
handleSubmit: form.handleSubmit,
|
|
18
18
|
reset: form.reset,
|
|
19
19
|
batch: form.batch,
|
|
20
|
+
validate: form.validate,
|
|
21
|
+
subscribeToPath: form.subscribeToPath,
|
|
22
|
+
getPayload: form.getPayload,
|
|
23
|
+
getAriaProps: form.getAriaProps,
|
|
24
|
+
getFieldMode: form.getFieldMode,
|
|
25
|
+
getConnectedCount: form.getConnectedCount,
|
|
26
|
+
destroy: form.destroy,
|
|
20
27
|
arrayAppend: form.arrayAppend,
|
|
21
28
|
arrayInsert: form.arrayInsert,
|
|
22
29
|
arrayRemove: form.arrayRemove,
|
|
23
30
|
arrayMove: form.arrayMove,
|
|
24
|
-
arraySwap: form.arraySwap
|
|
31
|
+
arraySwap: form.arraySwap,
|
|
32
|
+
setErrors: form.setErrors,
|
|
33
|
+
clearErrors: form.clearErrors
|
|
25
34
|
}
|
|
26
35
|
];
|
|
27
36
|
}
|
|
28
37
|
function useSolidFormPath(form, path) {
|
|
29
|
-
const [value, setValue] = createSignal(form.get(path
|
|
38
|
+
const [value, setValue] = createSignal(form.get(path));
|
|
30
39
|
const [fieldState, setFieldState] = createSignal(null);
|
|
31
|
-
const unsubscribe = form.subscribeToPath(path
|
|
40
|
+
const unsubscribe = form.subscribeToPath(path, (v, fs) => {
|
|
32
41
|
setValue(() => v);
|
|
33
42
|
setFieldState(() => fs);
|
|
34
43
|
});
|
package/dist/adapters/svelte.cjs
CHANGED
|
@@ -28,10 +28,10 @@ module.exports = __toCommonJS(svelte_exports);
|
|
|
28
28
|
// ../adapters/svelte/dist/index.js
|
|
29
29
|
var import_store = require("svelte/store");
|
|
30
30
|
function useSvelteForm(form) {
|
|
31
|
-
const state = (0, import_store.readable)(
|
|
32
|
-
form.getState()
|
|
33
|
-
|
|
34
|
-
);
|
|
31
|
+
const state = (0, import_store.readable)(form.getState(), (set) => {
|
|
32
|
+
set(form.getState());
|
|
33
|
+
return form.subscribe((s) => set(s));
|
|
34
|
+
});
|
|
35
35
|
return {
|
|
36
36
|
state,
|
|
37
37
|
get: form.get,
|
|
@@ -41,18 +41,27 @@ function useSvelteForm(form) {
|
|
|
41
41
|
handleSubmit: form.handleSubmit,
|
|
42
42
|
reset: form.reset,
|
|
43
43
|
batch: form.batch,
|
|
44
|
+
validate: form.validate,
|
|
45
|
+
subscribeToPath: form.subscribeToPath,
|
|
46
|
+
getPayload: form.getPayload,
|
|
47
|
+
getAriaProps: form.getAriaProps,
|
|
48
|
+
getFieldMode: form.getFieldMode,
|
|
49
|
+
getConnectedCount: form.getConnectedCount,
|
|
50
|
+
destroy: form.destroy,
|
|
44
51
|
arrayAppend: form.arrayAppend,
|
|
45
52
|
arrayInsert: form.arrayInsert,
|
|
46
53
|
arrayRemove: form.arrayRemove,
|
|
47
54
|
arrayMove: form.arrayMove,
|
|
48
|
-
arraySwap: form.arraySwap
|
|
55
|
+
arraySwap: form.arraySwap,
|
|
56
|
+
setErrors: form.setErrors,
|
|
57
|
+
clearErrors: form.clearErrors
|
|
49
58
|
};
|
|
50
59
|
}
|
|
51
60
|
function useSvelteFormPath(form, path) {
|
|
52
|
-
const field = (0, import_store.readable)(
|
|
53
|
-
{ value: form.get(path), fieldState: null }
|
|
54
|
-
|
|
55
|
-
);
|
|
61
|
+
const field = (0, import_store.readable)({ value: form.get(path), fieldState: null }, (set) => {
|
|
62
|
+
set({ value: form.get(path), fieldState: null });
|
|
63
|
+
return form.subscribeToPath(path, (v, fs) => set({ value: v, fieldState: fs }));
|
|
64
|
+
});
|
|
56
65
|
return field;
|
|
57
66
|
}
|
|
58
67
|
// Annotate the CommonJS export names for ESM import in node:
|