@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.
Files changed (130) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/UPSTREAM.md +95 -0
  4. package/package.json +65 -0
  5. package/src/components/Field/Field.tsrx +22 -0
  6. package/src/components/Field/Field.tsrx.d.ts +17 -0
  7. package/src/components/Field/index.ts +1 -0
  8. package/src/components/FieldArray/FieldArray.tsrx +22 -0
  9. package/src/components/FieldArray/FieldArray.tsrx.d.ts +18 -0
  10. package/src/components/FieldArray/index.ts +1 -0
  11. package/src/components/Form/Form.tsrx +28 -0
  12. package/src/components/Form/Form.tsrx.d.ts +15 -0
  13. package/src/components/Form/index.ts +1 -0
  14. package/src/components/index.ts +3 -0
  15. package/src/core/array/copyItemState/copyItemState.ts +101 -0
  16. package/src/core/array/copyItemState/index.ts +1 -0
  17. package/src/core/array/index.ts +3 -0
  18. package/src/core/array/resetItemState/index.ts +1 -0
  19. package/src/core/array/resetItemState/resetItemState.ts +172 -0
  20. package/src/core/array/swapItemState/index.ts +1 -0
  21. package/src/core/array/swapItemState/swapItemState.ts +138 -0
  22. package/src/core/field/focusFieldElement/focusFieldElement.ts +32 -0
  23. package/src/core/field/focusFieldElement/index.ts +1 -0
  24. package/src/core/field/getDirtyFieldInput/getDirtyFieldInput.ts +66 -0
  25. package/src/core/field/getDirtyFieldInput/index.ts +1 -0
  26. package/src/core/field/getElementInput/getElementInput.ts +78 -0
  27. package/src/core/field/getElementInput/index.ts +1 -0
  28. package/src/core/field/getFieldBool/getFieldBool.ts +22 -0
  29. package/src/core/field/getFieldBool/index.ts +1 -0
  30. package/src/core/field/getFieldInput/getFieldInput.ts +52 -0
  31. package/src/core/field/getFieldInput/index.ts +1 -0
  32. package/src/core/field/getFieldStore/getFieldStore.ts +34 -0
  33. package/src/core/field/getFieldStore/index.ts +1 -0
  34. package/src/core/field/index.ts +11 -0
  35. package/src/core/field/initializeFieldStore/index.ts +1 -0
  36. package/src/core/field/initializeFieldStore/initializeFieldStore.ts +325 -0
  37. package/src/core/field/setFieldBool/index.ts +1 -0
  38. package/src/core/field/setFieldBool/setFieldBool.ts +29 -0
  39. package/src/core/field/setFieldInput/index.ts +1 -0
  40. package/src/core/field/setFieldInput/setFieldInput.ts +180 -0
  41. package/src/core/field/setInitialFieldInput/index.ts +1 -0
  42. package/src/core/field/setInitialFieldInput/setInitialFieldInput.ts +99 -0
  43. package/src/core/field/walkFieldStore/index.ts +1 -0
  44. package/src/core/field/walkFieldStore/walkFieldStore.ts +49 -0
  45. package/src/core/form/createFormStore/createFormStore.ts +56 -0
  46. package/src/core/form/createFormStore/index.ts +1 -0
  47. package/src/core/form/decodeFormData/decodeFormData.ts +436 -0
  48. package/src/core/form/decodeFormData/index.ts +1 -0
  49. package/src/core/form/index.ts +4 -0
  50. package/src/core/form/validateFormInput/index.ts +1 -0
  51. package/src/core/form/validateFormInput/validateFormInput.ts +138 -0
  52. package/src/core/form/validateIfRequired/index.ts +1 -0
  53. package/src/core/form/validateIfRequired/validateIfRequired.ts +31 -0
  54. package/src/core/framework/index.ts +80 -0
  55. package/src/core/index.ts +6 -0
  56. package/src/core/types/field/field.ts +201 -0
  57. package/src/core/types/field/index.ts +1 -0
  58. package/src/core/types/form/form.ts +140 -0
  59. package/src/core/types/form/index.ts +1 -0
  60. package/src/core/types/index.ts +6 -0
  61. package/src/core/types/path/index.ts +10 -0
  62. package/src/core/types/path/path.ts +301 -0
  63. package/src/core/types/schema/index.ts +1 -0
  64. package/src/core/types/schema/schema.ts +18 -0
  65. package/src/core/types/signal/index.ts +1 -0
  66. package/src/core/types/signal/signal.ts +23 -0
  67. package/src/core/types/utils/index.ts +1 -0
  68. package/src/core/types/utils/utils.ts +46 -0
  69. package/src/core/values.ts +4 -0
  70. package/src/hooks/index.ts +3 -0
  71. package/src/hooks/useField/index.ts +1 -0
  72. package/src/hooks/useField/useField.ts +114 -0
  73. package/src/hooks/useFieldArray/index.ts +1 -0
  74. package/src/hooks/useFieldArray/useFieldArray.ts +63 -0
  75. package/src/hooks/useForm/index.ts +1 -0
  76. package/src/hooks/useForm/useForm.ts +68 -0
  77. package/src/hooks/useSignals/index.ts +1 -0
  78. package/src/hooks/useSignals/useSignals.ts +31 -0
  79. package/src/index.ts +19 -0
  80. package/src/internal.ts +32 -0
  81. package/src/methods/focus/focus.ts +35 -0
  82. package/src/methods/focus/index.ts +1 -0
  83. package/src/methods/getDeepErrorEntries/getDeepErrorEntries.ts +108 -0
  84. package/src/methods/getDeepErrorEntries/index.ts +1 -0
  85. package/src/methods/getDeepErrors/getDeepErrors.ts +90 -0
  86. package/src/methods/getDeepErrors/index.ts +1 -0
  87. package/src/methods/getDirtyInput/getDirtyInput.ts +87 -0
  88. package/src/methods/getDirtyInput/index.ts +1 -0
  89. package/src/methods/getDirtyPaths/getDirtyPaths.ts +123 -0
  90. package/src/methods/getDirtyPaths/index.ts +1 -0
  91. package/src/methods/getErrors/getErrors.ts +70 -0
  92. package/src/methods/getErrors/index.ts +1 -0
  93. package/src/methods/getInput/getInput.ts +75 -0
  94. package/src/methods/getInput/index.ts +1 -0
  95. package/src/methods/handleSubmit/handleSubmit.ts +83 -0
  96. package/src/methods/handleSubmit/index.ts +1 -0
  97. package/src/methods/index.ts +23 -0
  98. package/src/methods/insert/index.ts +1 -0
  99. package/src/methods/insert/insert.ts +134 -0
  100. package/src/methods/isDirty/index.ts +1 -0
  101. package/src/methods/isDirty/isDirty.ts +72 -0
  102. package/src/methods/isEdited/index.ts +1 -0
  103. package/src/methods/isEdited/isEdited.ts +72 -0
  104. package/src/methods/isTouched/index.ts +1 -0
  105. package/src/methods/isTouched/isTouched.ts +72 -0
  106. package/src/methods/isValid/index.ts +1 -0
  107. package/src/methods/isValid/isValid.ts +74 -0
  108. package/src/methods/move/index.ts +1 -0
  109. package/src/methods/move/move.ts +124 -0
  110. package/src/methods/pickDirty/index.ts +1 -0
  111. package/src/methods/pickDirty/pickDirty.ts +87 -0
  112. package/src/methods/remove/index.ts +1 -0
  113. package/src/methods/remove/remove.ts +76 -0
  114. package/src/methods/replace/index.ts +1 -0
  115. package/src/methods/replace/replace.ts +80 -0
  116. package/src/methods/reset/index.ts +1 -0
  117. package/src/methods/reset/reset.ts +216 -0
  118. package/src/methods/setErrors/index.ts +1 -0
  119. package/src/methods/setErrors/setErrors.ts +63 -0
  120. package/src/methods/setInput/index.ts +1 -0
  121. package/src/methods/setInput/setInput.ts +87 -0
  122. package/src/methods/submit/index.ts +1 -0
  123. package/src/methods/submit/submit.ts +11 -0
  124. package/src/methods/swap/index.ts +1 -0
  125. package/src/methods/swap/swap.ts +85 -0
  126. package/src/methods/validate/index.ts +1 -0
  127. package/src/methods/validate/validate.ts +34 -0
  128. package/src/types/field.ts +48 -0
  129. package/src/types/form.ts +12 -0
  130. 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
+ }
@@ -0,0 +1,2 @@
1
+ export * from './field.ts';
2
+ export * from './form.ts';