@proyecto-viviana/solid-stately 0.0.6 → 0.1.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 (208) hide show
  1. package/README.md +312 -0
  2. package/dist/index.d.ts +3363 -6
  3. package/dist/index.js +6194 -19
  4. package/dist/index.js.map +1 -1
  5. package/package.json +52 -48
  6. package/src/autocomplete/createAutocompleteState.d.ts +46 -0
  7. package/src/autocomplete/createAutocompleteState.d.ts.map +1 -0
  8. package/src/autocomplete/createAutocompleteState.ts +90 -0
  9. package/src/autocomplete/index.d.ts +2 -0
  10. package/src/autocomplete/index.d.ts.map +1 -0
  11. package/src/autocomplete/index.ts +5 -0
  12. package/src/calendar/createCalendarState.d.ts +130 -0
  13. package/src/calendar/createCalendarState.d.ts.map +1 -0
  14. package/src/calendar/createCalendarState.ts +461 -0
  15. package/src/calendar/createDateFieldState.d.ts +110 -0
  16. package/src/calendar/createDateFieldState.d.ts.map +1 -0
  17. package/src/calendar/createDateFieldState.ts +562 -0
  18. package/src/calendar/createRangeCalendarState.d.ts +146 -0
  19. package/src/calendar/createRangeCalendarState.d.ts.map +1 -0
  20. package/src/calendar/createRangeCalendarState.ts +535 -0
  21. package/src/calendar/createTimeFieldState.d.ts +95 -0
  22. package/src/calendar/createTimeFieldState.d.ts.map +1 -0
  23. package/src/calendar/createTimeFieldState.ts +483 -0
  24. package/src/calendar/index.d.ts +7 -0
  25. package/src/calendar/index.d.ts.map +1 -0
  26. package/src/calendar/index.ts +81 -0
  27. package/{dist → src}/checkbox/createCheckboxGroupState.d.ts +1 -0
  28. package/src/checkbox/createCheckboxGroupState.d.ts.map +1 -0
  29. package/{dist → src}/checkbox/index.d.ts +1 -0
  30. package/src/checkbox/index.d.ts.map +1 -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 +350 -1
  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/{dist → src}/radio/createRadioGroupState.d.ts +1 -0
  131. package/src/radio/createRadioGroupState.d.ts.map +1 -0
  132. package/{dist → src}/radio/index.d.ts +1 -0
  133. package/src/radio/index.d.ts.map +1 -0
  134. package/src/searchfield/createSearchFieldState.d.ts +25 -0
  135. package/src/searchfield/createSearchFieldState.d.ts.map +1 -0
  136. package/src/searchfield/createSearchFieldState.ts +62 -0
  137. package/src/searchfield/index.d.ts +3 -0
  138. package/src/searchfield/index.d.ts.map +1 -0
  139. package/src/searchfield/index.ts +5 -0
  140. package/src/select/createSelectState.d.ts +73 -0
  141. package/src/select/createSelectState.d.ts.map +1 -0
  142. package/src/select/createSelectState.ts +181 -0
  143. package/src/select/index.d.ts +2 -0
  144. package/src/select/index.d.ts.map +1 -0
  145. package/src/select/index.ts +5 -0
  146. package/src/slider/createSliderState.d.ts +72 -0
  147. package/src/slider/createSliderState.d.ts.map +1 -0
  148. package/src/slider/createSliderState.ts +211 -0
  149. package/src/slider/index.d.ts +3 -0
  150. package/src/slider/index.d.ts.map +1 -0
  151. package/src/slider/index.ts +6 -0
  152. package/{dist → src}/ssr/index.d.ts +5 -0
  153. package/src/ssr/index.d.ts.map +1 -0
  154. package/src/ssr/index.ts +6 -1
  155. package/src/table/TableCollection.d.ts +52 -0
  156. package/src/table/TableCollection.d.ts.map +1 -0
  157. package/src/table/TableCollection.ts +388 -0
  158. package/src/table/createTableState.d.ts +12 -0
  159. package/src/table/createTableState.d.ts.map +1 -0
  160. package/src/table/createTableState.ts +127 -0
  161. package/src/table/index.d.ts +8 -0
  162. package/src/table/index.d.ts.map +1 -0
  163. package/src/table/index.ts +18 -0
  164. package/src/table/types.d.ts +139 -0
  165. package/src/table/types.d.ts.map +1 -0
  166. package/src/table/types.ts +150 -0
  167. package/src/tabs/createTabListState.d.ts +68 -0
  168. package/src/tabs/createTabListState.d.ts.map +1 -0
  169. package/src/tabs/createTabListState.ts +240 -0
  170. package/src/tabs/index.d.ts +2 -0
  171. package/src/tabs/index.d.ts.map +1 -0
  172. package/src/tabs/index.ts +7 -0
  173. package/{dist → src}/textfield/createTextFieldState.d.ts +1 -0
  174. package/src/textfield/createTextFieldState.d.ts.map +1 -0
  175. package/{dist → src}/textfield/index.d.ts +1 -0
  176. package/src/textfield/index.d.ts.map +1 -0
  177. package/src/toast/createToastState.d.ts +118 -0
  178. package/src/toast/createToastState.d.ts.map +1 -0
  179. package/src/toast/createToastState.ts +316 -0
  180. package/src/toast/index.d.ts +2 -0
  181. package/src/toast/index.d.ts.map +1 -0
  182. package/src/toast/index.ts +11 -0
  183. package/{dist → src}/toggle/createToggleState.d.ts +1 -0
  184. package/src/toggle/createToggleState.d.ts.map +1 -0
  185. package/{dist → src}/toggle/index.d.ts +1 -0
  186. package/src/toggle/index.d.ts.map +1 -0
  187. package/src/tooltip/createTooltipTriggerState.d.ts +39 -0
  188. package/src/tooltip/createTooltipTriggerState.d.ts.map +1 -0
  189. package/src/tooltip/createTooltipTriggerState.ts +183 -0
  190. package/src/tooltip/index.d.ts +2 -0
  191. package/src/tooltip/index.d.ts.map +1 -0
  192. package/src/tooltip/index.ts +6 -0
  193. package/src/tree/TreeCollection.d.ts +40 -0
  194. package/src/tree/TreeCollection.d.ts.map +1 -0
  195. package/src/tree/TreeCollection.ts +175 -0
  196. package/src/tree/createTreeState.d.ts +14 -0
  197. package/src/tree/createTreeState.d.ts.map +1 -0
  198. package/src/tree/createTreeState.ts +392 -0
  199. package/src/tree/index.d.ts +7 -0
  200. package/src/tree/index.d.ts.map +1 -0
  201. package/src/tree/index.ts +13 -0
  202. package/src/tree/types.d.ts +157 -0
  203. package/src/tree/types.d.ts.map +1 -0
  204. package/src/tree/types.ts +174 -0
  205. package/{dist → src}/utils/index.d.ts +1 -0
  206. package/src/utils/index.d.ts.map +1 -0
  207. package/{dist → src}/utils/reactivity.d.ts +1 -0
  208. package/src/utils/reactivity.d.ts.map +1 -0
@@ -0,0 +1,292 @@
1
+ /**
2
+ * ColorField state management.
3
+ * Based on @react-stately/color useColorFieldState.
4
+ */
5
+
6
+ import { createSignal, createMemo, type Accessor } from 'solid-js';
7
+ import type { Color, ColorChannel, ColorFormat } from './types';
8
+ import { normalizeColor, parseColor } from './Color';
9
+
10
+ export interface ColorFieldStateOptions {
11
+ /** The current color value (controlled). */
12
+ value?: Color | string | null;
13
+ /** The default color value (uncontrolled). */
14
+ defaultValue?: Color | string;
15
+ /** Handler called when the color changes. */
16
+ onChange?: (color: Color | null) => void;
17
+ /** The color channel to edit (for single channel mode). */
18
+ channel?: ColorChannel;
19
+ /** The color format for parsing/displaying. */
20
+ colorFormat?: ColorFormat;
21
+ /** Whether the field is disabled. */
22
+ isDisabled?: boolean;
23
+ /** Whether the field is read-only. */
24
+ isReadOnly?: boolean;
25
+ }
26
+
27
+ export interface ColorFieldState {
28
+ /** The current color value (null if invalid). */
29
+ readonly value: Color | null;
30
+ /** The current input text. */
31
+ readonly inputValue: string;
32
+ /** Whether the input is invalid. */
33
+ readonly isInvalid: boolean;
34
+ /** Whether the field is disabled. */
35
+ readonly isDisabled: boolean;
36
+ /** Whether the field is read-only. */
37
+ readonly isReadOnly: boolean;
38
+ /** The color channel being edited (if single channel mode). */
39
+ readonly channel: ColorChannel | undefined;
40
+
41
+ /** Set the input text value. */
42
+ setInputValue(value: string): void;
43
+ /** Commit the current input value. */
44
+ commit(): void;
45
+ /** Increment the color channel value. */
46
+ increment(): void;
47
+ /** Decrement the color channel value. */
48
+ decrement(): void;
49
+ /** Increment by page size. */
50
+ incrementToMax(): void;
51
+ /** Decrement to minimum. */
52
+ decrementToMin(): void;
53
+ /** Validate the current input. */
54
+ validate(): boolean;
55
+ }
56
+
57
+ /**
58
+ * Creates state for a color field (text input for color values).
59
+ */
60
+ export function createColorFieldState(
61
+ options: Accessor<ColorFieldStateOptions>
62
+ ): ColorFieldState {
63
+ const getOptions = () => options();
64
+
65
+ // Internal value state
66
+ const [internalValue, setInternalValue] = createSignal<Color | null>(null);
67
+ const [inputValue, setInputValueInternal] = createSignal('');
68
+ const [isInvalid, setIsInvalid] = createSignal(false);
69
+
70
+ // Initialize internal value
71
+ const initValue = () => {
72
+ const opts = getOptions();
73
+ if (opts.defaultValue) {
74
+ const color = normalizeColor(opts.defaultValue);
75
+ return color;
76
+ }
77
+ return null;
78
+ };
79
+
80
+ // Set initial value
81
+ if (internalValue() === null) {
82
+ const init = initValue();
83
+ if (init) {
84
+ setInternalValue(init);
85
+ setInputValueInternal(formatColorValue(init, getOptions().channel, getOptions().colorFormat));
86
+ }
87
+ }
88
+
89
+ // Controlled vs uncontrolled value
90
+ const value = createMemo(() => {
91
+ const opts = getOptions();
92
+ if (opts.value !== undefined) {
93
+ if (opts.value === null) return null;
94
+ return normalizeColor(opts.value);
95
+ }
96
+ return internalValue();
97
+ });
98
+
99
+ const channel = createMemo(() => getOptions().channel);
100
+ const isDisabled = createMemo(() => getOptions().isDisabled ?? false);
101
+ const isReadOnly = createMemo(() => getOptions().isReadOnly ?? false);
102
+
103
+ // Format color value for display
104
+ function formatColorValue(
105
+ color: Color | null,
106
+ chan?: ColorChannel,
107
+ format?: ColorFormat
108
+ ): string {
109
+ if (!color) return '';
110
+
111
+ // Single channel mode
112
+ if (chan) {
113
+ return String(color.getChannelValue(chan));
114
+ }
115
+
116
+ // Full color mode
117
+ return color.toString(format ?? 'hex');
118
+ }
119
+
120
+ // Update value
121
+ const updateValue = (newColor: Color | null) => {
122
+ const opts = getOptions();
123
+
124
+ // Controlled mode
125
+ if (opts.value !== undefined) {
126
+ opts.onChange?.(newColor);
127
+ return;
128
+ }
129
+
130
+ // Uncontrolled mode
131
+ setInternalValue(newColor);
132
+ opts.onChange?.(newColor);
133
+ };
134
+
135
+ // Set input value
136
+ const setInputValue = (text: string) => {
137
+ setInputValueInternal(text);
138
+ setIsInvalid(false);
139
+ };
140
+
141
+ // Commit the input value
142
+ const commit = () => {
143
+ const text = inputValue().trim();
144
+ const opts = getOptions();
145
+ const chan = channel();
146
+
147
+ if (!text) {
148
+ updateValue(null);
149
+ setIsInvalid(false);
150
+ return;
151
+ }
152
+
153
+ try {
154
+ let newColor: Color;
155
+
156
+ if (chan) {
157
+ // Single channel mode - parse as number and update channel
158
+ const numValue = parseFloat(text);
159
+ if (isNaN(numValue)) {
160
+ setIsInvalid(true);
161
+ return;
162
+ }
163
+
164
+ const currentColor = value();
165
+ if (!currentColor) {
166
+ setIsInvalid(true);
167
+ return;
168
+ }
169
+
170
+ const range = currentColor.getChannelRange(chan);
171
+ const clamped = Math.max(range.minValue, Math.min(range.maxValue, numValue));
172
+ newColor = currentColor.withChannelValue(chan, clamped);
173
+ } else {
174
+ // Full color mode - parse the color string
175
+ newColor = parseColor(text);
176
+ if (opts.colorFormat) {
177
+ newColor = newColor.toFormat(opts.colorFormat);
178
+ }
179
+ }
180
+
181
+ updateValue(newColor);
182
+ setInputValueInternal(formatColorValue(newColor, chan, opts.colorFormat));
183
+ setIsInvalid(false);
184
+ } catch {
185
+ setIsInvalid(true);
186
+ }
187
+ };
188
+
189
+ // Increment channel value
190
+ const increment = () => {
191
+ const chan = channel();
192
+ const currentColor = value();
193
+ if (!currentColor || !chan) return;
194
+
195
+ const currentVal = currentColor.getChannelValue(chan);
196
+ const range = currentColor.getChannelRange(chan);
197
+ const newVal = Math.min(range.maxValue, currentVal + range.step);
198
+ const newColor = currentColor.withChannelValue(chan, newVal);
199
+
200
+ updateValue(newColor);
201
+ setInputValueInternal(formatColorValue(newColor, chan, getOptions().colorFormat));
202
+ };
203
+
204
+ // Decrement channel value
205
+ const decrement = () => {
206
+ const chan = channel();
207
+ const currentColor = value();
208
+ if (!currentColor || !chan) return;
209
+
210
+ const currentVal = currentColor.getChannelValue(chan);
211
+ const range = currentColor.getChannelRange(chan);
212
+ const newVal = Math.max(range.minValue, currentVal - range.step);
213
+ const newColor = currentColor.withChannelValue(chan, newVal);
214
+
215
+ updateValue(newColor);
216
+ setInputValueInternal(formatColorValue(newColor, chan, getOptions().colorFormat));
217
+ };
218
+
219
+ // Increment to max
220
+ const incrementToMax = () => {
221
+ const chan = channel();
222
+ const currentColor = value();
223
+ if (!currentColor || !chan) return;
224
+
225
+ const range = currentColor.getChannelRange(chan);
226
+ const newColor = currentColor.withChannelValue(chan, range.maxValue);
227
+
228
+ updateValue(newColor);
229
+ setInputValueInternal(formatColorValue(newColor, chan, getOptions().colorFormat));
230
+ };
231
+
232
+ // Decrement to min
233
+ const decrementToMin = () => {
234
+ const chan = channel();
235
+ const currentColor = value();
236
+ if (!currentColor || !chan) return;
237
+
238
+ const range = currentColor.getChannelRange(chan);
239
+ const newColor = currentColor.withChannelValue(chan, range.minValue);
240
+
241
+ updateValue(newColor);
242
+ setInputValueInternal(formatColorValue(newColor, chan, getOptions().colorFormat));
243
+ };
244
+
245
+ // Validate input
246
+ const validate = () => {
247
+ const text = inputValue().trim();
248
+ const chan = channel();
249
+
250
+ if (!text) return true;
251
+
252
+ try {
253
+ if (chan) {
254
+ const numValue = parseFloat(text);
255
+ return !isNaN(numValue);
256
+ } else {
257
+ parseColor(text);
258
+ return true;
259
+ }
260
+ } catch {
261
+ return false;
262
+ }
263
+ };
264
+
265
+ return {
266
+ get value() {
267
+ return value();
268
+ },
269
+ get inputValue() {
270
+ return inputValue();
271
+ },
272
+ get isInvalid() {
273
+ return isInvalid();
274
+ },
275
+ get isDisabled() {
276
+ return isDisabled();
277
+ },
278
+ get isReadOnly() {
279
+ return isReadOnly();
280
+ },
281
+ get channel() {
282
+ return channel();
283
+ },
284
+ setInputValue,
285
+ commit,
286
+ increment,
287
+ decrement,
288
+ incrementToMax,
289
+ decrementToMin,
290
+ validate,
291
+ };
292
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * ColorSlider state management.
3
+ * Based on @react-stately/color useColorSliderState.
4
+ */
5
+ import { type Accessor } from 'solid-js';
6
+ import type { Color, ColorChannel } from './types';
7
+ export interface ColorSliderStateOptions {
8
+ /** The current color value (controlled). */
9
+ value?: Color | string;
10
+ /** The default color value (uncontrolled). */
11
+ defaultValue?: Color | string;
12
+ /** Handler called when the color changes. */
13
+ onChange?: (color: Color) => void;
14
+ /** Handler called when dragging ends. */
15
+ onChangeEnd?: (color: Color) => void;
16
+ /** The color channel this slider controls. */
17
+ channel: ColorChannel;
18
+ /** Whether the slider is disabled. */
19
+ isDisabled?: boolean;
20
+ /** The locale for formatting. */
21
+ locale?: string;
22
+ }
23
+ export interface ColorSliderState {
24
+ /** The current color value. */
25
+ readonly value: Color;
26
+ /** Whether the slider is being dragged. */
27
+ readonly isDragging: boolean;
28
+ /** The color channel being controlled. */
29
+ readonly channel: ColorChannel;
30
+ /** The step value for the channel. */
31
+ readonly step: number;
32
+ /** The page step value for the channel. */
33
+ readonly pageSize: number;
34
+ /** The minimum value for the channel. */
35
+ readonly minValue: number;
36
+ /** The maximum value for the channel. */
37
+ readonly maxValue: number;
38
+ /** Whether the slider is disabled. */
39
+ readonly isDisabled: boolean;
40
+ /** Get the current channel value. */
41
+ getThumbValue(): number;
42
+ /** Get the minimum percent. */
43
+ getThumbMinValue(): number;
44
+ /** Get the maximum percent. */
45
+ getThumbMaxValue(): number;
46
+ /** Get the thumb value as a percentage. */
47
+ getThumbPercent(): number;
48
+ /** Set the channel value. */
49
+ setThumbValue(value: number): void;
50
+ /** Set the thumb value from a percentage (0-1). */
51
+ setThumbPercent(percent: number): void;
52
+ /** Increment the channel value. */
53
+ incrementThumb(stepSize?: number): void;
54
+ /** Decrement the channel value. */
55
+ decrementThumb(stepSize?: number): void;
56
+ /** Set the dragging state. */
57
+ setDragging(isDragging: boolean): void;
58
+ /** Get the display color (with alpha = 1). */
59
+ getDisplayColor(): Color;
60
+ /** Get the formatted value label. */
61
+ getThumbValueLabel(): string;
62
+ }
63
+ /**
64
+ * Creates state for a color slider.
65
+ */
66
+ export declare function createColorSliderState(options: Accessor<ColorSliderStateOptions>): ColorSliderState;
67
+ //# sourceMappingURL=createColorSliderState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createColorSliderState.d.ts","sourceRoot":"","sources":["createColorSliderState.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA4B,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGnD,MAAM,WAAW,uBAAuB;IACtC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,yCAAyC;IACzC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACrC,8CAA8C;IAC9C,OAAO,EAAE,YAAY,CAAC;IACtB,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAE7B,qCAAqC;IACrC,aAAa,IAAI,MAAM,CAAC;IACxB,+BAA+B;IAC/B,gBAAgB,IAAI,MAAM,CAAC;IAC3B,+BAA+B;IAC/B,gBAAgB,IAAI,MAAM,CAAC;IAC3B,2CAA2C;IAC3C,eAAe,IAAI,MAAM,CAAC;IAC1B,6BAA6B;IAC7B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,mDAAmD;IACnD,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,mCAAmC;IACnC,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,mCAAmC;IACnC,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,8BAA8B;IAC9B,WAAW,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,8CAA8C;IAC9C,eAAe,IAAI,KAAK,CAAC;IACzB,qCAAqC;IACrC,kBAAkB,IAAI,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GACzC,gBAAgB,CAuKlB"}
@@ -0,0 +1,241 @@
1
+ /**
2
+ * ColorSlider state management.
3
+ * Based on @react-stately/color useColorSliderState.
4
+ */
5
+
6
+ import { createSignal, createMemo, type Accessor } from 'solid-js';
7
+ import type { Color, ColorChannel } from './types';
8
+ import { normalizeColor } from './Color';
9
+
10
+ export interface ColorSliderStateOptions {
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 this slider controls. */
20
+ channel: ColorChannel;
21
+ /** Whether the slider is disabled. */
22
+ isDisabled?: boolean;
23
+ /** The locale for formatting. */
24
+ locale?: string;
25
+ }
26
+
27
+ export interface ColorSliderState {
28
+ /** The current color value. */
29
+ readonly value: Color;
30
+ /** Whether the slider is being dragged. */
31
+ readonly isDragging: boolean;
32
+ /** The color channel being controlled. */
33
+ readonly channel: ColorChannel;
34
+ /** The step value for the channel. */
35
+ readonly step: number;
36
+ /** The page step value for the channel. */
37
+ readonly pageSize: number;
38
+ /** The minimum value for the channel. */
39
+ readonly minValue: number;
40
+ /** The maximum value for the channel. */
41
+ readonly maxValue: number;
42
+ /** Whether the slider is disabled. */
43
+ readonly isDisabled: boolean;
44
+
45
+ /** Get the current channel value. */
46
+ getThumbValue(): number;
47
+ /** Get the minimum percent. */
48
+ getThumbMinValue(): number;
49
+ /** Get the maximum percent. */
50
+ getThumbMaxValue(): number;
51
+ /** Get the thumb value as a percentage. */
52
+ getThumbPercent(): number;
53
+ /** Set the channel value. */
54
+ setThumbValue(value: number): void;
55
+ /** Set the thumb value from a percentage (0-1). */
56
+ setThumbPercent(percent: number): void;
57
+ /** Increment the channel value. */
58
+ incrementThumb(stepSize?: number): void;
59
+ /** Decrement the channel value. */
60
+ decrementThumb(stepSize?: number): void;
61
+ /** Set the dragging state. */
62
+ setDragging(isDragging: boolean): void;
63
+ /** Get the display color (with alpha = 1). */
64
+ getDisplayColor(): Color;
65
+ /** Get the formatted value label. */
66
+ getThumbValueLabel(): string;
67
+ }
68
+
69
+ /**
70
+ * Creates state for a color slider.
71
+ */
72
+ export function createColorSliderState(
73
+ options: Accessor<ColorSliderStateOptions>
74
+ ): ColorSliderState {
75
+ const getOptions = () => options();
76
+
77
+ // Internal value state
78
+ const [internalValue, setInternalValue] = createSignal<Color | null>(null);
79
+ const [isDragging, setIsDragging] = createSignal(false);
80
+
81
+ // Initialize internal value
82
+ const initValue = () => {
83
+ const opts = getOptions();
84
+ if (opts.defaultValue) {
85
+ return normalizeColor(opts.defaultValue);
86
+ }
87
+ return null;
88
+ };
89
+
90
+ // Set initial value
91
+ if (internalValue() === null) {
92
+ const init = initValue();
93
+ if (init) {
94
+ setInternalValue(init);
95
+ }
96
+ }
97
+
98
+ // Controlled vs uncontrolled value
99
+ const value = createMemo(() => {
100
+ const opts = getOptions();
101
+ if (opts.value !== undefined) {
102
+ return normalizeColor(opts.value);
103
+ }
104
+ return internalValue() ?? normalizeColor('#ff0000');
105
+ });
106
+
107
+ const channel = createMemo(() => getOptions().channel);
108
+ const isDisabled = createMemo(() => getOptions().isDisabled ?? false);
109
+ const locale = createMemo(() => getOptions().locale ?? 'en-US');
110
+
111
+ // Get channel range
112
+ const channelRange = createMemo(() => value().getChannelRange(channel()));
113
+
114
+ const step = createMemo(() => channelRange().step);
115
+ const pageSize = createMemo(() => channelRange().pageSize);
116
+ const minValue = createMemo(() => channelRange().minValue);
117
+ const maxValue = createMemo(() => channelRange().maxValue);
118
+
119
+ // Update value
120
+ const updateValue = (newColor: Color) => {
121
+ const opts = getOptions();
122
+
123
+ // Controlled mode
124
+ if (opts.value !== undefined) {
125
+ opts.onChange?.(newColor);
126
+ return;
127
+ }
128
+
129
+ // Uncontrolled mode
130
+ setInternalValue(newColor);
131
+ opts.onChange?.(newColor);
132
+ };
133
+
134
+ // Get thumb value
135
+ const getThumbValue = () => {
136
+ return value().getChannelValue(channel());
137
+ };
138
+
139
+ // Get min/max values
140
+ const getThumbMinValue = () => minValue();
141
+ const getThumbMaxValue = () => maxValue();
142
+
143
+ // Get thumb percent
144
+ const getThumbPercent = () => {
145
+ const val = getThumbValue();
146
+ const min = minValue();
147
+ const max = maxValue();
148
+ return (val - min) / (max - min);
149
+ };
150
+
151
+ // Set thumb value
152
+ const setThumbValue = (newValue: number) => {
153
+ const clamped = Math.max(minValue(), Math.min(maxValue(), newValue));
154
+ const rounded = Math.round(clamped / step()) * step();
155
+ const newColor = value().withChannelValue(channel(), rounded);
156
+ updateValue(newColor);
157
+ };
158
+
159
+ // Set thumb from percent
160
+ const setThumbPercent = (percent: number) => {
161
+ const min = minValue();
162
+ const max = maxValue();
163
+ const val = min + (max - min) * percent;
164
+ setThumbValue(val);
165
+ };
166
+
167
+ // Increment
168
+ const incrementThumb = (stepSize?: number) => {
169
+ const s = stepSize ?? step();
170
+ setThumbValue(getThumbValue() + s);
171
+ };
172
+
173
+ // Decrement
174
+ const decrementThumb = (stepSize?: number) => {
175
+ const s = stepSize ?? step();
176
+ setThumbValue(getThumbValue() - s);
177
+ };
178
+
179
+ // Set dragging
180
+ const setDraggingState = (dragging: boolean) => {
181
+ const wasDragging = isDragging();
182
+ setIsDragging(dragging);
183
+
184
+ // Call onChangeEnd when dragging ends
185
+ if (wasDragging && !dragging) {
186
+ getOptions().onChangeEnd?.(value());
187
+ }
188
+ };
189
+
190
+ // Get display color (alpha = 1)
191
+ const getDisplayColor = () => {
192
+ const v = value();
193
+ return v.withChannelValue('alpha', 1);
194
+ };
195
+
196
+ // Get formatted value label
197
+ const getThumbValueLabel = () => {
198
+ const v = value();
199
+ const ch = channel();
200
+ const loc = locale();
201
+ return v.formatChannelValue(ch, loc);
202
+ };
203
+
204
+ return {
205
+ get value() {
206
+ return value();
207
+ },
208
+ get isDragging() {
209
+ return isDragging();
210
+ },
211
+ get channel() {
212
+ return channel();
213
+ },
214
+ get step() {
215
+ return step();
216
+ },
217
+ get pageSize() {
218
+ return pageSize();
219
+ },
220
+ get minValue() {
221
+ return minValue();
222
+ },
223
+ get maxValue() {
224
+ return maxValue();
225
+ },
226
+ get isDisabled() {
227
+ return isDisabled();
228
+ },
229
+ getThumbValue,
230
+ getThumbMinValue,
231
+ getThumbMaxValue,
232
+ getThumbPercent,
233
+ setThumbValue,
234
+ setThumbPercent,
235
+ incrementThumb,
236
+ decrementThumb,
237
+ setDragging: setDraggingState,
238
+ getDisplayColor,
239
+ getThumbValueLabel,
240
+ };
241
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * ColorWheel state management.
3
+ * Based on @react-stately/color useColorWheelState.
4
+ */
5
+ import { type Accessor } from 'solid-js';
6
+ import type { Color } from './types';
7
+ export interface ColorWheelStateOptions {
8
+ /** The current color value (controlled). */
9
+ value?: Color | string;
10
+ /** The default color value (uncontrolled). */
11
+ defaultValue?: Color | string;
12
+ /** Handler called when the color changes. */
13
+ onChange?: (color: Color) => void;
14
+ /** Handler called when dragging ends. */
15
+ onChangeEnd?: (color: Color) => void;
16
+ /** Whether the wheel is disabled. */
17
+ isDisabled?: boolean;
18
+ }
19
+ export interface ColorWheelState {
20
+ /** The current color value. */
21
+ readonly value: Color;
22
+ /** Whether the wheel is being dragged. */
23
+ readonly isDragging: boolean;
24
+ /** Whether the wheel is disabled. */
25
+ readonly isDisabled: boolean;
26
+ /** Step value for hue changes. */
27
+ readonly step: number;
28
+ /** Page step value for hue changes. */
29
+ readonly pageStep: number;
30
+ /** Get the current hue value (0-360). */
31
+ getHue(): number;
32
+ /** Set the hue value. */
33
+ setHue(value: number): void;
34
+ /** Set hue from an angle in radians. */
35
+ setHueFromAngle(angle: number): void;
36
+ /** Get the thumb angle in radians (0 = right, increases counterclockwise). */
37
+ getThumbAngle(): number;
38
+ /** Increment hue value. */
39
+ increment(stepSize?: number): void;
40
+ /** Decrement hue value. */
41
+ decrement(stepSize?: number): void;
42
+ /** Set the dragging state. */
43
+ setDragging(isDragging: boolean): void;
44
+ /** Get the display color (with full saturation/brightness for wheel). */
45
+ getDisplayColor(): Color;
46
+ }
47
+ /**
48
+ * Creates state for a color wheel (circular hue picker).
49
+ */
50
+ export declare function createColorWheelState(options: Accessor<ColorWheelStateOptions>): ColorWheelState;
51
+ //# sourceMappingURL=createColorWheelState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createColorWheelState.d.ts","sourceRoot":"","sources":["createColorWheelState.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA4B,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAgB,MAAM,SAAS,CAAC;AAGnD,MAAM,WAAW,sBAAsB;IACrC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,yCAAyC;IACzC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACrC,qCAAqC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,qCAAqC;IACrC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,yCAAyC;IACzC,MAAM,IAAI,MAAM,CAAC;IACjB,yBAAyB;IACzB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wCAAwC;IACxC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,8EAA8E;IAC9E,aAAa,IAAI,MAAM,CAAC;IACxB,2BAA2B;IAC3B,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,2BAA2B;IAC3B,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,8BAA8B;IAC9B,WAAW,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,yEAAyE;IACzE,eAAe,IAAI,KAAK,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GACxC,eAAe,CAyJjB"}