@proyecto-viviana/solid-stately 0.2.2 → 0.2.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.
Files changed (218) hide show
  1. package/dist/index.js +43 -43
  2. package/dist/index.js.map +1 -1
  3. package/package.json +7 -5
  4. package/src/autocomplete/createAutocompleteState.d.ts +46 -0
  5. package/src/autocomplete/createAutocompleteState.d.ts.map +1 -0
  6. package/src/autocomplete/createAutocompleteState.ts +90 -0
  7. package/src/autocomplete/index.d.ts +2 -0
  8. package/src/autocomplete/index.d.ts.map +1 -0
  9. package/src/autocomplete/index.ts +5 -0
  10. package/src/calendar/createCalendarState.d.ts +130 -0
  11. package/src/calendar/createCalendarState.d.ts.map +1 -0
  12. package/src/calendar/createCalendarState.ts +461 -0
  13. package/src/calendar/createDateFieldState.d.ts +110 -0
  14. package/src/calendar/createDateFieldState.d.ts.map +1 -0
  15. package/src/calendar/createDateFieldState.ts +562 -0
  16. package/src/calendar/createRangeCalendarState.d.ts +146 -0
  17. package/src/calendar/createRangeCalendarState.d.ts.map +1 -0
  18. package/src/calendar/createRangeCalendarState.ts +535 -0
  19. package/src/calendar/createTimeFieldState.d.ts +95 -0
  20. package/src/calendar/createTimeFieldState.d.ts.map +1 -0
  21. package/src/calendar/createTimeFieldState.ts +483 -0
  22. package/src/calendar/index.d.ts +7 -0
  23. package/src/calendar/index.d.ts.map +1 -0
  24. package/src/calendar/index.ts +81 -0
  25. package/src/checkbox/createCheckboxGroupState.d.ts +71 -0
  26. package/src/checkbox/createCheckboxGroupState.d.ts.map +1 -0
  27. package/src/checkbox/createCheckboxGroupState.ts +193 -0
  28. package/src/checkbox/index.d.ts +2 -0
  29. package/src/checkbox/index.d.ts.map +1 -0
  30. package/src/checkbox/index.ts +5 -0
  31. package/src/collections/ListCollection.d.ts +37 -0
  32. package/src/collections/ListCollection.d.ts.map +1 -0
  33. package/src/collections/ListCollection.ts +146 -0
  34. package/src/collections/createListState.d.ts +79 -0
  35. package/src/collections/createListState.d.ts.map +1 -0
  36. package/src/collections/createListState.ts +264 -0
  37. package/src/collections/createMenuState.d.ts +50 -0
  38. package/src/collections/createMenuState.d.ts.map +1 -0
  39. package/src/collections/createMenuState.ts +106 -0
  40. package/src/collections/createSelectionState.d.ts +76 -0
  41. package/src/collections/createSelectionState.d.ts.map +1 -0
  42. package/src/collections/createSelectionState.ts +336 -0
  43. package/src/collections/index.d.ts +6 -0
  44. package/src/collections/index.d.ts.map +1 -0
  45. package/src/collections/index.ts +46 -0
  46. package/src/collections/types.d.ts +147 -0
  47. package/src/collections/types.d.ts.map +1 -0
  48. package/src/collections/types.ts +169 -0
  49. package/src/color/Color.d.ts +28 -0
  50. package/src/color/Color.d.ts.map +1 -0
  51. package/src/color/Color.ts +951 -0
  52. package/src/color/createColorAreaState.d.ts +76 -0
  53. package/src/color/createColorAreaState.d.ts.map +1 -0
  54. package/src/color/createColorAreaState.ts +293 -0
  55. package/src/color/createColorFieldState.d.ts +55 -0
  56. package/src/color/createColorFieldState.d.ts.map +1 -0
  57. package/src/color/createColorFieldState.ts +292 -0
  58. package/src/color/createColorSliderState.d.ts +67 -0
  59. package/src/color/createColorSliderState.d.ts.map +1 -0
  60. package/src/color/createColorSliderState.ts +241 -0
  61. package/src/color/createColorWheelState.d.ts +51 -0
  62. package/src/color/createColorWheelState.d.ts.map +1 -0
  63. package/src/color/createColorWheelState.ts +211 -0
  64. package/src/color/index.d.ts +10 -0
  65. package/src/color/index.d.ts.map +1 -0
  66. package/src/color/index.ts +47 -0
  67. package/src/color/types.d.ts +106 -0
  68. package/src/color/types.d.ts.map +1 -0
  69. package/src/color/types.ts +127 -0
  70. package/src/combobox/createComboBoxState.d.ts +125 -0
  71. package/src/combobox/createComboBoxState.d.ts.map +1 -0
  72. package/src/combobox/createComboBoxState.ts +703 -0
  73. package/src/combobox/index.d.ts +5 -0
  74. package/src/combobox/index.d.ts.map +1 -0
  75. package/src/combobox/index.ts +13 -0
  76. package/src/disclosure/createDisclosureState.d.ts +64 -0
  77. package/src/disclosure/createDisclosureState.d.ts.map +1 -0
  78. package/src/disclosure/createDisclosureState.ts +193 -0
  79. package/src/disclosure/index.d.ts +2 -0
  80. package/src/disclosure/index.d.ts.map +1 -0
  81. package/src/disclosure/index.ts +9 -0
  82. package/src/dnd/createDragState.d.ts +59 -0
  83. package/src/dnd/createDragState.d.ts.map +1 -0
  84. package/src/dnd/createDragState.ts +153 -0
  85. package/src/dnd/createDraggableCollectionState.d.ts +57 -0
  86. package/src/dnd/createDraggableCollectionState.d.ts.map +1 -0
  87. package/src/dnd/createDraggableCollectionState.ts +165 -0
  88. package/src/dnd/createDropState.d.ts +61 -0
  89. package/src/dnd/createDropState.d.ts.map +1 -0
  90. package/src/dnd/createDropState.ts +212 -0
  91. package/src/dnd/createDroppableCollectionState.d.ts +78 -0
  92. package/src/dnd/createDroppableCollectionState.d.ts.map +1 -0
  93. package/src/dnd/createDroppableCollectionState.ts +357 -0
  94. package/src/dnd/index.d.ts +11 -0
  95. package/src/dnd/index.d.ts.map +1 -0
  96. package/src/dnd/index.ts +76 -0
  97. package/src/dnd/types.d.ts +264 -0
  98. package/src/dnd/types.d.ts.map +1 -0
  99. package/src/dnd/types.ts +317 -0
  100. package/src/form/createFormValidationState.d.ts +100 -0
  101. package/src/form/createFormValidationState.d.ts.map +1 -0
  102. package/src/form/createFormValidationState.ts +389 -0
  103. package/src/form/index.d.ts +2 -0
  104. package/src/form/index.d.ts.map +1 -0
  105. package/src/form/index.ts +15 -0
  106. package/src/grid/createGridState.d.ts +12 -0
  107. package/src/grid/createGridState.d.ts.map +1 -0
  108. package/src/grid/createGridState.ts +327 -0
  109. package/src/grid/index.d.ts +7 -0
  110. package/src/grid/index.d.ts.map +1 -0
  111. package/src/grid/index.ts +13 -0
  112. package/src/grid/types.d.ts +156 -0
  113. package/src/grid/types.d.ts.map +1 -0
  114. package/src/grid/types.ts +179 -0
  115. package/src/index.d.ts +26 -0
  116. package/src/index.d.ts.map +1 -0
  117. package/src/index.ts +383 -0
  118. package/src/numberfield/createNumberFieldState.d.ts +65 -0
  119. package/src/numberfield/createNumberFieldState.d.ts.map +1 -0
  120. package/src/numberfield/createNumberFieldState.ts +383 -0
  121. package/src/numberfield/index.d.ts +2 -0
  122. package/src/numberfield/index.d.ts.map +1 -0
  123. package/src/numberfield/index.ts +5 -0
  124. package/src/overlays/createOverlayTriggerState.d.ts +32 -0
  125. package/src/overlays/createOverlayTriggerState.d.ts.map +1 -0
  126. package/src/overlays/createOverlayTriggerState.ts +67 -0
  127. package/src/overlays/index.d.ts +2 -0
  128. package/src/overlays/index.d.ts.map +1 -0
  129. package/src/overlays/index.ts +5 -0
  130. package/src/radio/createRadioGroupState.d.ts +77 -0
  131. package/src/radio/createRadioGroupState.d.ts.map +1 -0
  132. package/src/radio/createRadioGroupState.ts +201 -0
  133. package/src/radio/index.d.ts +2 -0
  134. package/src/radio/index.d.ts.map +1 -0
  135. package/src/radio/index.ts +6 -0
  136. package/src/searchfield/createSearchFieldState.d.ts +25 -0
  137. package/src/searchfield/createSearchFieldState.d.ts.map +1 -0
  138. package/src/searchfield/createSearchFieldState.ts +62 -0
  139. package/src/searchfield/index.d.ts +3 -0
  140. package/src/searchfield/index.d.ts.map +1 -0
  141. package/src/searchfield/index.ts +5 -0
  142. package/src/select/createSelectState.d.ts +73 -0
  143. package/src/select/createSelectState.d.ts.map +1 -0
  144. package/src/select/createSelectState.ts +181 -0
  145. package/src/select/index.d.ts +2 -0
  146. package/src/select/index.d.ts.map +1 -0
  147. package/src/select/index.ts +5 -0
  148. package/src/slider/createSliderState.d.ts +72 -0
  149. package/src/slider/createSliderState.d.ts.map +1 -0
  150. package/src/slider/createSliderState.ts +211 -0
  151. package/src/slider/index.d.ts +3 -0
  152. package/src/slider/index.d.ts.map +1 -0
  153. package/src/slider/index.ts +6 -0
  154. package/src/ssr/index.d.ts +28 -0
  155. package/src/ssr/index.d.ts.map +1 -0
  156. package/src/ssr/index.ts +41 -0
  157. package/src/table/TableCollection.d.ts +52 -0
  158. package/src/table/TableCollection.d.ts.map +1 -0
  159. package/src/table/TableCollection.ts +388 -0
  160. package/src/table/createTableState.d.ts +12 -0
  161. package/src/table/createTableState.d.ts.map +1 -0
  162. package/src/table/createTableState.ts +127 -0
  163. package/src/table/index.d.ts +8 -0
  164. package/src/table/index.d.ts.map +1 -0
  165. package/src/table/index.ts +18 -0
  166. package/src/table/types.d.ts +139 -0
  167. package/src/table/types.d.ts.map +1 -0
  168. package/src/table/types.ts +150 -0
  169. package/src/tabs/createTabListState.d.ts +68 -0
  170. package/src/tabs/createTabListState.d.ts.map +1 -0
  171. package/src/tabs/createTabListState.ts +240 -0
  172. package/src/tabs/index.d.ts +2 -0
  173. package/src/tabs/index.d.ts.map +1 -0
  174. package/src/tabs/index.ts +7 -0
  175. package/src/textfield/createTextFieldState.d.ts +30 -0
  176. package/src/textfield/createTextFieldState.d.ts.map +1 -0
  177. package/src/textfield/createTextFieldState.ts +75 -0
  178. package/src/textfield/index.d.ts +2 -0
  179. package/src/textfield/index.d.ts.map +1 -0
  180. package/src/textfield/index.ts +5 -0
  181. package/src/toast/createToastState.d.ts +118 -0
  182. package/src/toast/createToastState.d.ts.map +1 -0
  183. package/src/toast/createToastState.ts +316 -0
  184. package/src/toast/index.d.ts +2 -0
  185. package/src/toast/index.d.ts.map +1 -0
  186. package/src/toast/index.ts +11 -0
  187. package/src/toggle/createToggleState.d.ts +34 -0
  188. package/src/toggle/createToggleState.d.ts.map +1 -0
  189. package/src/toggle/createToggleState.ts +94 -0
  190. package/src/toggle/index.d.ts +2 -0
  191. package/src/toggle/index.d.ts.map +1 -0
  192. package/src/toggle/index.ts +5 -0
  193. package/src/tooltip/createTooltipTriggerState.d.ts +39 -0
  194. package/src/tooltip/createTooltipTriggerState.d.ts.map +1 -0
  195. package/src/tooltip/createTooltipTriggerState.ts +183 -0
  196. package/src/tooltip/index.d.ts +2 -0
  197. package/src/tooltip/index.d.ts.map +1 -0
  198. package/src/tooltip/index.ts +6 -0
  199. package/src/tree/TreeCollection.d.ts +40 -0
  200. package/src/tree/TreeCollection.d.ts.map +1 -0
  201. package/src/tree/TreeCollection.ts +175 -0
  202. package/src/tree/createTreeState.d.ts +14 -0
  203. package/src/tree/createTreeState.d.ts.map +1 -0
  204. package/src/tree/createTreeState.ts +392 -0
  205. package/src/tree/index.d.ts +7 -0
  206. package/src/tree/index.d.ts.map +1 -0
  207. package/src/tree/index.ts +13 -0
  208. package/src/tree/types.d.ts +157 -0
  209. package/src/tree/types.d.ts.map +1 -0
  210. package/src/tree/types.ts +174 -0
  211. package/src/utils/index.d.ts +2 -0
  212. package/src/utils/index.d.ts.map +1 -0
  213. package/src/utils/index.ts +1 -0
  214. package/src/utils/reactivity.d.ts +28 -0
  215. package/src/utils/reactivity.d.ts.map +1 -0
  216. package/src/utils/reactivity.ts +36 -0
  217. package/dist/index.jsx +0 -6408
  218. package/dist/index.jsx.map +0 -7
@@ -0,0 +1,100 @@
1
+ /**
2
+ * createFormValidationState for solid-stately
3
+ *
4
+ * Manages form validation state including realtime and displayed validation results.
5
+ * Supports both ARIA (live) and native (on submit) validation behaviors.
6
+ *
7
+ * Port of react-stately's useFormValidationState.
8
+ */
9
+ import { type Accessor } from 'solid-js';
10
+ /** Standard HTML ValidityState interface. */
11
+ export interface ValidityState {
12
+ badInput: boolean;
13
+ customError: boolean;
14
+ patternMismatch: boolean;
15
+ rangeOverflow: boolean;
16
+ rangeUnderflow: boolean;
17
+ stepMismatch: boolean;
18
+ tooLong: boolean;
19
+ tooShort: boolean;
20
+ typeMismatch: boolean;
21
+ valueMissing: boolean;
22
+ valid: boolean;
23
+ }
24
+ /** Result of validation. */
25
+ export interface ValidationResult {
26
+ /** Whether the value is invalid. */
27
+ isInvalid: boolean;
28
+ /** Details about which validation constraints failed. */
29
+ validationDetails: ValidityState;
30
+ /** Error messages to display. */
31
+ validationErrors: string[];
32
+ }
33
+ /** Map of field names to their validation errors. */
34
+ export type ValidationErrors = Record<string, string | string[]>;
35
+ /** Validation function that returns error messages or true/false. */
36
+ export type ValidationFunction<T> = (value: T) => boolean | string | string[] | null | undefined;
37
+ /** Validation behavior mode. */
38
+ export type ValidationBehavior = 'aria' | 'native';
39
+ export interface FormValidationProps<T> {
40
+ /** Whether the value is invalid (controlled). */
41
+ isInvalid?: boolean;
42
+ /** @deprecated Use isInvalid instead. */
43
+ validationState?: 'valid' | 'invalid';
44
+ /** Custom validation function. */
45
+ validate?: ValidationFunction<T>;
46
+ /** Validation behavior: 'aria' for realtime, 'native' for on submit. */
47
+ validationBehavior?: ValidationBehavior;
48
+ /** Built-in validation result from native input. */
49
+ builtinValidation?: ValidationResult;
50
+ /** Field name(s) for server error lookup. */
51
+ name?: string | string[];
52
+ /** Current field value. */
53
+ value: T | null;
54
+ }
55
+ export interface FormValidationState {
56
+ /** Realtime validation results, updated as the user edits the value. */
57
+ realtimeValidation: Accessor<ValidationResult>;
58
+ /** Currently displayed validation results, updated when the user commits their changes. */
59
+ displayValidation: Accessor<ValidationResult>;
60
+ /** Updates the current validation result. Not displayed to the user until `commitValidation` is called. */
61
+ updateValidation(result: ValidationResult): void;
62
+ /** Resets the displayed validation state to valid when the user resets the form. */
63
+ resetValidation(): void;
64
+ /** Commits the realtime validation so it is displayed to the user. */
65
+ commitValidation(): void;
66
+ }
67
+ /** A valid validity state. */
68
+ export declare const VALID_VALIDITY_STATE: ValidityState;
69
+ /** Default validation result (valid). */
70
+ export declare const DEFAULT_VALIDATION_RESULT: ValidationResult;
71
+ /** Context for server-side validation errors. */
72
+ export declare const FormValidationContext: import("solid-js").Context<ValidationErrors>;
73
+ /** Private prop key for passing validation state to children. */
74
+ export declare const privateValidationStateProp: string;
75
+ /**
76
+ * Creates form validation state for a field.
77
+ *
78
+ * @example
79
+ * ```tsx
80
+ * const validationState = createFormValidationState({
81
+ * value: inputValue(),
82
+ * validate: (value) => {
83
+ * if (!value) return 'This field is required';
84
+ * if (value.length < 3) return 'Must be at least 3 characters';
85
+ * return null;
86
+ * },
87
+ * validationBehavior: 'aria',
88
+ * });
89
+ *
90
+ * // Access validation state
91
+ * const isInvalid = () => validationState.displayValidation().isInvalid;
92
+ * const errors = () => validationState.displayValidation().validationErrors;
93
+ * ```
94
+ */
95
+ export declare function createFormValidationState<T>(props: FormValidationProps<T>): FormValidationState;
96
+ /**
97
+ * Merges multiple validation results into one.
98
+ */
99
+ export declare function mergeValidation(...results: ValidationResult[]): ValidationResult;
100
+ //# sourceMappingURL=createFormValidationState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFormValidationState.d.ts","sourceRoot":"","sources":["createFormValidationState.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,KAAK,QAAQ,EAMd,MAAM,UAAU,CAAC;AAMlB,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,4BAA4B;AAC5B,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,yDAAyD;IACzD,iBAAiB,EAAE,aAAa,CAAC;IACjC,iCAAiC;IACjC,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAEjE,qEAAqE;AACrE,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAEjG,gCAAgC;AAChC,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yCAAyC;IACzC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,kCAAkC;IAClC,QAAQ,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IACjC,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,gBAAgB,CAAC;IACrC,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,2BAA2B;IAC3B,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,kBAAkB,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC/C,2FAA2F;IAC3F,iBAAiB,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC9C,2GAA2G;IAC3G,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjD,oFAAoF;IACpF,eAAe,IAAI,IAAI,CAAC;IACxB,sEAAsE;IACtE,gBAAgB,IAAI,IAAI,CAAC;CAC1B;AAMD,8BAA8B;AAC9B,eAAO,MAAM,oBAAoB,EAAE,aAYlC,CAAC;AASF,yCAAyC;AACzC,eAAO,MAAM,yBAAyB,EAAE,gBAIvC,CAAC;AAMF,iDAAiD;AACjD,eAAO,MAAM,qBAAqB,8CAAsC,CAAC;AAEzE,iEAAiE;AACjE,eAAO,MAAM,0BAA0B,QAAuC,CAAC;AAwD/E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EACzC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC5B,mBAAmB,CAwJrB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,GAAG,OAAO,EAAE,gBAAgB,EAAE,GAC7B,gBAAgB,CAwBlB"}
@@ -0,0 +1,389 @@
1
+ /**
2
+ * createFormValidationState for solid-stately
3
+ *
4
+ * Manages form validation state including realtime and displayed validation results.
5
+ * Supports both ARIA (live) and native (on submit) validation behaviors.
6
+ *
7
+ * Port of react-stately's useFormValidationState.
8
+ */
9
+
10
+ import {
11
+ type Accessor,
12
+ createContext,
13
+ createEffect,
14
+ createMemo,
15
+ createSignal,
16
+ useContext,
17
+ } from 'solid-js';
18
+
19
+ // ============================================
20
+ // TYPES
21
+ // ============================================
22
+
23
+ /** Standard HTML ValidityState interface. */
24
+ export interface ValidityState {
25
+ badInput: boolean;
26
+ customError: boolean;
27
+ patternMismatch: boolean;
28
+ rangeOverflow: boolean;
29
+ rangeUnderflow: boolean;
30
+ stepMismatch: boolean;
31
+ tooLong: boolean;
32
+ tooShort: boolean;
33
+ typeMismatch: boolean;
34
+ valueMissing: boolean;
35
+ valid: boolean;
36
+ }
37
+
38
+ /** Result of validation. */
39
+ export interface ValidationResult {
40
+ /** Whether the value is invalid. */
41
+ isInvalid: boolean;
42
+ /** Details about which validation constraints failed. */
43
+ validationDetails: ValidityState;
44
+ /** Error messages to display. */
45
+ validationErrors: string[];
46
+ }
47
+
48
+ /** Map of field names to their validation errors. */
49
+ export type ValidationErrors = Record<string, string | string[]>;
50
+
51
+ /** Validation function that returns error messages or true/false. */
52
+ export type ValidationFunction<T> = (value: T) => boolean | string | string[] | null | undefined;
53
+
54
+ /** Validation behavior mode. */
55
+ export type ValidationBehavior = 'aria' | 'native';
56
+
57
+ export interface FormValidationProps<T> {
58
+ /** Whether the value is invalid (controlled). */
59
+ isInvalid?: boolean;
60
+ /** @deprecated Use isInvalid instead. */
61
+ validationState?: 'valid' | 'invalid';
62
+ /** Custom validation function. */
63
+ validate?: ValidationFunction<T>;
64
+ /** Validation behavior: 'aria' for realtime, 'native' for on submit. */
65
+ validationBehavior?: ValidationBehavior;
66
+ /** Built-in validation result from native input. */
67
+ builtinValidation?: ValidationResult;
68
+ /** Field name(s) for server error lookup. */
69
+ name?: string | string[];
70
+ /** Current field value. */
71
+ value: T | null;
72
+ }
73
+
74
+ export interface FormValidationState {
75
+ /** Realtime validation results, updated as the user edits the value. */
76
+ realtimeValidation: Accessor<ValidationResult>;
77
+ /** Currently displayed validation results, updated when the user commits their changes. */
78
+ displayValidation: Accessor<ValidationResult>;
79
+ /** Updates the current validation result. Not displayed to the user until `commitValidation` is called. */
80
+ updateValidation(result: ValidationResult): void;
81
+ /** Resets the displayed validation state to valid when the user resets the form. */
82
+ resetValidation(): void;
83
+ /** Commits the realtime validation so it is displayed to the user. */
84
+ commitValidation(): void;
85
+ }
86
+
87
+ // ============================================
88
+ // CONSTANTS
89
+ // ============================================
90
+
91
+ /** A valid validity state. */
92
+ export const VALID_VALIDITY_STATE: ValidityState = {
93
+ badInput: false,
94
+ customError: false,
95
+ patternMismatch: false,
96
+ rangeOverflow: false,
97
+ rangeUnderflow: false,
98
+ stepMismatch: false,
99
+ tooLong: false,
100
+ tooShort: false,
101
+ typeMismatch: false,
102
+ valueMissing: false,
103
+ valid: true,
104
+ };
105
+
106
+ /** A custom error validity state. */
107
+ const CUSTOM_VALIDITY_STATE: ValidityState = {
108
+ ...VALID_VALIDITY_STATE,
109
+ customError: true,
110
+ valid: false,
111
+ };
112
+
113
+ /** Default validation result (valid). */
114
+ export const DEFAULT_VALIDATION_RESULT: ValidationResult = {
115
+ isInvalid: false,
116
+ validationDetails: VALID_VALIDITY_STATE,
117
+ validationErrors: [],
118
+ };
119
+
120
+ // ============================================
121
+ // CONTEXT
122
+ // ============================================
123
+
124
+ /** Context for server-side validation errors. */
125
+ export const FormValidationContext = createContext<ValidationErrors>({});
126
+
127
+ /** Private prop key for passing validation state to children. */
128
+ export const privateValidationStateProp = '__formValidationState' + Date.now();
129
+
130
+ // ============================================
131
+ // HELPERS
132
+ // ============================================
133
+
134
+ function asArray<T>(v: T | T[] | undefined): T[] {
135
+ if (!v) {
136
+ return [];
137
+ }
138
+ return Array.isArray(v) ? v : [v];
139
+ }
140
+
141
+ function runValidate<T>(validate: ValidationFunction<T>, value: T): string[] {
142
+ if (typeof validate === 'function') {
143
+ const e = validate(value);
144
+ if (e && typeof e !== 'boolean') {
145
+ return asArray(e);
146
+ }
147
+ }
148
+ return [];
149
+ }
150
+
151
+ function getValidationResult(errors: string[]): ValidationResult | null {
152
+ return errors.length
153
+ ? {
154
+ isInvalid: true,
155
+ validationErrors: errors,
156
+ validationDetails: CUSTOM_VALIDITY_STATE,
157
+ }
158
+ : null;
159
+ }
160
+
161
+ function isEqualValidation(
162
+ a: ValidationResult | null,
163
+ b: ValidationResult | null
164
+ ): boolean {
165
+ if (a === b) {
166
+ return true;
167
+ }
168
+ return (
169
+ !!a &&
170
+ !!b &&
171
+ a.isInvalid === b.isInvalid &&
172
+ a.validationErrors.length === b.validationErrors.length &&
173
+ a.validationErrors.every((ae, i) => ae === b.validationErrors[i]) &&
174
+ Object.entries(a.validationDetails).every(
175
+ ([k, v]) => b.validationDetails[k as keyof ValidityState] === v
176
+ )
177
+ );
178
+ }
179
+
180
+ // ============================================
181
+ // HOOK
182
+ // ============================================
183
+
184
+ /**
185
+ * Creates form validation state for a field.
186
+ *
187
+ * @example
188
+ * ```tsx
189
+ * const validationState = createFormValidationState({
190
+ * value: inputValue(),
191
+ * validate: (value) => {
192
+ * if (!value) return 'This field is required';
193
+ * if (value.length < 3) return 'Must be at least 3 characters';
194
+ * return null;
195
+ * },
196
+ * validationBehavior: 'aria',
197
+ * });
198
+ *
199
+ * // Access validation state
200
+ * const isInvalid = () => validationState.displayValidation().isInvalid;
201
+ * const errors = () => validationState.displayValidation().validationErrors;
202
+ * ```
203
+ */
204
+ export function createFormValidationState<T>(
205
+ props: FormValidationProps<T>
206
+ ): FormValidationState {
207
+ const {
208
+ isInvalid,
209
+ validationState,
210
+ name,
211
+ builtinValidation: builtinValidationProp,
212
+ validate,
213
+ validationBehavior = 'aria',
214
+ } = props;
215
+
216
+ // Backward compatibility
217
+ const isInvalidProp = createMemo(
218
+ () => isInvalid ?? (validationState === 'invalid' ? true : undefined)
219
+ );
220
+
221
+ // Controlled error from isInvalid prop
222
+ const controlledError = createMemo<ValidationResult | null>(() =>
223
+ isInvalidProp() !== undefined
224
+ ? {
225
+ isInvalid: isInvalidProp()!,
226
+ validationErrors: [],
227
+ validationDetails: CUSTOM_VALIDITY_STATE,
228
+ }
229
+ : null
230
+ );
231
+
232
+ // Client-side validation
233
+ const clientError = createMemo<ValidationResult | null>(() => {
234
+ if (!validate || props.value == null) {
235
+ return null;
236
+ }
237
+ const validateErrors = runValidate(validate, props.value);
238
+ return getValidationResult(validateErrors);
239
+ });
240
+
241
+ // Built-in validation (skip if valid)
242
+ const builtinValidation = createMemo<ValidationResult | undefined>(() => {
243
+ if (builtinValidationProp?.validationDetails.valid) {
244
+ return undefined;
245
+ }
246
+ return builtinValidationProp;
247
+ });
248
+
249
+ // Server errors from context
250
+ const serverErrors = useContext(FormValidationContext);
251
+ const serverErrorMessages = createMemo(() => {
252
+ if (name) {
253
+ return Array.isArray(name)
254
+ ? name.flatMap((n) => asArray(serverErrors[n]))
255
+ : asArray(serverErrors[name]);
256
+ }
257
+ return [];
258
+ });
259
+
260
+ // Track server errors clearing
261
+ const [lastServerErrors, setLastServerErrors] = createSignal(serverErrors);
262
+ const [isServerErrorCleared, setServerErrorCleared] = createSignal(false);
263
+
264
+ createEffect(() => {
265
+ if (serverErrors !== lastServerErrors()) {
266
+ setLastServerErrors(serverErrors);
267
+ setServerErrorCleared(false);
268
+ }
269
+ });
270
+
271
+ const serverError = createMemo<ValidationResult | null>(() =>
272
+ getValidationResult(isServerErrorCleared() ? [] : serverErrorMessages())
273
+ );
274
+
275
+ // Track validation state
276
+ const [currentValidity, setCurrentValidity] = createSignal(
277
+ DEFAULT_VALIDATION_RESULT
278
+ );
279
+ const [commitQueued, setCommitQueued] = createSignal(false);
280
+
281
+ let nextValidation = DEFAULT_VALIDATION_RESULT;
282
+ let lastError = DEFAULT_VALIDATION_RESULT;
283
+
284
+ // Commit validation effect
285
+ createEffect(() => {
286
+ if (!commitQueued()) {
287
+ return;
288
+ }
289
+ setCommitQueued(false);
290
+ const error = clientError() || builtinValidation() || nextValidation;
291
+ if (!isEqualValidation(error, lastError)) {
292
+ lastError = error;
293
+ setCurrentValidity(error);
294
+ }
295
+ });
296
+
297
+ // Realtime validation (for native input state)
298
+ const realtimeValidation = createMemo<ValidationResult>(
299
+ () =>
300
+ controlledError() ||
301
+ serverError() ||
302
+ clientError() ||
303
+ builtinValidation() ||
304
+ DEFAULT_VALIDATION_RESULT
305
+ );
306
+
307
+ // Display validation (what the user sees)
308
+ const displayValidation = createMemo<ValidationResult>(() => {
309
+ if (validationBehavior === 'native') {
310
+ return (
311
+ controlledError() || serverError() || currentValidity()
312
+ );
313
+ }
314
+ return (
315
+ controlledError() ||
316
+ serverError() ||
317
+ clientError() ||
318
+ builtinValidation() ||
319
+ currentValidity()
320
+ );
321
+ });
322
+
323
+ return {
324
+ realtimeValidation,
325
+ displayValidation,
326
+ updateValidation(value: ValidationResult) {
327
+ // If validationBehavior is 'aria', update in realtime. Otherwise, store until commit.
328
+ if (
329
+ validationBehavior === 'aria' &&
330
+ !isEqualValidation(currentValidity(), value)
331
+ ) {
332
+ setCurrentValidity(value);
333
+ } else {
334
+ nextValidation = value;
335
+ }
336
+ },
337
+ resetValidation() {
338
+ // Update the currently displayed validation state to valid on form reset.
339
+ const error = DEFAULT_VALIDATION_RESULT;
340
+ if (!isEqualValidation(error, lastError)) {
341
+ lastError = error;
342
+ setCurrentValidity(error);
343
+ }
344
+ // Do not commit validation after the next render for native behavior.
345
+ if (validationBehavior === 'native') {
346
+ setCommitQueued(false);
347
+ }
348
+ setServerErrorCleared(true);
349
+ },
350
+ commitValidation() {
351
+ // Commit validation state so the user sees it on blur/change/submit.
352
+ if (validationBehavior === 'native') {
353
+ setCommitQueued(true);
354
+ }
355
+ setServerErrorCleared(true);
356
+ },
357
+ };
358
+ }
359
+
360
+ /**
361
+ * Merges multiple validation results into one.
362
+ */
363
+ export function mergeValidation(
364
+ ...results: ValidationResult[]
365
+ ): ValidationResult {
366
+ const errors = new Set<string>();
367
+ let isInvalid = false;
368
+ const validationDetails: ValidityState = { ...VALID_VALIDITY_STATE };
369
+
370
+ for (const v of results) {
371
+ for (const e of v.validationErrors) {
372
+ errors.add(e);
373
+ }
374
+ isInvalid = isInvalid || v.isInvalid;
375
+ for (const key in validationDetails) {
376
+ const k = key as keyof ValidityState;
377
+ (validationDetails as unknown as Record<string, boolean>)[k] =
378
+ (validationDetails as unknown as Record<string, boolean>)[k] ||
379
+ (v.validationDetails as unknown as Record<string, boolean>)[k];
380
+ }
381
+ }
382
+
383
+ validationDetails.valid = !isInvalid;
384
+ return {
385
+ isInvalid,
386
+ validationErrors: [...errors],
387
+ validationDetails,
388
+ };
389
+ }
@@ -0,0 +1,2 @@
1
+ export { createFormValidationState, mergeValidation, FormValidationContext, privateValidationStateProp, VALID_VALIDITY_STATE, DEFAULT_VALIDATION_RESULT, type FormValidationState, type FormValidationProps, type ValidationResult, type ValidationErrors, type ValidationFunction, type ValidationBehavior, type ValidityState, } from './createFormValidationState';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,15 @@
1
+ export {
2
+ createFormValidationState,
3
+ mergeValidation,
4
+ FormValidationContext,
5
+ privateValidationStateProp,
6
+ VALID_VALIDITY_STATE,
7
+ DEFAULT_VALIDATION_RESULT,
8
+ type FormValidationState,
9
+ type FormValidationProps,
10
+ type ValidationResult,
11
+ type ValidationErrors,
12
+ type ValidationFunction,
13
+ type ValidationBehavior,
14
+ type ValidityState,
15
+ } from './createFormValidationState';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Grid state management for Table and GridList components.
3
+ * Based on @react-stately/grid/useGridState.
4
+ */
5
+ import { type Accessor } from 'solid-js';
6
+ import type { GridState, GridStateOptions, GridCollection } from './types';
7
+ /**
8
+ * Creates state management for a grid component.
9
+ * Handles row selection, focus management, and keyboard navigation state.
10
+ */
11
+ export declare function createGridState<T extends object, C extends GridCollection<T> = GridCollection<T>>(options: Accessor<GridStateOptions<T, C>>): GridState<T, C>;
12
+ //# sourceMappingURL=createGridState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createGridState.d.ts","sourceRoot":"","sources":["createGridState.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA8C,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACrF,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EAEf,MAAM,SAAS,CAAC;AAGjB;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,EAC/F,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GACxC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAuSjB"}