@octanejs/formisch 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/LICENSE +21 -0
- package/README.md +73 -0
- package/UPSTREAM.md +95 -0
- package/package.json +65 -0
- package/src/components/Field/Field.tsrx +22 -0
- package/src/components/Field/Field.tsrx.d.ts +17 -0
- package/src/components/Field/index.ts +1 -0
- package/src/components/FieldArray/FieldArray.tsrx +22 -0
- package/src/components/FieldArray/FieldArray.tsrx.d.ts +18 -0
- package/src/components/FieldArray/index.ts +1 -0
- package/src/components/Form/Form.tsrx +28 -0
- package/src/components/Form/Form.tsrx.d.ts +15 -0
- package/src/components/Form/index.ts +1 -0
- package/src/components/index.ts +3 -0
- package/src/core/array/copyItemState/copyItemState.ts +101 -0
- package/src/core/array/copyItemState/index.ts +1 -0
- package/src/core/array/index.ts +3 -0
- package/src/core/array/resetItemState/index.ts +1 -0
- package/src/core/array/resetItemState/resetItemState.ts +172 -0
- package/src/core/array/swapItemState/index.ts +1 -0
- package/src/core/array/swapItemState/swapItemState.ts +138 -0
- package/src/core/field/focusFieldElement/focusFieldElement.ts +32 -0
- package/src/core/field/focusFieldElement/index.ts +1 -0
- package/src/core/field/getDirtyFieldInput/getDirtyFieldInput.ts +66 -0
- package/src/core/field/getDirtyFieldInput/index.ts +1 -0
- package/src/core/field/getElementInput/getElementInput.ts +78 -0
- package/src/core/field/getElementInput/index.ts +1 -0
- package/src/core/field/getFieldBool/getFieldBool.ts +22 -0
- package/src/core/field/getFieldBool/index.ts +1 -0
- package/src/core/field/getFieldInput/getFieldInput.ts +52 -0
- package/src/core/field/getFieldInput/index.ts +1 -0
- package/src/core/field/getFieldStore/getFieldStore.ts +34 -0
- package/src/core/field/getFieldStore/index.ts +1 -0
- package/src/core/field/index.ts +11 -0
- package/src/core/field/initializeFieldStore/index.ts +1 -0
- package/src/core/field/initializeFieldStore/initializeFieldStore.ts +325 -0
- package/src/core/field/setFieldBool/index.ts +1 -0
- package/src/core/field/setFieldBool/setFieldBool.ts +29 -0
- package/src/core/field/setFieldInput/index.ts +1 -0
- package/src/core/field/setFieldInput/setFieldInput.ts +180 -0
- package/src/core/field/setInitialFieldInput/index.ts +1 -0
- package/src/core/field/setInitialFieldInput/setInitialFieldInput.ts +99 -0
- package/src/core/field/walkFieldStore/index.ts +1 -0
- package/src/core/field/walkFieldStore/walkFieldStore.ts +49 -0
- package/src/core/form/createFormStore/createFormStore.ts +56 -0
- package/src/core/form/createFormStore/index.ts +1 -0
- package/src/core/form/decodeFormData/decodeFormData.ts +436 -0
- package/src/core/form/decodeFormData/index.ts +1 -0
- package/src/core/form/index.ts +4 -0
- package/src/core/form/validateFormInput/index.ts +1 -0
- package/src/core/form/validateFormInput/validateFormInput.ts +138 -0
- package/src/core/form/validateIfRequired/index.ts +1 -0
- package/src/core/form/validateIfRequired/validateIfRequired.ts +31 -0
- package/src/core/framework/index.ts +80 -0
- package/src/core/index.ts +6 -0
- package/src/core/types/field/field.ts +201 -0
- package/src/core/types/field/index.ts +1 -0
- package/src/core/types/form/form.ts +140 -0
- package/src/core/types/form/index.ts +1 -0
- package/src/core/types/index.ts +6 -0
- package/src/core/types/path/index.ts +10 -0
- package/src/core/types/path/path.ts +301 -0
- package/src/core/types/schema/index.ts +1 -0
- package/src/core/types/schema/schema.ts +18 -0
- package/src/core/types/signal/index.ts +1 -0
- package/src/core/types/signal/signal.ts +23 -0
- package/src/core/types/utils/index.ts +1 -0
- package/src/core/types/utils/utils.ts +46 -0
- package/src/core/values.ts +4 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useField/index.ts +1 -0
- package/src/hooks/useField/useField.ts +114 -0
- package/src/hooks/useFieldArray/index.ts +1 -0
- package/src/hooks/useFieldArray/useFieldArray.ts +63 -0
- package/src/hooks/useForm/index.ts +1 -0
- package/src/hooks/useForm/useForm.ts +68 -0
- package/src/hooks/useSignals/index.ts +1 -0
- package/src/hooks/useSignals/useSignals.ts +31 -0
- package/src/index.ts +19 -0
- package/src/internal.ts +32 -0
- package/src/methods/focus/focus.ts +35 -0
- package/src/methods/focus/index.ts +1 -0
- package/src/methods/getDeepErrorEntries/getDeepErrorEntries.ts +108 -0
- package/src/methods/getDeepErrorEntries/index.ts +1 -0
- package/src/methods/getDeepErrors/getDeepErrors.ts +90 -0
- package/src/methods/getDeepErrors/index.ts +1 -0
- package/src/methods/getDirtyInput/getDirtyInput.ts +87 -0
- package/src/methods/getDirtyInput/index.ts +1 -0
- package/src/methods/getDirtyPaths/getDirtyPaths.ts +123 -0
- package/src/methods/getDirtyPaths/index.ts +1 -0
- package/src/methods/getErrors/getErrors.ts +70 -0
- package/src/methods/getErrors/index.ts +1 -0
- package/src/methods/getInput/getInput.ts +75 -0
- package/src/methods/getInput/index.ts +1 -0
- package/src/methods/handleSubmit/handleSubmit.ts +83 -0
- package/src/methods/handleSubmit/index.ts +1 -0
- package/src/methods/index.ts +23 -0
- package/src/methods/insert/index.ts +1 -0
- package/src/methods/insert/insert.ts +134 -0
- package/src/methods/isDirty/index.ts +1 -0
- package/src/methods/isDirty/isDirty.ts +72 -0
- package/src/methods/isEdited/index.ts +1 -0
- package/src/methods/isEdited/isEdited.ts +72 -0
- package/src/methods/isTouched/index.ts +1 -0
- package/src/methods/isTouched/isTouched.ts +72 -0
- package/src/methods/isValid/index.ts +1 -0
- package/src/methods/isValid/isValid.ts +74 -0
- package/src/methods/move/index.ts +1 -0
- package/src/methods/move/move.ts +124 -0
- package/src/methods/pickDirty/index.ts +1 -0
- package/src/methods/pickDirty/pickDirty.ts +87 -0
- package/src/methods/remove/index.ts +1 -0
- package/src/methods/remove/remove.ts +76 -0
- package/src/methods/replace/index.ts +1 -0
- package/src/methods/replace/replace.ts +80 -0
- package/src/methods/reset/index.ts +1 -0
- package/src/methods/reset/reset.ts +216 -0
- package/src/methods/setErrors/index.ts +1 -0
- package/src/methods/setErrors/setErrors.ts +63 -0
- package/src/methods/setInput/index.ts +1 -0
- package/src/methods/setInput/setInput.ts +87 -0
- package/src/methods/submit/index.ts +1 -0
- package/src/methods/submit/submit.ts +11 -0
- package/src/methods/swap/index.ts +1 -0
- package/src/methods/swap/swap.ts +85 -0
- package/src/methods/validate/index.ts +1 -0
- package/src/methods/validate/validate.ts +34 -0
- package/src/types/field.ts +48 -0
- package/src/types/form.ts +12 -0
- package/src/types/index.ts +2 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BaseFormStore,
|
|
3
|
+
batch,
|
|
4
|
+
type FormSchema,
|
|
5
|
+
getFieldStore,
|
|
6
|
+
INTERNAL,
|
|
7
|
+
type InternalArrayStore,
|
|
8
|
+
type RequiredPath,
|
|
9
|
+
swapItemState,
|
|
10
|
+
untrack,
|
|
11
|
+
type ValidArrayPath,
|
|
12
|
+
validateIfRequired,
|
|
13
|
+
} from '../../core/index.ts';
|
|
14
|
+
import type * as v from 'valibot';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Swap array field config interface.
|
|
18
|
+
*/
|
|
19
|
+
export interface SwapConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
|
|
20
|
+
/**
|
|
21
|
+
* The path to the field array to swap items within.
|
|
22
|
+
*/
|
|
23
|
+
readonly path: ValidArrayPath<v.InferInput<TSchema>, TFieldArrayPath>;
|
|
24
|
+
/**
|
|
25
|
+
* The index of the first item to swap.
|
|
26
|
+
*/
|
|
27
|
+
readonly at: number;
|
|
28
|
+
/**
|
|
29
|
+
* The index of the second item to swap with the first.
|
|
30
|
+
*/
|
|
31
|
+
readonly and: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Swaps two items in a field array by exchanging their positions.
|
|
36
|
+
*
|
|
37
|
+
* @param form The form store containing the field array.
|
|
38
|
+
* @param config The swap configuration specifying the path and indices to swap.
|
|
39
|
+
*/
|
|
40
|
+
export function swap<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(
|
|
41
|
+
form: BaseFormStore<TSchema>,
|
|
42
|
+
config: SwapConfig<TSchema, TFieldArrayPath>,
|
|
43
|
+
): void {
|
|
44
|
+
// Get internal form and array store
|
|
45
|
+
const internalFormStore = form[INTERNAL];
|
|
46
|
+
const internalArrayStore = getFieldStore(internalFormStore, config.path) as InternalArrayStore;
|
|
47
|
+
|
|
48
|
+
// Get current items of field array
|
|
49
|
+
const items = untrack(() => internalArrayStore.items.value);
|
|
50
|
+
|
|
51
|
+
// Continue if both specified indices are valid
|
|
52
|
+
if (
|
|
53
|
+
config.at >= 0 &&
|
|
54
|
+
config.at <= items.length - 1 &&
|
|
55
|
+
config.and >= 0 &&
|
|
56
|
+
config.and <= items.length - 1 &&
|
|
57
|
+
config.at !== config.and
|
|
58
|
+
) {
|
|
59
|
+
batch(() => {
|
|
60
|
+
// Swap item IDs in items array
|
|
61
|
+
const newItems = [...items];
|
|
62
|
+
const tempItemId = newItems[config.at];
|
|
63
|
+
newItems[config.at] = newItems[config.and];
|
|
64
|
+
newItems[config.and] = tempItemId;
|
|
65
|
+
internalArrayStore.items.value = newItems;
|
|
66
|
+
|
|
67
|
+
// Swap child stores directly
|
|
68
|
+
swapItemState(
|
|
69
|
+
internalFormStore,
|
|
70
|
+
internalArrayStore.children[config.at],
|
|
71
|
+
internalArrayStore.children[config.and],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Mark field array as touched and edited and update dirty state
|
|
75
|
+
internalArrayStore.isTouched.value = true;
|
|
76
|
+
internalArrayStore.isEdited.value = true;
|
|
77
|
+
internalArrayStore.isDirty.value =
|
|
78
|
+
internalArrayStore.startItems.value.join() !== newItems.join();
|
|
79
|
+
|
|
80
|
+
// Validate if required
|
|
81
|
+
// TODO: Should we validate on touch, change and blur too?
|
|
82
|
+
validateIfRequired(internalFormStore, internalArrayStore, 'input');
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './validate.ts';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BaseFormStore,
|
|
3
|
+
type FormSchema,
|
|
4
|
+
INTERNAL,
|
|
5
|
+
validateFormInput,
|
|
6
|
+
} from '../../core/index.ts';
|
|
7
|
+
import type * as v from 'valibot';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Validate form config interface.
|
|
11
|
+
*/
|
|
12
|
+
export interface ValidateFormConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Whether to focus the first field with errors after validation. Defaults to false.
|
|
15
|
+
*/
|
|
16
|
+
readonly shouldFocus?: boolean | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Validates the entire form input against its schema. Returns a safe parse result
|
|
21
|
+
* indicating success or failure with detailed issues. Optionally focuses the first
|
|
22
|
+
* field with validation errors.
|
|
23
|
+
*
|
|
24
|
+
* @param form The form store to validate.
|
|
25
|
+
* @param config The validate form configuration specifying focus behavior.
|
|
26
|
+
*
|
|
27
|
+
* @returns A promise resolving to the validation result.
|
|
28
|
+
*/
|
|
29
|
+
export function validate<TSchema extends FormSchema>(
|
|
30
|
+
form: BaseFormStore<TSchema>,
|
|
31
|
+
config?: ValidateFormConfig,
|
|
32
|
+
): Promise<v.SafeParseResult<TSchema>> {
|
|
33
|
+
return validateFormInput(form[INTERNAL], config) as Promise<v.SafeParseResult<TSchema>>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
FieldElement,
|
|
3
|
+
FormSchema,
|
|
4
|
+
PartialValues,
|
|
5
|
+
PathValue,
|
|
6
|
+
RequiredPath,
|
|
7
|
+
ValidArrayPath,
|
|
8
|
+
ValidPath,
|
|
9
|
+
} from '../core/index.ts';
|
|
10
|
+
import type * as v from 'valibot';
|
|
11
|
+
|
|
12
|
+
export interface FieldElementProps {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly autoFocus: boolean;
|
|
15
|
+
readonly ref: (element: FieldElement | null) => void;
|
|
16
|
+
readonly onFocus: (event: FocusEvent) => void;
|
|
17
|
+
readonly onInput: (event: InputEvent) => void;
|
|
18
|
+
readonly onChange: (event: Event) => void;
|
|
19
|
+
readonly onBlur: (event: FocusEvent) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface FieldStore<
|
|
23
|
+
TSchema extends FormSchema = FormSchema,
|
|
24
|
+
TFieldPath extends RequiredPath = RequiredPath,
|
|
25
|
+
> {
|
|
26
|
+
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
27
|
+
readonly input: PartialValues<PathValue<v.InferInput<TSchema>, TFieldPath>>;
|
|
28
|
+
readonly errors: [string, ...string[]] | null;
|
|
29
|
+
readonly isTouched: boolean;
|
|
30
|
+
readonly isEdited: boolean;
|
|
31
|
+
readonly isDirty: boolean;
|
|
32
|
+
readonly isValid: boolean;
|
|
33
|
+
readonly onChange: (value: PartialValues<PathValue<v.InferInput<TSchema>, TFieldPath>>) => void;
|
|
34
|
+
readonly props: FieldElementProps;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface FieldArrayStore<
|
|
38
|
+
TSchema extends FormSchema = FormSchema,
|
|
39
|
+
TFieldArrayPath extends RequiredPath = RequiredPath,
|
|
40
|
+
> {
|
|
41
|
+
readonly path: ValidArrayPath<v.InferInput<TSchema>, TFieldArrayPath>;
|
|
42
|
+
readonly items: string[];
|
|
43
|
+
readonly errors: [string, ...string[]] | null;
|
|
44
|
+
readonly isTouched: boolean;
|
|
45
|
+
readonly isEdited: boolean;
|
|
46
|
+
readonly isDirty: boolean;
|
|
47
|
+
readonly isValid: boolean;
|
|
48
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BaseFormStore, FormSchema } from '../core/index.ts';
|
|
2
|
+
|
|
3
|
+
export interface FormStore<TSchema extends FormSchema = FormSchema> extends BaseFormStore<TSchema> {
|
|
4
|
+
readonly isSubmitting: boolean;
|
|
5
|
+
readonly isSubmitted: boolean;
|
|
6
|
+
readonly isValidating: boolean;
|
|
7
|
+
readonly isTouched: boolean;
|
|
8
|
+
readonly isEdited: boolean;
|
|
9
|
+
readonly isDirty: boolean;
|
|
10
|
+
readonly isValid: boolean;
|
|
11
|
+
readonly errors: [string, ...string[]] | null;
|
|
12
|
+
}
|