@proyecto-viviana/solidaria-components 0.2.5 → 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 (225) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -272
  3. package/dist/ActionBar.d.ts +79 -0
  4. package/dist/ActionBar.d.ts.map +1 -0
  5. package/dist/ActionGroup.d.ts +74 -0
  6. package/dist/ActionGroup.d.ts.map +1 -0
  7. package/dist/Alert.d.ts +70 -0
  8. package/dist/Alert.d.ts.map +1 -0
  9. package/dist/Autocomplete.d.ts +5 -5
  10. package/dist/Autocomplete.d.ts.map +1 -1
  11. package/dist/Breadcrumbs.d.ts +27 -8
  12. package/dist/Breadcrumbs.d.ts.map +1 -1
  13. package/dist/Button.d.ts +28 -5
  14. package/dist/Button.d.ts.map +1 -1
  15. package/dist/Calendar.d.ts +51 -7
  16. package/dist/Calendar.d.ts.map +1 -1
  17. package/dist/Checkbox.d.ts +33 -8
  18. package/dist/Checkbox.d.ts.map +1 -1
  19. package/dist/Collection.d.ts +130 -0
  20. package/dist/Collection.d.ts.map +1 -0
  21. package/dist/Color.d.ts +210 -9
  22. package/dist/Color.d.ts.map +1 -1
  23. package/dist/ColorEditor.d.ts +42 -0
  24. package/dist/ColorEditor.d.ts.map +1 -0
  25. package/dist/ComboBox.d.ts +146 -16
  26. package/dist/ComboBox.d.ts.map +1 -1
  27. package/dist/ContextualHelpTrigger.d.ts +40 -0
  28. package/dist/ContextualHelpTrigger.d.ts.map +1 -0
  29. package/dist/DateField.d.ts +35 -8
  30. package/dist/DateField.d.ts.map +1 -1
  31. package/dist/DatePicker.d.ts +101 -5
  32. package/dist/DatePicker.d.ts.map +1 -1
  33. package/dist/DateRangePickerContext.d.ts +30 -0
  34. package/dist/DateRangePickerContext.d.ts.map +1 -0
  35. package/dist/Dialog.d.ts +5 -5
  36. package/dist/Dialog.d.ts.map +1 -1
  37. package/dist/Disclosure.d.ts +25 -5
  38. package/dist/Disclosure.d.ts.map +1 -1
  39. package/dist/DragAndDrop.d.ts +80 -0
  40. package/dist/DragAndDrop.d.ts.map +1 -0
  41. package/dist/DragPreview.d.ts +14 -0
  42. package/dist/DragPreview.d.ts.map +1 -0
  43. package/dist/DropZone.d.ts +27 -0
  44. package/dist/DropZone.d.ts.map +1 -0
  45. package/dist/FieldError.d.ts +27 -0
  46. package/dist/FieldError.d.ts.map +1 -0
  47. package/dist/FileTrigger.d.ts +26 -0
  48. package/dist/FileTrigger.d.ts.map +1 -0
  49. package/dist/Focusable.d.ts +27 -0
  50. package/dist/Focusable.d.ts.map +1 -0
  51. package/dist/Form.d.ts +41 -0
  52. package/dist/Form.d.ts.map +1 -0
  53. package/dist/GridList.d.ts +69 -10
  54. package/dist/GridList.d.ts.map +1 -1
  55. package/dist/HiddenDateInput.d.ts +26 -0
  56. package/dist/HiddenDateInput.d.ts.map +1 -0
  57. package/dist/HiddenTimeInput.d.ts +25 -0
  58. package/dist/HiddenTimeInput.d.ts.map +1 -0
  59. package/dist/Icon.d.ts +57 -0
  60. package/dist/Icon.d.ts.map +1 -0
  61. package/dist/Keyboard.d.ts +13 -0
  62. package/dist/Keyboard.d.ts.map +1 -0
  63. package/dist/Landmark.d.ts +3 -3
  64. package/dist/Landmark.d.ts.map +1 -1
  65. package/dist/Link.d.ts +10 -4
  66. package/dist/Link.d.ts.map +1 -1
  67. package/dist/ListBox.d.ts +73 -11
  68. package/dist/ListBox.d.ts.map +1 -1
  69. package/dist/ListDropTargetDelegate.d.ts +38 -0
  70. package/dist/ListDropTargetDelegate.d.ts.map +1 -0
  71. package/dist/Menu.d.ts +79 -10
  72. package/dist/Menu.d.ts.map +1 -1
  73. package/dist/Meter.d.ts +4 -4
  74. package/dist/Meter.d.ts.map +1 -1
  75. package/dist/Modal.d.ts +6 -4
  76. package/dist/Modal.d.ts.map +1 -1
  77. package/dist/NumberField.d.ts +10 -12
  78. package/dist/NumberField.d.ts.map +1 -1
  79. package/dist/Popover.d.ts +32 -7
  80. package/dist/Popover.d.ts.map +1 -1
  81. package/dist/Pressable.d.ts +27 -0
  82. package/dist/Pressable.d.ts.map +1 -0
  83. package/dist/ProgressBar.d.ts +6 -4
  84. package/dist/ProgressBar.d.ts.map +1 -1
  85. package/dist/RadioGroup.d.ts +43 -9
  86. package/dist/RadioGroup.d.ts.map +1 -1
  87. package/dist/RangeCalendar.d.ts +39 -7
  88. package/dist/RangeCalendar.d.ts.map +1 -1
  89. package/dist/RouterProvider.d.ts +75 -0
  90. package/dist/RouterProvider.d.ts.map +1 -0
  91. package/dist/SearchField.d.ts +23 -21
  92. package/dist/SearchField.d.ts.map +1 -1
  93. package/dist/Select.d.ts +48 -7
  94. package/dist/Select.d.ts.map +1 -1
  95. package/dist/SelectionIndicator.d.ts +30 -0
  96. package/dist/SelectionIndicator.d.ts.map +1 -0
  97. package/dist/Separator.d.ts +9 -3
  98. package/dist/Separator.d.ts.map +1 -1
  99. package/dist/SharedElementTransition.d.ts +41 -0
  100. package/dist/SharedElementTransition.d.ts.map +1 -0
  101. package/dist/Slider.d.ts +15 -8
  102. package/dist/Slider.d.ts.map +1 -1
  103. package/dist/StepList.d.ts +90 -0
  104. package/dist/StepList.d.ts.map +1 -0
  105. package/dist/Switch.d.ts +11 -5
  106. package/dist/Switch.d.ts.map +1 -1
  107. package/dist/Table.d.ts +222 -19
  108. package/dist/Table.d.ts.map +1 -1
  109. package/dist/Tabs.d.ts +47 -10
  110. package/dist/Tabs.d.ts.map +1 -1
  111. package/dist/TagGroup.d.ts +22 -10
  112. package/dist/TagGroup.d.ts.map +1 -1
  113. package/dist/Text.d.ts +10 -0
  114. package/dist/Text.d.ts.map +1 -0
  115. package/dist/TextField.d.ts +19 -11
  116. package/dist/TextField.d.ts.map +1 -1
  117. package/dist/TimeField.d.ts +32 -7
  118. package/dist/TimeField.d.ts.map +1 -1
  119. package/dist/Toast.d.ts +29 -14
  120. package/dist/Toast.d.ts.map +1 -1
  121. package/dist/ToggleButton.d.ts +36 -0
  122. package/dist/ToggleButton.d.ts.map +1 -0
  123. package/dist/ToggleButtonGroup.d.ts +33 -0
  124. package/dist/ToggleButtonGroup.d.ts.map +1 -0
  125. package/dist/Toolbar.d.ts +7 -3
  126. package/dist/Toolbar.d.ts.map +1 -1
  127. package/dist/Tooltip.d.ts +58 -7
  128. package/dist/Tooltip.d.ts.map +1 -1
  129. package/dist/Tree.d.ts +102 -11
  130. package/dist/Tree.d.ts.map +1 -1
  131. package/dist/Virtualizer.d.ts +61 -0
  132. package/dist/Virtualizer.d.ts.map +1 -0
  133. package/dist/VirtualizerLayouts.d.ts +82 -0
  134. package/dist/VirtualizerLayouts.d.ts.map +1 -0
  135. package/dist/VisuallyHidden.d.ts +4 -2
  136. package/dist/VisuallyHidden.d.ts.map +1 -1
  137. package/dist/contexts.d.ts +6 -1
  138. package/dist/contexts.d.ts.map +1 -1
  139. package/dist/index.d.ts +73 -39
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +23342 -10644
  142. package/dist/index.js.map +1 -7
  143. package/dist/index.jsx +18110 -0
  144. package/dist/index.jsx.map +1 -0
  145. package/dist/useDragAndDrop.d.ts +93 -0
  146. package/dist/useDragAndDrop.d.ts.map +1 -0
  147. package/dist/utils.d.ts +8 -2
  148. package/dist/utils.d.ts.map +1 -1
  149. package/dist/virtualizer/Layout.d.ts +79 -0
  150. package/dist/virtualizer/Layout.d.ts.map +1 -0
  151. package/package.json +33 -32
  152. package/src/ActionBar.tsx +251 -0
  153. package/src/ActionGroup.tsx +277 -0
  154. package/src/Alert.tsx +152 -0
  155. package/src/Autocomplete.tsx +39 -44
  156. package/src/Breadcrumbs.tsx +227 -72
  157. package/src/Button.tsx +315 -74
  158. package/src/Calendar.tsx +347 -141
  159. package/src/Checkbox.tsx +414 -123
  160. package/src/Collection.tsx +350 -0
  161. package/src/Color.tsx +1325 -284
  162. package/src/ColorEditor.tsx +213 -0
  163. package/src/ComboBox.tsx +644 -245
  164. package/src/ContextualHelpTrigger.tsx +195 -0
  165. package/src/DateField.tsx +274 -106
  166. package/src/DatePicker.tsx +892 -111
  167. package/src/DateRangePickerContext.tsx +44 -0
  168. package/src/Dialog.tsx +173 -104
  169. package/src/Disclosure.tsx +158 -105
  170. package/src/DragAndDrop.tsx +340 -0
  171. package/src/DragPreview.tsx +47 -0
  172. package/src/DropZone.tsx +233 -0
  173. package/src/FieldError.tsx +89 -0
  174. package/src/FileTrigger.tsx +83 -0
  175. package/src/Focusable.tsx +103 -0
  176. package/src/Form.tsx +140 -0
  177. package/src/GridList.tsx +542 -128
  178. package/src/HiddenDateInput.tsx +153 -0
  179. package/src/HiddenTimeInput.tsx +133 -0
  180. package/src/Icon.tsx +133 -0
  181. package/src/Keyboard.tsx +26 -0
  182. package/src/Landmark.tsx +37 -63
  183. package/src/Link.tsx +132 -69
  184. package/src/ListBox.tsx +656 -106
  185. package/src/ListDropTargetDelegate.ts +283 -0
  186. package/src/Menu.tsx +1234 -132
  187. package/src/Meter.tsx +44 -58
  188. package/src/Modal.tsx +262 -166
  189. package/src/NumberField.tsx +267 -151
  190. package/src/Popover.tsx +452 -343
  191. package/src/Pressable.tsx +108 -0
  192. package/src/ProgressBar.tsx +54 -59
  193. package/src/RadioGroup.tsx +533 -121
  194. package/src/RangeCalendar.tsx +249 -150
  195. package/src/RouterProvider.tsx +223 -0
  196. package/src/SearchField.tsx +460 -133
  197. package/src/Select.tsx +804 -233
  198. package/src/SelectionIndicator.tsx +108 -0
  199. package/src/Separator.tsx +47 -49
  200. package/src/SharedElementTransition.tsx +264 -0
  201. package/src/Slider.tsx +148 -98
  202. package/src/StepList.tsx +272 -0
  203. package/src/Switch.tsx +93 -46
  204. package/src/Table.tsx +1551 -225
  205. package/src/Tabs.tsx +377 -123
  206. package/src/TagGroup.tsx +233 -135
  207. package/src/Text.tsx +18 -0
  208. package/src/TextField.tsx +413 -86
  209. package/src/TimeField.tsx +232 -222
  210. package/src/Toast.tsx +306 -160
  211. package/src/ToggleButton.tsx +169 -0
  212. package/src/ToggleButtonGroup.tsx +141 -0
  213. package/src/Toolbar.tsx +61 -70
  214. package/src/Tooltip.tsx +473 -116
  215. package/src/Tree.tsx +1514 -175
  216. package/src/Virtualizer.tsx +730 -0
  217. package/src/VirtualizerLayouts.ts +280 -0
  218. package/src/VisuallyHidden.tsx +32 -38
  219. package/src/contexts.ts +29 -36
  220. package/src/index.ts +972 -620
  221. package/src/useDragAndDrop.ts +367 -0
  222. package/src/utils.tsx +69 -50
  223. package/src/virtualizer/Layout.ts +192 -0
  224. package/dist/index.ssr.js +0 -9785
  225. package/dist/index.ssr.js.map +0 -7
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Layout primitives for solidaria-components Virtualizer.
3
+ *
4
+ * These are lightweight parity contracts inspired by RAC virtualizer layout APIs.
5
+ */
6
+
7
+ export interface Point {
8
+ x: number;
9
+ y: number;
10
+ }
11
+
12
+ export interface Rect {
13
+ x: number;
14
+ y: number;
15
+ width: number;
16
+ height: number;
17
+ }
18
+
19
+ export interface Size {
20
+ width: number;
21
+ height: number;
22
+ }
23
+
24
+ export interface LayoutInfo {
25
+ key: string | number;
26
+ index: number;
27
+ rect: Rect;
28
+ }
29
+
30
+ export interface VirtualizerVisibleRange {
31
+ start: number;
32
+ end: number;
33
+ offsetTop: number;
34
+ offsetBottom: number;
35
+ }
36
+
37
+ export interface VirtualizerRangeContext {
38
+ itemCount: number;
39
+ scrollOffset: number;
40
+ viewportSize: number;
41
+ overscan: number;
42
+ viewportWidth?: number;
43
+ }
44
+
45
+ export interface DefaultVirtualizerLayoutOptions {
46
+ itemSize?: number;
47
+ overscan?: number;
48
+ viewportSize?: number;
49
+ }
50
+
51
+ export interface GridLayoutOptions extends DefaultVirtualizerLayoutOptions {
52
+ rowHeight?: number;
53
+ columnCount?: number;
54
+ viewportWidth?: number;
55
+ }
56
+
57
+ export interface WaterfallLayoutOptions extends GridLayoutOptions {
58
+ minColumnWidth?: number;
59
+ viewportWidth?: number;
60
+ gap?: number;
61
+ }
62
+
63
+ export interface VirtualizerLayoutInfoContext {
64
+ viewportWidth: number;
65
+ }
66
+
67
+ export interface VirtualizerDropTarget {
68
+ type: "item" | "root";
69
+ index: number;
70
+ position: "before" | "on" | "after";
71
+ key?: string | number;
72
+ parentKey?: string | number | null;
73
+ level?: number;
74
+ }
75
+
76
+ function clampRange(
77
+ itemCount: number,
78
+ start: number,
79
+ end: number,
80
+ itemSize: number,
81
+ ): VirtualizerVisibleRange {
82
+ const safeStart = Math.max(0, Math.min(start, itemCount));
83
+ const safeEnd = Math.max(safeStart, Math.min(end, itemCount));
84
+ return {
85
+ start: safeStart,
86
+ end: safeEnd,
87
+ offsetTop: safeStart * itemSize,
88
+ offsetBottom: Math.max(0, (itemCount - safeEnd) * itemSize),
89
+ };
90
+ }
91
+
92
+ export function calculateLinearVisibleRange(
93
+ itemCount: number,
94
+ scrollOffset: number,
95
+ viewportSize: number,
96
+ itemSize: number,
97
+ overscan: number,
98
+ ): VirtualizerVisibleRange {
99
+ if (itemCount <= 0) return { start: 0, end: 0, offsetTop: 0, offsetBottom: 0 };
100
+ const safeItemSize = Math.max(1, itemSize);
101
+ const safeViewport = Math.max(1, viewportSize);
102
+ const safeOverscan = Math.max(0, overscan);
103
+ const start = Math.floor(scrollOffset / safeItemSize) - safeOverscan;
104
+ const visibleCount = Math.ceil(safeViewport / safeItemSize) + safeOverscan * 2;
105
+ return clampRange(itemCount, start, start + visibleCount, safeItemSize);
106
+ }
107
+
108
+ export class ListLayout {
109
+ getVisibleRange(
110
+ ctx: VirtualizerRangeContext,
111
+ options?: DefaultVirtualizerLayoutOptions,
112
+ ): VirtualizerVisibleRange {
113
+ return calculateLinearVisibleRange(
114
+ ctx.itemCount,
115
+ ctx.scrollOffset,
116
+ ctx.viewportSize,
117
+ options?.itemSize ?? 40,
118
+ options?.overscan ?? ctx.overscan,
119
+ );
120
+ }
121
+
122
+ getLayoutInfo(
123
+ index: number,
124
+ context: VirtualizerLayoutInfoContext,
125
+ options?: DefaultVirtualizerLayoutOptions,
126
+ ): LayoutInfo {
127
+ const itemHeight = Math.max(1, options?.itemSize ?? 40);
128
+ return {
129
+ key: String(index),
130
+ index,
131
+ rect: {
132
+ x: 0,
133
+ y: index * itemHeight,
134
+ width: Math.max(0, context.viewportWidth),
135
+ height: itemHeight,
136
+ },
137
+ };
138
+ }
139
+
140
+ getDropTargetFromPoint(
141
+ point: Point,
142
+ itemCount: number,
143
+ options?: DefaultVirtualizerLayoutOptions,
144
+ ): VirtualizerDropTarget | null {
145
+ if (itemCount <= 0) return { type: "root", index: -1, position: "on" };
146
+ const itemHeight = Math.max(1, options?.itemSize ?? 40);
147
+ if (point.y < 0) {
148
+ return { type: "item", index: 0, position: "before" };
149
+ }
150
+ const totalHeight = itemCount * itemHeight;
151
+ if (point.y >= totalHeight) {
152
+ return { type: "item", index: itemCount - 1, position: "after" };
153
+ }
154
+ const rawIndex = Math.floor(point.y / itemHeight);
155
+ const index = Math.max(0, Math.min(rawIndex, itemCount - 1));
156
+ const offsetWithinItem = Math.max(0, point.y - index * itemHeight);
157
+ const threshold = itemHeight / 3;
158
+ const position: VirtualizerDropTarget["position"] =
159
+ offsetWithinItem < threshold ? "before" : offsetWithinItem > threshold * 2 ? "after" : "on";
160
+ return { type: "item", index, position };
161
+ }
162
+ }
163
+
164
+ export class TableLayout extends ListLayout {}
165
+
166
+ export class GridLayout {
167
+ getVisibleRange(
168
+ ctx: VirtualizerRangeContext,
169
+ options?: GridLayoutOptions,
170
+ ): VirtualizerVisibleRange {
171
+ if (ctx.itemCount <= 0) return { start: 0, end: 0, offsetTop: 0, offsetBottom: 0 };
172
+ const rowHeight = Math.max(1, options?.rowHeight ?? options?.itemSize ?? 40);
173
+ const columns = Math.max(1, options?.columnCount ?? 1);
174
+ const safeViewport = Math.max(1, ctx.viewportSize);
175
+ const safeOverscan = Math.max(0, options?.overscan ?? ctx.overscan);
176
+
177
+ const startRow = Math.max(0, Math.floor(ctx.scrollOffset / rowHeight) - safeOverscan);
178
+ const visibleRows = Math.ceil(safeViewport / rowHeight) + safeOverscan * 2;
179
+ const endRow = startRow + visibleRows;
180
+
181
+ const start = startRow * columns;
182
+ const end = Math.min(ctx.itemCount, endRow * columns);
183
+
184
+ const totalRows = Math.ceil(ctx.itemCount / columns);
185
+ const clampedStartRow = Math.floor(start / columns);
186
+ const renderedRows = Math.ceil((end - start) / columns);
187
+ const offsetTop = clampedStartRow * rowHeight;
188
+ const offsetBottom = Math.max(0, (totalRows - clampedStartRow - renderedRows) * rowHeight);
189
+
190
+ return { start, end, offsetTop, offsetBottom };
191
+ }
192
+
193
+ getLayoutInfo(
194
+ index: number,
195
+ context: VirtualizerLayoutInfoContext,
196
+ options?: GridLayoutOptions,
197
+ ): LayoutInfo {
198
+ const rowHeight = Math.max(1, options?.rowHeight ?? options?.itemSize ?? 40);
199
+ const columns = Math.max(1, options?.columnCount ?? 1);
200
+ const row = Math.floor(index / columns);
201
+ const col = index % columns;
202
+ const width = Math.max(1, context.viewportWidth);
203
+ const cellWidth = Math.floor(width / columns);
204
+ return {
205
+ key: String(index),
206
+ index,
207
+ rect: {
208
+ x: col * cellWidth,
209
+ y: row * rowHeight,
210
+ width: cellWidth,
211
+ height: rowHeight,
212
+ },
213
+ };
214
+ }
215
+
216
+ getDropTargetFromPoint(
217
+ point: Point,
218
+ itemCount: number,
219
+ options?: GridLayoutOptions,
220
+ ): VirtualizerDropTarget | null {
221
+ if (itemCount <= 0) return { type: "root", index: -1, position: "on" };
222
+ const rowHeight = Math.max(1, options?.rowHeight ?? options?.itemSize ?? 40);
223
+ const columns = Math.max(1, options?.columnCount ?? 1);
224
+ const totalRows = Math.ceil(itemCount / columns);
225
+ const totalHeight = totalRows * rowHeight;
226
+ if (point.y < 0) {
227
+ return { type: "item", index: 0, position: "before" };
228
+ }
229
+ if (point.y >= totalHeight) {
230
+ return { type: "item", index: itemCount - 1, position: "after" };
231
+ }
232
+ const width = Math.max(1, options?.viewportWidth ?? 320);
233
+ const cellWidth = width / columns;
234
+ const row = Math.max(0, Math.floor(point.y / rowHeight));
235
+ const col = Math.max(0, Math.min(columns - 1, Math.floor(Math.max(0, point.x) / cellWidth)));
236
+ const index = Math.max(0, Math.min(itemCount - 1, row * columns + col));
237
+ const withinRow = Math.max(0, point.y - row * rowHeight);
238
+ const threshold = rowHeight / 3;
239
+ const position: VirtualizerDropTarget["position"] =
240
+ withinRow < threshold ? "before" : withinRow > threshold * 2 ? "after" : "on";
241
+ return { type: "item", index, position };
242
+ }
243
+ }
244
+
245
+ export class WaterfallLayout extends GridLayout {
246
+ override getVisibleRange(
247
+ ctx: VirtualizerRangeContext,
248
+ options?: WaterfallLayoutOptions,
249
+ ): VirtualizerVisibleRange {
250
+ const width = Math.max(1, options?.viewportWidth ?? 320);
251
+ const minColumnWidth = Math.max(1, options?.minColumnWidth ?? 200);
252
+ const gap = Math.max(0, options?.gap ?? 0);
253
+ const columnCount = Math.max(1, Math.floor((width + gap) / (minColumnWidth + gap)));
254
+ return super.getVisibleRange(ctx, { ...options, columnCount });
255
+ }
256
+
257
+ override getLayoutInfo(
258
+ index: number,
259
+ context: VirtualizerLayoutInfoContext,
260
+ options?: WaterfallLayoutOptions,
261
+ ): LayoutInfo {
262
+ const width = Math.max(1, options?.viewportWidth ?? context.viewportWidth);
263
+ const minColumnWidth = Math.max(1, options?.minColumnWidth ?? 200);
264
+ const gap = Math.max(0, options?.gap ?? 0);
265
+ const columnCount = Math.max(1, Math.floor((width + gap) / (minColumnWidth + gap)));
266
+ return super.getLayoutInfo(index, context, { ...options, columnCount });
267
+ }
268
+
269
+ override getDropTargetFromPoint(
270
+ point: Point,
271
+ itemCount: number,
272
+ options?: WaterfallLayoutOptions,
273
+ ): VirtualizerDropTarget | null {
274
+ const width = Math.max(1, options?.viewportWidth ?? 320);
275
+ const minColumnWidth = Math.max(1, options?.minColumnWidth ?? 200);
276
+ const gap = Math.max(0, options?.gap ?? 0);
277
+ const columnCount = Math.max(1, Math.floor((width + gap) / (minColumnWidth + gap)));
278
+ return super.getDropTargetFromPoint(point, itemCount, { ...options, columnCount });
279
+ }
280
+ }
@@ -5,56 +5,50 @@
5
5
  * Port of react-aria's VisuallyHidden.
6
6
  */
7
7
 
8
- import { type JSX, type ParentProps, splitProps } from 'solid-js';
9
- import { Dynamic } from 'solid-js/web';
8
+ import { type JSX, type ParentProps, splitProps } from "solid-js";
9
+ import { Dynamic } from "solid-js/web";
10
+ import { createVisuallyHidden, mergeProps } from "@proyecto-viviana/solidaria";
10
11
 
11
- // ============================================
12
- // TYPES
13
- // ============================================
14
-
15
- export interface VisuallyHiddenProps extends ParentProps {
12
+ export interface VisuallyHiddenProps extends ParentProps, JSX.HTMLAttributes<HTMLElement> {
16
13
  /** The element type to render. @default 'span' */
17
14
  elementType?: keyof JSX.IntrinsicElements;
18
15
  /** Whether the element should be focusable when focused. */
19
16
  isFocusable?: boolean;
17
+ /** Inline style object merged with visually hidden styles. */
18
+ style?: JSX.CSSProperties;
20
19
  }
21
20
 
22
- // ============================================
23
- // STYLES
24
- // ============================================
25
-
26
- const visuallyHiddenStyles: JSX.CSSProperties = {
27
- border: '0',
28
- clip: 'rect(0 0 0 0)',
29
- 'clip-path': 'inset(50%)',
30
- height: '1px',
31
- margin: '-1px',
32
- overflow: 'hidden',
33
- padding: '0',
34
- position: 'absolute',
35
- width: '1px',
36
- 'white-space': 'nowrap',
37
- };
38
-
39
- // ============================================
40
- // COMPONENT
41
- // ============================================
42
-
43
21
  /**
44
22
  * VisuallyHidden hides its children visually, while keeping content visible to screen readers.
45
23
  */
46
24
  export function VisuallyHidden(props: VisuallyHiddenProps): JSX.Element {
47
- const [local, others] = splitProps(props, ['elementType', 'isFocusable']);
48
-
49
- const elementType = () => local.elementType ?? 'span';
50
-
25
+ // Split children so the getter is not read once through `{...mergedProps()}`
26
+ // and again during explicit rendering. Hydration code is sensitive to that.
27
+ const [local, others] = splitProps(props, ["elementType", "isFocusable", "style", "children"]);
28
+ const { visuallyHiddenProps } = createVisuallyHidden(() => ({
29
+ style: local.style,
30
+ isFocusable: local.isFocusable,
31
+ }));
32
+
33
+ const mergedProps = () =>
34
+ mergeProps<Record<string, unknown>>(
35
+ others as unknown as Record<string, unknown>,
36
+ visuallyHiddenProps() as unknown as Record<string, unknown>,
37
+ );
38
+
39
+ // elementType is read once (structural, not reactive). The default `span` is
40
+ // rendered as a static element rather than via `<Dynamic>`: a reactive
41
+ // `<Dynamic>` desyncs Solid's hydration markers, leaving the registry dirty so
42
+ // a later sibling re-render throws "template is not a function" in prod (and a
43
+ // hard hydration crash under solid-refresh in dev). `<Dynamic>` is reserved for
44
+ // an explicit custom elementType.
45
+ const tag = local.elementType ?? "span";
46
+ if (tag === "span") {
47
+ return <span {...mergedProps()}>{local.children}</span>;
48
+ }
51
49
  return (
52
- <Dynamic
53
- component={elementType()}
54
- style={visuallyHiddenStyles}
55
- {...others}
56
- >
57
- {props.children}
50
+ <Dynamic component={tag} {...mergedProps()}>
51
+ {local.children}
58
52
  </Dynamic>
59
53
  );
60
54
  }
package/src/contexts.ts CHANGED
@@ -5,70 +5,63 @@
5
5
  * Dialog, Modal, Popover, and Button components.
6
6
  */
7
7
 
8
- import { createContext, useContext } from 'solid-js'
9
- import type { OverlayTriggerState as StatelyOverlayTriggerState } from '@proyecto-viviana/solid-stately'
10
-
11
- // ============================================
12
- // OVERLAY TRIGGER STATE CONTEXT
13
- // ============================================
8
+ import { createContext, useContext } from "solid-js";
9
+ import type { OverlayTriggerState as StatelyOverlayTriggerState } from "@proyecto-viviana/solid-stately";
14
10
 
15
11
  export interface OverlayTriggerState {
16
- isOpen: boolean
17
- open: () => void
18
- close: () => void
19
- toggle: () => void
12
+ isOpen: boolean;
13
+ open: () => void;
14
+ close: () => void;
15
+ toggle: () => void;
20
16
  }
21
17
 
22
- export const OverlayTriggerStateContext = createContext<OverlayTriggerState | null>(null)
18
+ export const OverlayTriggerStateContext = createContext<OverlayTriggerState | null>(null);
23
19
 
24
20
  /**
25
21
  * Hook to access the overlay trigger state from context.
26
22
  */
27
23
  export function useOverlayTriggerState(): OverlayTriggerState | null {
28
- return useContext(OverlayTriggerStateContext)
24
+ return useContext(OverlayTriggerStateContext);
29
25
  }
30
26
 
31
- // ============================================
32
- // DIALOG TRIGGER CONTEXT
33
- // ============================================
34
-
35
27
  export interface DialogTriggerContextValue {
36
- state: StatelyOverlayTriggerState
37
- triggerRef: () => HTMLElement | null
38
- triggerId: string
28
+ state: StatelyOverlayTriggerState;
29
+ triggerRef: () => HTMLElement | null;
30
+ setTriggerRef: (el: HTMLElement | null) => void;
31
+ triggerId: string;
32
+ triggerProps?: Record<string, unknown>;
33
+ overlayProps?: Record<string, unknown>;
39
34
  }
40
35
 
41
- export const DialogTriggerContext = createContext<DialogTriggerContextValue | null>(null)
36
+ export const DialogTriggerContext = createContext<DialogTriggerContextValue | null>(null);
42
37
 
43
38
  /**
44
39
  * Hook to access the dialog trigger state from context.
45
40
  */
46
41
  export function useDialogTrigger(): DialogTriggerContextValue | null {
47
- return useContext(DialogTriggerContext)
42
+ return useContext(DialogTriggerContext);
48
43
  }
49
44
 
50
- // ============================================
51
- // POPOVER TRIGGER CONTEXT
52
- // ============================================
53
-
54
45
  export interface PopoverTriggerContextValue {
55
46
  state: {
56
- isOpen: () => boolean
57
- open: () => void
58
- close: () => void
59
- toggle: () => void
60
- }
61
- triggerRef: () => HTMLElement | null
62
- setTriggerRef: (el: HTMLElement | null) => void
63
- triggerId: string
64
- trigger: string
47
+ isOpen: () => boolean;
48
+ open: () => void;
49
+ close: () => void;
50
+ toggle: () => void;
51
+ };
52
+ triggerRef: () => HTMLElement | null;
53
+ setTriggerRef: (el: HTMLElement | null) => void;
54
+ triggerId: string;
55
+ triggerProps?: Record<string, unknown>;
56
+ overlayProps?: Record<string, unknown>;
57
+ trigger: string;
65
58
  }
66
59
 
67
- export const PopoverTriggerContext = createContext<PopoverTriggerContextValue | null>(null)
60
+ export const PopoverTriggerContext = createContext<PopoverTriggerContextValue | null>(null);
68
61
 
69
62
  /**
70
63
  * Hook to access the popover trigger state from context.
71
64
  */
72
65
  export function usePopoverTrigger(): PopoverTriggerContextValue | null {
73
- return useContext(PopoverTriggerContext)
66
+ return useContext(PopoverTriggerContext);
74
67
  }