@proyecto-viviana/solidaria-components 0.3.2 → 0.4.1

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 (417) hide show
  1. package/dist/ActionBar.d.ts.map +1 -1
  2. package/dist/ActionBar.js +175 -0
  3. package/dist/ActionBar.js.map +1 -0
  4. package/dist/ActionBar.jsx +119 -0
  5. package/dist/ActionBar.jsx.map +1 -0
  6. package/dist/ActionGroup.d.ts.map +1 -1
  7. package/dist/ActionGroup.js +179 -0
  8. package/dist/ActionGroup.js.map +1 -0
  9. package/dist/ActionGroup.jsx +129 -0
  10. package/dist/ActionGroup.jsx.map +1 -0
  11. package/dist/Alert.js +111 -0
  12. package/dist/Alert.js.map +1 -0
  13. package/dist/Alert.jsx +82 -0
  14. package/dist/Alert.jsx.map +1 -0
  15. package/dist/Autocomplete.d.ts +2 -2
  16. package/dist/Autocomplete.d.ts.map +1 -1
  17. package/dist/Autocomplete.js +130 -0
  18. package/dist/Autocomplete.js.map +1 -0
  19. package/dist/Autocomplete.jsx +116 -0
  20. package/dist/Autocomplete.jsx.map +1 -0
  21. package/dist/Breadcrumbs.d.ts.map +1 -1
  22. package/dist/Breadcrumbs.js +333 -0
  23. package/dist/Breadcrumbs.js.map +1 -0
  24. package/dist/Breadcrumbs.jsx +261 -0
  25. package/dist/Breadcrumbs.jsx.map +1 -0
  26. package/dist/Button.d.ts.map +1 -1
  27. package/dist/Button.js +348 -0
  28. package/dist/Button.js.map +1 -0
  29. package/dist/Button.jsx +314 -0
  30. package/dist/Button.jsx.map +1 -0
  31. package/dist/Calendar.d.ts +4 -4
  32. package/dist/Calendar.d.ts.map +1 -1
  33. package/dist/Calendar.js +573 -0
  34. package/dist/Calendar.js.map +1 -0
  35. package/dist/Calendar.jsx +342 -0
  36. package/dist/Calendar.jsx.map +1 -0
  37. package/dist/CalendarPicker.d.ts +33 -0
  38. package/dist/CalendarPicker.d.ts.map +1 -0
  39. package/dist/CalendarPicker.js +44 -0
  40. package/dist/CalendarPicker.js.map +1 -0
  41. package/dist/CalendarPicker.jsx +44 -0
  42. package/dist/CalendarPicker.jsx.map +1 -0
  43. package/dist/Checkbox.d.ts +83 -4
  44. package/dist/Checkbox.d.ts.map +1 -1
  45. package/dist/Checkbox.js +923 -0
  46. package/dist/Checkbox.js.map +1 -0
  47. package/dist/Checkbox.jsx +707 -0
  48. package/dist/Checkbox.jsx.map +1 -0
  49. package/dist/Collection.d.ts.map +1 -1
  50. package/dist/Collection.js +202 -0
  51. package/dist/Collection.js.map +1 -0
  52. package/dist/Collection.jsx +152 -0
  53. package/dist/Collection.jsx.map +1 -0
  54. package/dist/Color.d.ts.map +1 -1
  55. package/dist/Color.js +1717 -0
  56. package/dist/Color.js.map +1 -0
  57. package/dist/Color.jsx +1340 -0
  58. package/dist/Color.jsx.map +1 -0
  59. package/dist/ColorEditor.js +208 -0
  60. package/dist/ColorEditor.js.map +1 -0
  61. package/dist/ColorEditor.jsx +120 -0
  62. package/dist/ColorEditor.jsx.map +1 -0
  63. package/dist/ComboBox.d.ts +8 -4
  64. package/dist/ComboBox.d.ts.map +1 -1
  65. package/dist/ComboBox.js +1000 -0
  66. package/dist/ComboBox.js.map +1 -0
  67. package/dist/ComboBox.jsx +724 -0
  68. package/dist/ComboBox.jsx.map +1 -0
  69. package/dist/ContextualHelpTrigger.js +146 -0
  70. package/dist/ContextualHelpTrigger.js.map +1 -0
  71. package/dist/ContextualHelpTrigger.jsx +109 -0
  72. package/dist/ContextualHelpTrigger.jsx.map +1 -0
  73. package/dist/DateField.d.ts +14 -5
  74. package/dist/DateField.d.ts.map +1 -1
  75. package/dist/DateField.js +4 -0
  76. package/dist/DateField.jsx +4 -0
  77. package/dist/DateField2.js +502 -0
  78. package/dist/DateField2.js.map +1 -0
  79. package/dist/DateField2.jsx +354 -0
  80. package/dist/DateField2.jsx.map +1 -0
  81. package/dist/DatePicker.d.ts +46 -7
  82. package/dist/DatePicker.d.ts.map +1 -1
  83. package/dist/DatePicker.js +7 -0
  84. package/dist/DatePicker.jsx +7 -0
  85. package/dist/DatePicker2.js +1171 -0
  86. package/dist/DatePicker2.js.map +1 -0
  87. package/dist/DatePicker2.jsx +820 -0
  88. package/dist/DatePicker2.jsx.map +1 -0
  89. package/dist/DateRangePickerContext.d.ts +2 -0
  90. package/dist/DateRangePickerContext.d.ts.map +1 -1
  91. package/dist/Dialog.d.ts.map +1 -1
  92. package/dist/Dialog.js +337 -0
  93. package/dist/Dialog.js.map +1 -0
  94. package/dist/Dialog.jsx +192 -0
  95. package/dist/Dialog.jsx.map +1 -0
  96. package/dist/Disclosure.d.ts.map +1 -1
  97. package/dist/Disclosure.js +331 -0
  98. package/dist/Disclosure.js.map +1 -0
  99. package/dist/Disclosure.jsx +230 -0
  100. package/dist/Disclosure.jsx.map +1 -0
  101. package/dist/DragAndDrop.d.ts.map +1 -1
  102. package/dist/DragAndDrop.js +176 -0
  103. package/dist/DragAndDrop.js.map +1 -0
  104. package/dist/DragAndDrop.jsx +160 -0
  105. package/dist/DragAndDrop.jsx.map +1 -0
  106. package/dist/DropZone.d.ts.map +1 -1
  107. package/dist/DropZone.js +189 -0
  108. package/dist/DropZone.js.map +1 -0
  109. package/dist/DropZone.jsx +144 -0
  110. package/dist/DropZone.jsx.map +1 -0
  111. package/dist/FieldError.js +66 -0
  112. package/dist/FieldError.js.map +1 -0
  113. package/dist/FieldError.jsx +47 -0
  114. package/dist/FieldError.jsx.map +1 -0
  115. package/dist/FileTrigger.js +79 -0
  116. package/dist/FileTrigger.js.map +1 -0
  117. package/dist/FileTrigger.jsx +49 -0
  118. package/dist/FileTrigger.jsx.map +1 -0
  119. package/dist/Focusable.js +70 -0
  120. package/dist/Focusable.js.map +1 -0
  121. package/dist/Focusable.jsx +69 -0
  122. package/dist/Focusable.jsx.map +1 -0
  123. package/dist/Form.js +99 -0
  124. package/dist/Form.js.map +1 -0
  125. package/dist/Form.jsx +73 -0
  126. package/dist/Form.jsx.map +1 -0
  127. package/dist/GridList.d.ts +34 -2
  128. package/dist/GridList.d.ts.map +1 -1
  129. package/dist/GridList.js +723 -0
  130. package/dist/GridList.js.map +1 -0
  131. package/dist/GridList.jsx +552 -0
  132. package/dist/GridList.jsx.map +1 -0
  133. package/dist/Icon.d.ts.map +1 -1
  134. package/dist/Icon.js +127 -0
  135. package/dist/Icon.js.map +1 -0
  136. package/dist/Icon.jsx +72 -0
  137. package/dist/Icon.jsx.map +1 -0
  138. package/dist/Keyboard.js +30 -0
  139. package/dist/Keyboard.js.map +1 -0
  140. package/dist/Keyboard.jsx +24 -0
  141. package/dist/Keyboard.jsx.map +1 -0
  142. package/dist/Landmark.js +134 -0
  143. package/dist/Landmark.js.map +1 -0
  144. package/dist/Landmark.jsx +118 -0
  145. package/dist/Landmark.jsx.map +1 -0
  146. package/dist/Link.d.ts.map +1 -1
  147. package/dist/Link.js +219 -0
  148. package/dist/Link.js.map +1 -0
  149. package/dist/Link.jsx +189 -0
  150. package/dist/Link.jsx.map +1 -0
  151. package/dist/ListBox.d.ts +2 -2
  152. package/dist/ListBox.d.ts.map +1 -1
  153. package/dist/ListBox.js +831 -0
  154. package/dist/ListBox.js.map +1 -0
  155. package/dist/ListBox.jsx +644 -0
  156. package/dist/ListBox.jsx.map +1 -0
  157. package/dist/Menu.d.ts +27 -9
  158. package/dist/Menu.d.ts.map +1 -1
  159. package/dist/Menu.js +1254 -0
  160. package/dist/Menu.js.map +1 -0
  161. package/dist/Menu.jsx +1042 -0
  162. package/dist/Menu.jsx.map +1 -0
  163. package/dist/Meter.d.ts.map +1 -1
  164. package/dist/Meter.js +123 -0
  165. package/dist/Meter.js.map +1 -0
  166. package/dist/Meter.jsx +107 -0
  167. package/dist/Meter.jsx.map +1 -0
  168. package/dist/Modal.d.ts.map +1 -1
  169. package/dist/Modal.js +382 -0
  170. package/dist/Modal.js.map +1 -0
  171. package/dist/Modal.jsx +314 -0
  172. package/dist/Modal.jsx.map +1 -0
  173. package/dist/NumberField.d.ts +3 -3
  174. package/dist/NumberField.d.ts.map +1 -1
  175. package/dist/NumberField.js +573 -0
  176. package/dist/NumberField.js.map +1 -0
  177. package/dist/NumberField.jsx +443 -0
  178. package/dist/NumberField.jsx.map +1 -0
  179. package/dist/Popover.d.ts +10 -2
  180. package/dist/Popover.d.ts.map +1 -1
  181. package/dist/Popover.js +471 -0
  182. package/dist/Popover.js.map +1 -0
  183. package/dist/Popover.jsx +354 -0
  184. package/dist/Popover.jsx.map +1 -0
  185. package/dist/Pressable.js +69 -0
  186. package/dist/Pressable.js.map +1 -0
  187. package/dist/Pressable.jsx +68 -0
  188. package/dist/Pressable.jsx.map +1 -0
  189. package/dist/ProgressBar.d.ts.map +1 -1
  190. package/dist/ProgressBar.js +130 -0
  191. package/dist/ProgressBar.js.map +1 -0
  192. package/dist/ProgressBar.jsx +114 -0
  193. package/dist/ProgressBar.jsx.map +1 -0
  194. package/dist/RadioGroup.d.ts +82 -4
  195. package/dist/RadioGroup.d.ts.map +1 -1
  196. package/dist/RadioGroup.js +931 -0
  197. package/dist/RadioGroup.js.map +1 -0
  198. package/dist/RadioGroup.jsx +681 -0
  199. package/dist/RadioGroup.jsx.map +1 -0
  200. package/dist/RangeCalendar.d.ts.map +1 -1
  201. package/dist/RangeCalendar.js +546 -0
  202. package/dist/RangeCalendar.js.map +1 -0
  203. package/dist/RangeCalendar.jsx +323 -0
  204. package/dist/RangeCalendar.jsx.map +1 -0
  205. package/dist/RouterProvider.js +118 -0
  206. package/dist/RouterProvider.js.map +1 -0
  207. package/dist/RouterProvider.jsx +112 -0
  208. package/dist/RouterProvider.jsx.map +1 -0
  209. package/dist/SearchField.d.ts +2 -2
  210. package/dist/SearchField.d.ts.map +1 -1
  211. package/dist/SearchField.js +667 -0
  212. package/dist/SearchField.js.map +1 -0
  213. package/dist/SearchField.jsx +550 -0
  214. package/dist/SearchField.jsx.map +1 -0
  215. package/dist/Select.d.ts +7 -0
  216. package/dist/Select.d.ts.map +1 -1
  217. package/dist/Select.js +1044 -0
  218. package/dist/Select.js.map +1 -0
  219. package/dist/Select.jsx +759 -0
  220. package/dist/Select.jsx.map +1 -0
  221. package/dist/SelectionIndicator.d.ts.map +1 -1
  222. package/dist/SelectionIndicator.js +86 -0
  223. package/dist/SelectionIndicator.js.map +1 -0
  224. package/dist/SelectionIndicator.jsx +50 -0
  225. package/dist/SelectionIndicator.jsx.map +1 -0
  226. package/dist/Separator.js +97 -0
  227. package/dist/Separator.js.map +1 -0
  228. package/dist/Separator.jsx +85 -0
  229. package/dist/Separator.jsx.map +1 -0
  230. package/dist/SharedElementTransition.d.ts.map +1 -1
  231. package/dist/SharedElementTransition.js +167 -0
  232. package/dist/SharedElementTransition.js.map +1 -0
  233. package/dist/SharedElementTransition.jsx +140 -0
  234. package/dist/SharedElementTransition.jsx.map +1 -0
  235. package/dist/Slider.d.ts +33 -1
  236. package/dist/Slider.d.ts.map +1 -1
  237. package/dist/Slider.js +515 -0
  238. package/dist/Slider.js.map +1 -0
  239. package/dist/Slider.jsx +403 -0
  240. package/dist/Slider.jsx.map +1 -0
  241. package/dist/StepList.d.ts.map +1 -1
  242. package/dist/StepList.js +191 -0
  243. package/dist/StepList.js.map +1 -0
  244. package/dist/StepList.jsx +136 -0
  245. package/dist/StepList.jsx.map +1 -0
  246. package/dist/Switch.d.ts +65 -2
  247. package/dist/Switch.d.ts.map +1 -1
  248. package/dist/Switch.js +534 -0
  249. package/dist/Switch.js.map +1 -0
  250. package/dist/Switch.jsx +393 -0
  251. package/dist/Switch.jsx.map +1 -0
  252. package/dist/Table.d.ts +50 -0
  253. package/dist/Table.d.ts.map +1 -1
  254. package/dist/Table.js +1766 -0
  255. package/dist/Table.js.map +1 -0
  256. package/dist/Table.jsx +1355 -0
  257. package/dist/Table.jsx.map +1 -0
  258. package/dist/Tabs.d.ts +0 -4
  259. package/dist/Tabs.d.ts.map +1 -1
  260. package/dist/Tabs.js +598 -0
  261. package/dist/Tabs.js.map +1 -0
  262. package/dist/Tabs.jsx +367 -0
  263. package/dist/Tabs.jsx.map +1 -0
  264. package/dist/TagGroup.d.ts +3 -1
  265. package/dist/TagGroup.d.ts.map +1 -1
  266. package/dist/TagGroup.js +382 -0
  267. package/dist/TagGroup.js.map +1 -0
  268. package/dist/TagGroup.jsx +273 -0
  269. package/dist/TagGroup.jsx.map +1 -0
  270. package/dist/Text.d.ts +18 -6
  271. package/dist/Text.d.ts.map +1 -1
  272. package/dist/Text.js +42 -0
  273. package/dist/Text.js.map +1 -0
  274. package/dist/Text.jsx +35 -0
  275. package/dist/Text.jsx.map +1 -0
  276. package/dist/TextField.d.ts +6 -6
  277. package/dist/TextField.d.ts.map +1 -1
  278. package/dist/TextField.js +439 -0
  279. package/dist/TextField.js.map +1 -0
  280. package/dist/TextField.jsx +406 -0
  281. package/dist/TextField.jsx.map +1 -0
  282. package/dist/TimeField.d.ts +17 -53
  283. package/dist/TimeField.d.ts.map +1 -1
  284. package/dist/TimeField.js +278 -0
  285. package/dist/TimeField.js.map +1 -0
  286. package/dist/TimeField.jsx +218 -0
  287. package/dist/TimeField.jsx.map +1 -0
  288. package/dist/Toast.d.ts +14 -0
  289. package/dist/Toast.d.ts.map +1 -1
  290. package/dist/Toast.js +551 -0
  291. package/dist/Toast.js.map +1 -0
  292. package/dist/Toast.jsx +361 -0
  293. package/dist/Toast.jsx.map +1 -0
  294. package/dist/ToggleButton.d.ts.map +1 -1
  295. package/dist/ToggleButton.js +123 -0
  296. package/dist/ToggleButton.js.map +1 -0
  297. package/dist/ToggleButton.jsx +88 -0
  298. package/dist/ToggleButton.jsx.map +1 -0
  299. package/dist/ToggleButtonGroup.d.ts.map +1 -1
  300. package/dist/ToggleButtonGroup.js +114 -0
  301. package/dist/ToggleButtonGroup.js.map +1 -0
  302. package/dist/ToggleButtonGroup.jsx +85 -0
  303. package/dist/ToggleButtonGroup.jsx.map +1 -0
  304. package/dist/Toolbar.js +112 -0
  305. package/dist/Toolbar.js.map +1 -0
  306. package/dist/Toolbar.jsx +92 -0
  307. package/dist/Toolbar.jsx.map +1 -0
  308. package/dist/Tooltip.d.ts.map +1 -1
  309. package/dist/Tooltip.js +539 -0
  310. package/dist/Tooltip.js.map +1 -0
  311. package/dist/Tooltip.jsx +465 -0
  312. package/dist/Tooltip.jsx.map +1 -0
  313. package/dist/Tree.d.ts +14 -2
  314. package/dist/Tree.d.ts.map +1 -1
  315. package/dist/Tree.js +1424 -0
  316. package/dist/Tree.js.map +1 -0
  317. package/dist/Tree.jsx +1172 -0
  318. package/dist/Tree.jsx.map +1 -0
  319. package/dist/Virtualizer.d.ts +16 -2
  320. package/dist/Virtualizer.d.ts.map +1 -1
  321. package/dist/Virtualizer.js +2 -0
  322. package/dist/Virtualizer.jsx +2 -0
  323. package/dist/Virtualizer2.js +751 -0
  324. package/dist/Virtualizer2.js.map +1 -0
  325. package/dist/Virtualizer2.jsx +730 -0
  326. package/dist/Virtualizer2.jsx.map +1 -0
  327. package/dist/VirtualizerLayouts.d.ts +18 -0
  328. package/dist/VirtualizerLayouts.d.ts.map +1 -1
  329. package/dist/VisuallyHidden.js +42 -0
  330. package/dist/VisuallyHidden.js.map +1 -0
  331. package/dist/VisuallyHidden.jsx +35 -0
  332. package/dist/VisuallyHidden.jsx.map +1 -0
  333. package/dist/contexts.js +33 -0
  334. package/dist/contexts.js.map +1 -0
  335. package/dist/contexts.jsx +33 -0
  336. package/dist/contexts.jsx.map +1 -0
  337. package/dist/index.d.ts +9 -9
  338. package/dist/index.d.ts.map +1 -1
  339. package/dist/index.js +69 -23932
  340. package/dist/index.jsx +69 -18337
  341. package/dist/useDragAndDrop.d.ts +0 -8
  342. package/dist/useDragAndDrop.d.ts.map +1 -1
  343. package/dist/useDragAndDrop.js +2 -0
  344. package/dist/useDragAndDrop.jsx +2 -0
  345. package/dist/useDragAndDrop2.js +399 -0
  346. package/dist/useDragAndDrop2.js.map +1 -0
  347. package/dist/useDragAndDrop2.jsx +399 -0
  348. package/dist/useDragAndDrop2.jsx.map +1 -0
  349. package/dist/utils.d.ts +84 -11
  350. package/dist/utils.d.ts.map +1 -1
  351. package/dist/utils.js +285 -0
  352. package/dist/utils.js.map +1 -0
  353. package/dist/utils.jsx +277 -0
  354. package/dist/utils.jsx.map +1 -0
  355. package/dist/virtualizer/Layout.js +144 -0
  356. package/dist/virtualizer/Layout.js.map +1 -0
  357. package/dist/virtualizer/Layout.jsx +144 -0
  358. package/dist/virtualizer/Layout.jsx.map +1 -0
  359. package/package.json +395 -4
  360. package/src/ActionBar.tsx +10 -12
  361. package/src/ActionGroup.tsx +5 -3
  362. package/src/Autocomplete.tsx +14 -9
  363. package/src/Breadcrumbs.tsx +58 -39
  364. package/src/Button.tsx +22 -2
  365. package/src/Calendar.tsx +57 -11
  366. package/src/CalendarPicker.tsx +73 -0
  367. package/src/Checkbox.tsx +539 -3
  368. package/src/Collection.tsx +9 -3
  369. package/src/Color.tsx +84 -41
  370. package/src/ComboBox.tsx +97 -21
  371. package/src/DateField.tsx +304 -53
  372. package/src/DatePicker.tsx +402 -62
  373. package/src/DateRangePickerContext.tsx +2 -0
  374. package/src/Dialog.tsx +13 -5
  375. package/src/Disclosure.tsx +7 -1
  376. package/src/DragAndDrop.tsx +3 -1
  377. package/src/DropZone.tsx +3 -1
  378. package/src/GridList.tsx +133 -26
  379. package/src/Icon.tsx +3 -1
  380. package/src/Link.tsx +3 -1
  381. package/src/ListBox.tsx +354 -25
  382. package/src/Menu.tsx +252 -128
  383. package/src/Meter.tsx +3 -1
  384. package/src/Modal.tsx +120 -56
  385. package/src/NumberField.tsx +51 -8
  386. package/src/Popover.tsx +68 -17
  387. package/src/ProgressBar.tsx +3 -1
  388. package/src/RadioGroup.tsx +468 -4
  389. package/src/RangeCalendar.tsx +123 -2
  390. package/src/SearchField.tsx +80 -4
  391. package/src/Select.tsx +122 -26
  392. package/src/SelectionIndicator.tsx +3 -1
  393. package/src/SharedElementTransition.tsx +95 -37
  394. package/src/Slider.tsx +159 -13
  395. package/src/StepList.tsx +0 -7
  396. package/src/Switch.tsx +395 -2
  397. package/src/Table.tsx +428 -99
  398. package/src/Tabs.tsx +17 -45
  399. package/src/TagGroup.tsx +29 -7
  400. package/src/Text.tsx +31 -10
  401. package/src/TextField.tsx +44 -6
  402. package/src/TimeField.tsx +127 -192
  403. package/src/Toast.tsx +79 -14
  404. package/src/ToggleButton.tsx +3 -1
  405. package/src/ToggleButtonGroup.tsx +3 -1
  406. package/src/Tooltip.tsx +3 -1
  407. package/src/Tree.tsx +91 -13
  408. package/src/Virtualizer.tsx +180 -31
  409. package/src/VirtualizerLayouts.ts +45 -10
  410. package/src/index.ts +51 -8
  411. package/src/useDragAndDrop.ts +8 -10
  412. package/src/utils.tsx +246 -30
  413. package/dist/HiddenTimeInput.d.ts +0 -25
  414. package/dist/HiddenTimeInput.d.ts.map +0 -1
  415. package/dist/index.js.map +0 -1
  416. package/dist/index.jsx.map +0 -1
  417. package/src/HiddenTimeInput.tsx +0 -133
package/src/Tree.tsx CHANGED
@@ -24,6 +24,7 @@ import {
24
24
  createTree,
25
25
  createTreeItem,
26
26
  createTreeSelectionCheckbox,
27
+ createGridListSection,
27
28
  createFocusRing,
28
29
  createHover,
29
30
  mergeProps,
@@ -39,6 +40,7 @@ import {
39
40
  type Key,
40
41
  type DropTarget,
41
42
  type ItemDropTarget,
43
+ type Collection,
42
44
  } from "@proyecto-viviana/solid-stately";
43
45
  import {
44
46
  type RenderChildren,
@@ -60,14 +62,17 @@ import {
60
62
  CollectionRendererContext,
61
63
  flattenCollectionEntries,
62
64
  isCollectionSection,
63
- Section,
64
- Header,
65
65
  type CollectionEntry,
66
66
  type CollectionRendererContextValue,
67
67
  type SectionProps,
68
- type HeaderProps,
69
68
  useCollectionRenderer,
70
69
  } from "./Collection";
70
+ import {
71
+ GridListHeader,
72
+ GridListHeaderContext,
73
+ GridListHeaderInnerContext,
74
+ type GridListHeaderProps,
75
+ } from "./GridList";
71
76
  import { useVirtualizerContext } from "./Virtualizer";
72
77
  import {
73
78
  handleLinkClick,
@@ -242,7 +247,7 @@ export interface TreeLoadMoreItemProps extends SlotProps {
242
247
  }
243
248
 
244
249
  export interface TreeSectionProps extends SectionProps {}
245
- export interface TreeHeaderProps extends HeaderProps {}
250
+ export interface TreeHeaderProps extends GridListHeaderProps {}
246
251
 
247
252
  interface TreeContextValue<T extends object> {
248
253
  state: TreeState<T, TreeCollection<T>>;
@@ -882,7 +887,13 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
882
887
  // Resolve writing direction for keyboard expand/collapse parity
883
888
  const treeDirection = createMemo(() => ariaProps.direction ?? resolveTreeDirection(ref()));
884
889
 
885
- const { treeProps } = createTree<T, TreeCollection<T>>(
890
+ // Keep the aria object (do NOT destructure `treeProps`): its `treeProps` getter
891
+ // wraps a memo carrying the reactive roving-container `tabIndex`, which rolls to
892
+ // -1 once a row takes focus. Destructuring here would read the getter once and
893
+ // freeze it at its first value (tabIndex 0), so the roll would never reach the
894
+ // DOM. Read `treeAria.treeProps` inside `cleanTreeProps` instead, so the spread's
895
+ // reactive re-run re-enters the memo and tracks `focusedKey`. (Mirrors GridList.)
896
+ const treeAria = createTree<T, TreeCollection<T>>(
886
897
  () => ({
887
898
  id: ariaProps.id,
888
899
  "aria-label": ariaProps["aria-label"],
@@ -891,6 +902,7 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
891
902
  isVirtualized: ariaProps.isVirtualized,
892
903
  onAction: ariaProps.onAction,
893
904
  isDisabled: ariaProps.isDisabled,
905
+ keyboardNavigationBehavior: ariaProps.keyboardNavigationBehavior,
894
906
  direction: treeDirection(),
895
907
  }),
896
908
  () => state,
@@ -921,7 +933,7 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
921
933
  });
922
934
 
923
935
  const cleanTreeProps = () => {
924
- const { ref: _ref1, ...rest } = treeProps as Record<string, unknown>;
936
+ const { ref: _ref1, ...rest } = treeAria.treeProps as Record<string, unknown>;
925
937
  return rest;
926
938
  };
927
939
  const cleanFocusProps = () => {
@@ -1049,8 +1061,11 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
1049
1061
  getKeyPageBelow: (key) => state.collection.getKeyAfter(key),
1050
1062
  getKeyPageAbove: (key) => state.collection.getKeyBefore(key),
1051
1063
  },
1064
+ // TreeCollection carries a wider node.type union than the narrow
1065
+ // Collection option but is structurally a valid Collection for
1066
+ // navigate()/focus restoration — cast at the seam.
1052
1067
  get collection() {
1053
- return state.collection;
1068
+ return state.collection as unknown as Collection;
1054
1069
  },
1055
1070
  get selectedKeys() {
1056
1071
  return state.selectedKeys;
@@ -1565,7 +1580,9 @@ export function TreeItem<T extends object>(props: TreeItemProps<T>): JSX.Element
1565
1580
 
1566
1581
  const renderProps = useRenderProps(
1567
1582
  {
1568
- children: props.children,
1583
+ get children() {
1584
+ return props.children;
1585
+ },
1569
1586
  class: local.class,
1570
1587
  style: local.style,
1571
1588
  defaultClassName: "solidaria-Tree-item",
@@ -1762,7 +1779,7 @@ export function TreeSelectionCheckbox(props: {
1762
1779
  {...treeSelectionCheckboxAria.checkboxProps}
1763
1780
  class={props.class ?? "solidaria-Tree-checkbox"}
1764
1781
  style={props.style}
1765
- tabIndex={props.excludeFromTabOrder ? -1 : undefined}
1782
+ tabIndex={props.excludeFromTabOrder ? -1 : 0}
1766
1783
  aria-label={props["aria-label"] ?? treeSelectionCheckboxAria.checkboxProps["aria-label"]}
1767
1784
  />
1768
1785
  );
@@ -1805,7 +1822,9 @@ export function TreeLoadMoreItem(props: TreeLoadMoreItemProps): JSX.Element {
1805
1822
 
1806
1823
  const renderProps = useRenderProps(
1807
1824
  {
1808
- children: props.children ?? (() => (isLoading() ? "Loading more..." : "Load more")),
1825
+ get children() {
1826
+ return props.children ?? (() => (isLoading() ? "Loading more..." : "Load more"));
1827
+ },
1809
1828
  class: props.class,
1810
1829
  style: props.style,
1811
1830
  defaultClassName: "solidaria-Tree-loadMore",
@@ -1858,7 +1877,9 @@ export function TreeItemContent(props: TreeItemContentProps): JSX.Element {
1858
1877
 
1859
1878
  const renderProps = useRenderProps(
1860
1879
  {
1861
- children: props.children,
1880
+ get children() {
1881
+ return props.children;
1882
+ },
1862
1883
  },
1863
1884
  () => context,
1864
1885
  );
@@ -1866,12 +1887,69 @@ export function TreeItemContent(props: TreeItemContentProps): JSX.Element {
1866
1887
  return <>{renderProps.renderChildren()}</>;
1867
1888
  }
1868
1889
 
1890
+ /**
1891
+ * A section within a Tree. Renders as `role="rowgroup"` and supplies its
1892
+ * optional {@link TreeHeader} with the row/rowheader props that wire up the
1893
+ * section's `aria-labelledby` (mirrors upstream `TreeSection`, which reuses
1894
+ * `useGridListSection`).
1895
+ */
1869
1896
  export function TreeSection(props: TreeSectionProps): JSX.Element {
1870
- return <Section {...props} />;
1897
+ const [local, domProps] = splitProps(props, ["children", "class", "style", "slot", "ref"]);
1898
+
1899
+ const section = createGridListSection({
1900
+ get "aria-label"() {
1901
+ return (domProps as { "aria-label"?: string })["aria-label"];
1902
+ },
1903
+ });
1904
+
1905
+ // Mirror upstream: resolve class/style via renderProps but keep children out
1906
+ // of it. The real children must only be evaluated inside the header providers
1907
+ // below, otherwise a child <TreeHeader> would be instantiated in this
1908
+ // component's owner and read the header contexts as null. The values callback
1909
+ // runs during setup, so it must not read `local.children` either; mirror
1910
+ // upstream's `values: undefined` with a constant.
1911
+ const renderProps = useRenderProps(
1912
+ {
1913
+ children: undefined,
1914
+ class: local.class,
1915
+ style: local.style,
1916
+ defaultClassName: "solidaria-TreeSection",
1917
+ },
1918
+ () => ({ hasChildren: true }),
1919
+ );
1920
+
1921
+ const filteredDomProps = createMemo(() => filterDOMProps(domProps, { global: true }));
1922
+
1923
+ return (
1924
+ <div
1925
+ ref={(el) => assignRef(local.ref, el)}
1926
+ {...filteredDomProps()}
1927
+ {...section.rowGroupProps}
1928
+ class={renderProps.class()}
1929
+ style={renderProps.style()}
1930
+ slot={local.slot}
1931
+ data-section
1932
+ >
1933
+ <GridListHeaderContext.Provider value={section.rowProps}>
1934
+ <GridListHeaderInnerContext.Provider value={section.rowHeaderProps}>
1935
+ {local.children}
1936
+ </GridListHeaderInnerContext.Provider>
1937
+ </GridListHeaderContext.Provider>
1938
+ </div>
1939
+ );
1871
1940
  }
1872
1941
 
1942
+ /**
1943
+ * The header of a {@link TreeSection}. Mirrors upstream `TreeHeader`, which is a
1944
+ * thin wrapper over `GridListHeader` with a Tree-specific class. The row and
1945
+ * rowheader semantics come from the enclosing section through context.
1946
+ */
1873
1947
  export function TreeHeader(props: TreeHeaderProps): JSX.Element {
1874
- return <Header {...props} />;
1948
+ return (
1949
+ <GridListHeader class="solidaria-TreeHeader" {...props}>
1950
+ {props.children}
1951
+ </GridListHeader>
1952
+ );
1875
1953
  }
1876
1954
 
1877
1955
  Tree.Item = TreeItem;
@@ -32,6 +32,7 @@ import {
32
32
  type DefaultVirtualizerLayoutOptions,
33
33
  type GridLayoutOptions,
34
34
  type LayoutInfo,
35
+ type Orientation,
35
36
  type Point,
36
37
  type Rect,
37
38
  type Size,
@@ -70,6 +71,13 @@ export interface VirtualizerContextValue<O = unknown> {
70
71
  layout: VirtualizerLayout<O>;
71
72
  layoutOptions?: O;
72
73
  isVirtualized: boolean;
74
+ /**
75
+ * The resolved primary orientation of the layout. Consumers render their
76
+ * windowing spacers along this axis (`width` when `horizontal`, `height`
77
+ * when `vertical`) so the spacer size matches the offsets `getVisibleRange`
78
+ * produced.
79
+ */
80
+ orientation: Orientation;
73
81
  getVisibleRange: (itemCount: number) => VirtualizerVisibleRange;
74
82
  getLayoutInfo: (index: number) => LayoutInfo;
75
83
  getDropTargetFromPoint: (point: Point, itemCount: number) => VirtualizerDropTarget | null;
@@ -117,6 +125,13 @@ export interface VirtualizerProps<O> extends Omit<
117
125
  ) => JSX.Element | undefined;
118
126
  /** Optional operation resolver for collection drop target operations. */
119
127
  getDropOperation?: VirtualizerDropOperationResolver;
128
+ /**
129
+ * Whether the collection may scroll with the page rather than only within its
130
+ * own scroll container. When enabled (the default, matching react-aria-components),
131
+ * the visible rect is the intersection of the window viewport with the scroll view,
132
+ * so a virtualizer with unbounded height still virtualizes as the page scrolls.
133
+ */
134
+ allowsWindowScrolling?: boolean;
120
135
  class?: string;
121
136
  style?: string | JSX.CSSProperties;
122
137
  }
@@ -159,12 +174,29 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
159
174
  "layoutOptions",
160
175
  "renderDropIndicator",
161
176
  "getDropOperation",
177
+ "allowsWindowScrolling",
162
178
  "class",
163
179
  "style",
164
180
  ]);
181
+ // The scroll view's own scroll position (its scrollTop).
165
182
  const [scrollOffset, setScrollOffset] = createSignal(0);
183
+ // The scroll view's horizontal scroll position (its scrollLeft), used as the
184
+ // primary scroll axis when the layout's orientation is horizontal.
185
+ const [scrollOffsetX, setScrollOffsetX] = createSignal(0);
186
+ // How far the scroll view's top edge is above the window viewport, due to the
187
+ // page (or an ancestor) being scrolled. Mirrors upstream ScrollView.viewportOffset.
188
+ const [viewportOffset, setViewportOffset] = createSignal(0);
189
+ // The window viewport height, used as the visible height cap when window scrolling.
190
+ const [windowViewportSize, setWindowViewportSize] = createSignal(0);
191
+ // The scroll view's own measured size (clientHeight/clientWidth).
166
192
  const [measuredViewportSize, setMeasuredViewportSize] = createSignal(0);
167
193
  const [measuredViewportWidth, setMeasuredViewportWidth] = createSignal(0);
194
+ const allowsWindowScrolling = createMemo(() => local.allowsWindowScrolling ?? true);
195
+ // Whether the scroll view is actively scrolling. Mirrors upstream ScrollView's
196
+ // `isScrolling`: while scrolling, the content gets `pointer-events: none` so pointer
197
+ // events don't hit rows recycling under a stationary cursor (avoiding hover-state
198
+ // flicker and needless hit-testing). It flips back 300ms after the last scroll.
199
+ const [isScrolling, setIsScrolling] = createSignal(false);
168
200
  const [dropTargetResolver, setDropTargetResolver] = createSignal<
169
201
  VirtualizerDropTargetResolver | undefined
170
202
  >(undefined);
@@ -218,15 +250,44 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
218
250
  });
219
251
  const itemSize = createMemo(() => getObjectValue(virtualOptions(), "itemSize") ?? 40);
220
252
  const overscan = createMemo(() => getObjectValue(virtualOptions(), "overscan") ?? 2);
221
- const viewportSize = createMemo(
222
- () => getObjectValue(virtualOptions(), "viewportSize") ?? measuredViewportSize() ?? 0,
253
+ const orientation = createMemo<Orientation>(
254
+ () => getObjectValue(virtualOptions(), "orientation") ?? "vertical",
223
255
  );
256
+ // The effective visible height. When window scrolling, this is the scroll view's
257
+ // size intersected with the window viewport (capped to what is actually on screen),
258
+ // mirroring upstream ScrollView.updateVisibleRect. Otherwise it is the scroll view's
259
+ // own clientHeight. An explicit `viewportSize` layout option still takes precedence.
260
+ const viewportSize = createMemo(() => {
261
+ const explicit = getObjectValue(virtualOptions(), "viewportSize");
262
+ if (explicit != null) return explicit;
263
+ const elementSize = measuredViewportSize() ?? 0;
264
+ if (allowsWindowScrolling()) {
265
+ return Math.max(0, Math.min(elementSize - viewportOffset(), windowViewportSize()));
266
+ }
267
+ return elementSize;
268
+ });
269
+ // The top of the visible rect in content coordinates: the scroll view's own scroll
270
+ // position plus how far it has been pushed above the window viewport by page scroll.
271
+ const effectiveScrollOffset = createMemo(() =>
272
+ allowsWindowScrolling() ? scrollOffset() + viewportOffset() : scrollOffset(),
273
+ );
274
+ // The primary-axis scroll offset and viewport size, selected by orientation.
275
+ // A horizontal layout scrolls along x (scrollLeft / client width); the vertical
276
+ // default scrolls along y (with the window-scrolling adjustments above).
277
+ const mainScrollOffset = createMemo(() =>
278
+ orientation() === "horizontal" ? scrollOffsetX() : effectiveScrollOffset(),
279
+ );
280
+ const mainViewportSize = createMemo(() => {
281
+ if (orientation() !== "horizontal") return viewportSize();
282
+ const explicit = getObjectValue(virtualOptions(), "viewportSize");
283
+ return explicit != null ? explicit : measuredViewportWidth();
284
+ });
224
285
 
225
286
  const getVisibleRange = (itemCount: number): VirtualizerVisibleRange => {
226
287
  const ctx: VirtualizerRangeContext = {
227
288
  itemCount,
228
- scrollOffset: scrollOffset(),
229
- viewportSize: viewportSize(),
289
+ scrollOffset: mainScrollOffset(),
290
+ viewportSize: mainViewportSize(),
230
291
  overscan: overscan(),
231
292
  viewportWidth: measuredViewportWidth(),
232
293
  };
@@ -250,18 +311,32 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
250
311
  const getLayoutInfo = (index: number): LayoutInfo => {
251
312
  const ctx: VirtualizerLayoutInfoContext = {
252
313
  viewportWidth: measuredViewportWidth(),
314
+ viewportHeight: measuredViewportSize(),
253
315
  };
254
316
  const layoutResult = resolvedLayout().getLayoutInfo?.(index, ctx, layoutOptionsWithViewport());
255
- const nextInfo = layoutResult ?? {
256
- key: String(index),
257
- index,
258
- rect: {
259
- x: 0,
260
- y: index * itemSize(),
261
- width: Math.max(0, measuredViewportWidth()),
262
- height: itemSize(),
263
- },
264
- };
317
+ const nextInfo =
318
+ layoutResult ??
319
+ (orientation() === "horizontal"
320
+ ? {
321
+ key: String(index),
322
+ index,
323
+ rect: {
324
+ x: index * itemSize(),
325
+ y: 0,
326
+ width: itemSize(),
327
+ height: Math.max(0, measuredViewportSize()),
328
+ },
329
+ }
330
+ : {
331
+ key: String(index),
332
+ index,
333
+ rect: {
334
+ x: 0,
335
+ y: index * itemSize(),
336
+ width: Math.max(0, measuredViewportWidth()),
337
+ height: itemSize(),
338
+ },
339
+ });
265
340
  const cachedInfo = layoutInfoCache.get(index);
266
341
  if (cachedInfo && isSameLayoutInfo(cachedInfo, nextInfo)) {
267
342
  return cachedInfo;
@@ -566,7 +641,7 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
566
641
  : direction === "next"
567
642
  ? -1
568
643
  : itemCount;
569
- const pageSize = Math.max(1, Math.floor(viewportSize() / Math.max(1, itemSize())));
644
+ const pageSize = Math.max(1, Math.floor(mainViewportSize() / Math.max(1, itemSize())));
570
645
  const delta = direction === "next" ? 1 : -1;
571
646
  const nextStart = currentIndex + delta * pageSize;
572
647
  const clampedStart = Math.max(0, Math.min(itemCount - 1, nextStart));
@@ -633,6 +708,7 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
633
708
  layout: resolvedLayout(),
634
709
  layoutOptions: resolvedLayoutOptions(),
635
710
  isVirtualized: true,
711
+ orientation: orientation(),
636
712
  getVisibleRange,
637
713
  getLayoutInfo,
638
714
  getDropTargetFromPoint,
@@ -666,26 +742,96 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
666
742
  if (nextWidth !== measuredViewportWidth()) setMeasuredViewportWidth(nextWidth);
667
743
  };
668
744
 
745
+ const updateWindowViewport = () => {
746
+ if (typeof window === "undefined") return;
747
+ const next = window.innerHeight;
748
+ if (next !== windowViewportSize()) setWindowViewportSize(next);
749
+ };
750
+
751
+ // Recompute how far the scroll view's top edge sits above the window viewport.
752
+ // A negative bounding-rect top means the scroll view has been pushed up by page
753
+ // (or ancestor) scrolling; the offset is the amount scrolled past its top.
754
+ const updateViewportOffset = () => {
755
+ if (!containerRef || !allowsWindowScrolling()) return;
756
+ const rect = containerRef.getBoundingClientRect();
757
+ const next = rect.y < 0 ? -rect.y : 0;
758
+ if (next !== viewportOffset()) setViewportOffset(next);
759
+ };
760
+
761
+ let scrollFrame: number | undefined;
762
+ // Debounce handle that resets `isScrolling` after scrolling stops.
763
+ let scrollEndTimeout: ReturnType<typeof setTimeout> | undefined;
764
+ onCleanup(() => {
765
+ if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
766
+ if (scrollEndTimeout != null) clearTimeout(scrollEndTimeout);
767
+ });
768
+
669
769
  onMount(() => {
670
770
  updateViewportSize();
671
- const handleResize = () => updateViewportSize();
771
+ updateWindowViewport();
772
+ updateViewportOffset();
773
+
774
+ const handleResize = () => {
775
+ updateViewportSize();
776
+ updateWindowViewport();
777
+ updateViewportOffset();
778
+ };
672
779
  window.addEventListener("resize", handleResize);
780
+
673
781
  const resizeObserver =
674
782
  typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => updateViewportSize()) : null;
675
783
  if (containerRef && resizeObserver) {
676
784
  resizeObserver.observe(containerRef);
677
785
  }
786
+
787
+ // A capturing listener on the document sees scroll events on the scroll view
788
+ // itself as well as on any ancestor (including the page), so a single handler
789
+ // can update the local scroll position or the window offset as appropriate.
790
+ const handleDocumentScroll = (e: Event) => {
791
+ if (!containerRef) return;
792
+ const target = e.target as Node | null;
793
+ const isContainer = target === containerRef;
794
+ const isAncestor =
795
+ target === document ||
796
+ target === (window as unknown as Node) ||
797
+ (target instanceof Node && target.contains(containerRef));
798
+ if (!isContainer && !isAncestor) return;
799
+ // An ancestor/page scroll only matters when the collection scrolls with the page.
800
+ if (!isContainer && !allowsWindowScrolling()) return;
801
+
802
+ // Flag active scrolling and (re)arm the reset for 300ms after the last scroll.
803
+ // Our handler is already rAF-throttled, so a plain clear/reset debounce matches
804
+ // upstream's scrollEndTime bookkeeping without the extra accounting.
805
+ if (!isScrolling()) setIsScrolling(true);
806
+ if (scrollEndTimeout != null) clearTimeout(scrollEndTimeout);
807
+ scrollEndTimeout = setTimeout(() => {
808
+ scrollEndTimeout = undefined;
809
+ setIsScrolling(false);
810
+ }, 300);
811
+
812
+ if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
813
+ scrollFrame = requestAnimationFrame(() => {
814
+ scrollFrame = undefined;
815
+ if (isContainer) {
816
+ const next = Math.max(0, containerRef!.scrollTop);
817
+ if (next !== scrollOffset()) setScrollOffset(next);
818
+ const nextX = Math.max(0, containerRef!.scrollLeft);
819
+ if (nextX !== scrollOffsetX()) setScrollOffsetX(nextX);
820
+ } else {
821
+ updateViewportOffset();
822
+ }
823
+ updateViewportSize();
824
+ });
825
+ };
826
+ document.addEventListener("scroll", handleDocumentScroll, true);
827
+
678
828
  onCleanup(() => {
679
829
  window.removeEventListener("resize", handleResize);
680
830
  resizeObserver?.disconnect();
831
+ document.removeEventListener("scroll", handleDocumentScroll, true);
681
832
  });
682
833
  });
683
834
 
684
- let scrollFrame: number | undefined;
685
- onCleanup(() => {
686
- if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
687
- });
688
-
689
835
  return (
690
836
  <CollectionRendererContext.Provider value={collectionRenderer()}>
691
837
  <VirtualizerContext.Provider value={contextValue()}>
@@ -697,17 +843,19 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
697
843
  class={local.class}
698
844
  style={local.style}
699
845
  data-virtualizer
700
- onScroll={(e) => {
701
- const target = e.currentTarget as HTMLDivElement;
702
- if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
703
- scrollFrame = requestAnimationFrame(() => {
704
- scrollFrame = undefined;
705
- if (target.scrollTop !== scrollOffset()) setScrollOffset(target.scrollTop);
706
- updateViewportSize();
707
- });
708
- }}
709
846
  >
710
- {local.children}
847
+ {/*
848
+ Content wrapper mirroring upstream ScrollView's inner content div. It
849
+ carries the `pointer-events: none` while-scrolling optimization and is
850
+ otherwise a layout-transparent passthrough (the outer div remains the
851
+ scroll container we measure and read scroll offsets from).
852
+ */}
853
+ <div
854
+ data-virtualizer-content
855
+ style={{ "pointer-events": isScrolling() ? "none" : undefined }}
856
+ >
857
+ {local.children}
858
+ </div>
711
859
  </div>
712
860
  </VirtualizerContext.Provider>
713
861
  </CollectionRendererContext.Provider>
@@ -724,6 +872,7 @@ export type {
724
872
  WaterfallLayoutOptions,
725
873
  VirtualizerDropTarget,
726
874
  LayoutInfo,
875
+ Orientation,
727
876
  Rect,
728
877
  Size,
729
878
  Point,
@@ -21,6 +21,13 @@ export interface Size {
21
21
  height: number;
22
22
  }
23
23
 
24
+ /**
25
+ * The primary orientation of a linear layout — the axis items stack along, which
26
+ * is usually the direction the collection scrolls. Mirrors React Spectrum's
27
+ * `Orientation` and `ListLayout`'s `orientation` option.
28
+ */
29
+ export type Orientation = "horizontal" | "vertical";
30
+
24
31
  export interface LayoutInfo {
25
32
  key: string | number;
26
33
  index: number;
@@ -46,6 +53,13 @@ export interface DefaultVirtualizerLayoutOptions {
46
53
  itemSize?: number;
47
54
  overscan?: number;
48
55
  viewportSize?: number;
56
+ /**
57
+ * The primary orientation of the items. Items offset along `x`/`width` when
58
+ * `horizontal`, and along `y`/`height` when `vertical`.
59
+ *
60
+ * @default 'vertical'
61
+ */
62
+ orientation?: Orientation;
49
63
  }
50
64
 
51
65
  export interface GridLayoutOptions extends DefaultVirtualizerLayoutOptions {
@@ -62,6 +76,11 @@ export interface WaterfallLayoutOptions extends GridLayoutOptions {
62
76
 
63
77
  export interface VirtualizerLayoutInfoContext {
64
78
  viewportWidth: number;
79
+ /**
80
+ * The viewport height, used as the cross-axis size for a `horizontal` layout
81
+ * (the analogue of `viewportWidth` for the `vertical` default).
82
+ */
83
+ viewportHeight?: number;
65
84
  }
66
85
 
67
86
  export interface VirtualizerDropTarget {
@@ -124,15 +143,29 @@ export class ListLayout {
124
143
  context: VirtualizerLayoutInfoContext,
125
144
  options?: DefaultVirtualizerLayoutOptions,
126
145
  ): LayoutInfo {
127
- const itemHeight = Math.max(1, options?.itemSize ?? 40);
146
+ const itemSize = Math.max(1, options?.itemSize ?? 40);
147
+ if ((options?.orientation ?? "vertical") === "horizontal") {
148
+ // Items stack along the x axis; the cross axis (height) fills the viewport.
149
+ return {
150
+ key: String(index),
151
+ index,
152
+ rect: {
153
+ x: index * itemSize,
154
+ y: 0,
155
+ width: itemSize,
156
+ height: Math.max(0, context.viewportHeight ?? 0),
157
+ },
158
+ };
159
+ }
160
+ // Items stack along the y axis; the cross axis (width) fills the viewport.
128
161
  return {
129
162
  key: String(index),
130
163
  index,
131
164
  rect: {
132
165
  x: 0,
133
- y: index * itemHeight,
166
+ y: index * itemSize,
134
167
  width: Math.max(0, context.viewportWidth),
135
- height: itemHeight,
168
+ height: itemSize,
136
169
  },
137
170
  };
138
171
  }
@@ -143,18 +176,20 @@ export class ListLayout {
143
176
  options?: DefaultVirtualizerLayoutOptions,
144
177
  ): VirtualizerDropTarget | null {
145
178
  if (itemCount <= 0) return { type: "root", index: -1, position: "on" };
146
- const itemHeight = Math.max(1, options?.itemSize ?? 40);
147
- if (point.y < 0) {
179
+ const itemSize = Math.max(1, options?.itemSize ?? 40);
180
+ // Measure the drop point along the primary (scroll) axis.
181
+ const offset = (options?.orientation ?? "vertical") === "horizontal" ? point.x : point.y;
182
+ if (offset < 0) {
148
183
  return { type: "item", index: 0, position: "before" };
149
184
  }
150
- const totalHeight = itemCount * itemHeight;
151
- if (point.y >= totalHeight) {
185
+ const totalSize = itemCount * itemSize;
186
+ if (offset >= totalSize) {
152
187
  return { type: "item", index: itemCount - 1, position: "after" };
153
188
  }
154
- const rawIndex = Math.floor(point.y / itemHeight);
189
+ const rawIndex = Math.floor(offset / itemSize);
155
190
  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;
191
+ const offsetWithinItem = Math.max(0, offset - index * itemSize);
192
+ const threshold = itemSize / 3;
158
193
  const position: VirtualizerDropTarget["position"] =
159
194
  offsetWithinItem < threshold ? "before" : offsetWithinItem > threshold * 2 ? "after" : "on";
160
195
  return { type: "item", index, position };