@proyecto-viviana/solid-stately 0.2.4 → 0.3.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.
Files changed (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -283
  3. package/dist/autocomplete/createAutocompleteState.d.ts +3 -2
  4. package/dist/autocomplete/index.d.ts +1 -1
  5. package/dist/calendar/createCalendarState.d.ts +22 -7
  6. package/dist/calendar/createDateFieldState.d.ts +30 -7
  7. package/dist/calendar/createDatePickerState.d.ts +60 -0
  8. package/dist/calendar/createRangeCalendarState.d.ts +27 -8
  9. package/dist/calendar/createTimeFieldState.d.ts +34 -7
  10. package/dist/calendar/index.d.ts +7 -6
  11. package/dist/checkbox/createCheckboxGroupState.d.ts +12 -3
  12. package/dist/checkbox/index.d.ts +1 -1
  13. package/dist/collections/ListCollection.d.ts +1 -1
  14. package/dist/collections/createListState.d.ts +8 -8
  15. package/dist/collections/createMenuState.d.ts +7 -7
  16. package/dist/collections/createSelectionState.d.ts +5 -5
  17. package/dist/collections/index.d.ts +5 -5
  18. package/dist/collections/types.d.ts +23 -12
  19. package/dist/color/Color.d.ts +1 -1
  20. package/dist/color/createColorAreaState.d.ts +4 -2
  21. package/dist/color/createColorFieldState.d.ts +38 -12
  22. package/dist/color/createColorSliderState.d.ts +9 -2
  23. package/dist/color/createColorWheelState.d.ts +13 -2
  24. package/dist/color/getColorChannels.d.ts +20 -0
  25. package/dist/color/index.d.ts +6 -6
  26. package/dist/color/types.d.ts +4 -4
  27. package/dist/combobox/createComboBoxState.d.ts +27 -13
  28. package/dist/combobox/index.d.ts +1 -1
  29. package/dist/data/createAsyncList.d.ts +111 -0
  30. package/dist/data/createListData.d.ts +65 -0
  31. package/dist/data/createTreeData.d.ts +65 -0
  32. package/dist/data/index.d.ts +3 -0
  33. package/dist/datepicker/index.d.ts +8 -0
  34. package/dist/disclosure/createDisclosureState.d.ts +2 -2
  35. package/dist/disclosure/index.d.ts +1 -1
  36. package/dist/dnd/createDragState.d.ts +2 -2
  37. package/dist/dnd/createDraggableCollectionState.d.ts +2 -2
  38. package/dist/dnd/createDropState.d.ts +2 -2
  39. package/dist/dnd/createDroppableCollectionState.d.ts +3 -3
  40. package/dist/dnd/index.d.ts +5 -5
  41. package/dist/dnd/types.d.ts +16 -16
  42. package/dist/form/createFormValidationState.d.ts +3 -3
  43. package/dist/form/index.d.ts +1 -1
  44. package/dist/grid/createGridState.d.ts +2 -2
  45. package/dist/grid/index.d.ts +2 -2
  46. package/dist/grid/types.d.ts +17 -11
  47. package/dist/index.d.ts +31 -25
  48. package/dist/index.js +7990 -6264
  49. package/dist/index.js.map +1 -7
  50. package/dist/menu/index.d.ts +8 -0
  51. package/dist/numberfield/createNumberFieldState.d.ts +2 -2
  52. package/dist/numberfield/index.d.ts +1 -1
  53. package/dist/overlays/createOverlayTriggerState.d.ts +2 -2
  54. package/dist/overlays/index.d.ts +1 -1
  55. package/dist/radio/createRadioGroupState.d.ts +13 -4
  56. package/dist/radio/index.d.ts +1 -1
  57. package/dist/searchfield/createSearchFieldState.d.ts +2 -2
  58. package/dist/searchfield/index.d.ts +2 -2
  59. package/dist/select/createSelectState.d.ts +20 -3
  60. package/dist/select/index.d.ts +1 -1
  61. package/dist/selection/index.d.ts +11 -0
  62. package/dist/slider/createSliderState.d.ts +3 -3
  63. package/dist/slider/index.d.ts +2 -2
  64. package/dist/steplist/createStepListState.d.ts +48 -0
  65. package/dist/steplist/index.d.ts +1 -0
  66. package/dist/table/TableCollection.d.ts +3 -3
  67. package/dist/table/createTableColumnResizeState.d.ts +54 -0
  68. package/dist/table/createTableState.d.ts +2 -2
  69. package/dist/table/index.d.ts +5 -3
  70. package/dist/table/types.d.ts +10 -10
  71. package/dist/tabs/createTabListState.d.ts +5 -5
  72. package/dist/tabs/index.d.ts +1 -1
  73. package/dist/textfield/createTextFieldState.d.ts +2 -2
  74. package/dist/textfield/index.d.ts +1 -1
  75. package/dist/toast/createToastState.d.ts +15 -3
  76. package/dist/toast/index.d.ts +1 -1
  77. package/dist/toggle/createToggleGroupState.d.ts +45 -0
  78. package/dist/toggle/createToggleState.d.ts +2 -2
  79. package/dist/toggle/index.d.ts +2 -1
  80. package/dist/tooltip/createTooltipTriggerState.d.ts +2 -2
  81. package/dist/tooltip/index.d.ts +1 -1
  82. package/dist/tree/TreeCollection.d.ts +5 -4
  83. package/dist/tree/createTreeState.d.ts +2 -2
  84. package/dist/tree/index.d.ts +3 -3
  85. package/dist/tree/types.d.ts +19 -13
  86. package/dist/utils/index.d.ts +1 -1
  87. package/dist/utils/reactivity.d.ts +1 -1
  88. package/package.json +30 -30
  89. package/src/autocomplete/createAutocompleteState.d.ts +19 -17
  90. package/src/autocomplete/createAutocompleteState.ts +25 -32
  91. package/src/autocomplete/index.d.ts +6 -2
  92. package/src/autocomplete/index.ts +1 -1
  93. package/src/calendar/createCalendarState.d.ts +139 -117
  94. package/src/calendar/createCalendarState.ts +221 -74
  95. package/src/calendar/createDateFieldState.d.ts +130 -95
  96. package/src/calendar/createDateFieldState.ts +286 -151
  97. package/src/calendar/createDatePickerState.ts +347 -0
  98. package/src/calendar/createRangeCalendarState.d.ts +154 -129
  99. package/src/calendar/createRangeCalendarState.ts +293 -79
  100. package/src/calendar/createTimeFieldState.d.ts +81 -79
  101. package/src/calendar/createTimeFieldState.ts +187 -108
  102. package/src/calendar/index.d.ts +80 -7
  103. package/src/calendar/index.ts +21 -12
  104. package/src/checkbox/createCheckboxGroupState.d.ts +57 -55
  105. package/src/checkbox/createCheckboxGroupState.ts +57 -30
  106. package/src/checkbox/index.d.ts +6 -2
  107. package/src/checkbox/index.ts +1 -1
  108. package/src/collections/ListCollection.d.ts +25 -22
  109. package/src/collections/ListCollection.ts +152 -146
  110. package/src/collections/createListState.d.ts +73 -58
  111. package/src/collections/createListState.ts +267 -264
  112. package/src/collections/createMenuState.d.ts +36 -31
  113. package/src/collections/createMenuState.ts +112 -106
  114. package/src/collections/createSelectionState.d.ts +78 -65
  115. package/src/collections/createSelectionState.ts +340 -336
  116. package/src/collections/index.d.ts +38 -6
  117. package/src/collections/index.ts +41 -46
  118. package/src/collections/types.d.ts +101 -101
  119. package/src/collections/types.ts +181 -169
  120. package/src/color/Color.d.ts +20 -5
  121. package/src/color/Color.ts +1054 -951
  122. package/src/color/createColorAreaState.d.ts +67 -65
  123. package/src/color/createColorAreaState.ts +301 -293
  124. package/src/color/createColorFieldState.d.ts +46 -44
  125. package/src/color/createColorFieldState.ts +428 -292
  126. package/src/color/createColorSliderState.d.ts +58 -56
  127. package/src/color/createColorSliderState.ts +272 -241
  128. package/src/color/createColorWheelState.d.ts +42 -40
  129. package/src/color/createColorWheelState.ts +248 -211
  130. package/src/color/getColorChannels.ts +36 -0
  131. package/src/color/index.d.ts +36 -7
  132. package/src/color/index.ts +44 -47
  133. package/src/color/types.d.ts +68 -63
  134. package/src/color/types.ts +119 -127
  135. package/src/combobox/createComboBoxState.d.ts +107 -105
  136. package/src/combobox/createComboBoxState.ts +790 -703
  137. package/src/combobox/index.d.ts +10 -2
  138. package/src/combobox/index.ts +13 -13
  139. package/src/data/createAsyncList.ts +403 -0
  140. package/src/data/createListData.ts +298 -0
  141. package/src/data/createTreeData.ts +646 -0
  142. package/src/data/index.ts +25 -0
  143. package/src/datepicker/index.ts +32 -0
  144. package/src/disclosure/createDisclosureState.d.ts +47 -43
  145. package/src/disclosure/createDisclosureState.ts +9 -23
  146. package/src/disclosure/index.d.ts +10 -2
  147. package/src/disclosure/index.ts +1 -1
  148. package/src/dnd/createDragState.d.ts +51 -42
  149. package/src/dnd/createDragState.ts +151 -153
  150. package/src/dnd/createDraggableCollectionState.d.ts +52 -41
  151. package/src/dnd/createDraggableCollectionState.ts +158 -165
  152. package/src/dnd/createDropState.d.ts +64 -45
  153. package/src/dnd/createDropState.ts +202 -212
  154. package/src/dnd/createDroppableCollectionState.d.ts +88 -59
  155. package/src/dnd/createDroppableCollectionState.ts +354 -357
  156. package/src/dnd/index.d.ts +54 -6
  157. package/src/dnd/index.ts +63 -76
  158. package/src/dnd/types.d.ts +167 -156
  159. package/src/dnd/types.ts +316 -317
  160. package/src/form/createFormValidationState.d.ts +47 -45
  161. package/src/form/createFormValidationState.ts +356 -389
  162. package/src/form/index.d.ts +16 -2
  163. package/src/form/index.ts +15 -15
  164. package/src/grid/createGridState.d.ts +7 -4
  165. package/src/grid/createGridState.ts +44 -51
  166. package/src/grid/index.d.ts +3 -3
  167. package/src/grid/index.ts +2 -8
  168. package/src/grid/types.d.ts +136 -129
  169. package/src/grid/types.ts +24 -17
  170. package/src/index.d.ts +310 -26
  171. package/src/index.ts +87 -79
  172. package/src/menu/index.ts +17 -0
  173. package/src/numberfield/createNumberFieldState.d.ts +56 -54
  174. package/src/numberfield/createNumberFieldState.ts +422 -383
  175. package/src/numberfield/index.d.ts +6 -2
  176. package/src/numberfield/index.ts +5 -5
  177. package/src/overlays/createOverlayTriggerState.d.ts +22 -20
  178. package/src/overlays/createOverlayTriggerState.ts +66 -67
  179. package/src/overlays/index.d.ts +6 -2
  180. package/src/overlays/index.ts +5 -5
  181. package/src/radio/createRadioGroupState.d.ts +54 -52
  182. package/src/radio/createRadioGroupState.ts +66 -30
  183. package/src/radio/index.d.ts +7 -2
  184. package/src/radio/index.ts +1 -1
  185. package/src/searchfield/createSearchFieldState.d.ts +16 -14
  186. package/src/searchfield/createSearchFieldState.ts +56 -62
  187. package/src/searchfield/index.d.ts +3 -3
  188. package/src/searchfield/index.ts +2 -5
  189. package/src/select/createSelectState.d.ts +63 -61
  190. package/src/select/createSelectState.ts +290 -181
  191. package/src/select/index.d.ts +2 -2
  192. package/src/select/index.ts +1 -5
  193. package/src/selection/index.ts +27 -0
  194. package/src/slider/createSliderState.d.ts +60 -60
  195. package/src/slider/createSliderState.ts +233 -211
  196. package/src/slider/index.d.ts +3 -3
  197. package/src/slider/index.ts +2 -6
  198. package/src/ssr/index.d.ts +1 -1
  199. package/src/ssr/index.ts +2 -2
  200. package/src/steplist/createStepListState.ts +191 -0
  201. package/src/steplist/index.ts +5 -0
  202. package/src/table/TableCollection.d.ts +42 -40
  203. package/src/table/TableCollection.ts +61 -64
  204. package/src/table/createTableColumnResizeState.ts +242 -0
  205. package/src/table/createTableState.d.ts +7 -4
  206. package/src/table/createTableState.ts +10 -7
  207. package/src/table/index.d.ts +14 -4
  208. package/src/table/index.ts +10 -3
  209. package/src/table/types.d.ts +98 -92
  210. package/src/table/types.ts +17 -13
  211. package/src/tabs/createTabListState.d.ts +59 -57
  212. package/src/tabs/createTabListState.ts +58 -39
  213. package/src/tabs/index.d.ts +8 -2
  214. package/src/tabs/index.ts +1 -1
  215. package/src/textfield/createTextFieldState.d.ts +16 -14
  216. package/src/textfield/createTextFieldState.ts +7 -18
  217. package/src/textfield/index.d.ts +6 -2
  218. package/src/textfield/index.ts +1 -1
  219. package/src/toast/createToastState.d.ts +92 -81
  220. package/src/toast/createToastState.ts +56 -44
  221. package/src/toast/index.d.ts +12 -2
  222. package/src/toast/index.ts +1 -1
  223. package/src/toggle/createToggleGroupState.ts +117 -0
  224. package/src/toggle/createToggleState.d.ts +19 -19
  225. package/src/toggle/createToggleState.ts +2 -16
  226. package/src/toggle/index.d.ts +2 -2
  227. package/src/toggle/index.ts +6 -4
  228. package/src/tooltip/createTooltipTriggerState.d.ts +17 -17
  229. package/src/tooltip/createTooltipTriggerState.ts +184 -183
  230. package/src/tooltip/index.d.ts +7 -2
  231. package/src/tooltip/index.ts +6 -6
  232. package/src/tree/TreeCollection.d.ts +26 -23
  233. package/src/tree/TreeCollection.ts +215 -175
  234. package/src/tree/createTreeState.d.ts +7 -4
  235. package/src/tree/createTreeState.ts +390 -392
  236. package/src/tree/index.d.ts +10 -4
  237. package/src/tree/index.ts +13 -13
  238. package/src/tree/types.d.ts +131 -126
  239. package/src/tree/types.ts +183 -174
  240. package/src/utils/index.d.ts +2 -2
  241. package/src/utils/index.ts +1 -1
  242. package/src/utils/reactivity.d.ts +2 -2
  243. package/src/utils/reactivity.ts +3 -3
@@ -1,211 +1,233 @@
1
- /**
2
- * Creates state for a slider component.
3
- * Based on @react-stately/slider useSliderState.
4
- */
5
-
6
- import { type Accessor, createSignal, createMemo } from 'solid-js';
7
- import { access, type MaybeAccessor } from '../utils';
8
-
9
- export type SliderOrientation = 'horizontal' | 'vertical';
10
-
11
- export interface SliderStateProps {
12
- /** The current value (controlled). */
13
- value?: number;
14
- /** The default value (uncontrolled). */
15
- defaultValue?: number;
16
- /** Handler called when the value changes. */
17
- onChange?: (value: number) => void;
18
- /** Handler called when the user stops dragging. */
19
- onChangeEnd?: (value: number) => void;
20
- /** The minimum value. */
21
- minValue?: number;
22
- /** The maximum value. */
23
- maxValue?: number;
24
- /** The step value. */
25
- step?: number;
26
- /** The orientation of the slider. */
27
- orientation?: SliderOrientation;
28
- /** Whether the slider is disabled. */
29
- isDisabled?: boolean;
30
- /** The locale for number formatting. */
31
- locale?: string;
32
- /** Number format options. */
33
- formatOptions?: Intl.NumberFormatOptions;
34
- }
35
-
36
- export interface SliderState {
37
- /** The current value. */
38
- value: Accessor<number>;
39
- /** Sets the value. */
40
- setValue: (value: number) => void;
41
- /** Sets the value by percent (0-1). */
42
- setValuePercent: (percent: number) => void;
43
- /** Gets the value as a percent (0-1). */
44
- getValuePercent: Accessor<number>;
45
- /** Gets the formatted value string. */
46
- getFormattedValue: Accessor<string>;
47
- /** Whether the thumb is being dragged. */
48
- isDragging: Accessor<boolean>;
49
- /** Sets the dragging state. */
50
- setDragging: (dragging: boolean) => void;
51
- /** Whether the slider is focused. */
52
- isFocused: Accessor<boolean>;
53
- /** Sets the focused state. */
54
- setFocused: (focused: boolean) => void;
55
- /** Increments the value by step. */
56
- increment: (stepMultiplier?: number) => void;
57
- /** Decrements the value by step. */
58
- decrement: (stepMultiplier?: number) => void;
59
- /** The minimum value. */
60
- minValue: number;
61
- /** The maximum value. */
62
- maxValue: number;
63
- /** The step value. */
64
- step: number;
65
- /** The page step (larger step for Page Up/Down). */
66
- pageStep: number;
67
- /** The orientation. */
68
- orientation: SliderOrientation;
69
- /** Whether the slider is disabled. */
70
- isDisabled: boolean;
71
- }
72
-
73
- const DEFAULT_MIN = 0;
74
- const DEFAULT_MAX = 100;
75
- const DEFAULT_STEP = 1;
76
-
77
- /**
78
- * Clamps a value between min and max.
79
- */
80
- function clamp(value: number, min: number, max: number): number {
81
- return Math.min(Math.max(value, min), max);
82
- }
83
-
84
- /**
85
- * Snaps a value to the nearest step.
86
- */
87
- function snapToStep(value: number, min: number, max: number, step: number): number {
88
- const snapped = Math.round((value - min) / step) * step + min;
89
- // Handle floating point precision issues
90
- const decimalPlaces = (step.toString().split('.')[1] || '').length;
91
- const rounded = parseFloat(snapped.toFixed(decimalPlaces));
92
- return clamp(rounded, min, max);
93
- }
94
-
95
- /**
96
- * Provides state management for a slider component.
97
- */
98
- export function createSliderState(
99
- props: MaybeAccessor<SliderStateProps>
100
- ): SliderState {
101
- const getProps = () => access(props);
102
-
103
- // Get static values with defaults
104
- const minValue = getProps().minValue ?? DEFAULT_MIN;
105
- const maxValue = getProps().maxValue ?? DEFAULT_MAX;
106
- const step = getProps().step ?? DEFAULT_STEP;
107
- const orientation = getProps().orientation ?? 'horizontal';
108
- const isDisabled = getProps().isDisabled ?? false;
109
-
110
- // Calculate page step (10% of range, snapped to step)
111
- const pageStep = Math.max(step, snapToStep((maxValue - minValue) / 10, 0, maxValue - minValue, step));
112
-
113
- // Controlled vs uncontrolled
114
- const isControlled = () => getProps().value !== undefined;
115
-
116
- // Internal signal for uncontrolled mode
117
- const [internalValue, setInternalValue] = createSignal(
118
- snapToStep(getProps().defaultValue ?? minValue, minValue, maxValue, step)
119
- );
120
-
121
- // Dragging and focus state
122
- const [isDragging, setIsDragging] = createSignal(false);
123
- const [isFocused, setIsFocused] = createSignal(false);
124
-
125
- // Current value accessor
126
- const value = createMemo(() => {
127
- const p = getProps();
128
- const rawValue = isControlled() ? (p.value ?? minValue) : internalValue();
129
- return snapToStep(rawValue, minValue, maxValue, step);
130
- });
131
-
132
- // Value as percent (0-1)
133
- const getValuePercent = createMemo(() => {
134
- return (value() - minValue) / (maxValue - minValue);
135
- });
136
-
137
- // Formatted value
138
- const getFormattedValue = createMemo(() => {
139
- const p = getProps();
140
- const formatter = new Intl.NumberFormat(p.locale, p.formatOptions);
141
- return formatter.format(value());
142
- });
143
-
144
- // Set value function
145
- const setValue = (newValue: number) => {
146
- if (isDisabled) return;
147
-
148
- const p = getProps();
149
- const snappedValue = snapToStep(newValue, minValue, maxValue, step);
150
-
151
- if (!isControlled()) {
152
- setInternalValue(snappedValue);
153
- }
154
-
155
- p.onChange?.(snappedValue);
156
- };
157
-
158
- // Set value by percent
159
- const setValuePercent = (percent: number) => {
160
- const clampedPercent = clamp(percent, 0, 1);
161
- const newValue = clampedPercent * (maxValue - minValue) + minValue;
162
- setValue(newValue);
163
- };
164
-
165
- // Dragging state management
166
- const setDragging = (dragging: boolean) => {
167
- const wasDragging = isDragging();
168
- setIsDragging(dragging);
169
-
170
- // Call onChangeEnd when dragging stops
171
- if (wasDragging && !dragging) {
172
- getProps().onChangeEnd?.(value());
173
- }
174
- };
175
-
176
- // Increment/decrement
177
- const increment = (stepMultiplier = 1) => {
178
- if (isDisabled) return;
179
- setValue(value() + step * stepMultiplier);
180
- };
181
-
182
- const decrement = (stepMultiplier = 1) => {
183
- if (isDisabled) return;
184
- setValue(value() - step * stepMultiplier);
185
- };
186
-
187
- // Set focused state
188
- const setFocused = (focused: boolean) => {
189
- setIsFocused(focused);
190
- };
191
-
192
- return {
193
- value,
194
- setValue,
195
- setValuePercent,
196
- getValuePercent,
197
- getFormattedValue,
198
- isDragging,
199
- setDragging,
200
- isFocused,
201
- setFocused,
202
- increment,
203
- decrement,
204
- minValue,
205
- maxValue,
206
- step,
207
- pageStep,
208
- orientation,
209
- isDisabled,
210
- };
211
- }
1
+ /**
2
+ * Creates state for a slider component.
3
+ * Based on @react-stately/slider useSliderState.
4
+ */
5
+
6
+ import { type Accessor, createSignal, createMemo } from "solid-js";
7
+ import { access, type MaybeAccessor } from "../utils";
8
+
9
+ export type SliderOrientation = "horizontal" | "vertical";
10
+
11
+ export interface SliderStateProps {
12
+ /** The current value (controlled). */
13
+ value?: number;
14
+ /** The default value (uncontrolled). */
15
+ defaultValue?: number;
16
+ /** Handler called when the value changes. */
17
+ onChange?: (value: number) => void;
18
+ /** Handler called when the user stops dragging. */
19
+ onChangeEnd?: (value: number) => void;
20
+ /** The minimum value. */
21
+ minValue?: number;
22
+ /** The maximum value. */
23
+ maxValue?: number;
24
+ /** The step value. */
25
+ step?: number;
26
+ /** The orientation of the slider. */
27
+ orientation?: SliderOrientation;
28
+ /** Whether the slider is disabled. */
29
+ isDisabled?: boolean;
30
+ /** The locale for number formatting. */
31
+ locale?: string;
32
+ /** Number format options. */
33
+ formatOptions?: Intl.NumberFormatOptions;
34
+ }
35
+
36
+ export interface SliderState {
37
+ /** The current value. */
38
+ value: Accessor<number>;
39
+ /** Sets the value. */
40
+ setValue: (value: number) => void;
41
+ /** Sets the value by percent (0-1). */
42
+ setValuePercent: (percent: number) => void;
43
+ /** Gets the value as a percent (0-1). */
44
+ getValuePercent: Accessor<number>;
45
+ /** Gets the formatted value string. */
46
+ getFormattedValue: Accessor<string>;
47
+ /** Whether the thumb is being dragged. */
48
+ isDragging: Accessor<boolean>;
49
+ /** Sets the dragging state. */
50
+ setDragging: (dragging: boolean) => void;
51
+ /** Whether the slider is focused. */
52
+ isFocused: Accessor<boolean>;
53
+ /** Sets the focused state. */
54
+ setFocused: (focused: boolean) => void;
55
+ /** Increments the value by step. */
56
+ increment: (stepMultiplier?: number) => void;
57
+ /** Decrements the value by step. */
58
+ decrement: (stepMultiplier?: number) => void;
59
+ /** The minimum value. */
60
+ minValue: number;
61
+ /** The maximum value. */
62
+ maxValue: number;
63
+ /** The step value. */
64
+ step: number;
65
+ /** The page step (larger step for Page Up/Down). */
66
+ pageStep: number;
67
+ /** The orientation. */
68
+ orientation: SliderOrientation;
69
+ /** Whether the slider is disabled. */
70
+ isDisabled: boolean;
71
+ }
72
+
73
+ const DEFAULT_MIN = 0;
74
+ const DEFAULT_MAX = 100;
75
+ const DEFAULT_STEP = 1;
76
+
77
+ /**
78
+ * Clamps a value between min and max.
79
+ */
80
+ function clamp(value: number, min: number, max: number): number {
81
+ return Math.min(Math.max(value, min), max);
82
+ }
83
+
84
+ /**
85
+ * Snaps a value to the nearest step.
86
+ */
87
+ function snapToStep(value: number, min: number, max: number, step: number): number {
88
+ const snapped = Math.round((value - min) / step) * step + min;
89
+ // Handle floating point precision issues
90
+ const decimalPlaces = (step.toString().split(".")[1] || "").length;
91
+ const rounded = parseFloat(snapped.toFixed(decimalPlaces));
92
+ return clamp(rounded, min, max);
93
+ }
94
+
95
+ /**
96
+ * Provides state management for a slider component.
97
+ */
98
+ export function createSliderState(props: MaybeAccessor<SliderStateProps>): SliderState {
99
+ const getProps = () => access(props);
100
+
101
+ const initialProps = getProps();
102
+ const initialMinValue = initialProps.minValue ?? DEFAULT_MIN;
103
+ const initialMaxValue = initialProps.maxValue ?? DEFAULT_MAX;
104
+ const initialStep = initialProps.step ?? DEFAULT_STEP;
105
+
106
+ const minValue = createMemo(() => getProps().minValue ?? DEFAULT_MIN);
107
+ const maxValue = createMemo(() => getProps().maxValue ?? DEFAULT_MAX);
108
+ const step = createMemo(() => getProps().step ?? DEFAULT_STEP);
109
+ const orientation = createMemo(() => getProps().orientation ?? "horizontal");
110
+ const isDisabled = createMemo(() => getProps().isDisabled ?? false);
111
+ const pageStep = createMemo(() =>
112
+ Math.max(
113
+ step(),
114
+ snapToStep((maxValue() - minValue()) / 10, 0, maxValue() - minValue(), step()),
115
+ ),
116
+ );
117
+
118
+ // Controlled vs uncontrolled
119
+ const isControlled = () => getProps().value !== undefined;
120
+
121
+ // Internal signal for uncontrolled mode
122
+ const [internalValue, setInternalValue] = createSignal(
123
+ snapToStep(
124
+ initialProps.defaultValue ?? initialMinValue,
125
+ initialMinValue,
126
+ initialMaxValue,
127
+ initialStep,
128
+ ),
129
+ );
130
+
131
+ // Dragging and focus state
132
+ const [isDragging, setIsDragging] = createSignal(false);
133
+ const [isFocused, setIsFocused] = createSignal(false);
134
+
135
+ // Current value accessor
136
+ const value = createMemo(() => {
137
+ const p = getProps();
138
+ const rawValue = isControlled() ? (p.value ?? minValue()) : internalValue();
139
+ return snapToStep(rawValue, minValue(), maxValue(), step());
140
+ });
141
+
142
+ // Value as percent (0-1)
143
+ const getValuePercent = createMemo(() => {
144
+ return (value() - minValue()) / (maxValue() - minValue());
145
+ });
146
+
147
+ // Formatted value
148
+ const getFormattedValue = createMemo(() => {
149
+ const p = getProps();
150
+ const formatter = new Intl.NumberFormat(p.locale, p.formatOptions);
151
+ return formatter.format(value());
152
+ });
153
+
154
+ // Set value function
155
+ const setValue = (newValue: number) => {
156
+ if (isDisabled()) return;
157
+
158
+ const p = getProps();
159
+ const snappedValue = snapToStep(newValue, minValue(), maxValue(), step());
160
+
161
+ if (!isControlled()) {
162
+ setInternalValue(snappedValue);
163
+ }
164
+
165
+ p.onChange?.(snappedValue);
166
+ };
167
+
168
+ // Set value by percent
169
+ const setValuePercent = (percent: number) => {
170
+ const clampedPercent = clamp(percent, 0, 1);
171
+ const newValue = clampedPercent * (maxValue() - minValue()) + minValue();
172
+ setValue(newValue);
173
+ };
174
+
175
+ // Dragging state management
176
+ const setDragging = (dragging: boolean) => {
177
+ const wasDragging = isDragging();
178
+ setIsDragging(dragging);
179
+
180
+ // Call onChangeEnd when dragging stops
181
+ if (wasDragging && !dragging) {
182
+ getProps().onChangeEnd?.(value());
183
+ }
184
+ };
185
+
186
+ // Increment/decrement
187
+ const increment = (stepMultiplier = 1) => {
188
+ if (isDisabled()) return;
189
+ setValue(value() + step() * stepMultiplier);
190
+ };
191
+
192
+ const decrement = (stepMultiplier = 1) => {
193
+ if (isDisabled()) return;
194
+ setValue(value() - step() * stepMultiplier);
195
+ };
196
+
197
+ // Set focused state
198
+ const setFocused = (focused: boolean) => {
199
+ setIsFocused(focused);
200
+ };
201
+
202
+ return {
203
+ value,
204
+ setValue,
205
+ setValuePercent,
206
+ getValuePercent,
207
+ getFormattedValue,
208
+ isDragging,
209
+ setDragging,
210
+ isFocused,
211
+ setFocused,
212
+ increment,
213
+ decrement,
214
+ get minValue() {
215
+ return minValue();
216
+ },
217
+ get maxValue() {
218
+ return maxValue();
219
+ },
220
+ get step() {
221
+ return step();
222
+ },
223
+ get pageStep() {
224
+ return pageStep();
225
+ },
226
+ get orientation() {
227
+ return orientation();
228
+ },
229
+ get isDisabled() {
230
+ return isDisabled();
231
+ },
232
+ };
233
+ }
@@ -1,3 +1,3 @@
1
- export { createSliderState } from './createSliderState';
2
- export type { SliderState, SliderStateProps, SliderOrientation, } from './createSliderState';
3
- //# sourceMappingURL=index.d.ts.map
1
+ export { createSliderState } from "./createSliderState";
2
+ export type { SliderState, SliderStateProps, SliderOrientation } from "./createSliderState";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,2 @@
1
- export { createSliderState } from './createSliderState';
2
- export type {
3
- SliderState,
4
- SliderStateProps,
5
- SliderOrientation,
6
- } from './createSliderState';
1
+ export { createSliderState } from "./createSliderState";
2
+ export type { SliderState, SliderStateProps, SliderOrientation } from "./createSliderState";
@@ -25,4 +25,4 @@ export declare function createId(defaultId?: string): string;
25
25
  * This is useful for code that needs to run only in the browser.
26
26
  */
27
27
  export declare const canUseDOM: boolean;
28
- //# sourceMappingURL=index.d.ts.map
28
+ //# sourceMappingURL=index.d.ts.map
package/src/ssr/index.ts CHANGED
@@ -5,8 +5,8 @@
5
5
  * These utilities provide a consistent API matching React-Stately's patterns.
6
6
  */
7
7
 
8
- import { createUniqueId } from 'solid-js';
9
- import { isServer as _isServer } from 'solid-js/web';
8
+ import { createUniqueId } from "solid-js";
9
+ import { isServer as _isServer } from "solid-js/web";
10
10
 
11
11
  /**
12
12
  * Re-export isServer from solid-js/web for convenience.
@@ -0,0 +1,191 @@
1
+ /**
2
+ * State management for step list components.
3
+ * Tracks selected step, completion status, and selectability.
4
+ */
5
+
6
+ import { createMemo, createSignal, type Accessor } from "solid-js";
7
+ import type { Key } from "../collections/types";
8
+
9
+ export interface StepListStateProps {
10
+ /** The currently selected step key (controlled). */
11
+ selectedKey?: Key;
12
+ /** The default selected step key (uncontrolled). */
13
+ defaultSelectedKey?: Key;
14
+ /** Called when the selected step changes. */
15
+ onSelectionChange?: (key: Key) => void;
16
+ /** The last completed step key (controlled). */
17
+ lastCompletedStep?: Key;
18
+ /** The default last completed step key (uncontrolled). */
19
+ defaultLastCompletedStep?: Key;
20
+ /** Called when last completed step changes. */
21
+ onLastCompletedStepChange?: (key: Key | null) => void;
22
+ /** Whether all steps are disabled. */
23
+ isDisabled?: boolean;
24
+ /** Whether all steps are read-only. */
25
+ isReadOnly?: boolean;
26
+ /** Keys of individually disabled steps. */
27
+ disabledKeys?: Iterable<Key>;
28
+ /** The step items. */
29
+ items: Array<{ key: Key; [key: string]: any }>;
30
+ }
31
+
32
+ export interface StepListState {
33
+ readonly selectedKey: Accessor<Key | null>;
34
+ readonly lastCompletedStep: Accessor<Key | null>;
35
+ readonly items: Accessor<Array<{ key: Key }>>;
36
+ setSelectedKey(key: Key): void;
37
+ setLastCompletedStep(key: Key): void;
38
+ isCompleted(key: Key): boolean;
39
+ isSelectable(key: Key): boolean;
40
+ isDisabled: Accessor<boolean>;
41
+ isReadOnly: Accessor<boolean>;
42
+ }
43
+
44
+ /**
45
+ * Creates state for a step list component.
46
+ */
47
+ export function createStepListState(props: StepListStateProps): StepListState {
48
+ const items = () => props.items;
49
+
50
+ // Build an index map: Key -> index
51
+ const indexMap = createMemo(() => {
52
+ const map = new Map<Key, number>();
53
+ const currentItems = items();
54
+ for (let i = 0; i < currentItems.length; i++) {
55
+ map.set(currentItems[i].key, i);
56
+ }
57
+ return map;
58
+ });
59
+
60
+ // Disabled keys set
61
+ const disabledKeysSet = createMemo(() => new Set<Key>(props.disabledKeys ?? []));
62
+
63
+ const isDisabled: Accessor<boolean> = () => props.isDisabled ?? false;
64
+ const isReadOnly: Accessor<boolean> = () => props.isReadOnly ?? false;
65
+
66
+ // Last completed step signal (uncontrolled)
67
+ const [lastCompletedStepInternal, setLastCompletedStepInternal] = createSignal<Key | null>(
68
+ props.defaultLastCompletedStep ?? null,
69
+ );
70
+
71
+ const lastCompletedStep: Accessor<Key | null> = () => {
72
+ if (props.lastCompletedStep !== undefined) {
73
+ return props.lastCompletedStep;
74
+ }
75
+ return lastCompletedStepInternal();
76
+ };
77
+
78
+ const setLastCompletedStep = (key: Key) => {
79
+ const currentIndex = indexMap().get(key);
80
+ const prevIndex = lastCompletedStep() !== null ? indexMap().get(lastCompletedStep()!) : -1;
81
+
82
+ // Only advance completion, never go back
83
+ if (
84
+ currentIndex !== undefined &&
85
+ (prevIndex === undefined || currentIndex > (prevIndex ?? -1))
86
+ ) {
87
+ if (props.lastCompletedStep === undefined) {
88
+ setLastCompletedStepInternal(key);
89
+ }
90
+ props.onLastCompletedStepChange?.(key);
91
+ }
92
+ };
93
+
94
+ const isCompleted = (key: Key): boolean => {
95
+ const completed = lastCompletedStep();
96
+ if (completed === null) return false;
97
+ const keyIndex = indexMap().get(key);
98
+ const completedIndex = indexMap().get(completed);
99
+ if (keyIndex === undefined || completedIndex === undefined) return false;
100
+ return keyIndex <= completedIndex;
101
+ };
102
+
103
+ const isStepDisabled = (key: Key): boolean => {
104
+ if (isDisabled()) return true;
105
+ return disabledKeysSet().has(key);
106
+ };
107
+
108
+ const isSelectable = (key: Key): boolean => {
109
+ if (isDisabled() || isReadOnly() || isStepDisabled(key)) return false;
110
+ // Completed steps are always selectable
111
+ if (isCompleted(key)) return true;
112
+ // First step is always selectable
113
+ const keyIndex = indexMap().get(key);
114
+ if (keyIndex === 0) return true;
115
+ // A step is selectable if the previous step is completed OR is the currently selected step
116
+ const currentItems = items();
117
+ if (keyIndex !== undefined && keyIndex > 0) {
118
+ const prevKey = currentItems[keyIndex - 1].key;
119
+ if (isCompleted(prevKey)) return true;
120
+ // Allow advancing to the step immediately after the selected step
121
+ if (prevKey === selectedKey()) return true;
122
+ }
123
+ return false;
124
+ };
125
+
126
+ // Find the first selectable non-completed step
127
+ const findDefaultSelectedKey = (): Key | null => {
128
+ const currentItems = items();
129
+ for (const item of currentItems) {
130
+ if (!isCompleted(item.key) && !isStepDisabled(item.key)) {
131
+ return item.key;
132
+ }
133
+ }
134
+ // All completed - select first non-disabled
135
+ for (const item of currentItems) {
136
+ if (!isStepDisabled(item.key)) {
137
+ return item.key;
138
+ }
139
+ }
140
+ return currentItems.length > 0 ? currentItems[0].key : null;
141
+ };
142
+
143
+ // Selected key signal (uncontrolled)
144
+ const [selectedKeyInternal, setSelectedKeyInternal] = createSignal<Key | null>(
145
+ props.defaultSelectedKey ?? findDefaultSelectedKey(),
146
+ );
147
+
148
+ const selectedKey: Accessor<Key | null> = () => {
149
+ if (props.selectedKey !== undefined) {
150
+ return props.selectedKey;
151
+ }
152
+ return selectedKeyInternal();
153
+ };
154
+
155
+ const setSelectedKey = (key: Key) => {
156
+ if (isReadOnly() || isDisabled()) return;
157
+ if (!isSelectable(key)) return;
158
+
159
+ // Mark previous selected step as completed if advancing
160
+ const currentSelected = selectedKey();
161
+ if (currentSelected !== null) {
162
+ const currentIndex = indexMap().get(currentSelected);
163
+ const newIndex = indexMap().get(key);
164
+ if (
165
+ currentIndex !== undefined &&
166
+ newIndex !== undefined &&
167
+ newIndex > currentIndex &&
168
+ !isCompleted(currentSelected)
169
+ ) {
170
+ setLastCompletedStep(currentSelected);
171
+ }
172
+ }
173
+
174
+ if (props.selectedKey === undefined) {
175
+ setSelectedKeyInternal(key);
176
+ }
177
+ props.onSelectionChange?.(key);
178
+ };
179
+
180
+ return {
181
+ selectedKey,
182
+ lastCompletedStep,
183
+ items,
184
+ setSelectedKey,
185
+ setLastCompletedStep,
186
+ isCompleted,
187
+ isSelectable,
188
+ isDisabled,
189
+ isReadOnly,
190
+ };
191
+ }