@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/ListBox.tsx CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  createEffect,
12
12
  createMemo,
13
13
  createSignal,
14
+ on,
14
15
  onCleanup,
15
16
  splitProps,
16
17
  useContext,
@@ -21,16 +22,30 @@ import {
21
22
  createListBox,
22
23
  createOption,
23
24
  createFocusRing,
25
+ createScrollIntoViewOnFocus,
26
+ createStringFormatter,
27
+ createDragSession,
28
+ getGlobalDraggingCollectionRef,
29
+ getGlobalDraggingKeys,
30
+ registerDropItem,
31
+ dndIntlStrings,
24
32
  mergeProps,
33
+ moveVirtualFocus,
34
+ useLocale,
35
+ FOCUS_EVENT,
36
+ CLEAR_FOCUS_EVENT,
25
37
  type AriaListBoxProps,
26
38
  type AriaOptionProps,
27
39
  } from "@proyecto-viviana/solidaria";
28
40
  import {
29
41
  createListState,
42
+ createFilteredListState,
30
43
  type ListState,
44
+ type ListFilterFn,
31
45
  type Key,
32
46
  type DropTarget,
33
47
  } from "@proyecto-viviana/solid-stately";
48
+ import { useAutocompleteCollection } from "./Autocomplete";
34
49
  import {
35
50
  type RenderChildren,
36
51
  type ClassNameOrFunction,
@@ -51,7 +66,10 @@ import {
51
66
  mergePersistedKeysIntoVirtualRange,
52
67
  useDndPersistedKeys,
53
68
  useRenderDropIndicator,
69
+ DropIndicatorContext,
70
+ type DropIndicatorProps,
54
71
  } from "./DragAndDrop";
72
+ import type { ItemDropTarget } from "@proyecto-viviana/solid-stately";
55
73
  import {
56
74
  CollectionRendererContext,
57
75
  Section,
@@ -122,7 +140,7 @@ export interface ListBoxProps<T> extends Omit<AriaListBoxProps, "children">, Slo
122
140
  /** Called when the load more sentinel becomes visible. */
123
141
  onLoadMore?: () => void | Promise<void>;
124
142
  /** Ref for the listbox element. */
125
- ref?: RefLike<HTMLUListElement>;
143
+ ref?: RefLike<HTMLDivElement>;
126
144
  /** Drag and drop hooks from `useDragAndDrop`. */
127
145
  dragAndDropHooks?: DragAndDropHooks<T>;
128
146
  /** Layout hint for styling parity. */
@@ -163,7 +181,7 @@ export interface ListBoxOptionProps<T>
163
181
  /** The text value of the option (for typeahead). */
164
182
  textValue?: string;
165
183
  /** Ref for the option element. */
166
- ref?: RefLike<HTMLLIElement>;
184
+ ref?: RefLike<HTMLDivElement>;
167
185
  }
168
186
 
169
187
  export interface ListBoxLoadMoreItemProps extends SlotProps {
@@ -243,7 +261,7 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
243
261
 
244
262
  const hasSections = createMemo(() => stateProps.items.some((item) => isCollectionSection(item)));
245
263
 
246
- const state = createListState<T>({
264
+ const baseState = createListState<T>({
247
265
  get items() {
248
266
  return flatItems();
249
267
  },
@@ -279,6 +297,21 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
279
297
  },
280
298
  });
281
299
 
300
+ // When this ListBox is the collection of an Autocomplete, the input and the
301
+ // collection are separate components bridged by context. The collection's
302
+ // state is filtered by the input's predicate (mirrors RAC's
303
+ // UNSTABLE_useFilteredListState), and virtual focus is driven across the
304
+ // component boundary by synthetic DOM events (see the bridge effects below).
305
+ // ComboBox/Picker never provide this context, so their createListBox path is
306
+ // untouched.
307
+ const autocompleteCtx = useAutocompleteCollection();
308
+ const state = autocompleteCtx
309
+ ? createFilteredListState<T>(
310
+ baseState,
311
+ () => autocompleteCtx.filter as ListFilterFn<T> | undefined,
312
+ )
313
+ : baseState;
314
+
282
315
  const resolveDisabled = (): boolean => {
283
316
  const disabled = ariaProps.isDisabled;
284
317
  if (typeof disabled === "function") {
@@ -287,14 +320,46 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
287
320
  return !!disabled;
288
321
  };
289
322
 
323
+ const locale = useLocale();
324
+ // A parent Virtualizer publishes `isVirtualized` through the collection
325
+ // renderer context; the base ListBox forwards it into createListBox so each
326
+ // option emits aria-posinset/aria-setsize for the windowed (incomplete) DOM.
327
+ const parentCollectionRenderer = useCollectionRenderer<unknown>();
290
328
  const listBoxAria = createListBox(
291
329
  {
292
330
  ...ariaProps,
331
+ get isVirtualized() {
332
+ return parentCollectionRenderer?.isVirtualized ?? ariaProps.isVirtualized;
333
+ },
334
+ // Under Autocomplete, the input owns the collection's id (its
335
+ // aria-controls target), accessible name, and virtual-focus/type-ahead
336
+ // config; prefer the bridged values over any locally-passed props.
337
+ get id() {
338
+ return autocompleteCtx?.collectionProps.id ?? (ariaProps as { id?: string }).id;
339
+ },
340
+ get "aria-label"() {
341
+ return autocompleteCtx?.collectionProps["aria-label"] ?? ariaProps["aria-label"];
342
+ },
343
+ get shouldUseVirtualFocus() {
344
+ return (
345
+ autocompleteCtx?.collectionProps.shouldUseVirtualFocus ?? ariaProps.shouldUseVirtualFocus
346
+ );
347
+ },
348
+ get disallowTypeAhead() {
349
+ return autocompleteCtx?.collectionProps.disallowTypeAhead ?? ariaProps.disallowTypeAhead;
350
+ },
293
351
  get isDisabled() {
294
352
  return resolveDisabled();
295
353
  },
354
+ get orientation() {
355
+ return stateProps.orientation ?? "vertical";
356
+ },
357
+ get direction() {
358
+ return locale().direction;
359
+ },
296
360
  },
297
361
  state,
362
+ () => listRef(),
298
363
  );
299
364
 
300
365
  const { isFocused, isFocusVisible, focusProps } = createFocusRing();
@@ -334,8 +399,90 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
334
399
  };
335
400
  const [listRef, setListRef] = createSignal<HTMLElement | null>(null);
336
401
 
402
+ // Reveal the activedescendant-focused option on keyboard navigation. The
403
+ // listbox keeps real DOM focus on itself, so the browser won't natively scroll
404
+ // an off-screen focused option into view the way roving tabindex would.
405
+ createScrollIntoViewOnFocus({
406
+ focusedKey: () => state.focusedKey(),
407
+ isActive: () => state.isFocused(),
408
+ ref: () => listRef(),
409
+ });
410
+
411
+ // Autocomplete bridge. createListBox reimplements navigation inline (it does
412
+ // not route through createSelectableCollection), so the virtual-focus event
413
+ // wiring the Autocomplete input relies on lives here, gated on the bridge
414
+ // context. This mirrors createSelectableCollection's FOCUS_EVENT/CLEAR_FOCUS_EVENT
415
+ // handlers and useSelectableItem's per-item moveVirtualFocus, at the component
416
+ // layer, without touching the shared hooks (protecting ComboBox/Picker).
417
+ if (autocompleteCtx) {
418
+ // Forward path: the input dispatches FOCUS_EVENT/CLEAR_FOCUS_EVENT onto the
419
+ // collection element. FOCUS_EVENT marks the collection focused (and, when the
420
+ // user types forward, requests the first item); the actual arrow navigation
421
+ // arrives as a re-dispatched KeyboardEvent handled by createListBox's onKeyDown.
422
+ let shouldVirtualFocusFirst = false;
423
+ createEffect(() => {
424
+ const list = listRef();
425
+ if (!list) return;
426
+ const onFocusEvent = (e: Event) => {
427
+ const detail = (e as CustomEvent).detail;
428
+ e.stopPropagation();
429
+ state.setFocused(true);
430
+ if (detail?.focusStrategy === "first") {
431
+ shouldVirtualFocusFirst = true;
432
+ }
433
+ };
434
+ const onClearFocusEvent = (e: Event) => {
435
+ e.stopPropagation();
436
+ state.setFocused(false);
437
+ if ((e as CustomEvent).detail?.clearFocusKey) {
438
+ state.setFocusedKey(null);
439
+ }
440
+ };
441
+ list.addEventListener(FOCUS_EVENT, onFocusEvent);
442
+ list.addEventListener(CLEAR_FOCUS_EVENT, onClearFocusEvent);
443
+ onCleanup(() => {
444
+ list.removeEventListener(FOCUS_EVENT, onFocusEvent);
445
+ list.removeEventListener(CLEAR_FOCUS_EVENT, onClearFocusEvent);
446
+ });
447
+ });
448
+
449
+ // Focus the first item once the (filtered) collection settles after the user
450
+ // types forward. If nothing survives the filter, clear the input's active
451
+ // descendant by moving virtual focus onto the collection itself (its focusin
452
+ // reaches the input's clear branch). Mirrors useSelectableCollection.
453
+ createEffect(
454
+ on(
455
+ () => [state.collection().getFirstKey?.() ?? null, state.collection().size] as const,
456
+ ([firstKey, size]) => {
457
+ if (!shouldVirtualFocusFirst) return;
458
+ if (firstKey == null) {
459
+ const list = listRef();
460
+ if (list) moveVirtualFocus(list);
461
+ if (size > 0) shouldVirtualFocusFirst = false;
462
+ } else {
463
+ state.setFocusedKey(firstKey);
464
+ shouldVirtualFocusFirst = false;
465
+ }
466
+ },
467
+ { defer: true },
468
+ ),
469
+ );
470
+
471
+ // Reverse path: mirror the focused key onto the option's DOM element via a
472
+ // synthetic, bubbling focusin (moveVirtualFocus). The input's focusin listener
473
+ // reads target.id into its aria-activedescendant. Option ids are String(key)
474
+ // in this path (createOption). Real DOM focus stays on the input.
475
+ createEffect(() => {
476
+ const key = state.focusedKey();
477
+ const list = listRef();
478
+ if (!list || !state.isFocused()) return;
479
+ if (key == null) return;
480
+ const el = list.ownerDocument.getElementById(String(key));
481
+ if (el) moveVirtualFocus(el);
482
+ });
483
+ }
484
+
337
485
  const isEmpty = () => stateProps.items.length === 0;
338
- const parentCollectionRenderer = useCollectionRenderer<unknown>();
339
486
  const getItemNodes = createMemo(() =>
340
487
  Array.from(state.collection()).filter((node) => node.type === "item"),
341
488
  );
@@ -413,6 +560,14 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
413
560
  getKeyPageBelow: (key) => state.collection().getKeyAfter(key),
414
561
  getKeyPageAbove: (key) => state.collection().getKeyBefore(key),
415
562
  },
563
+ // The real collection drives keyboard drop-target navigation
564
+ // (`navigate()` walks getKeyAfter/getKeyBefore) and post-drop focus
565
+ // restoration. Reading it here re-registers the drop target when the
566
+ // collection changes (mirrors upstream keying its effect on the state).
567
+ collection: state.collection(),
568
+ selectedKeys: state.selectionManager.selectedKeys,
569
+ setSelectedKeys: (keys) => state.selectionManager.setSelectedKeys(keys),
570
+ setFocusedKey: (key) => state.setFocusedKey(key),
416
571
  },
417
572
  activeDropState,
418
573
  () => listRef(),
@@ -429,6 +584,165 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
429
584
  if (!target || target.type !== "item") return undefined;
430
585
  return dndRenderDropIndicator()?.(target);
431
586
  };
587
+
588
+ // ── Drop indicator (Fix B: labeled, self-focusing) ─────────────────────────
589
+ // The port of react-aria-components' ListBoxDropIndicatorWrapper +
590
+ // useDropIndicator. The droppable-collection state layer diverged to a minimal
591
+ // reactive target-holder with no collection reference, so the label (which
592
+ // needs the collection's text values) and the self-focus (which needs the live
593
+ // drag session) are computed here in the host layer, where both are available.
594
+ const dndFormatter = createStringFormatter(dndIntlStrings);
595
+ const dragSession = createDragSession();
596
+ const dropIndicatorTargetsEqual = (
597
+ a: DropTarget | null | undefined,
598
+ b: ItemDropTarget,
599
+ ): boolean =>
600
+ !!a && a.type === "item" && a.key === b.key && a.dropPosition === b.dropPosition;
601
+ // Faithful port of useDropIndicator's label logic: "Drop on X" for an on-item
602
+ // target, else "Insert between X and Y" / "Insert before X" / "Insert after X"
603
+ // resolved from the target's neighbours in the collection.
604
+ const dropIndicatorLabel = (target: ItemDropTarget): string => {
605
+ const collection = state.collection();
606
+ const getText = (key: Key | null): string => {
607
+ if (key == null) return "";
608
+ return collection.getTextValue(key) ?? collection.getItem(key)?.textValue ?? "";
609
+ };
610
+ if (target.dropPosition === "on") {
611
+ return dndFormatter().format("dropOnItem", { itemText: getText(target.key) });
612
+ }
613
+ let before: Key | null;
614
+ let after: Key | null;
615
+ if (target.dropPosition === "before") {
616
+ const prevKey = collection.getKeyBefore(target.key);
617
+ const prevNode = prevKey != null ? collection.getItem(prevKey) : null;
618
+ before = prevNode?.type === "item" ? prevNode.key : null;
619
+ } else {
620
+ before = target.key;
621
+ }
622
+ if (target.dropPosition === "after") {
623
+ const nextKey = collection.getKeyAfter(target.key);
624
+ const nextNode = nextKey != null ? collection.getItem(nextKey) : null;
625
+ after = nextNode?.type === "item" ? nextNode.key : null;
626
+ } else {
627
+ after = target.key;
628
+ }
629
+ if (before != null && after != null) {
630
+ return dndFormatter().format("insertBetween", {
631
+ beforeItemText: getText(before),
632
+ afterItemText: getText(after),
633
+ });
634
+ }
635
+ if (before != null) {
636
+ return dndFormatter().format("insertAfter", { itemText: getText(before) });
637
+ }
638
+ if (after != null) {
639
+ return dndFormatter().format("insertBefore", { itemText: getText(after) });
640
+ }
641
+ return "";
642
+ };
643
+ // Wrap the raw Set<string> the DragManager hands drop items into the DragTypes
644
+ // delegate the port state expects (mirrors createDroppableCollection.wrapTypes).
645
+ const wrapDropTypes = (types: Set<string>) => ({
646
+ has: (type: string | string[]) => {
647
+ if (typeof type === "string") return types.has(type);
648
+ if (Array.isArray(type)) return type.some((t) => typeof t === "string" && types.has(t));
649
+ return false;
650
+ },
651
+ });
652
+ const ListBoxDropIndicator = (props: { target: ItemDropTarget }): JSX.Element => {
653
+ const [indicatorRef, setIndicatorRef] = createSignal<HTMLDivElement | null>(null);
654
+ const isDropTarget = createMemo(() =>
655
+ dropIndicatorTargetsEqual(dropState()?.target, props.target),
656
+ );
657
+ // aria-hidden mirrors useDropIndicator: outside a drag session, or on a
658
+ // non-active target, the indicator is hidden from AT ('true'); the active
659
+ // target during a session is exposed (undefined). isHidden then tells us
660
+ // whether to omit the element entirely (RAC returns null when hidden).
661
+ const ariaHidden = createMemo(() =>
662
+ !dragSession() ? "true" : isDropTarget() ? undefined : "true",
663
+ );
664
+ const isHidden = createMemo(() => !isDropTarget() && !!ariaHidden());
665
+ // Faithful port of useDroppableItem. Registration (of the indicator element as
666
+ // a DragManager droppable item) and the self-focus must happen in one effect,
667
+ // registration first: the DragManager's onFocus keys off the dropItems map, so
668
+ // if the element self-focused before it was registered, onFocus would treat it
669
+ // as an unknown target and redirect focus back to the collection (a pickup
670
+ // bounce). React's two useDroppableItem effects run in guaranteed order after
671
+ // the ref is attached; Solid's independent effects race, so we fuse them. The
672
+ // dropItems map keys off live elements — the ref nulls itself on Show cleanup
673
+ // (below), so a hidden indicator unregisters instead of lingering as a stale
674
+ // detached entry.
675
+ createEffect(() => {
676
+ const el = indicatorRef();
677
+ if (!el) return;
678
+ const unregister = registerDropItem({
679
+ element: el,
680
+ target: props.target,
681
+ getDropOperation: (types, allowedOperations) => {
682
+ const st = dropState();
683
+ if (!st) return "cancel";
684
+ // Thread the same drag identity the collection uses (see
685
+ // createDroppableCollection.isInternalDropOperation): an internal
686
+ // keyboard reorder must report `isInternal` so the state's feature
687
+ // detection keeps before/after indicators valid (and rejects "on" for a
688
+ // reorder-only host). Without it every indicator would return "cancel"
689
+ // and drop out of the DragManager's ariaHideOutside keep-set.
690
+ const isInternal = getGlobalDraggingCollectionRef() === listRef();
691
+ return st.getDropOperation(
692
+ props.target,
693
+ wrapDropTypes(types) as Parameters<typeof st.getDropOperation>[1],
694
+ allowedOperations,
695
+ isInternal,
696
+ getGlobalDraggingKeys(),
697
+ );
698
+ },
699
+ });
700
+ onCleanup(unregister);
701
+ // While a drag session is active, the current drop target moves real DOM
702
+ // focus onto itself, so keyboard drop navigation lands on the labeled
703
+ // insertion point rather than the collection element. The self-focus is
704
+ // deferred to an animation frame to mirror upstream's timing: in
705
+ // useDroppableItem the focus is a *passive* useEffect, so it commits only
706
+ // after the browser's microtask checkpoint. That ordering matters because
707
+ // the DragManager keeps the active drop indicator visible via
708
+ // ariaHideOutside, whose keep-set is `[dragSource, ...registered drop
709
+ // items]` (the collection is dropped from the set once it owns items). A
710
+ // freshly-mounted indicator is momentarily `inert` — it only leaves the
711
+ // keep-set's blind spot once the DragManager's MutationObserver re-runs
712
+ // updateValidDropTargets on a later microtask. Focusing synchronously (or
713
+ // on a microtask) would call .focus() while the element is still inert and
714
+ // silently no-op; the animation frame runs after that refresh, exactly as
715
+ // React's passive effect does.
716
+ if (dragSession() && isDropTarget()) {
717
+ requestAnimationFrame(() => {
718
+ if (dragSession() && isDropTarget() && indicatorRef() === el) {
719
+ el.focus();
720
+ }
721
+ });
722
+ }
723
+ });
724
+ return (
725
+ <Show when={!isHidden()}>
726
+ <div
727
+ ref={(el) => {
728
+ setIndicatorRef(el);
729
+ onCleanup(() => setIndicatorRef(null));
730
+ }}
731
+ role="option"
732
+ class="solidaria-DropIndicator"
733
+ aria-roledescription={dndFormatter().format("dropIndicator")}
734
+ aria-label={dropIndicatorLabel(props.target)}
735
+ aria-hidden={ariaHidden()}
736
+ tabindex={-1}
737
+ data-drop-target={isDropTarget() || undefined}
738
+ />
739
+ </Show>
740
+ );
741
+ };
742
+ const dropIndicatorContextValue = {
743
+ render: (p: DropIndicatorProps) => <ListBoxDropIndicator target={p.target} />,
744
+ };
745
+
432
746
  const virtualizer = useVirtualizerContext();
433
747
  const persistedKeys = useDndPersistedKeys(
434
748
  { focusedKey: state.focusedKey },
@@ -495,6 +809,10 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
495
809
  if (!range) return stateProps.items;
496
810
  return stateProps.items.slice(range.start, range.end);
497
811
  });
812
+ // Spacers reserve the windowed-out extent along the virtualizer's primary axis,
813
+ // so a horizontal layout offsets along width rather than height.
814
+ const virtualSpacerStyle = (size: number): JSX.CSSProperties =>
815
+ virtualizer?.orientation === "horizontal" ? { width: `${size}px` } : { height: `${size}px` };
498
816
  const sectionedRenderEntries = createMemo(() => {
499
817
  let globalIndex = 0;
500
818
  return stateProps.items.map((entry) => {
@@ -542,11 +860,12 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
542
860
  >
543
861
  <ListBoxStateContext.Provider value={state}>
544
862
  <CollectionRendererContext.Provider value={collectionRenderer()}>
863
+ <DropIndicatorContext.Provider value={dropIndicatorContextValue}>
545
864
  <>
546
865
  <Show when={ariaProps.label}>
547
866
  <span {...cleanLabelProps()}>{ariaProps.label as JSX.Element}</span>
548
867
  </Show>
549
- <ul
868
+ <div
550
869
  {...mergeProps(
551
870
  domProps(),
552
871
  cleanListBoxProps(),
@@ -557,6 +876,7 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
557
876
  ref={(el) => {
558
877
  setListRef(el);
559
878
  assignRef(local.ref, el);
879
+ autocompleteCtx?.collectionRef(el);
560
880
  }}
561
881
  class={renderProps.class()}
562
882
  style={renderProps.style()}
@@ -571,14 +891,14 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
571
891
  >
572
892
  <SharedElementTransition>
573
893
  {isEmpty() && local.renderEmptyState ? (
574
- <li role="option" style={{ display: "contents" }} data-empty-state>
894
+ <div role="option" style={{ display: "contents" }} data-empty-state>
575
895
  {local.renderEmptyState()}
576
- </li>
896
+ </div>
577
897
  ) : hasSections() ? (
578
898
  <For each={sectionedRenderEntries()}>
579
899
  {(entry) =>
580
900
  entry.type === "section" ? (
581
- <li role="presentation" data-section-wrapper>
901
+ <div role="presentation" data-section-wrapper>
582
902
  <Section class="solidaria-ListBox-section">
583
903
  {entry.section.title != null && (
584
904
  <Header class="solidaria-ListBox-sectionHeader">
@@ -586,7 +906,7 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
586
906
  </Header>
587
907
  )}
588
908
  <Group class="solidaria-ListBox-sectionGroup">
589
- <ul role="group" aria-label={entry.section["aria-label"]}>
909
+ <div role="group" aria-label={entry.section["aria-label"]}>
590
910
  <For each={entry.items}>
591
911
  {(indexedItem) => (
592
912
  <>
@@ -606,10 +926,10 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
606
926
  </>
607
927
  )}
608
928
  </For>
609
- </ul>
929
+ </div>
610
930
  </Group>
611
931
  </Section>
612
- </li>
932
+ </div>
613
933
  ) : (
614
934
  <>
615
935
  {collectionRenderer().renderDropIndicator?.(entry.item.index, "before")}
@@ -623,10 +943,10 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
623
943
  ) : (
624
944
  <>
625
945
  {virtualRange()?.offsetTop ? (
626
- <li
946
+ <div
627
947
  role="presentation"
628
948
  aria-hidden="true"
629
- style={{ height: `${virtualRange()!.offsetTop}px` }}
949
+ style={virtualSpacerStyle(virtualRange()!.offsetTop)}
630
950
  data-virtualizer-spacer="top"
631
951
  />
632
952
  ) : null}
@@ -650,10 +970,10 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
650
970
  }}
651
971
  </For>
652
972
  {virtualRange()?.offsetBottom ? (
653
- <li
973
+ <div
654
974
  role="presentation"
655
975
  aria-hidden="true"
656
- style={{ height: `${virtualRange()!.offsetBottom}px` }}
976
+ style={virtualSpacerStyle(virtualRange()!.offsetBottom)}
657
977
  data-virtualizer-spacer="bottom"
658
978
  />
659
979
  ) : null}
@@ -663,8 +983,9 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
663
983
  {local.hasMore && local.onLoadMore && (
664
984
  <ListBoxLoadMoreItem onLoadMore={local.onLoadMore} isLoading={local.isLoading} />
665
985
  )}
666
- </ul>
986
+ </div>
667
987
  </>
988
+ </DropIndicatorContext.Provider>
668
989
  </CollectionRendererContext.Provider>
669
990
  </ListBoxStateContext.Provider>
670
991
  </ListBoxContext.Provider>
@@ -691,7 +1012,7 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
691
1012
  }
692
1013
  const state = context as ListState<T>;
693
1014
  const listContext = useContext(ListBoxContext) as ListBoxContextValue<T> | null;
694
- const [ref, setRef] = createSignal<HTMLLIElement | null>(null);
1015
+ const [ref, setRef] = createSignal<HTMLDivElement | null>(null);
695
1016
 
696
1017
  const optionAria = createOption<T>(
697
1018
  {
@@ -719,6 +1040,7 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
719
1040
  },
720
1041
  },
721
1042
  state,
1043
+ ref,
722
1044
  );
723
1045
 
724
1046
  const renderValues = createMemo<ListBoxOptionRenderProps>(() => ({
@@ -732,7 +1054,9 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
732
1054
 
733
1055
  const renderProps = useRenderProps(
734
1056
  {
735
- children: props.children,
1057
+ get children() {
1058
+ return props.children;
1059
+ },
736
1060
  class: local.class,
737
1061
  style: local.style,
738
1062
  defaultClassName: "solidaria-ListBox-option",
@@ -752,6 +1076,9 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
752
1076
  return listContext.dragAndDropHooks.useDraggableItem(
753
1077
  {
754
1078
  key: local.id as string | number,
1079
+ // Surfaces the drag-affordance description (aria-describedby) only for
1080
+ // selectable collections, mirroring upstream useDraggableItem.
1081
+ selectionMode: state.selectionManager.selectionMode,
755
1082
  },
756
1083
  listContext.dragState as Parameters<NonNullable<DragAndDropHooks<T>["useDraggableItem"]>>[1],
757
1084
  );
@@ -783,7 +1110,7 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
783
1110
 
784
1111
  return (
785
1112
  <SelectionIndicatorContext.Provider value={selectionIndicatorContext()}>
786
- <li
1113
+ <div
787
1114
  ref={(el) => {
788
1115
  setRef(el);
789
1116
  assignRef(local.ref, el);
@@ -811,7 +1138,7 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
811
1138
  ) : (
812
1139
  renderProps.renderChildren()
813
1140
  )}
814
- </li>
1141
+ </div>
815
1142
  </SelectionIndicatorContext.Provider>
816
1143
  );
817
1144
  }
@@ -855,7 +1182,9 @@ export function ListBoxLoadMoreItem(props: ListBoxLoadMoreItemProps): JSX.Elemen
855
1182
 
856
1183
  const renderProps = useRenderProps(
857
1184
  {
858
- children: props.children ?? (() => (isLoading() ? "Loading more..." : "Load more")),
1185
+ get children() {
1186
+ return props.children ?? (() => (isLoading() ? "Loading more..." : "Load more"));
1187
+ },
859
1188
  class: props.class,
860
1189
  style: props.style,
861
1190
  defaultClassName: "solidaria-ListBox-loadMore",
@@ -865,10 +1194,10 @@ export function ListBoxLoadMoreItem(props: ListBoxLoadMoreItemProps): JSX.Elemen
865
1194
 
866
1195
  return (
867
1196
  <>
868
- <li style={{ position: "relative", width: 0, height: 0, overflow: "hidden" }} inert>
1197
+ <div style={{ position: "relative", width: 0, height: 0, overflow: "hidden" }} inert>
869
1198
  <div ref={sentinelRef} style={{ position: "absolute", height: "1px", width: "1px" }} />
870
- </li>
871
- <li
1199
+ </div>
1200
+ <div
872
1201
  role="option"
873
1202
  aria-disabled={true}
874
1203
  tabIndex={0}
@@ -880,7 +1209,7 @@ export function ListBoxLoadMoreItem(props: ListBoxLoadMoreItemProps): JSX.Elemen
880
1209
  data-loading={isLoading() || undefined}
881
1210
  >
882
1211
  {renderProps.renderChildren()}
883
- </li>
1212
+ </div>
884
1213
  </>
885
1214
  );
886
1215
  }