@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,293 +1,301 @@
1
- /**
2
- * ColorArea state management.
3
- * Based on @react-stately/color useColorAreaState.
4
- */
5
-
6
- import { createSignal, createMemo, type Accessor } from 'solid-js';
7
- import type { Color, ColorChannel, ColorAxes } from './types';
8
- import { normalizeColor } from './Color';
9
-
10
- export interface ColorAreaStateOptions {
11
- /** The current color value (controlled). */
12
- value?: Color | string;
13
- /** The default color value (uncontrolled). */
14
- defaultValue?: Color | string;
15
- /** Handler called when the color changes. */
16
- onChange?: (color: Color) => void;
17
- /** Handler called when dragging ends. */
18
- onChangeEnd?: (color: Color) => void;
19
- /** The color channel for the X axis. */
20
- xChannel?: ColorChannel;
21
- /** The color channel for the Y axis. */
22
- yChannel?: ColorChannel;
23
- /** Whether the area is disabled. */
24
- isDisabled?: boolean;
25
- }
26
-
27
- export interface ColorAreaState {
28
- /** The current color value. */
29
- readonly value: Color;
30
- /** The X axis channel. */
31
- readonly xChannel: ColorChannel;
32
- /** The Y axis channel. */
33
- readonly yChannel: ColorChannel;
34
- /** The Z axis channel (the third channel). */
35
- readonly zChannel: ColorChannel;
36
- /** Whether the area is being dragged. */
37
- readonly isDragging: boolean;
38
- /** Whether the area is disabled. */
39
- readonly isDisabled: boolean;
40
- /** Step for X channel. */
41
- readonly xChannelStep: number;
42
- /** Step for Y channel. */
43
- readonly yChannelStep: number;
44
- /** Page step for X channel. */
45
- readonly xChannelPageStep: number;
46
- /** Page step for Y channel. */
47
- readonly yChannelPageStep: number;
48
-
49
- /** Get the X channel value. */
50
- getXValue(): number;
51
- /** Get the Y channel value. */
52
- getYValue(): number;
53
- /** Set the X channel value. */
54
- setXValue(value: number): void;
55
- /** Set the Y channel value. */
56
- setYValue(value: number): void;
57
- /** Set color from a point (0-1, 0-1). */
58
- setColorFromPoint(x: number, y: number): void;
59
- /** Get the thumb position as percentages. */
60
- getThumbPosition(): { x: number; y: number };
61
- /** Increment X value. */
62
- incrementX(stepSize?: number): void;
63
- /** Decrement X value. */
64
- decrementX(stepSize?: number): void;
65
- /** Increment Y value. */
66
- incrementY(stepSize?: number): void;
67
- /** Decrement Y value. */
68
- decrementY(stepSize?: number): void;
69
- /** Set the dragging state. */
70
- setDragging(isDragging: boolean): void;
71
- /** Get the display color (with alpha = 1). */
72
- getDisplayColor(): Color;
73
- }
74
-
75
- /**
76
- * Creates state for a color area (2D color picker).
77
- */
78
- export function createColorAreaState(
79
- options: Accessor<ColorAreaStateOptions>
80
- ): ColorAreaState {
81
- const getOptions = () => options();
82
-
83
- // Internal value state
84
- const [internalValue, setInternalValue] = createSignal<Color | null>(null);
85
- const [isDragging, setIsDragging] = createSignal(false);
86
-
87
- // Initialize internal value
88
- const initValue = () => {
89
- const opts = getOptions();
90
- if (opts.defaultValue) {
91
- return normalizeColor(opts.defaultValue);
92
- }
93
- return null;
94
- };
95
-
96
- // Set initial value
97
- if (internalValue() === null) {
98
- const init = initValue();
99
- if (init) {
100
- setInternalValue(init);
101
- }
102
- }
103
-
104
- // Controlled vs uncontrolled value
105
- const value = createMemo(() => {
106
- const opts = getOptions();
107
- if (opts.value !== undefined) {
108
- return normalizeColor(opts.value);
109
- }
110
- return internalValue() ?? normalizeColor('#ff0000');
111
- });
112
-
113
- const isDisabled = createMemo(() => getOptions().isDisabled ?? false);
114
-
115
- // Get color axes
116
- const axes = createMemo<ColorAxes>(() => {
117
- const opts = getOptions();
118
- return value().getColorSpaceAxes({
119
- xChannel: opts.xChannel,
120
- yChannel: opts.yChannel,
121
- });
122
- });
123
-
124
- const xChannel = createMemo(() => axes().xChannel);
125
- const yChannel = createMemo(() => axes().yChannel);
126
- const zChannel = createMemo(() => axes().zChannel);
127
-
128
- // Get channel ranges
129
- const xRange = createMemo(() => value().getChannelRange(xChannel()));
130
- const yRange = createMemo(() => value().getChannelRange(yChannel()));
131
-
132
- const xChannelStep = createMemo(() => xRange().step);
133
- const yChannelStep = createMemo(() => yRange().step);
134
- const xChannelPageStep = createMemo(() => xRange().pageSize);
135
- const yChannelPageStep = createMemo(() => yRange().pageSize);
136
-
137
- // Update value
138
- const updateValue = (newColor: Color) => {
139
- const opts = getOptions();
140
-
141
- // Controlled mode
142
- if (opts.value !== undefined) {
143
- opts.onChange?.(newColor);
144
- return;
145
- }
146
-
147
- // Uncontrolled mode
148
- setInternalValue(newColor);
149
- opts.onChange?.(newColor);
150
- };
151
-
152
- // Get X value
153
- const getXValue = () => value().getChannelValue(xChannel());
154
-
155
- // Get Y value
156
- const getYValue = () => value().getChannelValue(yChannel());
157
-
158
- // Set X value
159
- const setXValue = (newValue: number) => {
160
- const range = xRange();
161
- const clamped = Math.max(range.minValue, Math.min(range.maxValue, newValue));
162
- const rounded = Math.round(clamped / range.step) * range.step;
163
- const newColor = value().withChannelValue(xChannel(), rounded);
164
- updateValue(newColor);
165
- };
166
-
167
- // Set Y value
168
- const setYValue = (newValue: number) => {
169
- const range = yRange();
170
- const clamped = Math.max(range.minValue, Math.min(range.maxValue, newValue));
171
- const rounded = Math.round(clamped / range.step) * range.step;
172
- const newColor = value().withChannelValue(yChannel(), rounded);
173
- updateValue(newColor);
174
- };
175
-
176
- // Set color from point (x: 0-1, y: 0-1)
177
- const setColorFromPoint = (x: number, y: number) => {
178
- const xR = xRange();
179
- const yR = yRange();
180
-
181
- const xVal = xR.minValue + (xR.maxValue - xR.minValue) * x;
182
- const yVal = yR.minValue + (yR.maxValue - yR.minValue) * (1 - y); // Y is inverted
183
-
184
- const xClamped = Math.max(xR.minValue, Math.min(xR.maxValue, xVal));
185
- const yClamped = Math.max(yR.minValue, Math.min(yR.maxValue, yVal));
186
-
187
- const xRounded = Math.round(xClamped / xR.step) * xR.step;
188
- const yRounded = Math.round(yClamped / yR.step) * yR.step;
189
-
190
- const newColor = value()
191
- .withChannelValue(xChannel(), xRounded)
192
- .withChannelValue(yChannel(), yRounded);
193
- updateValue(newColor);
194
- };
195
-
196
- // Get thumb position as percentages
197
- const getThumbPosition = () => {
198
- const xR = xRange();
199
- const yR = yRange();
200
- const xVal = getXValue();
201
- const yVal = getYValue();
202
-
203
- return {
204
- x: (xVal - xR.minValue) / (xR.maxValue - xR.minValue),
205
- y: 1 - (yVal - yR.minValue) / (yR.maxValue - yR.minValue), // Y is inverted
206
- };
207
- };
208
-
209
- // Increment X
210
- const incrementX = (stepSize?: number) => {
211
- const s = stepSize ?? xChannelStep();
212
- setXValue(getXValue() + s);
213
- };
214
-
215
- // Decrement X
216
- const decrementX = (stepSize?: number) => {
217
- const s = stepSize ?? xChannelStep();
218
- setXValue(getXValue() - s);
219
- };
220
-
221
- // Increment Y
222
- const incrementY = (stepSize?: number) => {
223
- const s = stepSize ?? yChannelStep();
224
- setYValue(getYValue() + s);
225
- };
226
-
227
- // Decrement Y
228
- const decrementY = (stepSize?: number) => {
229
- const s = stepSize ?? yChannelStep();
230
- setYValue(getYValue() - s);
231
- };
232
-
233
- // Set dragging
234
- const setDraggingState = (dragging: boolean) => {
235
- const wasDragging = isDragging();
236
- setIsDragging(dragging);
237
-
238
- // Call onChangeEnd when dragging ends
239
- if (wasDragging && !dragging) {
240
- getOptions().onChangeEnd?.(value());
241
- }
242
- };
243
-
244
- // Get display color (alpha = 1)
245
- const getDisplayColor = () => {
246
- return value().withChannelValue('alpha', 1);
247
- };
248
-
249
- return {
250
- get value() {
251
- return value();
252
- },
253
- get xChannel() {
254
- return xChannel();
255
- },
256
- get yChannel() {
257
- return yChannel();
258
- },
259
- get zChannel() {
260
- return zChannel();
261
- },
262
- get isDragging() {
263
- return isDragging();
264
- },
265
- get isDisabled() {
266
- return isDisabled();
267
- },
268
- get xChannelStep() {
269
- return xChannelStep();
270
- },
271
- get yChannelStep() {
272
- return yChannelStep();
273
- },
274
- get xChannelPageStep() {
275
- return xChannelPageStep();
276
- },
277
- get yChannelPageStep() {
278
- return yChannelPageStep();
279
- },
280
- getXValue,
281
- getYValue,
282
- setXValue,
283
- setYValue,
284
- setColorFromPoint,
285
- getThumbPosition,
286
- incrementX,
287
- decrementX,
288
- incrementY,
289
- decrementY,
290
- setDragging: setDraggingState,
291
- getDisplayColor,
292
- };
293
- }
1
+ /**
2
+ * ColorArea state management.
3
+ * Based on @react-stately/color useColorAreaState.
4
+ */
5
+
6
+ import { createSignal, createMemo, type Accessor } from "solid-js";
7
+ import type { Color, ColorChannel, ColorAxes, ColorSpace } from "./types";
8
+ import { normalizeColor } from "./Color";
9
+
10
+ export interface ColorAreaStateOptions {
11
+ /** The current color value (controlled). */
12
+ value?: Color | string;
13
+ /** The default color value (uncontrolled). */
14
+ defaultValue?: Color | string;
15
+ /** Handler called when the color changes. */
16
+ onChange?: (color: Color) => void;
17
+ /** Handler called when dragging ends. */
18
+ onChangeEnd?: (color: Color) => void;
19
+ /** The color channel for the X axis. */
20
+ xChannel?: ColorChannel;
21
+ /** The color channel for the Y axis. */
22
+ yChannel?: ColorChannel;
23
+ /** The color space to use for the color area. */
24
+ colorSpace?: ColorSpace;
25
+ /** Whether the area is disabled. */
26
+ isDisabled?: boolean;
27
+ }
28
+
29
+ export interface ColorAreaState {
30
+ /** The current color value. */
31
+ readonly value: Color;
32
+ /** The X axis channel. */
33
+ readonly xChannel: ColorChannel;
34
+ /** The Y axis channel. */
35
+ readonly yChannel: ColorChannel;
36
+ /** The Z axis channel (the third channel). */
37
+ readonly zChannel: ColorChannel;
38
+ /** Whether the area is being dragged. */
39
+ readonly isDragging: boolean;
40
+ /** Whether the area is disabled. */
41
+ readonly isDisabled: boolean;
42
+ /** Step for X channel. */
43
+ readonly xChannelStep: number;
44
+ /** Step for Y channel. */
45
+ readonly yChannelStep: number;
46
+ /** Page step for X channel. */
47
+ readonly xChannelPageStep: number;
48
+ /** Page step for Y channel. */
49
+ readonly yChannelPageStep: number;
50
+
51
+ /** Get the X channel value. */
52
+ getXValue(): number;
53
+ /** Get the Y channel value. */
54
+ getYValue(): number;
55
+ /** Set the X channel value. */
56
+ setXValue(value: number): void;
57
+ /** Set the Y channel value. */
58
+ setYValue(value: number): void;
59
+ /** Set color from a point (0-1, 0-1). */
60
+ setColorFromPoint(x: number, y: number): void;
61
+ /** Get the thumb position as percentages. */
62
+ getThumbPosition(): { x: number; y: number };
63
+ /** Increment X value. */
64
+ incrementX(stepSize?: number): void;
65
+ /** Decrement X value. */
66
+ decrementX(stepSize?: number): void;
67
+ /** Increment Y value. */
68
+ incrementY(stepSize?: number): void;
69
+ /** Decrement Y value. */
70
+ decrementY(stepSize?: number): void;
71
+ /** Set the dragging state. */
72
+ setDragging(isDragging: boolean): void;
73
+ /** Get the display color (with alpha = 1). */
74
+ getDisplayColor(): Color;
75
+ }
76
+
77
+ /**
78
+ * Creates state for a color area (2D color picker).
79
+ */
80
+ export function createColorAreaState(options: Accessor<ColorAreaStateOptions>): ColorAreaState {
81
+ const getOptions = () => options();
82
+
83
+ const normalizeValue = (value: Color | string) => {
84
+ const color = normalizeColor(value);
85
+ const colorSpace = getOptions().colorSpace;
86
+ return colorSpace ? color.toFormat(colorSpace) : color;
87
+ };
88
+
89
+ // Internal value state
90
+ const [internalValue, setInternalValue] = createSignal<Color | null>(null);
91
+ const [isDragging, setIsDragging] = createSignal(false);
92
+
93
+ // Initialize internal value
94
+ const initValue = () => {
95
+ const opts = getOptions();
96
+ if (opts.defaultValue) {
97
+ return normalizeValue(opts.defaultValue);
98
+ }
99
+ return null;
100
+ };
101
+
102
+ // Set initial value
103
+ if (internalValue() === null) {
104
+ const init = initValue();
105
+ if (init) {
106
+ setInternalValue(init);
107
+ }
108
+ }
109
+
110
+ // Controlled vs uncontrolled value
111
+ const value = createMemo(() => {
112
+ const opts = getOptions();
113
+ if (opts.value !== undefined) {
114
+ return normalizeValue(opts.value);
115
+ }
116
+ const fallback = internalValue() ?? normalizeValue("#ff0000");
117
+ return opts.colorSpace ? fallback.toFormat(opts.colorSpace) : fallback;
118
+ });
119
+
120
+ const isDisabled = createMemo(() => getOptions().isDisabled ?? false);
121
+
122
+ // Get color axes
123
+ const axes = createMemo<ColorAxes>(() => {
124
+ const opts = getOptions();
125
+ return value().getColorSpaceAxes({
126
+ xChannel: opts.xChannel,
127
+ yChannel: opts.yChannel,
128
+ });
129
+ });
130
+
131
+ const xChannel = createMemo(() => axes().xChannel);
132
+ const yChannel = createMemo(() => axes().yChannel);
133
+ const zChannel = createMemo(() => axes().zChannel);
134
+
135
+ // Get channel ranges
136
+ const xRange = createMemo(() => value().getChannelRange(xChannel()));
137
+ const yRange = createMemo(() => value().getChannelRange(yChannel()));
138
+
139
+ const xChannelStep = createMemo(() => xRange().step);
140
+ const yChannelStep = createMemo(() => yRange().step);
141
+ const xChannelPageStep = createMemo(() => xRange().pageSize);
142
+ const yChannelPageStep = createMemo(() => yRange().pageSize);
143
+
144
+ // Update value
145
+ const updateValue = (newColor: Color) => {
146
+ const opts = getOptions();
147
+ const nextColor = opts.colorSpace ? newColor.toFormat(opts.colorSpace) : newColor;
148
+
149
+ // Controlled mode
150
+ if (opts.value !== undefined) {
151
+ opts.onChange?.(nextColor);
152
+ return;
153
+ }
154
+
155
+ // Uncontrolled mode
156
+ setInternalValue(nextColor);
157
+ opts.onChange?.(nextColor);
158
+ };
159
+
160
+ // Get X value
161
+ const getXValue = () => value().getChannelValue(xChannel());
162
+
163
+ // Get Y value
164
+ const getYValue = () => value().getChannelValue(yChannel());
165
+
166
+ // Set X value
167
+ const setXValue = (newValue: number) => {
168
+ const range = xRange();
169
+ const clamped = Math.max(range.minValue, Math.min(range.maxValue, newValue));
170
+ const rounded = Math.round(clamped / range.step) * range.step;
171
+ const newColor = value().withChannelValue(xChannel(), rounded);
172
+ updateValue(newColor);
173
+ };
174
+
175
+ // Set Y value
176
+ const setYValue = (newValue: number) => {
177
+ const range = yRange();
178
+ const clamped = Math.max(range.minValue, Math.min(range.maxValue, newValue));
179
+ const rounded = Math.round(clamped / range.step) * range.step;
180
+ const newColor = value().withChannelValue(yChannel(), rounded);
181
+ updateValue(newColor);
182
+ };
183
+
184
+ // Set color from point (x: 0-1, y: 0-1)
185
+ const setColorFromPoint = (x: number, y: number) => {
186
+ const xR = xRange();
187
+ const yR = yRange();
188
+
189
+ const xVal = xR.minValue + (xR.maxValue - xR.minValue) * x;
190
+ const yVal = yR.minValue + (yR.maxValue - yR.minValue) * (1 - y); // Y is inverted
191
+
192
+ const xClamped = Math.max(xR.minValue, Math.min(xR.maxValue, xVal));
193
+ const yClamped = Math.max(yR.minValue, Math.min(yR.maxValue, yVal));
194
+
195
+ const xRounded = Math.round(xClamped / xR.step) * xR.step;
196
+ const yRounded = Math.round(yClamped / yR.step) * yR.step;
197
+
198
+ const newColor = value()
199
+ .withChannelValue(xChannel(), xRounded)
200
+ .withChannelValue(yChannel(), yRounded);
201
+ updateValue(newColor);
202
+ };
203
+
204
+ // Get thumb position as percentages
205
+ const getThumbPosition = () => {
206
+ const xR = xRange();
207
+ const yR = yRange();
208
+ const xVal = getXValue();
209
+ const yVal = getYValue();
210
+
211
+ return {
212
+ x: (xVal - xR.minValue) / (xR.maxValue - xR.minValue),
213
+ y: 1 - (yVal - yR.minValue) / (yR.maxValue - yR.minValue), // Y is inverted
214
+ };
215
+ };
216
+
217
+ // Increment X
218
+ const incrementX = (stepSize?: number) => {
219
+ const s = stepSize ?? xChannelStep();
220
+ setXValue(getXValue() + s);
221
+ };
222
+
223
+ // Decrement X
224
+ const decrementX = (stepSize?: number) => {
225
+ const s = stepSize ?? xChannelStep();
226
+ setXValue(getXValue() - s);
227
+ };
228
+
229
+ // Increment Y
230
+ const incrementY = (stepSize?: number) => {
231
+ const s = stepSize ?? yChannelStep();
232
+ setYValue(getYValue() + s);
233
+ };
234
+
235
+ // Decrement Y
236
+ const decrementY = (stepSize?: number) => {
237
+ const s = stepSize ?? yChannelStep();
238
+ setYValue(getYValue() - s);
239
+ };
240
+
241
+ // Set dragging
242
+ const setDraggingState = (dragging: boolean) => {
243
+ const wasDragging = isDragging();
244
+ setIsDragging(dragging);
245
+
246
+ // Call onChangeEnd when dragging ends
247
+ if (wasDragging && !dragging) {
248
+ getOptions().onChangeEnd?.(value());
249
+ }
250
+ };
251
+
252
+ // Get display color (alpha = 1)
253
+ const getDisplayColor = () => {
254
+ return value().withChannelValue("alpha", 1);
255
+ };
256
+
257
+ return {
258
+ get value() {
259
+ return value();
260
+ },
261
+ get xChannel() {
262
+ return xChannel();
263
+ },
264
+ get yChannel() {
265
+ return yChannel();
266
+ },
267
+ get zChannel() {
268
+ return zChannel();
269
+ },
270
+ get isDragging() {
271
+ return isDragging();
272
+ },
273
+ get isDisabled() {
274
+ return isDisabled();
275
+ },
276
+ get xChannelStep() {
277
+ return xChannelStep();
278
+ },
279
+ get yChannelStep() {
280
+ return yChannelStep();
281
+ },
282
+ get xChannelPageStep() {
283
+ return xChannelPageStep();
284
+ },
285
+ get yChannelPageStep() {
286
+ return yChannelPageStep();
287
+ },
288
+ getXValue,
289
+ getYValue,
290
+ setXValue,
291
+ setYValue,
292
+ setColorFromPoint,
293
+ getThumbPosition,
294
+ incrementX,
295
+ decrementX,
296
+ incrementY,
297
+ decrementY,
298
+ setDragging: setDraggingState,
299
+ getDisplayColor,
300
+ };
301
+ }