@proyecto-viviana/solidaria 0.4.0 → 0.4.2

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 (480) hide show
  1. package/dist/_chunk/DragManager.js +627 -0
  2. package/dist/_chunk/DragManager.js.map +1 -0
  3. package/dist/_chunk/DragManager.jsx +627 -0
  4. package/dist/_chunk/DragManager.jsx.map +1 -0
  5. package/dist/_chunk/FocusScope.js +400 -0
  6. package/dist/_chunk/FocusScope.js.map +1 -0
  7. package/dist/_chunk/FocusScope.jsx +375 -0
  8. package/dist/_chunk/FocusScope.jsx.map +1 -0
  9. package/dist/_chunk/actiongroup.js +13 -79
  10. package/dist/_chunk/actiongroup.js.map +1 -1
  11. package/dist/_chunk/actiongroup.jsx +13 -79
  12. package/dist/_chunk/actiongroup.jsx.map +1 -1
  13. package/dist/_chunk/{live-announcer.js → announce.js} +1 -1
  14. package/dist/_chunk/announce.js.map +1 -0
  15. package/dist/_chunk/{live-announcer.jsx → announce.jsx} +1 -1
  16. package/dist/_chunk/announce.jsx.map +1 -0
  17. package/dist/_chunk/autocomplete.js +56 -8
  18. package/dist/_chunk/autocomplete.js.map +1 -1
  19. package/dist/_chunk/autocomplete.jsx +56 -8
  20. package/dist/_chunk/autocomplete.jsx.map +1 -1
  21. package/dist/_chunk/breadcrumbs.js +6 -4
  22. package/dist/_chunk/breadcrumbs.js.map +1 -1
  23. package/dist/_chunk/breadcrumbs.jsx +6 -4
  24. package/dist/_chunk/breadcrumbs.jsx.map +1 -1
  25. package/dist/_chunk/button.js +8 -9
  26. package/dist/_chunk/button.js.map +1 -1
  27. package/dist/_chunk/button.jsx +8 -9
  28. package/dist/_chunk/button.jsx.map +1 -1
  29. package/dist/_chunk/calendar.js +27 -26
  30. package/dist/_chunk/calendar.js.map +1 -1
  31. package/dist/_chunk/calendar.jsx +27 -26
  32. package/dist/_chunk/calendar.jsx.map +1 -1
  33. package/dist/_chunk/checkbox.js +5 -4
  34. package/dist/_chunk/checkbox.js.map +1 -1
  35. package/dist/_chunk/checkbox.jsx +5 -4
  36. package/dist/_chunk/checkbox.jsx.map +1 -1
  37. package/dist/_chunk/color.js +302 -18
  38. package/dist/_chunk/color.js.map +1 -1
  39. package/dist/_chunk/color.jsx +302 -18
  40. package/dist/_chunk/color.jsx.map +1 -1
  41. package/dist/_chunk/combobox.js +638 -12
  42. package/dist/_chunk/combobox.js.map +1 -1
  43. package/dist/_chunk/combobox.jsx +638 -12
  44. package/dist/_chunk/combobox.jsx.map +1 -1
  45. package/dist/_chunk/constants.js +19 -0
  46. package/dist/_chunk/constants.js.map +1 -0
  47. package/dist/_chunk/constants.jsx +19 -0
  48. package/dist/_chunk/constants.jsx.map +1 -0
  49. package/dist/_chunk/createCollator.js +3 -171
  50. package/dist/_chunk/createCollator.js.map +1 -1
  51. package/dist/_chunk/createCollator.jsx +3 -165
  52. package/dist/_chunk/createCollator.jsx.map +1 -1
  53. package/dist/_chunk/createField.js +2 -1
  54. package/dist/_chunk/createField.js.map +1 -1
  55. package/dist/_chunk/createField.jsx +2 -1
  56. package/dist/_chunk/createField.jsx.map +1 -1
  57. package/dist/_chunk/createFocus.js +12 -8
  58. package/dist/_chunk/createFocus.js.map +1 -1
  59. package/dist/_chunk/createFocus.jsx +12 -8
  60. package/dist/_chunk/createFocus.jsx.map +1 -1
  61. package/dist/_chunk/createFocusWithin.js +12 -13
  62. package/dist/_chunk/createFocusWithin.js.map +1 -1
  63. package/dist/_chunk/createFocusWithin.jsx +12 -13
  64. package/dist/_chunk/createFocusWithin.jsx.map +1 -1
  65. package/dist/_chunk/createFocusable.js +3 -3
  66. package/dist/_chunk/createFocusable.js.map +1 -1
  67. package/dist/_chunk/createFocusable.jsx +3 -3
  68. package/dist/_chunk/createFocusable.jsx.map +1 -1
  69. package/dist/_chunk/{form.js → createFormReset.js} +1 -1
  70. package/dist/_chunk/createFormReset.js.map +1 -0
  71. package/dist/_chunk/{form.jsx → createFormReset.jsx} +1 -1
  72. package/dist/_chunk/createFormReset.jsx.map +1 -0
  73. package/dist/_chunk/createHover.js +2 -1
  74. package/dist/_chunk/createHover.js.map +1 -1
  75. package/dist/_chunk/createHover.jsx +2 -1
  76. package/dist/_chunk/createHover.jsx.map +1 -1
  77. package/dist/_chunk/createInteractionModality.js +2 -3
  78. package/dist/_chunk/createInteractionModality.js.map +1 -1
  79. package/dist/_chunk/createInteractionModality.jsx +2 -3
  80. package/dist/_chunk/createInteractionModality.jsx.map +1 -1
  81. package/dist/_chunk/createLabel.js +2 -1
  82. package/dist/_chunk/createLabel.js.map +1 -1
  83. package/dist/_chunk/createLabel.jsx +2 -1
  84. package/dist/_chunk/createLabel.jsx.map +1 -1
  85. package/dist/_chunk/createLabels.js +3 -2
  86. package/dist/_chunk/createLabels.js.map +1 -1
  87. package/dist/_chunk/createLabels.jsx +3 -2
  88. package/dist/_chunk/createLabels.jsx.map +1 -1
  89. package/dist/_chunk/createLandmark.js +1 -1
  90. package/dist/_chunk/createLandmark.jsx +1 -1
  91. package/dist/_chunk/createProgressBar.js +2 -1
  92. package/dist/_chunk/createProgressBar.js.map +1 -1
  93. package/dist/_chunk/createProgressBar.jsx +2 -1
  94. package/dist/_chunk/createProgressBar.jsx.map +1 -1
  95. package/dist/_chunk/createSelectableItem.js +7 -3
  96. package/dist/_chunk/createSelectableItem.js.map +1 -1
  97. package/dist/_chunk/createSelectableItem.jsx +7 -3
  98. package/dist/_chunk/createSelectableItem.jsx.map +1 -1
  99. package/dist/_chunk/createStringFormatter.js +61 -0
  100. package/dist/_chunk/createStringFormatter.js.map +1 -0
  101. package/dist/_chunk/createStringFormatter.jsx +61 -0
  102. package/dist/_chunk/createStringFormatter.jsx.map +1 -0
  103. package/dist/_chunk/createToggle.js +5 -4
  104. package/dist/_chunk/createToggle.js.map +1 -1
  105. package/dist/_chunk/createToggle.jsx +5 -4
  106. package/dist/_chunk/createToggle.jsx.map +1 -1
  107. package/dist/_chunk/datepicker.js +1413 -1100
  108. package/dist/_chunk/datepicker.js.map +1 -1
  109. package/dist/_chunk/datepicker.jsx +1413 -1100
  110. package/dist/_chunk/datepicker.jsx.map +1 -1
  111. package/dist/_chunk/disclosure.js +2 -2
  112. package/dist/_chunk/disclosure.js.map +1 -1
  113. package/dist/_chunk/disclosure.jsx +2 -2
  114. package/dist/_chunk/disclosure.jsx.map +1 -1
  115. package/dist/_chunk/dnd.js +1586 -495
  116. package/dist/_chunk/dnd.js.map +1 -1
  117. package/dist/_chunk/dnd.jsx +1586 -495
  118. package/dist/_chunk/dnd.jsx.map +1 -1
  119. package/dist/_chunk/env.js +1 -19
  120. package/dist/_chunk/env.js.map +1 -1
  121. package/dist/_chunk/env.jsx +1 -19
  122. package/dist/_chunk/env.jsx.map +1 -1
  123. package/dist/_chunk/focus.js +1 -1
  124. package/dist/_chunk/focus.js.map +1 -1
  125. package/dist/_chunk/focus.jsx +1 -1
  126. package/dist/_chunk/focus.jsx.map +1 -1
  127. package/dist/_chunk/focus2.js +54 -318
  128. package/dist/_chunk/focus2.js.map +1 -1
  129. package/dist/_chunk/focus2.jsx +53 -292
  130. package/dist/_chunk/focus2.jsx.map +1 -1
  131. package/dist/_chunk/grid.js +1 -1
  132. package/dist/_chunk/grid.jsx +1 -1
  133. package/dist/_chunk/gridlist.js +14 -9
  134. package/dist/_chunk/gridlist.js.map +1 -1
  135. package/dist/_chunk/gridlist.jsx +14 -9
  136. package/dist/_chunk/gridlist.jsx.map +1 -1
  137. package/dist/_chunk/i18n.js +3 -58
  138. package/dist/_chunk/i18n.js.map +1 -1
  139. package/dist/_chunk/i18n.jsx +3 -58
  140. package/dist/_chunk/i18n.jsx.map +1 -1
  141. package/dist/_chunk/interactions.js +99 -9
  142. package/dist/_chunk/interactions.js.map +1 -1
  143. package/dist/_chunk/interactions.jsx +97 -9
  144. package/dist/_chunk/interactions.jsx.map +1 -1
  145. package/dist/_chunk/link.js +2 -1
  146. package/dist/_chunk/link.js.map +1 -1
  147. package/dist/_chunk/link.jsx +2 -1
  148. package/dist/_chunk/link.jsx.map +1 -1
  149. package/dist/_chunk/listbox.js +42 -10
  150. package/dist/_chunk/listbox.js.map +1 -1
  151. package/dist/_chunk/listbox.jsx +42 -10
  152. package/dist/_chunk/listbox.jsx.map +1 -1
  153. package/dist/_chunk/locale.js +173 -0
  154. package/dist/_chunk/locale.js.map +1 -0
  155. package/dist/_chunk/locale.jsx +167 -0
  156. package/dist/_chunk/locale.jsx.map +1 -0
  157. package/dist/_chunk/menu.js +5 -4
  158. package/dist/_chunk/menu.js.map +1 -1
  159. package/dist/_chunk/menu.jsx +5 -4
  160. package/dist/_chunk/menu.jsx.map +1 -1
  161. package/dist/_chunk/numberfield.js +3 -2
  162. package/dist/_chunk/numberfield.js.map +1 -1
  163. package/dist/_chunk/numberfield.jsx +3 -2
  164. package/dist/_chunk/numberfield.jsx.map +1 -1
  165. package/dist/_chunk/overlays.js +1 -1
  166. package/dist/_chunk/overlays.jsx +1 -1
  167. package/dist/_chunk/popover.js +3 -3
  168. package/dist/_chunk/popover.js.map +1 -1
  169. package/dist/_chunk/popover.jsx +3 -3
  170. package/dist/_chunk/popover.jsx.map +1 -1
  171. package/dist/_chunk/radio.js +7 -6
  172. package/dist/_chunk/radio.js.map +1 -1
  173. package/dist/_chunk/radio.jsx +7 -6
  174. package/dist/_chunk/radio.jsx.map +1 -1
  175. package/dist/_chunk/reactivity.js +21 -0
  176. package/dist/_chunk/reactivity.js.map +1 -0
  177. package/dist/_chunk/reactivity.jsx +21 -0
  178. package/dist/_chunk/reactivity.jsx.map +1 -0
  179. package/dist/_chunk/searchfield.js +2 -1
  180. package/dist/_chunk/searchfield.js.map +1 -1
  181. package/dist/_chunk/searchfield.jsx +2 -1
  182. package/dist/_chunk/searchfield.jsx.map +1 -1
  183. package/dist/_chunk/select.js +8 -5
  184. package/dist/_chunk/select.js.map +1 -1
  185. package/dist/_chunk/select.jsx +8 -5
  186. package/dist/_chunk/select.jsx.map +1 -1
  187. package/dist/_chunk/selection.js +8 -21
  188. package/dist/_chunk/selection.js.map +1 -1
  189. package/dist/_chunk/selection.jsx +8 -21
  190. package/dist/_chunk/selection.jsx.map +1 -1
  191. package/dist/_chunk/separator.js +1 -1
  192. package/dist/_chunk/separator.jsx +1 -1
  193. package/dist/_chunk/slider.js +5 -4
  194. package/dist/_chunk/slider.js.map +1 -1
  195. package/dist/_chunk/slider.jsx +5 -4
  196. package/dist/_chunk/slider.jsx.map +1 -1
  197. package/dist/_chunk/spinbutton.js +153 -0
  198. package/dist/_chunk/spinbutton.js.map +1 -0
  199. package/dist/_chunk/spinbutton.jsx +153 -0
  200. package/dist/_chunk/spinbutton.jsx.map +1 -0
  201. package/dist/_chunk/table.js +45 -8
  202. package/dist/_chunk/table.js.map +1 -1
  203. package/dist/_chunk/table.jsx +45 -8
  204. package/dist/_chunk/table.jsx.map +1 -1
  205. package/dist/_chunk/tabs.js +11 -8
  206. package/dist/_chunk/tabs.js.map +1 -1
  207. package/dist/_chunk/tabs.jsx +11 -8
  208. package/dist/_chunk/tabs.jsx.map +1 -1
  209. package/dist/_chunk/tag.js +54 -18
  210. package/dist/_chunk/tag.js.map +1 -1
  211. package/dist/_chunk/tag.jsx +54 -18
  212. package/dist/_chunk/tag.jsx.map +1 -1
  213. package/dist/_chunk/textfield.js +2 -1
  214. package/dist/_chunk/textfield.js.map +1 -1
  215. package/dist/_chunk/textfield.jsx +2 -1
  216. package/dist/_chunk/textfield.jsx.map +1 -1
  217. package/dist/_chunk/toolbar.js +4 -36
  218. package/dist/_chunk/toolbar.js.map +1 -1
  219. package/dist/_chunk/toolbar.jsx +4 -36
  220. package/dist/_chunk/toolbar.jsx.map +1 -1
  221. package/dist/_chunk/tooltip.js +2 -2
  222. package/dist/_chunk/tooltip.js.map +1 -1
  223. package/dist/_chunk/tooltip.jsx +2 -2
  224. package/dist/_chunk/tooltip.jsx.map +1 -1
  225. package/dist/_chunk/tree.js +42 -14
  226. package/dist/_chunk/tree.js.map +1 -1
  227. package/dist/_chunk/tree.jsx +42 -14
  228. package/dist/_chunk/tree.jsx.map +1 -1
  229. package/dist/_chunk/utils.js +59 -19
  230. package/dist/_chunk/utils.js.map +1 -1
  231. package/dist/_chunk/utils.jsx +59 -19
  232. package/dist/_chunk/utils.jsx.map +1 -1
  233. package/dist/_chunk/visually-hidden.js +3 -2
  234. package/dist/_chunk/visually-hidden.js.map +1 -1
  235. package/dist/_chunk/visually-hidden.jsx +3 -2
  236. package/dist/_chunk/visually-hidden.jsx.map +1 -1
  237. package/dist/actiongroup/createActionGroup.d.ts.map +1 -1
  238. package/dist/autocomplete/createAutocomplete.d.ts +10 -7
  239. package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
  240. package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
  241. package/dist/button/createToggleButtonGroup.d.ts.map +1 -1
  242. package/dist/calendar/createCalendar.d.ts.map +1 -1
  243. package/dist/calendar/createCalendarCell.d.ts.map +1 -1
  244. package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
  245. package/dist/calendar/createRangeCalendar.d.ts.map +1 -1
  246. package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
  247. package/dist/calendar/intl/index.d.ts +1 -1
  248. package/dist/calendar/intl/index.d.ts.map +1 -1
  249. package/dist/collections/index.js +1 -1
  250. package/dist/collections/index.jsx +1 -1
  251. package/dist/color/createColorArea.d.ts.map +1 -1
  252. package/dist/color/createColorField.d.ts.map +1 -1
  253. package/dist/color/createColorSlider.d.ts.map +1 -1
  254. package/dist/color/createColorSwatch.d.ts.map +1 -1
  255. package/dist/color/createColorWheel.d.ts.map +1 -1
  256. package/dist/color/intl/index.d.ts +30 -0
  257. package/dist/color/intl/index.d.ts.map +1 -0
  258. package/dist/combobox/createComboBox.d.ts.map +1 -1
  259. package/dist/combobox/intl/generated-locales.d.ts +16 -0
  260. package/dist/combobox/intl/generated-locales.d.ts.map +1 -0
  261. package/dist/combobox/intl/index.d.ts +2 -2
  262. package/dist/combobox/intl/index.d.ts.map +1 -1
  263. package/dist/datepicker/createDateField.d.ts +45 -23
  264. package/dist/datepicker/createDateField.d.ts.map +1 -1
  265. package/dist/datepicker/createDatePicker.d.ts +34 -6
  266. package/dist/datepicker/createDatePicker.d.ts.map +1 -1
  267. package/dist/datepicker/createDatePickerGroup.d.ts +13 -13
  268. package/dist/datepicker/createDatePickerGroup.d.ts.map +1 -1
  269. package/dist/datepicker/createDateRangePicker.d.ts +55 -7
  270. package/dist/datepicker/createDateRangePicker.d.ts.map +1 -1
  271. package/dist/datepicker/createDateSegment.d.ts +6 -15
  272. package/dist/datepicker/createDateSegment.d.ts.map +1 -1
  273. package/dist/datepicker/createDisplayNames.d.ts +17 -0
  274. package/dist/datepicker/createDisplayNames.d.ts.map +1 -0
  275. package/dist/datepicker/createTimeField.d.ts +12 -49
  276. package/dist/datepicker/createTimeField.d.ts.map +1 -1
  277. package/dist/datepicker/index.d.ts +3 -3
  278. package/dist/datepicker/index.d.ts.map +1 -1
  279. package/dist/datepicker/index.js +2 -2
  280. package/dist/datepicker/index.jsx +2 -2
  281. package/dist/datepicker/intl.d.ts +12 -0
  282. package/dist/datepicker/intl.d.ts.map +1 -0
  283. package/dist/dnd/DragManager.d.ts +86 -0
  284. package/dist/dnd/DragManager.d.ts.map +1 -0
  285. package/dist/dnd/DropTargetKeyboardNavigation.d.ts +42 -0
  286. package/dist/dnd/DropTargetKeyboardNavigation.d.ts.map +1 -0
  287. package/dist/dnd/createDrag.d.ts.map +1 -1
  288. package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
  289. package/dist/dnd/createDraggableItem.d.ts +12 -7
  290. package/dist/dnd/createDraggableItem.d.ts.map +1 -1
  291. package/dist/dnd/createDroppableCollection.d.ts +7 -15
  292. package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
  293. package/dist/dnd/index.d.ts +5 -1
  294. package/dist/dnd/index.d.ts.map +1 -1
  295. package/dist/dnd/index.js +3 -2
  296. package/dist/dnd/index.jsx +3 -2
  297. package/dist/dnd/intl/index.d.ts +39 -0
  298. package/dist/dnd/intl/index.d.ts.map +1 -0
  299. package/dist/dnd/utils.d.ts +5 -0
  300. package/dist/dnd/utils.d.ts.map +1 -1
  301. package/dist/focus/FocusScope.d.ts +7 -0
  302. package/dist/focus/FocusScope.d.ts.map +1 -1
  303. package/dist/focus/index.d.ts +2 -1
  304. package/dist/focus/index.d.ts.map +1 -1
  305. package/dist/focus/index.js +3 -2
  306. package/dist/focus/index.jsx +3 -2
  307. package/dist/focus/virtualFocus.d.ts +26 -0
  308. package/dist/focus/virtualFocus.d.ts.map +1 -0
  309. package/dist/form/index.js +1 -1
  310. package/dist/form/index.jsx +1 -1
  311. package/dist/gridlist/createGridList.d.ts.map +1 -1
  312. package/dist/i18n/index.js +4 -2
  313. package/dist/i18n/index.jsx +4 -2
  314. package/dist/index.d.ts +3 -3
  315. package/dist/index.d.ts.map +1 -1
  316. package/dist/index.js +18 -12
  317. package/dist/index.jsx +18 -12
  318. package/dist/interactions/FocusableProvider.d.ts.map +1 -1
  319. package/dist/interactions/createFocus.d.ts.map +1 -1
  320. package/dist/interactions/createFocusWithin.d.ts.map +1 -1
  321. package/dist/interactions/createInteractionModality.d.ts.map +1 -1
  322. package/dist/interactions/index.js +1 -2
  323. package/dist/interactions/index.jsx +1 -2
  324. package/dist/label/createLabels.d.ts.map +1 -1
  325. package/dist/listbox/createListBox.d.ts.map +1 -1
  326. package/dist/listbox/createOption.d.ts +1 -1
  327. package/dist/listbox/createOption.d.ts.map +1 -1
  328. package/dist/live-announcer/index.js +1 -1
  329. package/dist/live-announcer/index.jsx +1 -1
  330. package/dist/select/createSelect.d.ts +2 -0
  331. package/dist/select/createSelect.d.ts.map +1 -1
  332. package/dist/selection/createSelectableItem.d.ts.map +1 -1
  333. package/dist/selection/index.js +2 -1
  334. package/dist/selection/index.jsx +2 -1
  335. package/dist/spinbutton/createSpinButton.d.ts +41 -0
  336. package/dist/spinbutton/createSpinButton.d.ts.map +1 -0
  337. package/dist/spinbutton/index.d.ts +3 -0
  338. package/dist/spinbutton/index.d.ts.map +1 -0
  339. package/dist/spinbutton/index.js +2 -0
  340. package/dist/spinbutton/index.jsx +2 -0
  341. package/dist/spinbutton/intl.d.ts +5 -0
  342. package/dist/spinbutton/intl.d.ts.map +1 -0
  343. package/dist/table/createTable.d.ts.map +1 -1
  344. package/dist/table/createTableColumnHeader.d.ts.map +1 -1
  345. package/dist/table/createTableRow.d.ts.map +1 -1
  346. package/dist/table/createTableSelectionCheckbox.d.ts.map +1 -1
  347. package/dist/table/types.d.ts +8 -0
  348. package/dist/table/types.d.ts.map +1 -1
  349. package/dist/table/utils.d.ts +15 -0
  350. package/dist/table/utils.d.ts.map +1 -0
  351. package/dist/tabs/createTabs.d.ts +1 -0
  352. package/dist/tabs/createTabs.d.ts.map +1 -1
  353. package/dist/tag/createTag.d.ts.map +1 -1
  354. package/dist/tag/createTagGroup.d.ts +7 -0
  355. package/dist/tag/createTagGroup.d.ts.map +1 -1
  356. package/dist/toolbar/createToolbar.d.ts.map +1 -1
  357. package/dist/tree/createTree.d.ts.map +1 -1
  358. package/dist/tree/createTreeSelectionCheckbox.d.ts.map +1 -1
  359. package/dist/utils/animation.d.ts.map +1 -1
  360. package/dist/utils/dom.d.ts +1 -0
  361. package/dist/utils/dom.d.ts.map +1 -1
  362. package/dist/utils/index.d.ts +1 -1
  363. package/dist/utils/index.d.ts.map +1 -1
  364. package/dist/utils/index.js +4 -3
  365. package/dist/utils/index.jsx +4 -3
  366. package/package.json +2 -2
  367. package/src/actiongroup/createActionGroup.ts +26 -109
  368. package/src/autocomplete/createAutocomplete.ts +136 -15
  369. package/src/breadcrumbs/createBreadcrumbs.ts +12 -4
  370. package/src/button/createToggleButtonGroup.ts +19 -14
  371. package/src/calendar/createCalendar.ts +3 -4
  372. package/src/calendar/createCalendarCell.ts +17 -3
  373. package/src/calendar/createCalendarGrid.ts +5 -4
  374. package/src/calendar/createRangeCalendar.ts +27 -17
  375. package/src/calendar/createRangeCalendarCell.ts +17 -3
  376. package/src/calendar/intl/index.ts +8 -0
  377. package/src/color/createColorArea.ts +17 -10
  378. package/src/color/createColorField.ts +8 -1
  379. package/src/color/createColorSlider.ts +1 -2
  380. package/src/color/createColorSwatch.ts +4 -2
  381. package/src/color/createColorWheel.ts +0 -6
  382. package/src/color/intl/index.ts +316 -0
  383. package/src/combobox/createComboBox.ts +35 -4
  384. package/src/combobox/intl/generated-locales.ts +635 -0
  385. package/src/combobox/intl/index.ts +8 -2
  386. package/src/datepicker/createDateField.ts +228 -213
  387. package/src/datepicker/createDatePicker.ts +157 -146
  388. package/src/datepicker/createDatePickerGroup.ts +88 -82
  389. package/src/datepicker/createDateRangePicker.ts +230 -179
  390. package/src/datepicker/createDateSegment.ts +386 -389
  391. package/src/datepicker/createDisplayNames.ts +45 -0
  392. package/src/datepicker/createTimeField.ts +36 -129
  393. package/src/datepicker/index.ts +13 -14
  394. package/src/datepicker/intl.ts +633 -0
  395. package/src/dnd/DragManager.ts +693 -0
  396. package/src/dnd/DropTargetKeyboardNavigation.ts +337 -0
  397. package/src/dnd/createDrag.ts +31 -5
  398. package/src/dnd/createDraggableCollection.ts +33 -15
  399. package/src/dnd/createDraggableItem.ts +92 -5
  400. package/src/dnd/createDroppableCollection.ts +487 -373
  401. package/src/dnd/index.ts +11 -0
  402. package/src/dnd/intl/ar-AE.json +29 -0
  403. package/src/dnd/intl/bg-BG.json +29 -0
  404. package/src/dnd/intl/cs-CZ.json +29 -0
  405. package/src/dnd/intl/da-DK.json +29 -0
  406. package/src/dnd/intl/de-DE.json +29 -0
  407. package/src/dnd/intl/el-GR.json +29 -0
  408. package/src/dnd/intl/en-US.json +29 -0
  409. package/src/dnd/intl/es-ES.json +29 -0
  410. package/src/dnd/intl/et-EE.json +29 -0
  411. package/src/dnd/intl/fi-FI.json +29 -0
  412. package/src/dnd/intl/fr-FR.json +29 -0
  413. package/src/dnd/intl/he-IL.json +29 -0
  414. package/src/dnd/intl/hr-HR.json +29 -0
  415. package/src/dnd/intl/hu-HU.json +29 -0
  416. package/src/dnd/intl/index.ts +139 -0
  417. package/src/dnd/intl/it-IT.json +29 -0
  418. package/src/dnd/intl/ja-JP.json +29 -0
  419. package/src/dnd/intl/ko-KR.json +29 -0
  420. package/src/dnd/intl/lt-LT.json +29 -0
  421. package/src/dnd/intl/lv-LV.json +29 -0
  422. package/src/dnd/intl/nb-NO.json +29 -0
  423. package/src/dnd/intl/nl-NL.json +29 -0
  424. package/src/dnd/intl/pl-PL.json +29 -0
  425. package/src/dnd/intl/pt-BR.json +29 -0
  426. package/src/dnd/intl/pt-PT.json +29 -0
  427. package/src/dnd/intl/ro-RO.json +29 -0
  428. package/src/dnd/intl/ru-RU.json +29 -0
  429. package/src/dnd/intl/sk-SK.json +29 -0
  430. package/src/dnd/intl/sl-SI.json +29 -0
  431. package/src/dnd/intl/sr-SP.json +29 -0
  432. package/src/dnd/intl/sv-SE.json +29 -0
  433. package/src/dnd/intl/tr-TR.json +29 -0
  434. package/src/dnd/intl/uk-UA.json +29 -0
  435. package/src/dnd/intl/zh-CN.json +29 -0
  436. package/src/dnd/intl/zh-TW.json +29 -0
  437. package/src/dnd/utils.ts +36 -0
  438. package/src/focus/FocusScope.tsx +120 -12
  439. package/src/focus/index.ts +8 -0
  440. package/src/focus/virtualFocus.ts +55 -0
  441. package/src/gridlist/createGridList.ts +52 -16
  442. package/src/index.ts +11 -3
  443. package/src/interactions/FocusableProvider.tsx +11 -6
  444. package/src/interactions/createFocus.ts +26 -21
  445. package/src/interactions/createFocusWithin.ts +23 -24
  446. package/src/interactions/createInteractionModality.ts +5 -3
  447. package/src/label/createLabels.ts +7 -4
  448. package/src/listbox/createListBox.ts +74 -2
  449. package/src/listbox/createOption.ts +16 -1
  450. package/src/select/createSelect.ts +23 -2
  451. package/src/selection/createSelectableItem.ts +14 -0
  452. package/src/spinbutton/createSpinButton.ts +163 -0
  453. package/src/spinbutton/index.ts +10 -0
  454. package/src/spinbutton/intl.ts +115 -0
  455. package/src/table/createTable.ts +26 -1
  456. package/src/table/createTableColumnHeader.ts +10 -0
  457. package/src/table/createTableRow.ts +10 -0
  458. package/src/table/createTableSelectionCheckbox.ts +24 -1
  459. package/src/table/types.ts +8 -0
  460. package/src/table/utils.ts +41 -0
  461. package/src/tabs/createTabs.ts +53 -12
  462. package/src/tag/createTag.ts +21 -32
  463. package/src/tag/createTagGroup.ts +92 -0
  464. package/src/toolbar/createToolbar.ts +6 -58
  465. package/src/tree/createTree.ts +69 -14
  466. package/src/tree/createTreeSelectionCheckbox.ts +14 -1
  467. package/src/utils/animation.ts +119 -27
  468. package/src/utils/dom.ts +3 -2
  469. package/src/utils/index.ts +2 -0
  470. package/dist/_chunk/createLongPress.js +0 -91
  471. package/dist/_chunk/createLongPress.js.map +0 -1
  472. package/dist/_chunk/createLongPress.jsx +0 -91
  473. package/dist/_chunk/createLongPress.jsx.map +0 -1
  474. package/dist/_chunk/form.js.map +0 -1
  475. package/dist/_chunk/form.jsx.map +0 -1
  476. package/dist/_chunk/live-announcer.js.map +0 -1
  477. package/dist/_chunk/live-announcer.jsx.map +0 -1
  478. package/dist/datepicker/createTimeSegment.d.ts +0 -29
  479. package/dist/datepicker/createTimeSegment.d.ts.map +0 -1
  480. package/src/datepicker/createTimeSegment.ts +0 -352
@@ -1,295 +1,6 @@
1
- import { g as isTabbable, p as isFocusable, s as getOwnerDocument, t as focusSafely } from "./focus.jsx";
2
- import { createContext, createEffect, createSignal, onCleanup, onMount, useContext } from "solid-js";
1
+ import { i as getActiveElement$1, s as getOwnerDocument, t as focusSafely } from "./focus.jsx";
2
+ import { createSignal, onCleanup, onMount } from "solid-js";
3
3
  import { isServer } from "solid-js/web";
4
- //#region src/focus/FocusScope.tsx
5
- /**
6
- * FocusScope component for managing focus containment, restoration, and auto-focus.
7
- * Based on @react-aria/focus FocusScope.
8
- */
9
- const FocusScopeContext = createContext(null);
10
- /**
11
- * Returns a FocusManager interface for the parent FocusScope.
12
- * A FocusManager can be used to programmatically move focus within
13
- * a FocusScope, e.g. in response to user events like keyboard navigation.
14
- */
15
- function useFocusManager() {
16
- return useContext(FocusScopeContext)?.focusManager;
17
- }
18
- /**
19
- * Gets all focusable elements within a scope.
20
- */
21
- function getFocusableElements(scope, tabbable = false) {
22
- const elements = [];
23
- const filter = tabbable ? isTabbable : isFocusable;
24
- for (const scopeElement of scope) {
25
- if (filter(scopeElement)) elements.push(scopeElement);
26
- const descendants = scopeElement.querySelectorAll("*");
27
- for (let i = 0; i < descendants.length; i++) {
28
- const el = descendants[i];
29
- if (filter(el)) elements.push(el);
30
- }
31
- }
32
- return elements;
33
- }
34
- /**
35
- * Checks if an element is within a scope.
36
- */
37
- function isElementInScope(element, scope) {
38
- if (!element) return false;
39
- return scope.some((node) => node.contains(element));
40
- }
41
- /**
42
- * Gets the active element, accounting for shadow DOM.
43
- */
44
- function getActiveElement$1(doc) {
45
- let activeElement = doc.activeElement;
46
- while (activeElement?.shadowRoot?.activeElement) activeElement = activeElement.shadowRoot.activeElement;
47
- return activeElement;
48
- }
49
- /**
50
- * A registry of the live FocusScopes and their parent/child relationships,
51
- * mirroring @react-aria/focus's `focusScopeTree`. The DOM tree alone can't
52
- * express scope nesting because a child scope (e.g. a menu opened from inside a
53
- * modal popover) is rendered in a portal, outside its parent scope's subtree.
54
- * The tree records that nesting so containment can recognize a portaled
55
- * descendant scope as "inside".
56
- */
57
- var FocusScopeTree = class {
58
- root;
59
- fastMap = /* @__PURE__ */ new Map();
60
- constructor() {
61
- this.root = {
62
- scopeRef: null,
63
- parent: null,
64
- children: /* @__PURE__ */ new Set()
65
- };
66
- this.fastMap.set(null, this.root);
67
- }
68
- getTreeNode(scopeRef) {
69
- return this.fastMap.get(scopeRef);
70
- }
71
- addTreeNode(scopeRef, parent) {
72
- const parentNode = this.fastMap.get(parent) ?? this.root;
73
- const node = {
74
- scopeRef,
75
- parent: parentNode,
76
- children: /* @__PURE__ */ new Set()
77
- };
78
- parentNode.children.add(node);
79
- this.fastMap.set(scopeRef, node);
80
- }
81
- removeTreeNode(scopeRef) {
82
- if (scopeRef === null) return;
83
- const node = this.fastMap.get(scopeRef);
84
- if (!node) return;
85
- const parentNode = node.parent;
86
- if (parentNode) {
87
- parentNode.children.delete(node);
88
- for (const child of node.children) {
89
- child.parent = parentNode;
90
- parentNode.children.add(child);
91
- }
92
- }
93
- this.fastMap.delete(scopeRef);
94
- }
95
- *traverse(node = this.root) {
96
- if (node.scopeRef != null) yield node;
97
- for (const child of node.children) yield* this.traverse(child);
98
- }
99
- };
100
- const focusScopeTree = new FocusScopeTree();
101
- /**
102
- * Whether the element is inside `scope` or any of its descendant scopes.
103
- *
104
- * `isElementInScope`'s `node.contains` already covers descendant scopes that
105
- * are DOM children, but not those rendered in a portal. Walking the scope
106
- * subtree closes that gap so focus moving into a portaled child scope still
107
- * counts as "inside". Mirrors @react-aria/focus's `isElementInChildScope`.
108
- */
109
- function isElementInChildScope(element, scope = null) {
110
- if (element instanceof Element && element.closest("[data-react-aria-top-layer]")) return true;
111
- for (const node of focusScopeTree.traverse(focusScopeTree.getTreeNode(scope))) if (node.scopeRef && isElementInScope(element, node.scopeRef())) return true;
112
- return false;
113
- }
114
- /**
115
- * A FocusScope manages focus for its descendants. It supports containing focus inside
116
- * the scope, restoring focus to the previously focused element on unmount, and auto
117
- * focusing children on mount. It also acts as a container for a programmatic focus
118
- * management interface that can be used to move focus forward and back in response
119
- * to user events.
120
- */
121
- const FocusScope = (props) => {
122
- if (isServer) return <>{props.children}</>;
123
- let startRef;
124
- let endRef;
125
- const [scopeElements, setScopeElements] = createSignal([]);
126
- const parentScopeRef = useContext(FocusScopeContext)?.scopeRef ?? null;
127
- let nodeToRestore = null;
128
- const getRestorableElement = (element, doc) => {
129
- if (!element || element === doc.body || element === doc.documentElement) return null;
130
- return element;
131
- };
132
- const focusManager = {
133
- focusNext(opts = {}) {
134
- const scope = scopeElements();
135
- if (scope.length === 0) return null;
136
- const { from, tabbable = true, wrap = false, accept } = opts;
137
- const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));
138
- const doc = getOwnerDocument(scope[0]);
139
- const current = from || getActiveElement$1(doc);
140
- if (!current || elements.length === 0) return null;
141
- let nextIndex = elements.indexOf(current) + 1;
142
- if (nextIndex >= elements.length) if (wrap) nextIndex = 0;
143
- else return null;
144
- const nextElement = elements[nextIndex];
145
- if (nextElement) {
146
- focusSafely(nextElement);
147
- return nextElement;
148
- }
149
- return null;
150
- },
151
- focusPrevious(opts = {}) {
152
- const scope = scopeElements();
153
- if (scope.length === 0) return null;
154
- const { from, tabbable = true, wrap = false, accept } = opts;
155
- const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));
156
- const doc = getOwnerDocument(scope[0]);
157
- const current = from || getActiveElement$1(doc);
158
- if (!current || elements.length === 0) return null;
159
- let prevIndex = elements.indexOf(current) - 1;
160
- if (prevIndex < 0) if (wrap) prevIndex = elements.length - 1;
161
- else return null;
162
- const prevElement = elements[prevIndex];
163
- if (prevElement) {
164
- focusSafely(prevElement);
165
- return prevElement;
166
- }
167
- return null;
168
- },
169
- focusFirst(opts = {}) {
170
- const scope = scopeElements();
171
- if (scope.length === 0) return null;
172
- const { tabbable = true, accept } = opts;
173
- const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));
174
- if (elements.length > 0) {
175
- focusSafely(elements[0]);
176
- return elements[0];
177
- }
178
- return null;
179
- },
180
- focusLast(opts = {}) {
181
- const scope = scopeElements();
182
- if (scope.length === 0) return null;
183
- const { tabbable = true, accept } = opts;
184
- const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));
185
- if (elements.length > 0) {
186
- const lastElement = elements[elements.length - 1];
187
- focusSafely(lastElement);
188
- return lastElement;
189
- }
190
- return null;
191
- }
192
- };
193
- onMount(() => {});
194
- onMount(() => {
195
- focusScopeTree.addTreeNode(scopeElements, parentScopeRef);
196
- });
197
- onCleanup(() => {
198
- focusScopeTree.removeTreeNode(scopeElements);
199
- });
200
- onMount(() => {
201
- if (!props.restoreFocus) return;
202
- const scopeDoc = document;
203
- const scopeActive = getActiveElement$1(scopeDoc);
204
- const topActive = getActiveElement$1(document);
205
- if (scopeDoc !== document && document.activeElement instanceof HTMLIFrameElement && document.activeElement.contentDocument === scopeDoc && scopeActive && scopeActive !== scopeDoc.body) {
206
- nodeToRestore = getRestorableElement(scopeActive, scopeDoc);
207
- return;
208
- }
209
- nodeToRestore = getRestorableElement(topActive, document);
210
- });
211
- createEffect(() => {
212
- if (!props.autoFocus) return;
213
- const scope = scopeElements();
214
- if (scope.length === 0) return;
215
- if (!isElementInScope(getActiveElement$1(getOwnerDocument(scope[0])), scope)) focusManager.focusFirst();
216
- });
217
- createEffect(() => {
218
- if (!props.contain) return;
219
- const scope = scopeElements();
220
- if (scope.length === 0) return;
221
- const doc = getOwnerDocument(scope[0]);
222
- let focusedNode = null;
223
- const onKeyDown = (e) => {
224
- if (e.key !== "Tab" || e.altKey || e.ctrlKey || e.metaKey) return;
225
- const scope = scopeElements();
226
- const activeElement = getActiveElement$1(doc);
227
- if (!isElementInScope(activeElement, scope)) return;
228
- const elements = getFocusableElements(scope, true);
229
- if (elements.length === 0) return;
230
- const firstElement = elements[0];
231
- const lastElement = elements[elements.length - 1];
232
- if (e.shiftKey && activeElement === firstElement) {
233
- e.preventDefault();
234
- focusSafely(lastElement);
235
- } else if (!e.shiftKey && activeElement === lastElement) {
236
- e.preventDefault();
237
- focusSafely(firstElement);
238
- }
239
- };
240
- const onFocusIn = (e) => {
241
- const scope = scopeElements();
242
- const target = e.target;
243
- if (isElementInScope(target, scope)) focusedNode = target;
244
- else if (isElementInChildScope(target, scopeElements)) focusedNode = target;
245
- else if (focusedNode) focusSafely(focusedNode);
246
- else focusManager.focusFirst();
247
- };
248
- let restoreRaf = null;
249
- const onFocusOut = (e) => {
250
- const target = e.target;
251
- if (!isElementInScope(target, scopeElements())) return;
252
- const win = doc.defaultView ?? window;
253
- if (restoreRaf != null) win.cancelAnimationFrame(restoreRaf);
254
- restoreRaf = win.requestAnimationFrame(() => {
255
- restoreRaf = null;
256
- const scope = scopeElements();
257
- const activeElement = getActiveElement$1(doc);
258
- if (activeElement && (isElementInScope(activeElement, scope) || isElementInChildScope(activeElement, scopeElements))) return;
259
- if (doc.body.contains(target)) {
260
- focusedNode = target;
261
- focusSafely(target);
262
- } else focusManager.focusFirst();
263
- });
264
- };
265
- doc.addEventListener("keydown", onKeyDown, true);
266
- doc.addEventListener("focusin", onFocusIn, true);
267
- doc.addEventListener("focusout", onFocusOut, true);
268
- onCleanup(() => {
269
- doc.removeEventListener("keydown", onKeyDown, true);
270
- doc.removeEventListener("focusin", onFocusIn, true);
271
- doc.removeEventListener("focusout", onFocusOut, true);
272
- if (restoreRaf != null) (doc.defaultView ?? window).cancelAnimationFrame(restoreRaf);
273
- });
274
- });
275
- onCleanup(() => {
276
- if (props.restoreFocus && nodeToRestore && nodeToRestore.focus) {
277
- const doc = getOwnerDocument(nodeToRestore);
278
- (doc.defaultView ?? window).requestAnimationFrame(() => {
279
- if (nodeToRestore && doc.body.contains(nodeToRestore)) nodeToRestore.focus();
280
- });
281
- }
282
- });
283
- return <FocusScopeContext.Provider value={{
284
- focusManager,
285
- scopeRef: scopeElements
286
- }}>
287
- <span data-focus-scope-start hidden ref={startRef} />
288
- {props.children}
289
- <span data-focus-scope-end hidden ref={endRef} />
290
- </FocusScopeContext.Provider>;
291
- };
292
- //#endregion
293
4
  //#region src/focus/createFocusRestore.ts
294
5
  /**
295
6
  * Focus restoration utilities for solidaria
@@ -692,6 +403,56 @@ function createVirtualFocus(options) {
692
403
  };
693
404
  }
694
405
  //#endregion
406
+ //#region src/focus/virtualFocus.ts
407
+ /**
408
+ * Virtual-focus event dispatch primitives.
409
+ *
410
+ * A faithful port of @react-aria/focus's `virtualFocus` module. Under virtual
411
+ * focus (e.g. Autocomplete), real DOM focus stays on an input while the
412
+ * "focused" collection option is indicated by `aria-activedescendant`. Moving
413
+ * that virtual cursor dispatches synthetic `focus`/`blur` events (with matching
414
+ * bubbling `focusin`/`focusout`) on the option elements so listeners — notably
415
+ * the autocomplete input's `focusin` handler that mirrors the active descendant
416
+ * — react as if the element were really focused.
417
+ */
418
+ /**
419
+ * Moves virtual focus to `to`, dispatching a virtual blur on the previously
420
+ * virtually-focused element (if any) and a virtual focus on `to` (if non-null).
421
+ */
422
+ function moveVirtualFocus(to) {
423
+ const from = getVirtuallyFocusedElement(getOwnerDocument(to));
424
+ if (from !== to) {
425
+ if (from) dispatchVirtualBlur(from, to);
426
+ if (to) dispatchVirtualFocus(to, from);
427
+ }
428
+ }
429
+ /** Dispatches synthetic `blur` + bubbling `focusout` events on `from`. */
430
+ function dispatchVirtualBlur(from, to) {
431
+ from.dispatchEvent(new FocusEvent("blur", { relatedTarget: to }));
432
+ from.dispatchEvent(new FocusEvent("focusout", {
433
+ bubbles: true,
434
+ relatedTarget: to
435
+ }));
436
+ }
437
+ /** Dispatches synthetic `focus` + bubbling `focusin` events on `to`. */
438
+ function dispatchVirtualFocus(to, from) {
439
+ to.dispatchEvent(new FocusEvent("focus", { relatedTarget: from }));
440
+ to.dispatchEvent(new FocusEvent("focusin", {
441
+ bubbles: true,
442
+ relatedTarget: from
443
+ }));
444
+ }
445
+ /**
446
+ * Returns the currently virtually-focused element: the element referenced by the
447
+ * active element's `aria-activedescendant`, or the active element itself.
448
+ */
449
+ function getVirtuallyFocusedElement(document) {
450
+ const activeElement = getActiveElement$1(document);
451
+ const activeDescendant = activeElement?.getAttribute("aria-activedescendant");
452
+ if (activeDescendant) return document.getElementById(activeDescendant) || activeElement;
453
+ return activeElement;
454
+ }
455
+ //#endregion
695
456
  //#region src/focus/createAutoFocus.ts
696
457
  /**
697
458
  * Auto-focus management for solidaria
@@ -865,6 +626,6 @@ function getAutoFocusQueueLength() {
865
626
  return autoFocusQueue.length;
866
627
  }
867
628
  //#endregion
868
- export { clearFocusStack as a, popFocusStack as c, useFocusManager as d, createVirtualFocus as i, pushFocusStack as l, createAutoFocus as n, createFocusRestore as o, getAutoFocusQueueLength as r, getFocusStackLength as s, clearAutoFocusQueue as t, FocusScope as u };
629
+ export { dispatchVirtualFocus as a, createVirtualFocus as c, getFocusStackLength as d, popFocusStack as f, dispatchVirtualBlur as i, clearFocusStack as l, createAutoFocus as n, getVirtuallyFocusedElement as o, pushFocusStack as p, getAutoFocusQueueLength as r, moveVirtualFocus as s, clearAutoFocusQueue as t, createFocusRestore as u };
869
630
 
870
631
  //# sourceMappingURL=focus2.jsx.map
@@ -1 +1 @@
1
- {"version":3,"file":"focus2.jsx","names":["getActiveElement"],"sources":["../../src/focus/FocusScope.tsx","../../src/focus/createFocusRestore.ts","../../src/focus/createVirtualFocus.ts","../../src/focus/createAutoFocus.ts"],"sourcesContent":["/**\n * FocusScope component for managing focus containment, restoration, and auto-focus.\n * Based on @react-aria/focus FocusScope.\n */\n\nimport {\n createContext,\n useContext,\n createEffect,\n onCleanup,\n type JSX,\n type Accessor,\n type ParentComponent,\n createSignal,\n onMount,\n} from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { getOwnerDocument, isFocusable, isTabbable } from \"../utils\";\nimport { focusSafely } from \"../utils/focus\";\n\nexport interface FocusScopeProps {\n /** The contents of the focus scope. */\n children: JSX.Element;\n /**\n * Whether to contain focus inside the scope, so users cannot\n * move focus outside, for example in a modal dialog.\n */\n contain?: boolean;\n /**\n * Whether to restore focus back to the element that was focused\n * when the focus scope mounted, after the focus scope unmounts.\n */\n restoreFocus?: boolean;\n /** Whether to auto focus the first focusable element in the focus scope on mount. */\n autoFocus?: boolean;\n}\n\nexport interface FocusManagerOptions {\n /** The element to start searching from. The currently focused element by default. */\n from?: Element;\n /** Whether to only include tabbable elements, or all focusable elements. */\n tabbable?: boolean;\n /** Whether focus should wrap around when it reaches the end of the scope. */\n wrap?: boolean;\n /** A callback that determines whether the given element is focused. */\n accept?: (node: Element) => boolean;\n}\n\nexport interface FocusManager {\n /** Moves focus to the next focusable or tabbable element in the focus scope. */\n focusNext(opts?: FocusManagerOptions): HTMLElement | null;\n /** Moves focus to the previous focusable or tabbable element in the focus scope. */\n focusPrevious(opts?: FocusManagerOptions): HTMLElement | null;\n /** Moves focus to the first focusable or tabbable element in the focus scope. */\n focusFirst(opts?: FocusManagerOptions): HTMLElement | null;\n /** Moves focus to the last focusable or tabbable element in the focus scope. */\n focusLast(opts?: FocusManagerOptions): HTMLElement | null;\n}\n\ninterface FocusScopeContextValue {\n focusManager: FocusManager;\n scopeRef: Accessor<Element[]>;\n}\n\nconst FocusScopeContext = createContext<FocusScopeContextValue | null>(null);\n\n/**\n * Returns a FocusManager interface for the parent FocusScope.\n * A FocusManager can be used to programmatically move focus within\n * a FocusScope, e.g. in response to user events like keyboard navigation.\n */\nexport function useFocusManager(): FocusManager | undefined {\n return useContext(FocusScopeContext)?.focusManager;\n}\n\n/**\n * Gets all focusable elements within a scope.\n */\nfunction getFocusableElements(scope: Element[], tabbable = false): HTMLElement[] {\n const elements: HTMLElement[] = [];\n const filter = tabbable ? isTabbable : isFocusable;\n\n for (const scopeElement of scope) {\n // Check the element itself\n if (filter(scopeElement)) {\n elements.push(scopeElement as HTMLElement);\n }\n\n // Check all descendants\n const descendants = scopeElement.querySelectorAll(\"*\");\n for (let i = 0; i < descendants.length; i++) {\n const el = descendants[i];\n if (filter(el)) {\n elements.push(el as HTMLElement);\n }\n }\n }\n\n return elements;\n}\n\n/**\n * Checks if an element is within a scope.\n */\nfunction isElementInScope(element: Element | null, scope: Element[]): boolean {\n if (!element) return false;\n return scope.some((node) => node.contains(element));\n}\n\n/**\n * Gets the active element, accounting for shadow DOM.\n */\nfunction getActiveElement(doc: Document): Element | null {\n let activeElement = doc.activeElement;\n while (activeElement?.shadowRoot?.activeElement) {\n activeElement = activeElement.shadowRoot.activeElement;\n }\n return activeElement;\n}\n\n/**\n * A scope is identified by its (stable) scope-elements accessor; `null` is the\n * tree root. Mirrors @react-aria/focus's `ScopeRef`.\n */\ntype ScopeRef = Accessor<Element[]> | null;\n\ninterface FocusScopeTreeNode {\n scopeRef: ScopeRef;\n parent: FocusScopeTreeNode | null;\n children: Set<FocusScopeTreeNode>;\n}\n\n/**\n * A registry of the live FocusScopes and their parent/child relationships,\n * mirroring @react-aria/focus's `focusScopeTree`. The DOM tree alone can't\n * express scope nesting because a child scope (e.g. a menu opened from inside a\n * modal popover) is rendered in a portal, outside its parent scope's subtree.\n * The tree records that nesting so containment can recognize a portaled\n * descendant scope as \"inside\".\n */\nclass FocusScopeTree {\n root: FocusScopeTreeNode;\n private fastMap = new Map<ScopeRef, FocusScopeTreeNode>();\n\n constructor() {\n this.root = { scopeRef: null, parent: null, children: new Set() };\n this.fastMap.set(null, this.root);\n }\n\n getTreeNode(scopeRef: ScopeRef): FocusScopeTreeNode | undefined {\n return this.fastMap.get(scopeRef);\n }\n\n addTreeNode(scopeRef: ScopeRef, parent: ScopeRef): void {\n const parentNode = this.fastMap.get(parent) ?? this.root;\n const node: FocusScopeTreeNode = { scopeRef, parent: parentNode, children: new Set() };\n parentNode.children.add(node);\n this.fastMap.set(scopeRef, node);\n }\n\n removeTreeNode(scopeRef: ScopeRef): void {\n // never remove the root\n if (scopeRef === null) return;\n const node = this.fastMap.get(scopeRef);\n if (!node) return;\n const parentNode = node.parent;\n if (parentNode) {\n parentNode.children.delete(node);\n // Re-parent any children so a mid-tree unmount doesn't orphan descendants.\n for (const child of node.children) {\n child.parent = parentNode;\n parentNode.children.add(child);\n }\n }\n this.fastMap.delete(scopeRef);\n }\n\n // Pre-order depth-first; skips the null-scoped root, like upstream.\n *traverse(node: FocusScopeTreeNode = this.root): Generator<FocusScopeTreeNode> {\n if (node.scopeRef != null) {\n yield node;\n }\n for (const child of node.children) {\n yield* this.traverse(child);\n }\n }\n}\n\nconst focusScopeTree = new FocusScopeTree();\n\n/**\n * Whether the element is inside `scope` or any of its descendant scopes.\n *\n * `isElementInScope`'s `node.contains` already covers descendant scopes that\n * are DOM children, but not those rendered in a portal. Walking the scope\n * subtree closes that gap so focus moving into a portaled child scope still\n * counts as \"inside\". Mirrors @react-aria/focus's `isElementInChildScope`.\n */\nfunction isElementInChildScope(element: Element, scope: ScopeRef = null): boolean {\n // Always allow focus to move into a top-layer element (e.g. toasts).\n if (element instanceof Element && element.closest(\"[data-react-aria-top-layer]\")) {\n return true;\n }\n\n for (const node of focusScopeTree.traverse(focusScopeTree.getTreeNode(scope))) {\n if (node.scopeRef && isElementInScope(element, node.scopeRef())) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * A FocusScope manages focus for its descendants. It supports containing focus inside\n * the scope, restoring focus to the previously focused element on unmount, and auto\n * focusing children on mount. It also acts as a container for a programmatic focus\n * management interface that can be used to move focus forward and back in response\n * to user events.\n */\nexport const FocusScope: ParentComponent<FocusScopeProps> = (props) => {\n if (isServer) {\n return <>{props.children}</>;\n }\n\n let startRef: HTMLSpanElement | undefined;\n let endRef: HTMLSpanElement | undefined;\n const [scopeElements, setScopeElements] = createSignal<Element[]>([]);\n\n // The nearest enclosing FocusScope (through context, which Solid propagates\n // across portals) is this scope's parent in the focus-scope tree. Read it\n // before we shadow the context with our own provider below.\n const parentScopeRef = useContext(FocusScopeContext)?.scopeRef ?? null;\n\n // Store the element that was focused when the scope mounted\n let nodeToRestore: Element | null = null;\n\n const getRestorableElement = (element: Element | null, doc: Document): Element | null => {\n if (!element || element === doc.body || element === doc.documentElement) {\n return null;\n }\n return element;\n };\n\n // Create focus manager\n const focusManager: FocusManager = {\n focusNext(opts = {}) {\n const scope = scopeElements();\n if (scope.length === 0) return null;\n\n const { from, tabbable = true, wrap = false, accept } = opts;\n const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));\n const doc = getOwnerDocument(scope[0]);\n const current = from || getActiveElement(doc);\n\n if (!current || elements.length === 0) return null;\n\n const currentIndex = elements.indexOf(current as HTMLElement);\n let nextIndex = currentIndex + 1;\n\n if (nextIndex >= elements.length) {\n if (wrap) {\n nextIndex = 0;\n } else {\n return null;\n }\n }\n\n const nextElement = elements[nextIndex];\n if (nextElement) {\n focusSafely(nextElement);\n return nextElement;\n }\n\n return null;\n },\n\n focusPrevious(opts = {}) {\n const scope = scopeElements();\n if (scope.length === 0) return null;\n\n const { from, tabbable = true, wrap = false, accept } = opts;\n const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));\n const doc = getOwnerDocument(scope[0]);\n const current = from || getActiveElement(doc);\n\n if (!current || elements.length === 0) return null;\n\n const currentIndex = elements.indexOf(current as HTMLElement);\n let prevIndex = currentIndex - 1;\n\n if (prevIndex < 0) {\n if (wrap) {\n prevIndex = elements.length - 1;\n } else {\n return null;\n }\n }\n\n const prevElement = elements[prevIndex];\n if (prevElement) {\n focusSafely(prevElement);\n return prevElement;\n }\n\n return null;\n },\n\n focusFirst(opts = {}) {\n const scope = scopeElements();\n if (scope.length === 0) return null;\n\n const { tabbable = true, accept } = opts;\n const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));\n\n if (elements.length > 0) {\n focusSafely(elements[0]);\n return elements[0];\n }\n\n return null;\n },\n\n focusLast(opts = {}) {\n const scope = scopeElements();\n if (scope.length === 0) return null;\n\n const { tabbable = true, accept } = opts;\n const elements = getFocusableElements(scope, tabbable).filter((el) => !accept || accept(el));\n\n if (elements.length > 0) {\n const lastElement = elements[elements.length - 1];\n focusSafely(lastElement);\n return lastElement;\n }\n\n return null;\n },\n };\n\n // Collect scope elements after render\n onMount(() => {\n if (!startRef || !endRef) return;\n\n const nodes: Element[] = [];\n let node = startRef.nextSibling;\n while (node && node !== endRef) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n nodes.push(node as Element);\n }\n node = node.nextSibling;\n }\n setScopeElements(nodes);\n });\n\n // Register this scope in the focus-scope tree so containment can recognize a\n // portaled descendant scope as \"inside\" it. The scope-elements accessor is a\n // stable identity, so it works as the tree key even before it's populated.\n onMount(() => {\n focusScopeTree.addTreeNode(scopeElements, parentScopeRef);\n });\n onCleanup(() => {\n focusScopeTree.removeTreeNode(scopeElements);\n });\n\n // Save the currently focused element for restoration (must happen before autoFocus/contain effects run).\n onMount(() => {\n if (!props.restoreFocus) return;\n\n // Focus can be in the main document, or inside this iframe's document.\n const scopeDoc = startRef ? getOwnerDocument(startRef) : document;\n const scopeActive = getActiveElement(scopeDoc);\n const topActive = getActiveElement(document);\n\n // If the scope is in an iframe and that iframe is currently focused, prefer the iframe document's active element.\n if (\n scopeDoc !== document &&\n document.activeElement instanceof HTMLIFrameElement &&\n document.activeElement.contentDocument === scopeDoc &&\n scopeActive &&\n scopeActive !== scopeDoc.body\n ) {\n nodeToRestore = getRestorableElement(scopeActive, scopeDoc);\n return;\n }\n\n nodeToRestore = getRestorableElement(topActive, document);\n });\n\n // Auto-focus first element\n createEffect(() => {\n if (!props.autoFocus) return;\n\n const scope = scopeElements();\n if (scope.length === 0) return;\n\n const doc = getOwnerDocument(scope[0]);\n const activeElement = getActiveElement(doc);\n\n // Only auto-focus if focus is not already inside the scope\n if (!isElementInScope(activeElement, scope)) {\n focusManager.focusFirst();\n }\n });\n\n // Focus containment\n createEffect(() => {\n if (!props.contain) return;\n\n const scope = scopeElements();\n if (scope.length === 0) return;\n\n const doc = getOwnerDocument(scope[0]);\n let focusedNode: Element | null = null;\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\" || e.altKey || e.ctrlKey || e.metaKey) {\n return;\n }\n\n const scope = scopeElements();\n const activeElement = getActiveElement(doc);\n if (!isElementInScope(activeElement, scope)) {\n return;\n }\n\n const elements = getFocusableElements(scope, true);\n if (elements.length === 0) return;\n\n const firstElement = elements[0];\n const lastElement = elements[elements.length - 1];\n\n if (e.shiftKey && activeElement === firstElement) {\n e.preventDefault();\n focusSafely(lastElement);\n } else if (!e.shiftKey && activeElement === lastElement) {\n e.preventDefault();\n focusSafely(firstElement);\n }\n };\n\n const onFocusIn = (e: FocusEvent) => {\n const scope = scopeElements();\n const target = e.target as Element;\n\n if (isElementInScope(target, scope)) {\n focusedNode = target;\n } else if (isElementInChildScope(target, scopeElements)) {\n // Focus moved into a descendant scope — e.g. a menu opened from inside\n // this modal popover, rendered in a portal outside this scope's DOM\n // subtree. Track it but don't pull focus back, which would tear the\n // nested overlay down.\n focusedNode = target;\n } else if (focusedNode) {\n // Focus escaped the scope, bring it back\n focusSafely(focusedNode as HTMLElement);\n } else {\n // No previous focus, focus first element\n focusManager.focusFirst();\n }\n };\n\n let restoreRaf: number | null = null;\n\n const onFocusOut = (e: FocusEvent) => {\n const target = e.target as Element;\n if (!isElementInScope(target, scopeElements())) return;\n\n // Focus left an element inside the scope. Wait a frame (like upstream's\n // onBlur) so a synchronous refocus elsewhere can settle; if focus ended\n // up outside every scope (e.g. blur() to body), pull it back.\n const win = doc.defaultView ?? window;\n if (restoreRaf != null) win.cancelAnimationFrame(restoreRaf);\n restoreRaf = win.requestAnimationFrame(() => {\n restoreRaf = null;\n const scope = scopeElements();\n const activeElement = getActiveElement(doc);\n if (\n activeElement &&\n (isElementInScope(activeElement, scope) ||\n isElementInChildScope(activeElement, scopeElements))\n ) {\n return;\n }\n\n if (doc.body.contains(target)) {\n focusedNode = target;\n focusSafely(target as HTMLElement);\n } else {\n focusManager.focusFirst();\n }\n });\n };\n\n doc.addEventListener(\"keydown\", onKeyDown, true);\n doc.addEventListener(\"focusin\", onFocusIn, true);\n doc.addEventListener(\"focusout\", onFocusOut, true);\n\n onCleanup(() => {\n doc.removeEventListener(\"keydown\", onKeyDown, true);\n doc.removeEventListener(\"focusin\", onFocusIn, true);\n doc.removeEventListener(\"focusout\", onFocusOut, true);\n if (restoreRaf != null) {\n (doc.defaultView ?? window).cancelAnimationFrame(restoreRaf);\n }\n });\n });\n\n // Restore focus on unmount\n onCleanup(() => {\n if (props.restoreFocus && nodeToRestore && (nodeToRestore as HTMLElement).focus) {\n const doc = getOwnerDocument(nodeToRestore as Element);\n const win = doc.defaultView ?? window;\n\n // Use requestAnimationFrame to ensure the element is still in the DOM\n win.requestAnimationFrame(() => {\n if (nodeToRestore && doc.body.contains(nodeToRestore as Node)) {\n (nodeToRestore as HTMLElement).focus();\n }\n });\n }\n });\n\n return (\n <FocusScopeContext.Provider value={{ focusManager, scopeRef: scopeElements }}>\n <span data-focus-scope-start hidden ref={startRef} />\n {props.children}\n <span data-focus-scope-end hidden ref={endRef} />\n </FocusScopeContext.Provider>\n );\n};\n\nexport default FocusScope;\n","/**\n * Focus restoration utilities for solidaria\n *\n * Provides enhanced focus restoration with retry logic, cross-scope tracking,\n * and safe restoration patterns.\n */\n\nimport { createEffect, onCleanup, onMount } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { getOwnerDocument } from \"../utils\";\nimport { focusSafely } from \"../utils/focus\";\n\nexport interface FocusRestoreOptions {\n /**\n * Whether to restore focus when the component unmounts.\n * @default true\n */\n restoreOnUnmount?: boolean;\n /**\n * Maximum number of retries if the element is not in the DOM.\n * @default 3\n */\n maxRetries?: number;\n /**\n * Delay between retries in milliseconds.\n * @default 50\n */\n retryDelay?: number;\n /**\n * Callback when focus is successfully restored.\n */\n onRestore?: (element: HTMLElement) => void;\n /**\n * Callback when focus restoration fails.\n */\n onRestoreFailed?: () => void;\n /**\n * Whether to prevent scrolling when restoring focus.\n * @default true\n */\n preventScroll?: boolean;\n}\n\nexport interface FocusRestoreResult {\n /**\n * Manually restore focus to the saved element.\n */\n restore: () => boolean;\n /**\n * Get the saved element (if any).\n */\n getSavedElement: () => HTMLElement | null;\n /**\n * Save the currently focused element.\n */\n saveCurrentFocus: () => void;\n /**\n * Clear the saved element without restoring.\n */\n clear: () => void;\n}\n\n// Stack to track focus history across scopes\nconst focusStack: HTMLElement[] = [];\n\n/**\n * Push an element onto the focus stack.\n */\nexport function pushFocusStack(element: HTMLElement): void {\n focusStack.push(element);\n}\n\n/**\n * Pop the last element from the focus stack.\n */\nexport function popFocusStack(): HTMLElement | undefined {\n return focusStack.pop();\n}\n\n/**\n * Get the current focus stack length.\n */\nexport function getFocusStackLength(): number {\n return focusStack.length;\n}\n\n/**\n * Clear the entire focus stack.\n */\nexport function clearFocusStack(): void {\n focusStack.length = 0;\n}\n\n/**\n * Gets the active element, accounting for shadow DOM.\n */\nfunction getActiveElement(doc: Document): HTMLElement | null {\n let activeElement = doc.activeElement as HTMLElement | null;\n while (activeElement?.shadowRoot?.activeElement) {\n activeElement = activeElement.shadowRoot.activeElement as HTMLElement;\n }\n return activeElement;\n}\n\n/**\n * Checks if an element is still valid for focus restoration.\n */\nfunction isValidForRestore(element: HTMLElement | null): boolean {\n if (!element) return false;\n if (!document.body.contains(element)) return false;\n if (element.hasAttribute(\"disabled\")) return false;\n if (element.getAttribute(\"aria-disabled\") === \"true\") return false;\n if (element.getAttribute(\"aria-hidden\") === \"true\") return false;\n return true;\n}\n\n/**\n * Attempts to restore focus with retries.\n */\nfunction tryRestoreFocus(\n element: HTMLElement | null,\n options: Required<\n Pick<\n FocusRestoreOptions,\n \"maxRetries\" | \"retryDelay\" | \"preventScroll\" | \"onRestore\" | \"onRestoreFailed\"\n >\n >,\n): void {\n const { maxRetries, retryDelay, preventScroll, onRestore, onRestoreFailed } = options;\n let attempts = 0;\n\n const attempt = () => {\n if (!element) {\n onRestoreFailed?.();\n return;\n }\n\n if (isValidForRestore(element)) {\n if (preventScroll) {\n focusSafely(element);\n } else {\n element.focus();\n }\n onRestore?.(element);\n return;\n }\n\n attempts++;\n if (attempts < maxRetries) {\n setTimeout(attempt, retryDelay);\n } else {\n onRestoreFailed?.();\n }\n };\n\n // Use requestAnimationFrame for the first attempt to ensure DOM is ready\n requestAnimationFrame(attempt);\n}\n\n/**\n * Creates a focus restoration manager.\n *\n * This hook saves the currently focused element when mounted and provides\n * methods to restore focus later, with retry logic for reliability.\n *\n * @example\n * ```tsx\n * function Modal(props) {\n * const focusRestore = createFocusRestore({\n * restoreOnUnmount: true,\n * onRestore: () => console.log('Focus restored'),\n * });\n *\n * return (\n * <div role=\"dialog\">\n * {props.children}\n * <button onClick={() => focusRestore.restore()}>\n * Close\n * </button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Manual focus management\n * function Dropdown() {\n * const focusRestore = createFocusRestore({ restoreOnUnmount: false });\n *\n * const onOpen = () => {\n * focusRestore.saveCurrentFocus();\n * // Focus dropdown content\n * };\n *\n * const onClose = () => {\n * focusRestore.restore();\n * };\n *\n * return <div>...</div>;\n * }\n * ```\n */\nexport function createFocusRestore(options: FocusRestoreOptions = {}): FocusRestoreResult {\n const {\n restoreOnUnmount = true,\n maxRetries = 3,\n retryDelay = 50,\n onRestore,\n onRestoreFailed,\n preventScroll = true,\n } = options;\n\n // During SSR, return no-op functions\n if (isServer) {\n return {\n restore: () => false,\n getSavedElement: () => null,\n saveCurrentFocus: () => {},\n clear: () => {},\n };\n }\n\n let savedElement: HTMLElement | null = null;\n\n // Save focus on mount\n onMount(() => {\n saveCurrentFocus();\n });\n\n // Restore focus on cleanup\n onCleanup(() => {\n if (restoreOnUnmount && savedElement) {\n tryRestoreFocus(savedElement, {\n maxRetries,\n retryDelay,\n preventScroll,\n onRestore: onRestore ?? (() => {}),\n onRestoreFailed: onRestoreFailed ?? (() => {}),\n });\n }\n });\n\n function saveCurrentFocus(): void {\n const doc = typeof document !== \"undefined\" ? document : null;\n if (!doc) return;\n\n const active = getActiveElement(doc);\n if (active && active !== doc.body) {\n savedElement = active;\n pushFocusStack(active);\n }\n }\n\n function restore(): boolean {\n if (!savedElement) return false;\n\n if (isValidForRestore(savedElement)) {\n if (preventScroll) {\n focusSafely(savedElement);\n } else {\n savedElement.focus();\n }\n onRestore?.(savedElement);\n return true;\n }\n\n // Try the focus stack\n while (focusStack.length > 0) {\n const stackElement = popFocusStack();\n if (stackElement && isValidForRestore(stackElement)) {\n if (preventScroll) {\n focusSafely(stackElement);\n } else {\n stackElement.focus();\n }\n onRestore?.(stackElement);\n return true;\n }\n }\n\n onRestoreFailed?.();\n return false;\n }\n\n function getSavedElement(): HTMLElement | null {\n return savedElement;\n }\n\n function clear(): void {\n savedElement = null;\n }\n\n return {\n restore,\n getSavedElement,\n saveCurrentFocus,\n clear,\n };\n}\n","/**\n * Virtual focus management for solidaria\n *\n * Provides virtual focus for large collections where tracking DOM focus\n * on every item is impractical. Instead, a single element receives real\n * focus while aria-activedescendant indicates the virtually focused item.\n *\n * This is commonly used in:\n * - Virtualized lists (where not all items are in the DOM)\n * - Large trees\n * - Autocomplete/combobox suggestions\n * - Grid/table navigation\n */\n\nimport { type Accessor, createSignal, createEffect, onCleanup } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\n\nexport interface VirtualFocusOptions<T> {\n /**\n * The items in the collection.\n */\n items: Accessor<T[]>;\n /**\n * Function to get a unique key for each item.\n */\n getKey: (item: T) => string;\n /**\n * Function to check if an item is disabled.\n */\n isDisabled?: (item: T) => boolean;\n /**\n * Initial focused key.\n */\n defaultFocusedKey?: string;\n /**\n * Controlled focused key.\n */\n focusedKey?: Accessor<string | null>;\n /**\n * Callback when focused key changes.\n */\n onFocusChange?: (key: string | null) => void;\n /**\n * Whether to wrap focus at the edges.\n * @default true\n */\n wrap?: boolean;\n /**\n * Whether to loop through disabled items.\n * @default false\n */\n skipDisabled?: boolean;\n /**\n * Orientation for keyboard navigation.\n * @default 'vertical'\n */\n orientation?: \"horizontal\" | \"vertical\" | \"both\";\n}\n\nexport interface VirtualFocusResult<T> {\n /**\n * The currently focused key.\n */\n focusedKey: Accessor<string | null>;\n /**\n * The currently focused item (if any).\n */\n focusedItem: Accessor<T | null>;\n /**\n * Set the focused key.\n */\n setFocusedKey: (key: string | null) => void;\n /**\n * Move focus to the next item.\n */\n focusNext: () => void;\n /**\n * Move focus to the previous item.\n */\n focusPrevious: () => void;\n /**\n * Move focus to the first item.\n */\n focusFirst: () => void;\n /**\n * Move focus to the last item.\n */\n focusLast: () => void;\n /**\n * Move focus by a page (for large lists).\n */\n focusPageDown: (pageSize?: number) => void;\n /**\n * Move focus up by a page (for large lists).\n */\n focusPageUp: (pageSize?: number) => void;\n /**\n * Check if a key is the currently focused key.\n */\n isFocused: (key: string) => boolean;\n /**\n * Props to spread on the container element.\n */\n containerProps: {\n \"aria-activedescendant\": Accessor<string | undefined>;\n onKeyDown: (e: KeyboardEvent) => void;\n };\n /**\n * Get props for an item element.\n */\n getItemProps: (key: string) => {\n id: string;\n \"aria-selected\"?: boolean;\n };\n}\n\nconst DEFAULT_PAGE_SIZE = 10;\n\n/**\n * Creates virtual focus management for a collection.\n *\n * Virtual focus uses aria-activedescendant to indicate which item is\n * \"focused\" while keeping real DOM focus on a container element. This\n * is more performant for large collections and required for virtualized\n * lists where items may not be in the DOM.\n *\n * @example\n * ```tsx\n * function Listbox(props) {\n * const virtualFocus = createVirtualFocus({\n * items: () => props.items,\n * getKey: (item) => item.id,\n * isDisabled: (item) => item.disabled,\n * });\n *\n * return (\n * <ul\n * role=\"listbox\"\n * tabIndex={0}\n * aria-activedescendant={virtualFocus.containerProps['aria-activedescendant']()}\n * onKeyDown={virtualFocus.containerProps.onKeyDown}\n * >\n * <For each={props.items}>\n * {(item) => (\n * <li\n * {...virtualFocus.getItemProps(item.id)}\n * role=\"option\"\n * aria-selected={virtualFocus.isFocused(item.id)}\n * >\n * {item.name}\n * </li>\n * )}\n * </For>\n * </ul>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With controlled focus\n * function ControlledListbox() {\n * const [focusedKey, setFocusedKey] = createSignal<string | null>(null);\n *\n * const virtualFocus = createVirtualFocus({\n * items: () => items,\n * getKey: (item) => item.id,\n * focusedKey: focusedKey,\n * onFocusChange: setFocusedKey,\n * });\n *\n * return <ul>...</ul>;\n * }\n * ```\n */\nexport function createVirtualFocus<T>(options: VirtualFocusOptions<T>): VirtualFocusResult<T> {\n const {\n items,\n getKey,\n isDisabled = () => false,\n defaultFocusedKey,\n focusedKey: controlledFocusedKey,\n onFocusChange,\n wrap = true,\n skipDisabled = true,\n orientation = \"vertical\",\n } = options;\n\n // During SSR, return minimal implementation\n if (isServer) {\n const emptyAccessor = () => null;\n return {\n focusedKey: emptyAccessor,\n focusedItem: emptyAccessor,\n setFocusedKey: () => {},\n focusNext: () => {},\n focusPrevious: () => {},\n focusFirst: () => {},\n focusLast: () => {},\n focusPageDown: () => {},\n focusPageUp: () => {},\n isFocused: () => false,\n containerProps: {\n \"aria-activedescendant\": () => undefined,\n onKeyDown: () => {},\n },\n getItemProps: (key: string) => ({ id: `item-${key}` }),\n };\n }\n\n // Internal state for uncontrolled mode\n const [internalKey, setInternalKey] = createSignal<string | null>(defaultFocusedKey ?? null);\n\n // Use controlled or uncontrolled value\n const focusedKey = controlledFocusedKey ?? internalKey;\n\n const setFocusedKey = (key: string | null) => {\n if (controlledFocusedKey) {\n onFocusChange?.(key);\n } else {\n setInternalKey(key);\n onFocusChange?.(key);\n }\n };\n\n // Get focused item\n const focusedItem = (): T | null => {\n const key = focusedKey();\n if (!key) return null;\n return items().find((item) => getKey(item) === key) ?? null;\n };\n\n // Get valid items (not disabled if skipDisabled is true)\n const getValidItems = (): T[] => {\n if (!skipDisabled) return items();\n return items().filter((item) => !isDisabled(item));\n };\n\n // Get index of key in valid items\n const getKeyIndex = (key: string | null): number => {\n if (!key) return -1;\n const validItems = getValidItems();\n return validItems.findIndex((item) => getKey(item) === key);\n };\n\n // Focus by index\n const focusByIndex = (index: number): void => {\n const validItems = getValidItems();\n if (validItems.length === 0) return;\n\n let targetIndex = index;\n\n if (wrap) {\n targetIndex = ((index % validItems.length) + validItems.length) % validItems.length;\n } else {\n targetIndex = Math.max(0, Math.min(index, validItems.length - 1));\n }\n\n const item = validItems[targetIndex];\n if (item) {\n setFocusedKey(getKey(item));\n }\n };\n\n const focusNext = (): void => {\n const currentIndex = getKeyIndex(focusedKey());\n focusByIndex(currentIndex + 1);\n };\n\n const focusPrevious = (): void => {\n const currentIndex = getKeyIndex(focusedKey());\n if (currentIndex === -1) {\n focusByIndex(getValidItems().length - 1);\n } else {\n focusByIndex(currentIndex - 1);\n }\n };\n\n const focusFirst = (): void => {\n focusByIndex(0);\n };\n\n const focusLast = (): void => {\n focusByIndex(getValidItems().length - 1);\n };\n\n const focusPageDown = (pageSize: number = DEFAULT_PAGE_SIZE): void => {\n const currentIndex = getKeyIndex(focusedKey());\n focusByIndex(currentIndex + pageSize);\n };\n\n const focusPageUp = (pageSize: number = DEFAULT_PAGE_SIZE): void => {\n const currentIndex = getKeyIndex(focusedKey());\n if (currentIndex === -1) {\n focusByIndex(getValidItems().length - 1);\n } else {\n focusByIndex(currentIndex - pageSize);\n }\n };\n\n const isFocused = (key: string): boolean => {\n return focusedKey() === key;\n };\n\n // Keyboard handler\n const onKeyDown = (e: KeyboardEvent): void => {\n const isVertical = orientation === \"vertical\" || orientation === \"both\";\n const isHorizontal = orientation === \"horizontal\" || orientation === \"both\";\n\n switch (e.key) {\n case \"ArrowDown\":\n if (isVertical) {\n e.preventDefault();\n focusNext();\n }\n break;\n case \"ArrowUp\":\n if (isVertical) {\n e.preventDefault();\n focusPrevious();\n }\n break;\n case \"ArrowRight\":\n if (isHorizontal) {\n e.preventDefault();\n focusNext();\n }\n break;\n case \"ArrowLeft\":\n if (isHorizontal) {\n e.preventDefault();\n focusPrevious();\n }\n break;\n case \"Home\":\n e.preventDefault();\n focusFirst();\n break;\n case \"End\":\n e.preventDefault();\n focusLast();\n break;\n case \"PageDown\":\n e.preventDefault();\n focusPageDown();\n break;\n case \"PageUp\":\n e.preventDefault();\n focusPageUp();\n break;\n }\n };\n\n const containerProps = {\n \"aria-activedescendant\": () => {\n const key = focusedKey();\n return key ? `item-${key}` : undefined;\n },\n onKeyDown,\n };\n\n const getItemProps = (key: string) => ({\n id: `item-${key}`,\n });\n\n return {\n focusedKey,\n focusedItem,\n setFocusedKey,\n focusNext,\n focusPrevious,\n focusFirst,\n focusLast,\n focusPageDown,\n focusPageUp,\n isFocused,\n containerProps,\n getItemProps,\n };\n}\n","/**\n * Auto-focus management for solidaria\n *\n * Provides priority-based auto-focus with deferred execution\n * and conflict resolution for multiple auto-focus elements.\n */\n\nimport { createEffect, onCleanup, onMount } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { focusSafely } from \"../utils/focus\";\n\nexport interface AutoFocusOptions {\n /**\n * Whether auto-focus is enabled.\n * @default true\n */\n isEnabled?: boolean;\n /**\n * Priority level (higher = more important).\n * When multiple elements request auto-focus, the highest priority wins.\n * @default 0\n */\n priority?: number;\n /**\n * Delay in milliseconds before focusing.\n * Useful for animations or transitions.\n * @default 0\n */\n delay?: number;\n /**\n * Whether to focus even if another element is already focused.\n * @default false\n */\n force?: boolean;\n /**\n * Whether to prevent scrolling when focusing.\n * @default true\n */\n preventScroll?: boolean;\n /**\n * Callback when focus is applied.\n */\n onFocus?: (element: HTMLElement) => void;\n /**\n * Callback when focus is skipped (due to lower priority or other reasons).\n */\n onSkip?: () => void;\n}\n\nexport interface AutoFocusResult {\n /**\n * Manually trigger the auto-focus.\n */\n focus: () => void;\n /**\n * Cancel any pending auto-focus.\n */\n cancel: () => void;\n}\n\ninterface QueuedFocus {\n ref: () => HTMLElement | null | undefined;\n priority: number;\n delay: number;\n force: boolean;\n preventScroll: boolean;\n onFocus?: (element: HTMLElement) => void;\n onSkip?: () => void;\n}\n\n// Global queue for managing auto-focus requests\nlet autoFocusQueue: QueuedFocus[] = [];\nlet processingTimeout: ReturnType<typeof setTimeout> | null = null;\n\n/**\n * Process the auto-focus queue and focus the highest priority element.\n */\nfunction processAutoFocusQueue(): void {\n if (processingTimeout) {\n clearTimeout(processingTimeout);\n processingTimeout = null;\n }\n\n if (autoFocusQueue.length === 0) return;\n\n // Sort by priority (highest first)\n autoFocusQueue.sort((a, b) => b.priority - a.priority);\n\n // Get the highest priority item\n const winner = autoFocusQueue[0];\n const losers = autoFocusQueue.slice(1);\n\n // Clear the queue\n autoFocusQueue = [];\n\n // Notify losers\n for (const loser of losers) {\n loser.onSkip?.();\n }\n\n // Focus the winner\n const element = winner.ref();\n if (!element) {\n winner.onSkip?.();\n return;\n }\n\n // Check if we should focus\n const activeElement = document.activeElement;\n const shouldFocus =\n winner.force ||\n !activeElement ||\n activeElement === document.body ||\n activeElement === document.documentElement;\n\n if (!shouldFocus) {\n winner.onSkip?.();\n return;\n }\n\n // Apply focus with optional delay\n if (winner.delay > 0) {\n setTimeout(() => {\n const el = winner.ref();\n if (el && document.body.contains(el)) {\n if (winner.preventScroll) {\n focusSafely(el);\n } else {\n el.focus();\n }\n winner.onFocus?.(el);\n }\n }, winner.delay);\n } else {\n if (winner.preventScroll) {\n focusSafely(element);\n } else {\n element.focus();\n }\n winner.onFocus?.(element);\n }\n}\n\n/**\n * Queue an element for auto-focus.\n */\nfunction queueAutoFocus(item: QueuedFocus): void {\n autoFocusQueue.push(item);\n\n // Schedule processing on next frame to allow all components to register\n if (processingTimeout === null) {\n processingTimeout = setTimeout(processAutoFocusQueue, 0);\n }\n}\n\n/**\n * Remove an item from the auto-focus queue.\n */\nfunction removeFromQueue(ref: () => HTMLElement | null | undefined): void {\n autoFocusQueue = autoFocusQueue.filter((item) => item.ref !== ref);\n}\n\n/**\n * Creates auto-focus behavior for an element.\n *\n * This hook registers the element for auto-focus when mounted. If multiple\n * elements request auto-focus, the one with the highest priority wins.\n *\n * @param ref - Accessor for the element to focus\n * @param options - Auto-focus options\n *\n * @example\n * ```tsx\n * function Dialog(props) {\n * let contentRef: HTMLDivElement | undefined;\n *\n * createAutoFocus(() => contentRef, {\n * priority: 10, // High priority for dialogs\n * onFocus: () => console.log('Dialog focused'),\n * });\n *\n * return (\n * <div ref={contentRef} tabIndex={-1}>\n * {props.children}\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With delay for animations\n * function AnimatedPanel() {\n * let panelRef: HTMLDivElement | undefined;\n *\n * createAutoFocus(() => panelRef, {\n * delay: 300, // Wait for animation\n * });\n *\n * return <div ref={panelRef} class=\"animated-panel\">...</div>;\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Conditional auto-focus\n * function Input(props) {\n * let inputRef: HTMLInputElement | undefined;\n *\n * createAutoFocus(() => inputRef, {\n * isEnabled: props.autoFocus,\n * });\n *\n * return <input ref={inputRef} />;\n * }\n * ```\n */\nexport function createAutoFocus(\n ref: () => HTMLElement | null | undefined,\n options: AutoFocusOptions = {},\n): AutoFocusResult {\n const {\n isEnabled = true,\n priority = 0,\n delay = 0,\n force = false,\n preventScroll = true,\n onFocus,\n onSkip,\n } = options;\n\n // During SSR, return no-op functions\n if (isServer) {\n return {\n focus: () => {},\n cancel: () => {},\n };\n }\n\n let canceled = false;\n\n // Queue auto-focus on mount\n onMount(() => {\n if (!isEnabled || canceled) return;\n\n queueAutoFocus({\n ref,\n priority,\n delay,\n force,\n preventScroll,\n onFocus,\n onSkip,\n });\n });\n\n // Remove from queue on cleanup\n onCleanup(() => {\n removeFromQueue(ref);\n });\n\n const focus = (): void => {\n if (canceled) return;\n\n const element = ref();\n if (!element) return;\n\n if (preventScroll) {\n focusSafely(element);\n } else {\n element.focus();\n }\n onFocus?.(element);\n };\n\n const cancel = (): void => {\n canceled = true;\n removeFromQueue(ref);\n };\n\n return {\n focus,\n cancel,\n };\n}\n\n/**\n * Clears all pending auto-focus requests.\n * Useful for testing or when navigating away.\n */\nexport function clearAutoFocusQueue(): void {\n if (processingTimeout) {\n clearTimeout(processingTimeout);\n processingTimeout = null;\n }\n autoFocusQueue = [];\n}\n\n/**\n * Gets the current auto-focus queue length.\n * Useful for debugging.\n */\nexport function getAutoFocusQueueLength(): number {\n return autoFocusQueue.length;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"focus2.jsx","names":["getActiveElement"],"sources":["../../src/focus/createFocusRestore.ts","../../src/focus/createVirtualFocus.ts","../../src/focus/virtualFocus.ts","../../src/focus/createAutoFocus.ts"],"sourcesContent":["/**\n * Focus restoration utilities for solidaria\n *\n * Provides enhanced focus restoration with retry logic, cross-scope tracking,\n * and safe restoration patterns.\n */\n\nimport { createEffect, onCleanup, onMount } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { getOwnerDocument } from \"../utils\";\nimport { focusSafely } from \"../utils/focus\";\n\nexport interface FocusRestoreOptions {\n /**\n * Whether to restore focus when the component unmounts.\n * @default true\n */\n restoreOnUnmount?: boolean;\n /**\n * Maximum number of retries if the element is not in the DOM.\n * @default 3\n */\n maxRetries?: number;\n /**\n * Delay between retries in milliseconds.\n * @default 50\n */\n retryDelay?: number;\n /**\n * Callback when focus is successfully restored.\n */\n onRestore?: (element: HTMLElement) => void;\n /**\n * Callback when focus restoration fails.\n */\n onRestoreFailed?: () => void;\n /**\n * Whether to prevent scrolling when restoring focus.\n * @default true\n */\n preventScroll?: boolean;\n}\n\nexport interface FocusRestoreResult {\n /**\n * Manually restore focus to the saved element.\n */\n restore: () => boolean;\n /**\n * Get the saved element (if any).\n */\n getSavedElement: () => HTMLElement | null;\n /**\n * Save the currently focused element.\n */\n saveCurrentFocus: () => void;\n /**\n * Clear the saved element without restoring.\n */\n clear: () => void;\n}\n\n// Stack to track focus history across scopes\nconst focusStack: HTMLElement[] = [];\n\n/**\n * Push an element onto the focus stack.\n */\nexport function pushFocusStack(element: HTMLElement): void {\n focusStack.push(element);\n}\n\n/**\n * Pop the last element from the focus stack.\n */\nexport function popFocusStack(): HTMLElement | undefined {\n return focusStack.pop();\n}\n\n/**\n * Get the current focus stack length.\n */\nexport function getFocusStackLength(): number {\n return focusStack.length;\n}\n\n/**\n * Clear the entire focus stack.\n */\nexport function clearFocusStack(): void {\n focusStack.length = 0;\n}\n\n/**\n * Gets the active element, accounting for shadow DOM.\n */\nfunction getActiveElement(doc: Document): HTMLElement | null {\n let activeElement = doc.activeElement as HTMLElement | null;\n while (activeElement?.shadowRoot?.activeElement) {\n activeElement = activeElement.shadowRoot.activeElement as HTMLElement;\n }\n return activeElement;\n}\n\n/**\n * Checks if an element is still valid for focus restoration.\n */\nfunction isValidForRestore(element: HTMLElement | null): boolean {\n if (!element) return false;\n if (!document.body.contains(element)) return false;\n if (element.hasAttribute(\"disabled\")) return false;\n if (element.getAttribute(\"aria-disabled\") === \"true\") return false;\n if (element.getAttribute(\"aria-hidden\") === \"true\") return false;\n return true;\n}\n\n/**\n * Attempts to restore focus with retries.\n */\nfunction tryRestoreFocus(\n element: HTMLElement | null,\n options: Required<\n Pick<\n FocusRestoreOptions,\n \"maxRetries\" | \"retryDelay\" | \"preventScroll\" | \"onRestore\" | \"onRestoreFailed\"\n >\n >,\n): void {\n const { maxRetries, retryDelay, preventScroll, onRestore, onRestoreFailed } = options;\n let attempts = 0;\n\n const attempt = () => {\n if (!element) {\n onRestoreFailed?.();\n return;\n }\n\n if (isValidForRestore(element)) {\n if (preventScroll) {\n focusSafely(element);\n } else {\n element.focus();\n }\n onRestore?.(element);\n return;\n }\n\n attempts++;\n if (attempts < maxRetries) {\n setTimeout(attempt, retryDelay);\n } else {\n onRestoreFailed?.();\n }\n };\n\n // Use requestAnimationFrame for the first attempt to ensure DOM is ready\n requestAnimationFrame(attempt);\n}\n\n/**\n * Creates a focus restoration manager.\n *\n * This hook saves the currently focused element when mounted and provides\n * methods to restore focus later, with retry logic for reliability.\n *\n * @example\n * ```tsx\n * function Modal(props) {\n * const focusRestore = createFocusRestore({\n * restoreOnUnmount: true,\n * onRestore: () => console.log('Focus restored'),\n * });\n *\n * return (\n * <div role=\"dialog\">\n * {props.children}\n * <button onClick={() => focusRestore.restore()}>\n * Close\n * </button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Manual focus management\n * function Dropdown() {\n * const focusRestore = createFocusRestore({ restoreOnUnmount: false });\n *\n * const onOpen = () => {\n * focusRestore.saveCurrentFocus();\n * // Focus dropdown content\n * };\n *\n * const onClose = () => {\n * focusRestore.restore();\n * };\n *\n * return <div>...</div>;\n * }\n * ```\n */\nexport function createFocusRestore(options: FocusRestoreOptions = {}): FocusRestoreResult {\n const {\n restoreOnUnmount = true,\n maxRetries = 3,\n retryDelay = 50,\n onRestore,\n onRestoreFailed,\n preventScroll = true,\n } = options;\n\n // During SSR, return no-op functions\n if (isServer) {\n return {\n restore: () => false,\n getSavedElement: () => null,\n saveCurrentFocus: () => {},\n clear: () => {},\n };\n }\n\n let savedElement: HTMLElement | null = null;\n\n // Save focus on mount\n onMount(() => {\n saveCurrentFocus();\n });\n\n // Restore focus on cleanup\n onCleanup(() => {\n if (restoreOnUnmount && savedElement) {\n tryRestoreFocus(savedElement, {\n maxRetries,\n retryDelay,\n preventScroll,\n onRestore: onRestore ?? (() => {}),\n onRestoreFailed: onRestoreFailed ?? (() => {}),\n });\n }\n });\n\n function saveCurrentFocus(): void {\n const doc = typeof document !== \"undefined\" ? document : null;\n if (!doc) return;\n\n const active = getActiveElement(doc);\n if (active && active !== doc.body) {\n savedElement = active;\n pushFocusStack(active);\n }\n }\n\n function restore(): boolean {\n if (!savedElement) return false;\n\n if (isValidForRestore(savedElement)) {\n if (preventScroll) {\n focusSafely(savedElement);\n } else {\n savedElement.focus();\n }\n onRestore?.(savedElement);\n return true;\n }\n\n // Try the focus stack\n while (focusStack.length > 0) {\n const stackElement = popFocusStack();\n if (stackElement && isValidForRestore(stackElement)) {\n if (preventScroll) {\n focusSafely(stackElement);\n } else {\n stackElement.focus();\n }\n onRestore?.(stackElement);\n return true;\n }\n }\n\n onRestoreFailed?.();\n return false;\n }\n\n function getSavedElement(): HTMLElement | null {\n return savedElement;\n }\n\n function clear(): void {\n savedElement = null;\n }\n\n return {\n restore,\n getSavedElement,\n saveCurrentFocus,\n clear,\n };\n}\n","/**\n * Virtual focus management for solidaria\n *\n * Provides virtual focus for large collections where tracking DOM focus\n * on every item is impractical. Instead, a single element receives real\n * focus while aria-activedescendant indicates the virtually focused item.\n *\n * This is commonly used in:\n * - Virtualized lists (where not all items are in the DOM)\n * - Large trees\n * - Autocomplete/combobox suggestions\n * - Grid/table navigation\n */\n\nimport { type Accessor, createSignal, createEffect, onCleanup } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\n\nexport interface VirtualFocusOptions<T> {\n /**\n * The items in the collection.\n */\n items: Accessor<T[]>;\n /**\n * Function to get a unique key for each item.\n */\n getKey: (item: T) => string;\n /**\n * Function to check if an item is disabled.\n */\n isDisabled?: (item: T) => boolean;\n /**\n * Initial focused key.\n */\n defaultFocusedKey?: string;\n /**\n * Controlled focused key.\n */\n focusedKey?: Accessor<string | null>;\n /**\n * Callback when focused key changes.\n */\n onFocusChange?: (key: string | null) => void;\n /**\n * Whether to wrap focus at the edges.\n * @default true\n */\n wrap?: boolean;\n /**\n * Whether to loop through disabled items.\n * @default false\n */\n skipDisabled?: boolean;\n /**\n * Orientation for keyboard navigation.\n * @default 'vertical'\n */\n orientation?: \"horizontal\" | \"vertical\" | \"both\";\n}\n\nexport interface VirtualFocusResult<T> {\n /**\n * The currently focused key.\n */\n focusedKey: Accessor<string | null>;\n /**\n * The currently focused item (if any).\n */\n focusedItem: Accessor<T | null>;\n /**\n * Set the focused key.\n */\n setFocusedKey: (key: string | null) => void;\n /**\n * Move focus to the next item.\n */\n focusNext: () => void;\n /**\n * Move focus to the previous item.\n */\n focusPrevious: () => void;\n /**\n * Move focus to the first item.\n */\n focusFirst: () => void;\n /**\n * Move focus to the last item.\n */\n focusLast: () => void;\n /**\n * Move focus by a page (for large lists).\n */\n focusPageDown: (pageSize?: number) => void;\n /**\n * Move focus up by a page (for large lists).\n */\n focusPageUp: (pageSize?: number) => void;\n /**\n * Check if a key is the currently focused key.\n */\n isFocused: (key: string) => boolean;\n /**\n * Props to spread on the container element.\n */\n containerProps: {\n \"aria-activedescendant\": Accessor<string | undefined>;\n onKeyDown: (e: KeyboardEvent) => void;\n };\n /**\n * Get props for an item element.\n */\n getItemProps: (key: string) => {\n id: string;\n \"aria-selected\"?: boolean;\n };\n}\n\nconst DEFAULT_PAGE_SIZE = 10;\n\n/**\n * Creates virtual focus management for a collection.\n *\n * Virtual focus uses aria-activedescendant to indicate which item is\n * \"focused\" while keeping real DOM focus on a container element. This\n * is more performant for large collections and required for virtualized\n * lists where items may not be in the DOM.\n *\n * @example\n * ```tsx\n * function Listbox(props) {\n * const virtualFocus = createVirtualFocus({\n * items: () => props.items,\n * getKey: (item) => item.id,\n * isDisabled: (item) => item.disabled,\n * });\n *\n * return (\n * <ul\n * role=\"listbox\"\n * tabIndex={0}\n * aria-activedescendant={virtualFocus.containerProps['aria-activedescendant']()}\n * onKeyDown={virtualFocus.containerProps.onKeyDown}\n * >\n * <For each={props.items}>\n * {(item) => (\n * <li\n * {...virtualFocus.getItemProps(item.id)}\n * role=\"option\"\n * aria-selected={virtualFocus.isFocused(item.id)}\n * >\n * {item.name}\n * </li>\n * )}\n * </For>\n * </ul>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With controlled focus\n * function ControlledListbox() {\n * const [focusedKey, setFocusedKey] = createSignal<string | null>(null);\n *\n * const virtualFocus = createVirtualFocus({\n * items: () => items,\n * getKey: (item) => item.id,\n * focusedKey: focusedKey,\n * onFocusChange: setFocusedKey,\n * });\n *\n * return <ul>...</ul>;\n * }\n * ```\n */\nexport function createVirtualFocus<T>(options: VirtualFocusOptions<T>): VirtualFocusResult<T> {\n const {\n items,\n getKey,\n isDisabled = () => false,\n defaultFocusedKey,\n focusedKey: controlledFocusedKey,\n onFocusChange,\n wrap = true,\n skipDisabled = true,\n orientation = \"vertical\",\n } = options;\n\n // During SSR, return minimal implementation\n if (isServer) {\n const emptyAccessor = () => null;\n return {\n focusedKey: emptyAccessor,\n focusedItem: emptyAccessor,\n setFocusedKey: () => {},\n focusNext: () => {},\n focusPrevious: () => {},\n focusFirst: () => {},\n focusLast: () => {},\n focusPageDown: () => {},\n focusPageUp: () => {},\n isFocused: () => false,\n containerProps: {\n \"aria-activedescendant\": () => undefined,\n onKeyDown: () => {},\n },\n getItemProps: (key: string) => ({ id: `item-${key}` }),\n };\n }\n\n // Internal state for uncontrolled mode\n const [internalKey, setInternalKey] = createSignal<string | null>(defaultFocusedKey ?? null);\n\n // Use controlled or uncontrolled value\n const focusedKey = controlledFocusedKey ?? internalKey;\n\n const setFocusedKey = (key: string | null) => {\n if (controlledFocusedKey) {\n onFocusChange?.(key);\n } else {\n setInternalKey(key);\n onFocusChange?.(key);\n }\n };\n\n // Get focused item\n const focusedItem = (): T | null => {\n const key = focusedKey();\n if (!key) return null;\n return items().find((item) => getKey(item) === key) ?? null;\n };\n\n // Get valid items (not disabled if skipDisabled is true)\n const getValidItems = (): T[] => {\n if (!skipDisabled) return items();\n return items().filter((item) => !isDisabled(item));\n };\n\n // Get index of key in valid items\n const getKeyIndex = (key: string | null): number => {\n if (!key) return -1;\n const validItems = getValidItems();\n return validItems.findIndex((item) => getKey(item) === key);\n };\n\n // Focus by index\n const focusByIndex = (index: number): void => {\n const validItems = getValidItems();\n if (validItems.length === 0) return;\n\n let targetIndex = index;\n\n if (wrap) {\n targetIndex = ((index % validItems.length) + validItems.length) % validItems.length;\n } else {\n targetIndex = Math.max(0, Math.min(index, validItems.length - 1));\n }\n\n const item = validItems[targetIndex];\n if (item) {\n setFocusedKey(getKey(item));\n }\n };\n\n const focusNext = (): void => {\n const currentIndex = getKeyIndex(focusedKey());\n focusByIndex(currentIndex + 1);\n };\n\n const focusPrevious = (): void => {\n const currentIndex = getKeyIndex(focusedKey());\n if (currentIndex === -1) {\n focusByIndex(getValidItems().length - 1);\n } else {\n focusByIndex(currentIndex - 1);\n }\n };\n\n const focusFirst = (): void => {\n focusByIndex(0);\n };\n\n const focusLast = (): void => {\n focusByIndex(getValidItems().length - 1);\n };\n\n const focusPageDown = (pageSize: number = DEFAULT_PAGE_SIZE): void => {\n const currentIndex = getKeyIndex(focusedKey());\n focusByIndex(currentIndex + pageSize);\n };\n\n const focusPageUp = (pageSize: number = DEFAULT_PAGE_SIZE): void => {\n const currentIndex = getKeyIndex(focusedKey());\n if (currentIndex === -1) {\n focusByIndex(getValidItems().length - 1);\n } else {\n focusByIndex(currentIndex - pageSize);\n }\n };\n\n const isFocused = (key: string): boolean => {\n return focusedKey() === key;\n };\n\n // Keyboard handler\n const onKeyDown = (e: KeyboardEvent): void => {\n const isVertical = orientation === \"vertical\" || orientation === \"both\";\n const isHorizontal = orientation === \"horizontal\" || orientation === \"both\";\n\n switch (e.key) {\n case \"ArrowDown\":\n if (isVertical) {\n e.preventDefault();\n focusNext();\n }\n break;\n case \"ArrowUp\":\n if (isVertical) {\n e.preventDefault();\n focusPrevious();\n }\n break;\n case \"ArrowRight\":\n if (isHorizontal) {\n e.preventDefault();\n focusNext();\n }\n break;\n case \"ArrowLeft\":\n if (isHorizontal) {\n e.preventDefault();\n focusPrevious();\n }\n break;\n case \"Home\":\n e.preventDefault();\n focusFirst();\n break;\n case \"End\":\n e.preventDefault();\n focusLast();\n break;\n case \"PageDown\":\n e.preventDefault();\n focusPageDown();\n break;\n case \"PageUp\":\n e.preventDefault();\n focusPageUp();\n break;\n }\n };\n\n const containerProps = {\n \"aria-activedescendant\": () => {\n const key = focusedKey();\n return key ? `item-${key}` : undefined;\n },\n onKeyDown,\n };\n\n const getItemProps = (key: string) => ({\n id: `item-${key}`,\n });\n\n return {\n focusedKey,\n focusedItem,\n setFocusedKey,\n focusNext,\n focusPrevious,\n focusFirst,\n focusLast,\n focusPageDown,\n focusPageUp,\n isFocused,\n containerProps,\n getItemProps,\n };\n}\n","/**\n * Virtual-focus event dispatch primitives.\n *\n * A faithful port of @react-aria/focus's `virtualFocus` module. Under virtual\n * focus (e.g. Autocomplete), real DOM focus stays on an input while the\n * \"focused\" collection option is indicated by `aria-activedescendant`. Moving\n * that virtual cursor dispatches synthetic `focus`/`blur` events (with matching\n * bubbling `focusin`/`focusout`) on the option elements so listeners — notably\n * the autocomplete input's `focusin` handler that mirrors the active descendant\n * — react as if the element were really focused.\n */\n\nimport { getActiveElement, getOwnerDocument } from \"../utils/dom\";\n\n/**\n * Moves virtual focus to `to`, dispatching a virtual blur on the previously\n * virtually-focused element (if any) and a virtual focus on `to` (if non-null).\n */\nexport function moveVirtualFocus(to: Element | null): void {\n const from = getVirtuallyFocusedElement(getOwnerDocument(to));\n if (from !== to) {\n if (from) {\n dispatchVirtualBlur(from, to);\n }\n if (to) {\n dispatchVirtualFocus(to, from);\n }\n }\n}\n\n/** Dispatches synthetic `blur` + bubbling `focusout` events on `from`. */\nexport function dispatchVirtualBlur(from: Element, to: Element | null): void {\n from.dispatchEvent(new FocusEvent(\"blur\", { relatedTarget: to }));\n from.dispatchEvent(new FocusEvent(\"focusout\", { bubbles: true, relatedTarget: to }));\n}\n\n/** Dispatches synthetic `focus` + bubbling `focusin` events on `to`. */\nexport function dispatchVirtualFocus(to: Element, from: Element | null): void {\n to.dispatchEvent(new FocusEvent(\"focus\", { relatedTarget: from }));\n to.dispatchEvent(new FocusEvent(\"focusin\", { bubbles: true, relatedTarget: from }));\n}\n\n/**\n * Returns the currently virtually-focused element: the element referenced by the\n * active element's `aria-activedescendant`, or the active element itself.\n */\nexport function getVirtuallyFocusedElement(document: Document): Element | null {\n const activeElement = getActiveElement(document);\n const activeDescendant = activeElement?.getAttribute(\"aria-activedescendant\");\n if (activeDescendant) {\n return document.getElementById(activeDescendant) || activeElement;\n }\n\n return activeElement;\n}\n","/**\n * Auto-focus management for solidaria\n *\n * Provides priority-based auto-focus with deferred execution\n * and conflict resolution for multiple auto-focus elements.\n */\n\nimport { createEffect, onCleanup, onMount } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { focusSafely } from \"../utils/focus\";\n\nexport interface AutoFocusOptions {\n /**\n * Whether auto-focus is enabled.\n * @default true\n */\n isEnabled?: boolean;\n /**\n * Priority level (higher = more important).\n * When multiple elements request auto-focus, the highest priority wins.\n * @default 0\n */\n priority?: number;\n /**\n * Delay in milliseconds before focusing.\n * Useful for animations or transitions.\n * @default 0\n */\n delay?: number;\n /**\n * Whether to focus even if another element is already focused.\n * @default false\n */\n force?: boolean;\n /**\n * Whether to prevent scrolling when focusing.\n * @default true\n */\n preventScroll?: boolean;\n /**\n * Callback when focus is applied.\n */\n onFocus?: (element: HTMLElement) => void;\n /**\n * Callback when focus is skipped (due to lower priority or other reasons).\n */\n onSkip?: () => void;\n}\n\nexport interface AutoFocusResult {\n /**\n * Manually trigger the auto-focus.\n */\n focus: () => void;\n /**\n * Cancel any pending auto-focus.\n */\n cancel: () => void;\n}\n\ninterface QueuedFocus {\n ref: () => HTMLElement | null | undefined;\n priority: number;\n delay: number;\n force: boolean;\n preventScroll: boolean;\n onFocus?: (element: HTMLElement) => void;\n onSkip?: () => void;\n}\n\n// Global queue for managing auto-focus requests\nlet autoFocusQueue: QueuedFocus[] = [];\nlet processingTimeout: ReturnType<typeof setTimeout> | null = null;\n\n/**\n * Process the auto-focus queue and focus the highest priority element.\n */\nfunction processAutoFocusQueue(): void {\n if (processingTimeout) {\n clearTimeout(processingTimeout);\n processingTimeout = null;\n }\n\n if (autoFocusQueue.length === 0) return;\n\n // Sort by priority (highest first)\n autoFocusQueue.sort((a, b) => b.priority - a.priority);\n\n // Get the highest priority item\n const winner = autoFocusQueue[0];\n const losers = autoFocusQueue.slice(1);\n\n // Clear the queue\n autoFocusQueue = [];\n\n // Notify losers\n for (const loser of losers) {\n loser.onSkip?.();\n }\n\n // Focus the winner\n const element = winner.ref();\n if (!element) {\n winner.onSkip?.();\n return;\n }\n\n // Check if we should focus\n const activeElement = document.activeElement;\n const shouldFocus =\n winner.force ||\n !activeElement ||\n activeElement === document.body ||\n activeElement === document.documentElement;\n\n if (!shouldFocus) {\n winner.onSkip?.();\n return;\n }\n\n // Apply focus with optional delay\n if (winner.delay > 0) {\n setTimeout(() => {\n const el = winner.ref();\n if (el && document.body.contains(el)) {\n if (winner.preventScroll) {\n focusSafely(el);\n } else {\n el.focus();\n }\n winner.onFocus?.(el);\n }\n }, winner.delay);\n } else {\n if (winner.preventScroll) {\n focusSafely(element);\n } else {\n element.focus();\n }\n winner.onFocus?.(element);\n }\n}\n\n/**\n * Queue an element for auto-focus.\n */\nfunction queueAutoFocus(item: QueuedFocus): void {\n autoFocusQueue.push(item);\n\n // Schedule processing on next frame to allow all components to register\n if (processingTimeout === null) {\n processingTimeout = setTimeout(processAutoFocusQueue, 0);\n }\n}\n\n/**\n * Remove an item from the auto-focus queue.\n */\nfunction removeFromQueue(ref: () => HTMLElement | null | undefined): void {\n autoFocusQueue = autoFocusQueue.filter((item) => item.ref !== ref);\n}\n\n/**\n * Creates auto-focus behavior for an element.\n *\n * This hook registers the element for auto-focus when mounted. If multiple\n * elements request auto-focus, the one with the highest priority wins.\n *\n * @param ref - Accessor for the element to focus\n * @param options - Auto-focus options\n *\n * @example\n * ```tsx\n * function Dialog(props) {\n * let contentRef: HTMLDivElement | undefined;\n *\n * createAutoFocus(() => contentRef, {\n * priority: 10, // High priority for dialogs\n * onFocus: () => console.log('Dialog focused'),\n * });\n *\n * return (\n * <div ref={contentRef} tabIndex={-1}>\n * {props.children}\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With delay for animations\n * function AnimatedPanel() {\n * let panelRef: HTMLDivElement | undefined;\n *\n * createAutoFocus(() => panelRef, {\n * delay: 300, // Wait for animation\n * });\n *\n * return <div ref={panelRef} class=\"animated-panel\">...</div>;\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Conditional auto-focus\n * function Input(props) {\n * let inputRef: HTMLInputElement | undefined;\n *\n * createAutoFocus(() => inputRef, {\n * isEnabled: props.autoFocus,\n * });\n *\n * return <input ref={inputRef} />;\n * }\n * ```\n */\nexport function createAutoFocus(\n ref: () => HTMLElement | null | undefined,\n options: AutoFocusOptions = {},\n): AutoFocusResult {\n const {\n isEnabled = true,\n priority = 0,\n delay = 0,\n force = false,\n preventScroll = true,\n onFocus,\n onSkip,\n } = options;\n\n // During SSR, return no-op functions\n if (isServer) {\n return {\n focus: () => {},\n cancel: () => {},\n };\n }\n\n let canceled = false;\n\n // Queue auto-focus on mount\n onMount(() => {\n if (!isEnabled || canceled) return;\n\n queueAutoFocus({\n ref,\n priority,\n delay,\n force,\n preventScroll,\n onFocus,\n onSkip,\n });\n });\n\n // Remove from queue on cleanup\n onCleanup(() => {\n removeFromQueue(ref);\n });\n\n const focus = (): void => {\n if (canceled) return;\n\n const element = ref();\n if (!element) return;\n\n if (preventScroll) {\n focusSafely(element);\n } else {\n element.focus();\n }\n onFocus?.(element);\n };\n\n const cancel = (): void => {\n canceled = true;\n removeFromQueue(ref);\n };\n\n return {\n focus,\n cancel,\n };\n}\n\n/**\n * Clears all pending auto-focus requests.\n * Useful for testing or when navigating away.\n */\nexport function clearAutoFocusQueue(): void {\n if (processingTimeout) {\n clearTimeout(processingTimeout);\n processingTimeout = null;\n }\n autoFocusQueue = [];\n}\n\n/**\n * Gets the current auto-focus queue length.\n * Useful for debugging.\n */\nexport function getAutoFocusQueueLength(): number {\n return autoFocusQueue.length;\n}\n"],"mappings":";;;;;;;;;;AA+DA,MAAM,aAA4B,CAAC;;;;AAKnC,SAAgB,eAAe,SAA4B;CACzD,WAAW,KAAK,OAAO;AACzB;;;;AAKA,SAAgB,gBAAyC;CACvD,OAAO,WAAW,IAAI;AACxB;;;;AAKA,SAAgB,sBAA8B;CAC5C,OAAO,WAAW;AACpB;;;;AAKA,SAAgB,kBAAwB;CACtC,WAAW,SAAS;AACtB;;;;AAKA,SAAS,iBAAiB,KAAmC;CAC3D,IAAI,gBAAgB,IAAI;CACxB,OAAO,eAAe,YAAY,eAChC,gBAAgB,cAAc,WAAW;CAE3C,OAAO;AACT;;;;AAKA,SAAS,kBAAkB,SAAsC;CAC/D,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI,CAAC,SAAS,KAAK,SAAS,OAAO,GAAG,OAAO;CAC7C,IAAI,QAAQ,aAAa,UAAU,GAAG,OAAO;CAC7C,IAAI,QAAQ,aAAa,eAAe,MAAM,QAAQ,OAAO;CAC7D,IAAI,QAAQ,aAAa,aAAa,MAAM,QAAQ,OAAO;CAC3D,OAAO;AACT;;;;AAKA,SAAS,gBACP,SACA,SAMM;CACN,MAAM,EAAE,YAAY,YAAY,eAAe,WAAW,oBAAoB;CAC9E,IAAI,WAAW;CAEf,MAAM,gBAAgB;EACpB,IAAI,CAAC,SAAS;GACZ,kBAAkB;GAClB;EACF;EAEA,IAAI,kBAAkB,OAAO,GAAG;GAC9B,IAAI,eACF,YAAY,OAAO;QAEnB,QAAQ,MAAM;GAEhB,YAAY,OAAO;GACnB;EACF;EAEA;EACA,IAAI,WAAW,YACb,WAAW,SAAS,UAAU;OAE9B,kBAAkB;CAEtB;CAGA,sBAAsB,OAAO;AAC/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,mBAAmB,UAA+B,CAAC,GAAuB;CACxF,MAAM,EACJ,mBAAmB,MACnB,aAAa,GACb,aAAa,IACb,WACA,iBACA,gBAAgB,SACd;CAGJ,IAAI,UACF,OAAO;EACL,eAAe;EACf,uBAAuB;EACvB,wBAAwB,CAAC;EACzB,aAAa,CAAC;CAChB;CAGF,IAAI,eAAmC;CAGvC,cAAc;EACZ,iBAAiB;CACnB,CAAC;CAGD,gBAAgB;EACd,IAAI,oBAAoB,cACtB,gBAAgB,cAAc;GAC5B;GACA;GACA;GACA,WAAW,oBAAoB,CAAC;GAChC,iBAAiB,0BAA0B,CAAC;EAC9C,CAAC;CAEL,CAAC;CAED,SAAS,mBAAyB;EAChC,MAAM,MAAM,OAAO,aAAa,cAAc,WAAW;EACzD,IAAI,CAAC,KAAK;EAEV,MAAM,SAAS,iBAAiB,GAAG;EACnC,IAAI,UAAU,WAAW,IAAI,MAAM;GACjC,eAAe;GACf,eAAe,MAAM;EACvB;CACF;CAEA,SAAS,UAAmB;EAC1B,IAAI,CAAC,cAAc,OAAO;EAE1B,IAAI,kBAAkB,YAAY,GAAG;GACnC,IAAI,eACF,YAAY,YAAY;QAExB,aAAa,MAAM;GAErB,YAAY,YAAY;GACxB,OAAO;EACT;EAGA,OAAO,WAAW,SAAS,GAAG;GAC5B,MAAM,eAAe,cAAc;GACnC,IAAI,gBAAgB,kBAAkB,YAAY,GAAG;IACnD,IAAI,eACF,YAAY,YAAY;SAExB,aAAa,MAAM;IAErB,YAAY,YAAY;IACxB,OAAO;GACT;EACF;EAEA,kBAAkB;EAClB,OAAO;CACT;CAEA,SAAS,kBAAsC;EAC7C,OAAO;CACT;CAEA,SAAS,QAAc;EACrB,eAAe;CACjB;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF;;;;;;;;;;;;;;;;ACvLA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2D1B,SAAgB,mBAAsB,SAAwD;CAC5F,MAAM,EACJ,OACA,QACA,mBAAmB,OACnB,mBACA,YAAY,sBACZ,eACA,OAAO,MACP,eAAe,MACf,cAAc,eACZ;CAGJ,IAAI,UAAU;EACZ,MAAM,sBAAsB;EAC5B,OAAO;GACL,YAAY;GACZ,aAAa;GACb,qBAAqB,CAAC;GACtB,iBAAiB,CAAC;GAClB,qBAAqB,CAAC;GACtB,kBAAkB,CAAC;GACnB,iBAAiB,CAAC;GAClB,qBAAqB,CAAC;GACtB,mBAAmB,CAAC;GACpB,iBAAiB;GACjB,gBAAgB;IACd,+BAA+B,KAAA;IAC/B,iBAAiB,CAAC;GACpB;GACA,eAAe,SAAiB,EAAE,IAAI,QAAQ,MAAM;EACtD;CACF;CAGA,MAAM,CAAC,aAAa,kBAAkB,aAA4B,qBAAqB,IAAI;CAG3F,MAAM,aAAa,wBAAwB;CAE3C,MAAM,iBAAiB,QAAuB;EAC5C,IAAI,sBACF,gBAAgB,GAAG;OACd;GACL,eAAe,GAAG;GAClB,gBAAgB,GAAG;EACrB;CACF;CAGA,MAAM,oBAA8B;EAClC,MAAM,MAAM,WAAW;EACvB,IAAI,CAAC,KAAK,OAAO;EACjB,OAAO,MAAM,CAAC,CAAC,MAAM,SAAS,OAAO,IAAI,MAAM,GAAG,KAAK;CACzD;CAGA,MAAM,sBAA2B;EAC/B,IAAI,CAAC,cAAc,OAAO,MAAM;EAChC,OAAO,MAAM,CAAC,CAAC,QAAQ,SAAS,CAAC,WAAW,IAAI,CAAC;CACnD;CAGA,MAAM,eAAe,QAA+B;EAClD,IAAI,CAAC,KAAK,OAAO;EAEjB,OADmB,cACH,CAAC,CAAC,WAAW,SAAS,OAAO,IAAI,MAAM,GAAG;CAC5D;CAGA,MAAM,gBAAgB,UAAwB;EAC5C,MAAM,aAAa,cAAc;EACjC,IAAI,WAAW,WAAW,GAAG;EAE7B,IAAI,cAAc;EAElB,IAAI,MACF,eAAgB,QAAQ,WAAW,SAAU,WAAW,UAAU,WAAW;OAE7E,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,WAAW,SAAS,CAAC,CAAC;EAGlE,MAAM,OAAO,WAAW;EACxB,IAAI,MACF,cAAc,OAAO,IAAI,CAAC;CAE9B;CAEA,MAAM,kBAAwB;EAE5B,aADqB,YAAY,WAAW,CACpB,IAAI,CAAC;CAC/B;CAEA,MAAM,sBAA4B;EAChC,MAAM,eAAe,YAAY,WAAW,CAAC;EAC7C,IAAI,iBAAiB,IACnB,aAAa,cAAc,CAAC,CAAC,SAAS,CAAC;OAEvC,aAAa,eAAe,CAAC;CAEjC;CAEA,MAAM,mBAAyB;EAC7B,aAAa,CAAC;CAChB;CAEA,MAAM,kBAAwB;EAC5B,aAAa,cAAc,CAAC,CAAC,SAAS,CAAC;CACzC;CAEA,MAAM,iBAAiB,WAAmB,sBAA4B;EAEpE,aADqB,YAAY,WAAW,CACpB,IAAI,QAAQ;CACtC;CAEA,MAAM,eAAe,WAAmB,sBAA4B;EAClE,MAAM,eAAe,YAAY,WAAW,CAAC;EAC7C,IAAI,iBAAiB,IACnB,aAAa,cAAc,CAAC,CAAC,SAAS,CAAC;OAEvC,aAAa,eAAe,QAAQ;CAExC;CAEA,MAAM,aAAa,QAAyB;EAC1C,OAAO,WAAW,MAAM;CAC1B;CAGA,MAAM,aAAa,MAA2B;EAC5C,MAAM,aAAa,gBAAgB,cAAc,gBAAgB;EACjE,MAAM,eAAe,gBAAgB,gBAAgB,gBAAgB;EAErE,QAAQ,EAAE,KAAV;GACE,KAAK;IACH,IAAI,YAAY;KACd,EAAE,eAAe;KACjB,UAAU;IACZ;IACA;GACF,KAAK;IACH,IAAI,YAAY;KACd,EAAE,eAAe;KACjB,cAAc;IAChB;IACA;GACF,KAAK;IACH,IAAI,cAAc;KAChB,EAAE,eAAe;KACjB,UAAU;IACZ;IACA;GACF,KAAK;IACH,IAAI,cAAc;KAChB,EAAE,eAAe;KACjB,cAAc;IAChB;IACA;GACF,KAAK;IACH,EAAE,eAAe;IACjB,WAAW;IACX;GACF,KAAK;IACH,EAAE,eAAe;IACjB,UAAU;IACV;GACF,KAAK;IACH,EAAE,eAAe;IACjB,cAAc;IACd;GACF,KAAK;IACH,EAAE,eAAe;IACjB,YAAY;IACZ;EACJ;CACF;CAEA,MAAM,iBAAiB;EACrB,+BAA+B;GAC7B,MAAM,MAAM,WAAW;GACvB,OAAO,MAAM,QAAQ,QAAQ,KAAA;EAC/B;EACA;CACF;CAEA,MAAM,gBAAgB,SAAiB,EACrC,IAAI,QAAQ,MACd;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;;;;;;;;;;;;;;;ACzWA,SAAgB,iBAAiB,IAA0B;CACzD,MAAM,OAAO,2BAA2B,iBAAiB,EAAE,CAAC;CAC5D,IAAI,SAAS,IAAI;EACf,IAAI,MACF,oBAAoB,MAAM,EAAE;EAE9B,IAAI,IACF,qBAAqB,IAAI,IAAI;CAEjC;AACF;;AAGA,SAAgB,oBAAoB,MAAe,IAA0B;CAC3E,KAAK,cAAc,IAAI,WAAW,QAAQ,EAAE,eAAe,GAAG,CAAC,CAAC;CAChE,KAAK,cAAc,IAAI,WAAW,YAAY;EAAE,SAAS;EAAM,eAAe;CAAG,CAAC,CAAC;AACrF;;AAGA,SAAgB,qBAAqB,IAAa,MAA4B;CAC5E,GAAG,cAAc,IAAI,WAAW,SAAS,EAAE,eAAe,KAAK,CAAC,CAAC;CACjE,GAAG,cAAc,IAAI,WAAW,WAAW;EAAE,SAAS;EAAM,eAAe;CAAK,CAAC,CAAC;AACpF;;;;;AAMA,SAAgB,2BAA2B,UAAoC;CAC7E,MAAM,gBAAgBA,mBAAiB,QAAQ;CAC/C,MAAM,mBAAmB,eAAe,aAAa,uBAAuB;CAC5E,IAAI,kBACF,OAAO,SAAS,eAAe,gBAAgB,KAAK;CAGtD,OAAO;AACT;;;;;;;;;ACiBA,IAAI,iBAAgC,CAAC;AACrC,IAAI,oBAA0D;;;;AAK9D,SAAS,wBAA8B;CACrC,IAAI,mBAAmB;EACrB,aAAa,iBAAiB;EAC9B,oBAAoB;CACtB;CAEA,IAAI,eAAe,WAAW,GAAG;CAGjC,eAAe,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;CAGrD,MAAM,SAAS,eAAe;CAC9B,MAAM,SAAS,eAAe,MAAM,CAAC;CAGrC,iBAAiB,CAAC;CAGlB,KAAK,MAAM,SAAS,QAClB,MAAM,SAAS;CAIjB,MAAM,UAAU,OAAO,IAAI;CAC3B,IAAI,CAAC,SAAS;EACZ,OAAO,SAAS;EAChB;CACF;CAGA,MAAM,gBAAgB,SAAS;CAO/B,IAAI,EALF,OAAO,SACP,CAAC,iBACD,kBAAkB,SAAS,QAC3B,kBAAkB,SAAS,kBAEX;EAChB,OAAO,SAAS;EAChB;CACF;CAGA,IAAI,OAAO,QAAQ,GACjB,iBAAiB;EACf,MAAM,KAAK,OAAO,IAAI;EACtB,IAAI,MAAM,SAAS,KAAK,SAAS,EAAE,GAAG;GACpC,IAAI,OAAO,eACT,YAAY,EAAE;QAEd,GAAG,MAAM;GAEX,OAAO,UAAU,EAAE;EACrB;CACF,GAAG,OAAO,KAAK;MACV;EACL,IAAI,OAAO,eACT,YAAY,OAAO;OAEnB,QAAQ,MAAM;EAEhB,OAAO,UAAU,OAAO;CAC1B;AACF;;;;AAKA,SAAS,eAAe,MAAyB;CAC/C,eAAe,KAAK,IAAI;CAGxB,IAAI,sBAAsB,MACxB,oBAAoB,WAAW,uBAAuB,CAAC;AAE3D;;;;AAKA,SAAS,gBAAgB,KAAiD;CACxE,iBAAiB,eAAe,QAAQ,SAAS,KAAK,QAAQ,GAAG;AACnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,SAAgB,gBACd,KACA,UAA4B,CAAC,GACZ;CACjB,MAAM,EACJ,YAAY,MACZ,WAAW,GACX,QAAQ,GACR,QAAQ,OACR,gBAAgB,MAChB,SACA,WACE;CAGJ,IAAI,UACF,OAAO;EACL,aAAa,CAAC;EACd,cAAc,CAAC;CACjB;CAGF,IAAI,WAAW;CAGf,cAAc;EACZ,IAAI,CAAC,aAAa,UAAU;EAE5B,eAAe;GACb;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;CACH,CAAC;CAGD,gBAAgB;EACd,gBAAgB,GAAG;CACrB,CAAC;CAED,MAAM,cAAoB;EACxB,IAAI,UAAU;EAEd,MAAM,UAAU,IAAI;EACpB,IAAI,CAAC,SAAS;EAEd,IAAI,eACF,YAAY,OAAO;OAEnB,QAAQ,MAAM;EAEhB,UAAU,OAAO;CACnB;CAEA,MAAM,eAAqB;EACzB,WAAW;EACX,gBAAgB,GAAG;CACrB;CAEA,OAAO;EACL;EACA;CACF;AACF;;;;;AAMA,SAAgB,sBAA4B;CAC1C,IAAI,mBAAmB;EACrB,aAAa,iBAAiB;EAC9B,oBAAoB;CACtB;CACA,iBAAiB,CAAC;AACpB;;;;;AAMA,SAAgB,0BAAkC;CAChD,OAAO,eAAe;AACxB"}
@@ -1,4 +1,4 @@
1
- import { a as useLocale } from "./createCollator.js";
1
+ import { i as useLocale } from "./locale.js";
2
2
  import { createMemo, createSignal } from "solid-js";
3
3
  import { createId } from "@proyecto-viviana/solid-stately";
4
4
  //#region src/grid/GridKeyboardDelegate.ts
@@ -1,4 +1,4 @@
1
- import { a as useLocale } from "./createCollator.jsx";
1
+ import { i as useLocale } from "./locale.jsx";
2
2
  import { createMemo, createSignal } from "solid-js";
3
3
  import { createId } from "@proyecto-viviana/solid-stately";
4
4
  //#region src/grid/GridKeyboardDelegate.ts
@@ -1,4 +1,4 @@
1
- import { o as mergeProps } from "./env.js";
1
+ import { i as mergeProps$1 } from "./env.js";
2
2
  import { S as scrollIntoViewport } from "./utils.js";
3
3
  import { o as getInteractionModality } from "./createInteractionModality.js";
4
4
  import { createId as createId$1, createSlotId } from "../ssr/index.js";
@@ -88,7 +88,8 @@ function createGridList(props, state, ref) {
88
88
  }
89
89
  case "ArrowRight":
90
90
  case "ArrowLeft": {
91
- if (p.orientation !== "horizontal") break;
91
+ const behavior = p.keyboardNavigationBehavior ?? "arrow";
92
+ if (p.orientation !== "horizontal" || behavior !== "tab") break;
92
93
  e.preventDefault();
93
94
  const isRtl = p.direction === "rtl";
94
95
  const step = (e.key === "ArrowRight" ? !isRtl : isRtl) ? (k) => collection.getKeyAfter(k) : (k) => collection.getKeyBefore(k);
@@ -123,13 +124,17 @@ function createGridList(props, state, ref) {
123
124
  break;
124
125
  }
125
126
  };
126
- const onFocus = () => {
127
+ const onFocus = (e) => {
127
128
  const s = state();
129
+ const p = props();
128
130
  s.setFocused(true);
129
- if (s.focusedKey == null) {
130
- const firstKey = findNextNavigableKey(s, s.collection.getFirstKey(), (k) => s.collection.getKeyAfter(k));
131
- if (firstKey != null) s.setFocusedKey(firstKey);
132
- }
131
+ const container = e.currentTarget;
132
+ if (container && !container.contains(e.target)) return;
133
+ if (s.focusedKey != null || p.isDisabled) return;
134
+ const collection = s.collection;
135
+ const relatedTarget = e.relatedTarget;
136
+ const enterKey = relatedTarget && container && container.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING ? findNextNavigableKey(s, collection.getLastKey(), (k) => collection.getKeyBefore(k)) : findNextNavigableKey(s, collection.getFirstKey(), (k) => collection.getKeyAfter(k));
137
+ if (enterKey != null) s.setFocusedKey(enterKey);
133
138
  };
134
139
  const onBlur = () => {
135
140
  state().setFocused(false);
@@ -157,7 +162,7 @@ function createGridList(props, state, ref) {
157
162
  "aria-describedby": p["aria-describedby"],
158
163
  "aria-multiselectable": s.selectionMode === "multiple" ? true : void 0,
159
164
  "aria-disabled": p.isDisabled || void 0,
160
- tabIndex: p.isDisabled ? void 0 : 0,
165
+ tabIndex: p.isDisabled ? void 0 : s.focusedKey != null ? -1 : 0,
161
166
  onKeyDown,
162
167
  onFocus,
163
168
  onBlur
@@ -247,7 +252,7 @@ function createGridListItem(props, state, ref) {
247
252
  };
248
253
  if (p.isVirtualized && node.rowIndex != null) baseProps["aria-rowindex"] = node.rowIndex + 1;
249
254
  const gridListData = getGridListData(s);
250
- return mergeCollectionRowInteractionProps(mergeProps(selectableItem.itemProps, baseProps), {
255
+ return mergeCollectionRowInteractionProps(mergeProps$1(selectableItem.itemProps, baseProps), {
251
256
  ref,
252
257
  keyboardNavigationBehavior: () => gridListData?.keyboardNavigationBehavior ?? "arrow",
253
258
  direction: () => gridListData?.direction ?? "ltr"