@proyecto-viviana/solid-stately 0.2.4 → 0.2.7

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/dist/autocomplete/createAutocompleteState.d.ts +2 -1
  3. package/dist/checkbox/createCheckboxGroupState.d.ts +10 -1
  4. package/dist/collections/types.d.ts +11 -0
  5. package/dist/color/getColorChannels.d.ts +20 -0
  6. package/dist/data/createAsyncList.d.ts +111 -0
  7. package/dist/data/createListData.d.ts +65 -0
  8. package/dist/data/createTreeData.d.ts +61 -0
  9. package/dist/data/index.d.ts +3 -0
  10. package/dist/datepicker/index.d.ts +10 -0
  11. package/dist/grid/types.d.ts +5 -1
  12. package/dist/index.d.ts +6 -1
  13. package/dist/index.js +3737 -2697
  14. package/dist/index.js.map +1 -7
  15. package/dist/menu/index.d.ts +8 -0
  16. package/dist/radio/createRadioGroupState.d.ts +10 -1
  17. package/dist/select/createSelectState.d.ts +17 -0
  18. package/dist/selection/index.d.ts +11 -0
  19. package/dist/toast/createToastState.d.ts +7 -1
  20. package/dist/toggle/createToggleGroupState.d.ts +45 -0
  21. package/dist/toggle/index.d.ts +1 -0
  22. package/dist/tree/TreeCollection.d.ts +3 -2
  23. package/package.json +6 -5
  24. package/src/autocomplete/createAutocompleteState.ts +10 -11
  25. package/src/calendar/createDateFieldState.ts +24 -1
  26. package/src/checkbox/createCheckboxGroupState.ts +42 -6
  27. package/src/collections/ListCollection.ts +152 -146
  28. package/src/collections/createListState.ts +266 -264
  29. package/src/collections/createMenuState.ts +106 -106
  30. package/src/collections/createSelectionState.ts +336 -336
  31. package/src/collections/index.ts +46 -46
  32. package/src/collections/types.ts +181 -169
  33. package/src/color/Color.ts +951 -951
  34. package/src/color/createColorAreaState.ts +293 -293
  35. package/src/color/createColorFieldState.ts +292 -292
  36. package/src/color/createColorSliderState.ts +241 -241
  37. package/src/color/createColorWheelState.ts +211 -211
  38. package/src/color/getColorChannels.ts +34 -0
  39. package/src/color/index.ts +47 -47
  40. package/src/color/types.ts +127 -127
  41. package/src/combobox/createComboBoxState.ts +703 -703
  42. package/src/combobox/index.ts +13 -13
  43. package/src/data/createAsyncList.ts +377 -0
  44. package/src/data/createListData.ts +298 -0
  45. package/src/data/createTreeData.ts +433 -0
  46. package/src/data/index.ts +25 -0
  47. package/src/datepicker/index.ts +36 -0
  48. package/src/disclosure/createDisclosureState.ts +4 -4
  49. package/src/dnd/createDragState.ts +153 -153
  50. package/src/dnd/createDraggableCollectionState.ts +165 -165
  51. package/src/dnd/createDropState.ts +212 -212
  52. package/src/dnd/createDroppableCollectionState.ts +357 -357
  53. package/src/dnd/index.ts +76 -76
  54. package/src/dnd/types.ts +317 -317
  55. package/src/form/createFormValidationState.ts +389 -389
  56. package/src/form/index.ts +15 -15
  57. package/src/grid/types.ts +5 -0
  58. package/src/index.ts +49 -0
  59. package/src/menu/index.ts +19 -0
  60. package/src/numberfield/createNumberFieldState.ts +427 -383
  61. package/src/numberfield/index.ts +5 -5
  62. package/src/overlays/createOverlayTriggerState.ts +67 -67
  63. package/src/overlays/index.ts +5 -5
  64. package/src/radio/createRadioGroupState.ts +44 -6
  65. package/src/searchfield/createSearchFieldState.ts +62 -62
  66. package/src/searchfield/index.ts +5 -5
  67. package/src/select/createSelectState.ts +290 -181
  68. package/src/select/index.ts +5 -5
  69. package/src/selection/index.ts +28 -0
  70. package/src/slider/createSliderState.ts +211 -211
  71. package/src/slider/index.ts +6 -6
  72. package/src/tabs/createTabListState.ts +37 -11
  73. package/src/toast/createToastState.d.ts +6 -1
  74. package/src/toast/createToastState.ts +8 -1
  75. package/src/toggle/createToggleGroupState.ts +127 -0
  76. package/src/toggle/index.ts +6 -0
  77. package/src/tooltip/createTooltipTriggerState.ts +183 -183
  78. package/src/tooltip/index.ts +6 -6
  79. package/src/tree/TreeCollection.ts +208 -175
  80. package/src/tree/createTreeState.ts +392 -392
  81. package/src/tree/index.ts +13 -13
  82. package/src/tree/types.ts +174 -174
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Toggle group state for Solid Stately
3
+ *
4
+ * Provides state management for groups of toggle buttons with
5
+ * single or multiple selection.
6
+ *
7
+ * This is a port of @react-stately/toggle's useToggleGroupState.
8
+ */
9
+
10
+ import { createSignal } from 'solid-js';
11
+ import type { Key } from '../collections';
12
+ import { type MaybeAccessor, access } from '../utils';
13
+
14
+ // ============================================
15
+ // TYPES
16
+ // ============================================
17
+
18
+ export interface ToggleGroupProps {
19
+ /**
20
+ * Whether single or multiple selection is enabled.
21
+ * @default 'single'
22
+ */
23
+ selectionMode?: 'single' | 'multiple';
24
+ /** Whether empty selection is disallowed. */
25
+ disallowEmptySelection?: boolean;
26
+ /** Controlled selected keys. */
27
+ selectedKeys?: Iterable<Key>;
28
+ /** Uncontrolled initial selected keys. */
29
+ defaultSelectedKeys?: Iterable<Key>;
30
+ /** Called when selected keys change. */
31
+ onSelectionChange?: (keys: Set<Key>) => void;
32
+ /** Whether all items are disabled. */
33
+ isDisabled?: boolean;
34
+ }
35
+
36
+ export interface ToggleGroupState {
37
+ /** Whether single or multiple selection is enabled. */
38
+ readonly selectionMode: 'single' | 'multiple';
39
+ /** Whether all items are disabled. */
40
+ readonly isDisabled: boolean;
41
+ /** Current selected keys. */
42
+ readonly selectedKeys: Set<Key>;
43
+ /** Toggles selected state for a key. */
44
+ toggleKey(key: Key): void;
45
+ /** Sets selected state for a key. */
46
+ setSelected(key: Key, isSelected: boolean): void;
47
+ /** Replaces selected keys. */
48
+ setSelectedKeys(keys: Set<Key>): void;
49
+ }
50
+
51
+ function toKeySet(keys?: Iterable<Key>): Set<Key> {
52
+ return new Set(keys ? Array.from(keys) : []);
53
+ }
54
+
55
+ // ============================================
56
+ // IMPLEMENTATION
57
+ // ============================================
58
+
59
+ /**
60
+ * Manages state for a group of toggle buttons.
61
+ */
62
+ export function createToggleGroupState(
63
+ props: MaybeAccessor<ToggleGroupProps> = {}
64
+ ): ToggleGroupState {
65
+ const getProps = () => access(props);
66
+
67
+ const initialProps = getProps();
68
+ const [internalSelectedKeys, setInternalSelectedKeys] = createSignal<Set<Key>>(
69
+ toKeySet(initialProps.defaultSelectedKeys)
70
+ );
71
+
72
+ const isControlled = () => getProps().selectedKeys !== undefined;
73
+ const selectedKeys = () =>
74
+ isControlled() ? toKeySet(getProps().selectedKeys) : internalSelectedKeys();
75
+
76
+ function setSelectedKeys(keys: Set<Key>): void {
77
+ const nextKeys = new Set(keys);
78
+ if (!isControlled()) {
79
+ setInternalSelectedKeys(nextKeys);
80
+ }
81
+ getProps().onSelectionChange?.(nextKeys);
82
+ }
83
+
84
+ function toggleKey(key: Key): void {
85
+ const props = getProps();
86
+ const mode = props.selectionMode ?? 'single';
87
+ const disallowEmptySelection = props.disallowEmptySelection ?? false;
88
+ const currentKeys = selectedKeys();
89
+
90
+ let nextKeys: Set<Key>;
91
+ if (mode === 'multiple') {
92
+ nextKeys = new Set(currentKeys);
93
+ if (nextKeys.has(key) && (!disallowEmptySelection || nextKeys.size > 1)) {
94
+ nextKeys.delete(key);
95
+ } else {
96
+ nextKeys.add(key);
97
+ }
98
+ } else {
99
+ nextKeys = new Set(
100
+ currentKeys.has(key) && !disallowEmptySelection ? [] : [key]
101
+ );
102
+ }
103
+
104
+ setSelectedKeys(nextKeys);
105
+ }
106
+
107
+ function setSelected(key: Key, isSelected: boolean): void {
108
+ if (isSelected !== selectedKeys().has(key)) {
109
+ toggleKey(key);
110
+ }
111
+ }
112
+
113
+ return {
114
+ get selectionMode() {
115
+ return getProps().selectionMode ?? 'single';
116
+ },
117
+ get isDisabled() {
118
+ return getProps().isDisabled ?? false;
119
+ },
120
+ get selectedKeys() {
121
+ return new Set(selectedKeys());
122
+ },
123
+ toggleKey,
124
+ setSelected,
125
+ setSelectedKeys,
126
+ };
127
+ }
@@ -3,3 +3,9 @@ export {
3
3
  type ToggleStateOptions,
4
4
  type ToggleState,
5
5
  } from './createToggleState';
6
+
7
+ export {
8
+ createToggleGroupState,
9
+ type ToggleGroupProps,
10
+ type ToggleGroupState,
11
+ } from './createToggleGroupState';
@@ -1,183 +1,183 @@
1
- /**
2
- * Manages state for a tooltip trigger.
3
- * Based on @react-stately/tooltip useTooltipTriggerState.
4
- *
5
- * Tracks whether the tooltip is open, and provides methods to toggle this state.
6
- * Ensures only one tooltip is open at a time and controls the delay for showing a tooltip.
7
- */
8
-
9
- import { createSignal, onCleanup, type Accessor } from 'solid-js';
10
- import { createOverlayTriggerState, type OverlayTriggerProps } from '../overlays';
11
- import { isServer } from '../ssr';
12
-
13
- // Default delays (in ms)
14
- const TOOLTIP_DELAY = 1500;
15
- const TOOLTIP_COOLDOWN = 500;
16
-
17
- export interface TooltipTriggerProps extends OverlayTriggerProps {
18
- /** The delay time in milliseconds for the tooltip to show up. */
19
- delay?: number;
20
- /** The delay time in milliseconds for the tooltip to close. */
21
- closeDelay?: number;
22
- }
23
-
24
- export interface TooltipTriggerState {
25
- /** Whether the tooltip is currently showing. */
26
- readonly isOpen: Accessor<boolean>;
27
- /**
28
- * Shows the tooltip. By default, the tooltip becomes visible after a delay
29
- * depending on a global warmup timer. The `immediate` option shows the
30
- * tooltip immediately instead.
31
- */
32
- open(immediate?: boolean): void;
33
- /** Hides the tooltip. */
34
- close(immediate?: boolean): void;
35
- }
36
-
37
- // Global state for coordinating tooltips
38
- let tooltips: Record<string, (immediate?: boolean) => void> = {};
39
- let tooltipId = 0;
40
- let globalWarmedUp = false;
41
- let globalWarmUpTimeout: ReturnType<typeof setTimeout> | null = null;
42
- let globalCooldownTimeout: ReturnType<typeof setTimeout> | null = null;
43
-
44
- /**
45
- * Resets the global tooltip state. Useful for testing.
46
- * @internal
47
- */
48
- export function resetTooltipState(): void {
49
- tooltips = {};
50
- tooltipId = 0;
51
- globalWarmedUp = false;
52
- if (globalWarmUpTimeout) {
53
- clearTimeout(globalWarmUpTimeout);
54
- globalWarmUpTimeout = null;
55
- }
56
- if (globalCooldownTimeout) {
57
- clearTimeout(globalCooldownTimeout);
58
- globalCooldownTimeout = null;
59
- }
60
- }
61
-
62
- /**
63
- * Manages state for a tooltip trigger. Tracks whether the tooltip is open, and provides
64
- * methods to toggle this state. Ensures only one tooltip is open at a time and controls
65
- * the delay for showing a tooltip.
66
- */
67
- export function createTooltipTriggerState(
68
- props: TooltipTriggerProps = {}
69
- ): TooltipTriggerState {
70
- const delay = () => props.delay ?? TOOLTIP_DELAY;
71
- const closeDelay = () => props.closeDelay ?? TOOLTIP_COOLDOWN;
72
-
73
- const overlayState = createOverlayTriggerState(props);
74
- const id = `tooltip-${++tooltipId}`;
75
-
76
- let closeTimeout: ReturnType<typeof setTimeout> | null = null;
77
- const [closeCallback, setCloseCallback] = createSignal<() => void>(() => overlayState.close());
78
-
79
- const ensureTooltipEntry = () => {
80
- tooltips[id] = hideTooltip;
81
- };
82
-
83
- const closeOpenTooltips = () => {
84
- for (const hideTooltipId in tooltips) {
85
- if (hideTooltipId !== id) {
86
- tooltips[hideTooltipId](true);
87
- delete tooltips[hideTooltipId];
88
- }
89
- }
90
- };
91
-
92
- const showTooltip = () => {
93
- if (closeTimeout) {
94
- clearTimeout(closeTimeout);
95
- closeTimeout = null;
96
- }
97
- closeOpenTooltips();
98
- ensureTooltipEntry();
99
- globalWarmedUp = true;
100
- overlayState.open();
101
-
102
- if (globalWarmUpTimeout) {
103
- clearTimeout(globalWarmUpTimeout);
104
- globalWarmUpTimeout = null;
105
- }
106
- if (globalCooldownTimeout) {
107
- clearTimeout(globalCooldownTimeout);
108
- globalCooldownTimeout = null;
109
- }
110
- };
111
-
112
- const hideTooltip = (immediate?: boolean) => {
113
- if (immediate || closeDelay() <= 0) {
114
- if (closeTimeout) {
115
- clearTimeout(closeTimeout);
116
- closeTimeout = null;
117
- }
118
- closeCallback()();
119
- } else if (!closeTimeout) {
120
- closeTimeout = setTimeout(() => {
121
- closeTimeout = null;
122
- closeCallback()();
123
- }, closeDelay());
124
- }
125
-
126
- if (globalWarmUpTimeout) {
127
- clearTimeout(globalWarmUpTimeout);
128
- globalWarmUpTimeout = null;
129
- }
130
-
131
- if (globalWarmedUp) {
132
- if (globalCooldownTimeout) {
133
- clearTimeout(globalCooldownTimeout);
134
- }
135
- globalCooldownTimeout = setTimeout(() => {
136
- delete tooltips[id];
137
- globalCooldownTimeout = null;
138
- globalWarmedUp = false;
139
- }, Math.max(TOOLTIP_COOLDOWN, closeDelay()));
140
- }
141
- };
142
-
143
- const warmupTooltip = () => {
144
- closeOpenTooltips();
145
- ensureTooltipEntry();
146
-
147
- if (!overlayState.isOpen() && !globalWarmUpTimeout && !globalWarmedUp) {
148
- globalWarmUpTimeout = setTimeout(() => {
149
- globalWarmUpTimeout = null;
150
- globalWarmedUp = true;
151
- showTooltip();
152
- }, delay());
153
- } else if (!overlayState.isOpen()) {
154
- showTooltip();
155
- }
156
- };
157
-
158
- // Update close callback when overlayState.close changes
159
- setCloseCallback(() => overlayState.close);
160
-
161
- // Cleanup on unmount
162
- onCleanup(() => {
163
- if (closeTimeout) {
164
- clearTimeout(closeTimeout);
165
- }
166
- if (tooltips[id]) {
167
- delete tooltips[id];
168
- }
169
- });
170
-
171
- return {
172
- isOpen: overlayState.isOpen,
173
- open: (immediate?: boolean) => {
174
- if (isServer) return;
175
- if (!immediate && delay() > 0 && !closeTimeout) {
176
- warmupTooltip();
177
- } else {
178
- showTooltip();
179
- }
180
- },
181
- close: hideTooltip,
182
- };
183
- }
1
+ /**
2
+ * Manages state for a tooltip trigger.
3
+ * Based on @react-stately/tooltip useTooltipTriggerState.
4
+ *
5
+ * Tracks whether the tooltip is open, and provides methods to toggle this state.
6
+ * Ensures only one tooltip is open at a time and controls the delay for showing a tooltip.
7
+ */
8
+
9
+ import { createSignal, onCleanup, type Accessor } from 'solid-js';
10
+ import { createOverlayTriggerState, type OverlayTriggerProps } from '../overlays';
11
+ import { isServer } from '../ssr';
12
+
13
+ // Default delays (in ms)
14
+ const TOOLTIP_DELAY = 1500;
15
+ const TOOLTIP_COOLDOWN = 500;
16
+
17
+ export interface TooltipTriggerProps extends OverlayTriggerProps {
18
+ /** The delay time in milliseconds for the tooltip to show up. */
19
+ delay?: number;
20
+ /** The delay time in milliseconds for the tooltip to close. */
21
+ closeDelay?: number;
22
+ }
23
+
24
+ export interface TooltipTriggerState {
25
+ /** Whether the tooltip is currently showing. */
26
+ readonly isOpen: Accessor<boolean>;
27
+ /**
28
+ * Shows the tooltip. By default, the tooltip becomes visible after a delay
29
+ * depending on a global warmup timer. The `immediate` option shows the
30
+ * tooltip immediately instead.
31
+ */
32
+ open(immediate?: boolean): void;
33
+ /** Hides the tooltip. */
34
+ close(immediate?: boolean): void;
35
+ }
36
+
37
+ // Global state for coordinating tooltips
38
+ let tooltips: Record<string, (immediate?: boolean) => void> = {};
39
+ let tooltipId = 0;
40
+ let globalWarmedUp = false;
41
+ let globalWarmUpTimeout: ReturnType<typeof setTimeout> | null = null;
42
+ let globalCooldownTimeout: ReturnType<typeof setTimeout> | null = null;
43
+
44
+ /**
45
+ * Resets the global tooltip state. Useful for testing.
46
+ * @internal
47
+ */
48
+ export function resetTooltipState(): void {
49
+ tooltips = {};
50
+ tooltipId = 0;
51
+ globalWarmedUp = false;
52
+ if (globalWarmUpTimeout) {
53
+ clearTimeout(globalWarmUpTimeout);
54
+ globalWarmUpTimeout = null;
55
+ }
56
+ if (globalCooldownTimeout) {
57
+ clearTimeout(globalCooldownTimeout);
58
+ globalCooldownTimeout = null;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Manages state for a tooltip trigger. Tracks whether the tooltip is open, and provides
64
+ * methods to toggle this state. Ensures only one tooltip is open at a time and controls
65
+ * the delay for showing a tooltip.
66
+ */
67
+ export function createTooltipTriggerState(
68
+ props: TooltipTriggerProps = {}
69
+ ): TooltipTriggerState {
70
+ const delay = () => props.delay ?? TOOLTIP_DELAY;
71
+ const closeDelay = () => props.closeDelay ?? TOOLTIP_COOLDOWN;
72
+
73
+ const overlayState = createOverlayTriggerState(props);
74
+ const id = `tooltip-${++tooltipId}`;
75
+
76
+ let closeTimeout: ReturnType<typeof setTimeout> | null = null;
77
+ const [closeCallback, setCloseCallback] = createSignal<() => void>(() => overlayState.close());
78
+
79
+ const ensureTooltipEntry = () => {
80
+ tooltips[id] = hideTooltip;
81
+ };
82
+
83
+ const closeOpenTooltips = () => {
84
+ for (const hideTooltipId in tooltips) {
85
+ if (hideTooltipId !== id) {
86
+ tooltips[hideTooltipId](true);
87
+ delete tooltips[hideTooltipId];
88
+ }
89
+ }
90
+ };
91
+
92
+ const showTooltip = () => {
93
+ if (closeTimeout) {
94
+ clearTimeout(closeTimeout);
95
+ closeTimeout = null;
96
+ }
97
+ closeOpenTooltips();
98
+ ensureTooltipEntry();
99
+ globalWarmedUp = true;
100
+ overlayState.open();
101
+
102
+ if (globalWarmUpTimeout) {
103
+ clearTimeout(globalWarmUpTimeout);
104
+ globalWarmUpTimeout = null;
105
+ }
106
+ if (globalCooldownTimeout) {
107
+ clearTimeout(globalCooldownTimeout);
108
+ globalCooldownTimeout = null;
109
+ }
110
+ };
111
+
112
+ const hideTooltip = (immediate?: boolean) => {
113
+ if (immediate || closeDelay() <= 0) {
114
+ if (closeTimeout) {
115
+ clearTimeout(closeTimeout);
116
+ closeTimeout = null;
117
+ }
118
+ closeCallback()();
119
+ } else if (!closeTimeout) {
120
+ closeTimeout = setTimeout(() => {
121
+ closeTimeout = null;
122
+ closeCallback()();
123
+ }, closeDelay());
124
+ }
125
+
126
+ if (globalWarmUpTimeout) {
127
+ clearTimeout(globalWarmUpTimeout);
128
+ globalWarmUpTimeout = null;
129
+ }
130
+
131
+ if (globalWarmedUp) {
132
+ if (globalCooldownTimeout) {
133
+ clearTimeout(globalCooldownTimeout);
134
+ }
135
+ globalCooldownTimeout = setTimeout(() => {
136
+ delete tooltips[id];
137
+ globalCooldownTimeout = null;
138
+ globalWarmedUp = false;
139
+ }, Math.max(TOOLTIP_COOLDOWN, closeDelay()));
140
+ }
141
+ };
142
+
143
+ const warmupTooltip = () => {
144
+ closeOpenTooltips();
145
+ ensureTooltipEntry();
146
+
147
+ if (!overlayState.isOpen() && !globalWarmUpTimeout && !globalWarmedUp) {
148
+ globalWarmUpTimeout = setTimeout(() => {
149
+ globalWarmUpTimeout = null;
150
+ globalWarmedUp = true;
151
+ showTooltip();
152
+ }, delay());
153
+ } else if (!overlayState.isOpen()) {
154
+ showTooltip();
155
+ }
156
+ };
157
+
158
+ // Update close callback when overlayState.close changes
159
+ setCloseCallback(() => overlayState.close);
160
+
161
+ // Cleanup on unmount
162
+ onCleanup(() => {
163
+ if (closeTimeout) {
164
+ clearTimeout(closeTimeout);
165
+ }
166
+ if (tooltips[id]) {
167
+ delete tooltips[id];
168
+ }
169
+ });
170
+
171
+ return {
172
+ isOpen: overlayState.isOpen,
173
+ open: (immediate?: boolean) => {
174
+ if (isServer) return;
175
+ if (!immediate && delay() > 0 && !closeTimeout) {
176
+ warmupTooltip();
177
+ } else {
178
+ showTooltip();
179
+ }
180
+ },
181
+ close: hideTooltip,
182
+ };
183
+ }
@@ -1,6 +1,6 @@
1
- export {
2
- createTooltipTriggerState,
3
- resetTooltipState,
4
- type TooltipTriggerProps,
5
- type TooltipTriggerState,
6
- } from './createTooltipTriggerState';
1
+ export {
2
+ createTooltipTriggerState,
3
+ resetTooltipState,
4
+ type TooltipTriggerProps,
5
+ type TooltipTriggerState,
6
+ } from './createTooltipTriggerState';