@proyecto-viviana/solidaria 0.2.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (555) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -236
  3. package/dist/actiongroup/createActionGroup.d.ts +29 -0
  4. package/dist/actiongroup/createActionGroup.d.ts.map +1 -0
  5. package/dist/actiongroup/index.d.ts +2 -0
  6. package/dist/actiongroup/index.d.ts.map +1 -0
  7. package/dist/autocomplete/createAutocomplete.d.ts +16 -12
  8. package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
  9. package/dist/autocomplete/index.d.ts +1 -1
  10. package/dist/autocomplete/index.d.ts.map +1 -1
  11. package/dist/breadcrumbs/createBreadcrumbs.d.ts +11 -7
  12. package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
  13. package/dist/breadcrumbs/index.d.ts +1 -1
  14. package/dist/button/createButton.d.ts +1 -1
  15. package/dist/button/createButton.d.ts.map +1 -1
  16. package/dist/button/createToggleButton.d.ts +3 -3
  17. package/dist/button/createToggleButtonGroup.d.ts +32 -0
  18. package/dist/button/createToggleButtonGroup.d.ts.map +1 -0
  19. package/dist/button/index.d.ts +6 -4
  20. package/dist/button/index.d.ts.map +1 -1
  21. package/dist/button/types.d.ts +18 -12
  22. package/dist/button/types.d.ts.map +1 -1
  23. package/dist/calendar/createCalendar.d.ts +15 -5
  24. package/dist/calendar/createCalendar.d.ts.map +1 -1
  25. package/dist/calendar/createCalendarCell.d.ts +8 -2
  26. package/dist/calendar/createCalendarCell.d.ts.map +1 -1
  27. package/dist/calendar/createCalendarGrid.d.ts +4 -4
  28. package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
  29. package/dist/calendar/createRangeCalendar.d.ts +15 -5
  30. package/dist/calendar/createRangeCalendar.d.ts.map +1 -1
  31. package/dist/calendar/createRangeCalendarCell.d.ts +7 -3
  32. package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
  33. package/dist/calendar/index.d.ts +5 -5
  34. package/dist/calendar/index.d.ts.map +1 -1
  35. package/dist/calendar/intl/index.d.ts +12 -0
  36. package/dist/calendar/intl/index.d.ts.map +1 -0
  37. package/dist/calendar/utils.d.ts +12 -0
  38. package/dist/calendar/utils.d.ts.map +1 -0
  39. package/dist/checkbox/createCheckbox.d.ts +6 -6
  40. package/dist/checkbox/createCheckbox.d.ts.map +1 -1
  41. package/dist/checkbox/createCheckboxGroup.d.ts +11 -7
  42. package/dist/checkbox/createCheckboxGroup.d.ts.map +1 -1
  43. package/dist/checkbox/createCheckboxGroupItem.d.ts +4 -4
  44. package/dist/checkbox/createCheckboxGroupItem.d.ts.map +1 -1
  45. package/dist/checkbox/createCheckboxGroupState.d.ts +2 -2
  46. package/dist/checkbox/createCheckboxGroupState.d.ts.map +1 -1
  47. package/dist/checkbox/index.d.ts +8 -8
  48. package/dist/checkbox/index.d.ts.map +1 -1
  49. package/dist/collections/index.d.ts +56 -0
  50. package/dist/collections/index.d.ts.map +1 -0
  51. package/dist/color/createColorArea.d.ts +3 -3
  52. package/dist/color/createColorArea.d.ts.map +1 -1
  53. package/dist/color/createColorField.d.ts +4 -4
  54. package/dist/color/createColorField.d.ts.map +1 -1
  55. package/dist/color/createColorSlider.d.ts +4 -4
  56. package/dist/color/createColorSlider.d.ts.map +1 -1
  57. package/dist/color/createColorSwatch.d.ts +2 -2
  58. package/dist/color/createColorSwatch.d.ts.map +1 -1
  59. package/dist/color/createColorWheel.d.ts +3 -3
  60. package/dist/color/createColorWheel.d.ts.map +1 -1
  61. package/dist/color/index.d.ts +6 -6
  62. package/dist/color/types.d.ts +98 -16
  63. package/dist/color/types.d.ts.map +1 -1
  64. package/dist/combobox/createComboBox.d.ts +16 -7
  65. package/dist/combobox/createComboBox.d.ts.map +1 -1
  66. package/dist/combobox/index.d.ts +1 -1
  67. package/dist/combobox/intl/index.d.ts +1 -1
  68. package/dist/datepicker/createDateField.d.ts +18 -6
  69. package/dist/datepicker/createDateField.d.ts.map +1 -1
  70. package/dist/datepicker/createDatePicker.d.ts +57 -5
  71. package/dist/datepicker/createDatePicker.d.ts.map +1 -1
  72. package/dist/datepicker/createDatePickerGroup.d.ts +19 -0
  73. package/dist/datepicker/createDatePickerGroup.d.ts.map +1 -0
  74. package/dist/datepicker/createDateRangePicker.d.ts +42 -0
  75. package/dist/datepicker/createDateRangePicker.d.ts.map +1 -0
  76. package/dist/datepicker/createDateSegment.d.ts +11 -3
  77. package/dist/datepicker/createDateSegment.d.ts.map +1 -1
  78. package/dist/datepicker/createTimeField.d.ts +11 -5
  79. package/dist/datepicker/createTimeField.d.ts.map +1 -1
  80. package/dist/datepicker/createTimeSegment.d.ts +29 -0
  81. package/dist/datepicker/createTimeSegment.d.ts.map +1 -0
  82. package/dist/datepicker/index.d.ts +7 -4
  83. package/dist/datepicker/index.d.ts.map +1 -1
  84. package/dist/dialog/createDialog.d.ts +5 -5
  85. package/dist/dialog/createDialog.d.ts.map +1 -1
  86. package/dist/dialog/index.d.ts +2 -2
  87. package/dist/dialog/index.d.ts.map +1 -1
  88. package/dist/dialog/types.d.ts +4 -4
  89. package/dist/disclosure/createDisclosure.d.ts +5 -2
  90. package/dist/disclosure/createDisclosure.d.ts.map +1 -1
  91. package/dist/disclosure/createDisclosureGroup.d.ts +4 -3
  92. package/dist/disclosure/createDisclosureGroup.d.ts.map +1 -1
  93. package/dist/disclosure/index.d.ts +2 -2
  94. package/dist/dnd/createDrag.d.ts +2 -2
  95. package/dist/dnd/createDrag.d.ts.map +1 -1
  96. package/dist/dnd/createDraggableCollection.d.ts +6 -2
  97. package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
  98. package/dist/dnd/createDraggableItem.d.ts +3 -3
  99. package/dist/dnd/createDraggableItem.d.ts.map +1 -1
  100. package/dist/dnd/createDrop.d.ts +2 -2
  101. package/dist/dnd/createDrop.d.ts.map +1 -1
  102. package/dist/dnd/createDroppableCollection.d.ts +55 -4
  103. package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
  104. package/dist/dnd/createDroppableItem.d.ts +3 -3
  105. package/dist/dnd/createDroppableItem.d.ts.map +1 -1
  106. package/dist/dnd/index.d.ts +12 -12
  107. package/dist/dnd/index.d.ts.map +1 -1
  108. package/dist/dnd/types.d.ts +2 -2
  109. package/dist/dnd/types.d.ts.map +1 -1
  110. package/dist/dnd/utils.d.ts +1 -1
  111. package/dist/dnd/utils.d.ts.map +1 -1
  112. package/dist/focus/FocusScope.d.ts +1 -1
  113. package/dist/focus/FocusScope.d.ts.map +1 -1
  114. package/dist/focus/createAutoFocus.d.ts.map +1 -1
  115. package/dist/focus/createFocusRestore.d.ts.map +1 -1
  116. package/dist/focus/createVirtualFocus.d.ts +4 -4
  117. package/dist/focus/createVirtualFocus.d.ts.map +1 -1
  118. package/dist/focus/index.d.ts +4 -4
  119. package/dist/focus/index.d.ts.map +1 -1
  120. package/dist/form/createFormReset.d.ts +1 -1
  121. package/dist/form/createFormValidation.d.ts +3 -3
  122. package/dist/form/createFormValidation.d.ts.map +1 -1
  123. package/dist/form/index.d.ts +2 -2
  124. package/dist/form/index.d.ts.map +1 -1
  125. package/dist/grid/GridKeyboardDelegate.d.ts +5 -5
  126. package/dist/grid/createGrid.d.ts +3 -3
  127. package/dist/grid/createGrid.d.ts.map +1 -1
  128. package/dist/grid/createGridCell.d.ts +3 -3
  129. package/dist/grid/createGridRow.d.ts +3 -3
  130. package/dist/grid/index.d.ts +5 -5
  131. package/dist/grid/types.d.ts +8 -8
  132. package/dist/gridlist/createGridList.d.ts +6 -4
  133. package/dist/gridlist/createGridList.d.ts.map +1 -1
  134. package/dist/gridlist/createGridListItem.d.ts +4 -4
  135. package/dist/gridlist/createGridListItem.d.ts.map +1 -1
  136. package/dist/gridlist/createGridListSelectionCheckbox.d.ts +3 -3
  137. package/dist/gridlist/createGridListSelectionCheckbox.d.ts.map +1 -1
  138. package/dist/gridlist/index.d.ts +4 -4
  139. package/dist/gridlist/types.d.ts +11 -7
  140. package/dist/gridlist/types.d.ts.map +1 -1
  141. package/dist/i18n/createCollator.d.ts.map +1 -1
  142. package/dist/i18n/createDateFormatter.d.ts.map +1 -1
  143. package/dist/i18n/createFilter.d.ts.map +1 -1
  144. package/dist/i18n/createNumberFormatter.d.ts +1 -1
  145. package/dist/i18n/createNumberFormatter.d.ts.map +1 -1
  146. package/dist/i18n/createStringFormatter.d.ts +2 -2
  147. package/dist/i18n/createStringFormatter.d.ts.map +1 -1
  148. package/dist/i18n/index.d.ts +8 -8
  149. package/dist/i18n/index.d.ts.map +1 -1
  150. package/dist/i18n/locale.d.ts +2 -2
  151. package/dist/i18n/locale.d.ts.map +1 -1
  152. package/dist/i18n/utils.d.ts.map +1 -1
  153. package/dist/index.d.ts +52 -49
  154. package/dist/index.d.ts.map +1 -1
  155. package/dist/index.js +18089 -15690
  156. package/dist/index.js.map +1 -7
  157. package/dist/index.jsx +18242 -0
  158. package/dist/index.jsx.map +1 -0
  159. package/dist/interactions/FocusableProvider.d.ts +2 -2
  160. package/dist/interactions/FocusableProvider.d.ts.map +1 -1
  161. package/dist/interactions/PressEvent.d.ts +2 -2
  162. package/dist/interactions/createFocus.d.ts +1 -1
  163. package/dist/interactions/createFocus.d.ts.map +1 -1
  164. package/dist/interactions/createFocusRing.d.ts +1 -1
  165. package/dist/interactions/createFocusRing.d.ts.map +1 -1
  166. package/dist/interactions/createFocusWithin.d.ts +1 -1
  167. package/dist/interactions/createFocusWithin.d.ts.map +1 -1
  168. package/dist/interactions/createFocusable.d.ts +3 -3
  169. package/dist/interactions/createFocusable.d.ts.map +1 -1
  170. package/dist/interactions/createHover.d.ts +5 -5
  171. package/dist/interactions/createHover.d.ts.map +1 -1
  172. package/dist/interactions/createInteractionModality.d.ts +3 -3
  173. package/dist/interactions/createInteractionModality.d.ts.map +1 -1
  174. package/dist/interactions/createKeyboard.d.ts +1 -1
  175. package/dist/interactions/createLongPress.d.ts +5 -5
  176. package/dist/interactions/createMove.d.ts +5 -5
  177. package/dist/interactions/createMove.d.ts.map +1 -1
  178. package/dist/interactions/createPress.d.ts +4 -4
  179. package/dist/interactions/createPress.d.ts.map +1 -1
  180. package/dist/interactions/index.d.ts +12 -12
  181. package/dist/interactions/index.d.ts.map +1 -1
  182. package/dist/label/createField.d.ts +4 -4
  183. package/dist/label/createField.d.ts.map +1 -1
  184. package/dist/label/createLabel.d.ts +7 -7
  185. package/dist/label/createLabel.d.ts.map +1 -1
  186. package/dist/label/createLabels.d.ts +1 -1
  187. package/dist/label/createLabels.d.ts.map +1 -1
  188. package/dist/label/index.d.ts +5 -5
  189. package/dist/landmark/createLandmark.d.ts +5 -5
  190. package/dist/landmark/createLandmark.d.ts.map +1 -1
  191. package/dist/landmark/index.d.ts +1 -1
  192. package/dist/link/createLink.d.ts +23 -7
  193. package/dist/link/createLink.d.ts.map +1 -1
  194. package/dist/link/index.d.ts +1 -1
  195. package/dist/listbox/createListBox.d.ts +12 -6
  196. package/dist/listbox/createListBox.d.ts.map +1 -1
  197. package/dist/listbox/createOption.d.ts +21 -4
  198. package/dist/listbox/createOption.d.ts.map +1 -1
  199. package/dist/listbox/index.d.ts +2 -2
  200. package/dist/listbox/index.d.ts.map +1 -1
  201. package/dist/live-announcer/announce.d.ts +2 -2
  202. package/dist/live-announcer/announce.d.ts.map +1 -1
  203. package/dist/live-announcer/index.d.ts +1 -1
  204. package/dist/menu/createMenu.d.ts +8 -7
  205. package/dist/menu/createMenu.d.ts.map +1 -1
  206. package/dist/menu/createMenuItem.d.ts +16 -4
  207. package/dist/menu/createMenuItem.d.ts.map +1 -1
  208. package/dist/menu/createMenuTrigger.d.ts +4 -4
  209. package/dist/menu/index.d.ts +3 -3
  210. package/dist/menu/index.d.ts.map +1 -1
  211. package/dist/meter/createMeter.d.ts +6 -6
  212. package/dist/meter/createMeter.d.ts.map +1 -1
  213. package/dist/meter/index.d.ts +1 -1
  214. package/dist/numberfield/createNumberField.d.ts +27 -8
  215. package/dist/numberfield/createNumberField.d.ts.map +1 -1
  216. package/dist/numberfield/index.d.ts +1 -1
  217. package/dist/overlays/ariaHideOutside.d.ts.map +1 -1
  218. package/dist/overlays/createModal.d.ts +19 -3
  219. package/dist/overlays/createModal.d.ts.map +1 -1
  220. package/dist/overlays/createOverlay.d.ts +1 -1
  221. package/dist/overlays/createOverlay.d.ts.map +1 -1
  222. package/dist/overlays/createOverlayTrigger.d.ts +6 -6
  223. package/dist/overlays/index.d.ts +6 -6
  224. package/dist/overlays/index.d.ts.map +1 -1
  225. package/dist/popover/calculatePosition.d.ts +4 -4
  226. package/dist/popover/calculatePosition.d.ts.map +1 -1
  227. package/dist/popover/createOverlayPosition.d.ts +3 -3
  228. package/dist/popover/createOverlayPosition.d.ts.map +1 -1
  229. package/dist/popover/createPopover.d.ts +4 -4
  230. package/dist/popover/createPopover.d.ts.map +1 -1
  231. package/dist/popover/index.d.ts +3 -3
  232. package/dist/progress/createProgressBar.d.ts +7 -5
  233. package/dist/progress/createProgressBar.d.ts.map +1 -1
  234. package/dist/progress/index.d.ts +1 -1
  235. package/dist/radio/createRadio.d.ts +7 -7
  236. package/dist/radio/createRadio.d.ts.map +1 -1
  237. package/dist/radio/createRadioGroup.d.ts +11 -11
  238. package/dist/radio/createRadioGroup.d.ts.map +1 -1
  239. package/dist/radio/createRadioGroupState.d.ts +3 -3
  240. package/dist/radio/createRadioGroupState.d.ts.map +1 -1
  241. package/dist/radio/index.d.ts +3 -3
  242. package/dist/radio/index.d.ts.map +1 -1
  243. package/dist/searchfield/createSearchField.d.ts +7 -7
  244. package/dist/searchfield/createSearchField.d.ts.map +1 -1
  245. package/dist/searchfield/index.d.ts +2 -2
  246. package/dist/select/createHiddenSelect.d.ts +4 -4
  247. package/dist/select/createHiddenSelect.d.ts.map +1 -1
  248. package/dist/select/createSelect.d.ts +14 -6
  249. package/dist/select/createSelect.d.ts.map +1 -1
  250. package/dist/select/index.d.ts +2 -2
  251. package/dist/select/index.d.ts.map +1 -1
  252. package/dist/selection/createTypeSelect.d.ts +2 -2
  253. package/dist/selection/index.d.ts +1 -1
  254. package/dist/separator/createSeparator.d.ts +9 -5
  255. package/dist/separator/createSeparator.d.ts.map +1 -1
  256. package/dist/separator/index.d.ts +1 -1
  257. package/dist/slider/createSlider.d.ts +11 -7
  258. package/dist/slider/createSlider.d.ts.map +1 -1
  259. package/dist/slider/index.d.ts +2 -2
  260. package/dist/ssr/index.d.ts +1 -1
  261. package/dist/ssr/index.d.ts.map +1 -1
  262. package/dist/steplist/createStepList.d.ts +36 -0
  263. package/dist/steplist/createStepList.d.ts.map +1 -0
  264. package/dist/steplist/index.d.ts +2 -0
  265. package/dist/steplist/index.d.ts.map +1 -0
  266. package/dist/switch/createSwitch.d.ts +6 -4
  267. package/dist/switch/createSwitch.d.ts.map +1 -1
  268. package/dist/switch/index.d.ts +1 -1
  269. package/dist/table/createTable.d.ts +3 -3
  270. package/dist/table/createTable.d.ts.map +1 -1
  271. package/dist/table/createTableCell.d.ts +3 -3
  272. package/dist/table/createTableCell.d.ts.map +1 -1
  273. package/dist/table/createTableColumnHeader.d.ts +3 -3
  274. package/dist/table/createTableColumnHeader.d.ts.map +1 -1
  275. package/dist/table/createTableColumnResize.d.ts +41 -0
  276. package/dist/table/createTableColumnResize.d.ts.map +1 -0
  277. package/dist/table/createTableHeaderRow.d.ts +3 -3
  278. package/dist/table/createTableRow.d.ts +3 -3
  279. package/dist/table/createTableRow.d.ts.map +1 -1
  280. package/dist/table/createTableRowGroup.d.ts +2 -2
  281. package/dist/table/createTableRowGroup.d.ts.map +1 -1
  282. package/dist/table/createTableSelectAllCheckbox.d.ts +3 -3
  283. package/dist/table/createTableSelectAllCheckbox.d.ts.map +1 -1
  284. package/dist/table/createTableSelectionCheckbox.d.ts +3 -3
  285. package/dist/table/index.d.ts +11 -9
  286. package/dist/table/index.d.ts.map +1 -1
  287. package/dist/table/types.d.ts +15 -7
  288. package/dist/table/types.d.ts.map +1 -1
  289. package/dist/tabs/createTabs.d.ts +28 -25
  290. package/dist/tabs/createTabs.d.ts.map +1 -1
  291. package/dist/tabs/index.d.ts +1 -1
  292. package/dist/tag/createTag.d.ts +2 -2
  293. package/dist/tag/createTag.d.ts.map +1 -1
  294. package/dist/tag/createTagGroup.d.ts +5 -5
  295. package/dist/tag/createTagGroup.d.ts.map +1 -1
  296. package/dist/tag/index.d.ts +2 -2
  297. package/dist/tag/index.d.ts.map +1 -1
  298. package/dist/textfield/createTextField.d.ts +17 -11
  299. package/dist/textfield/createTextField.d.ts.map +1 -1
  300. package/dist/textfield/index.d.ts +1 -1
  301. package/dist/textfield/index.d.ts.map +1 -1
  302. package/dist/toast/createToast.d.ts +6 -2
  303. package/dist/toast/createToast.d.ts.map +1 -1
  304. package/dist/toast/createToastRegion.d.ts +5 -3
  305. package/dist/toast/createToastRegion.d.ts.map +1 -1
  306. package/dist/toast/index.d.ts +2 -2
  307. package/dist/toast/index.d.ts.map +1 -1
  308. package/dist/toggle/createToggle.d.ts +9 -9
  309. package/dist/toggle/createToggle.d.ts.map +1 -1
  310. package/dist/toggle/createToggleState.d.ts +2 -2
  311. package/dist/toggle/createToggleState.d.ts.map +1 -1
  312. package/dist/toggle/index.d.ts +4 -4
  313. package/dist/toggle/index.d.ts.map +1 -1
  314. package/dist/toolbar/createToolbar.d.ts +9 -9
  315. package/dist/toolbar/createToolbar.d.ts.map +1 -1
  316. package/dist/toolbar/index.d.ts +1 -1
  317. package/dist/toolbar/index.d.ts.map +1 -1
  318. package/dist/tooltip/createTooltip.d.ts +5 -5
  319. package/dist/tooltip/createTooltip.d.ts.map +1 -1
  320. package/dist/tooltip/createTooltipTrigger.d.ts +10 -5
  321. package/dist/tooltip/createTooltipTrigger.d.ts.map +1 -1
  322. package/dist/tooltip/index.d.ts +2 -2
  323. package/dist/tree/createTree.d.ts +3 -3
  324. package/dist/tree/createTree.d.ts.map +1 -1
  325. package/dist/tree/createTreeItem.d.ts +4 -4
  326. package/dist/tree/createTreeItem.d.ts.map +1 -1
  327. package/dist/tree/createTreeSelectionCheckbox.d.ts +3 -3
  328. package/dist/tree/createTreeSelectionCheckbox.d.ts.map +1 -1
  329. package/dist/tree/index.d.ts +4 -4
  330. package/dist/tree/types.d.ts +13 -5
  331. package/dist/tree/types.d.ts.map +1 -1
  332. package/dist/utils/createDescription.d.ts +2 -2
  333. package/dist/utils/createDescription.d.ts.map +1 -1
  334. package/dist/utils/dom.d.ts.map +1 -1
  335. package/dist/utils/env.d.ts +1 -1
  336. package/dist/utils/env.d.ts.map +1 -1
  337. package/dist/utils/focus.d.ts +1 -1
  338. package/dist/utils/focus.d.ts.map +1 -1
  339. package/dist/utils/geometry.d.ts.map +1 -1
  340. package/dist/utils/index.d.ts +12 -12
  341. package/dist/utils/index.d.ts.map +1 -1
  342. package/dist/utils/mergeProps.d.ts.map +1 -1
  343. package/dist/utils/platform.d.ts.map +1 -1
  344. package/dist/utils/reactivity.d.ts +1 -1
  345. package/dist/visually-hidden/createVisuallyHidden.d.ts +2 -2
  346. package/dist/visually-hidden/createVisuallyHidden.d.ts.map +1 -1
  347. package/dist/visually-hidden/index.d.ts +1 -1
  348. package/package.json +34 -32
  349. package/src/actiongroup/createActionGroup.ts +334 -0
  350. package/src/actiongroup/index.ts +8 -0
  351. package/src/autocomplete/createAutocomplete.ts +137 -131
  352. package/src/autocomplete/index.ts +1 -1
  353. package/src/breadcrumbs/createBreadcrumbs.ts +37 -51
  354. package/src/breadcrumbs/index.ts +1 -1
  355. package/src/button/createButton.ts +102 -73
  356. package/src/button/createToggleButton.ts +10 -10
  357. package/src/button/createToggleButtonGroup.ts +121 -0
  358. package/src/button/index.ts +10 -4
  359. package/src/button/types.ts +18 -12
  360. package/src/calendar/createCalendar.ts +62 -29
  361. package/src/calendar/createCalendarCell.ts +102 -48
  362. package/src/calendar/createCalendarGrid.ts +78 -47
  363. package/src/calendar/createRangeCalendar.ts +66 -31
  364. package/src/calendar/createRangeCalendarCell.ts +115 -37
  365. package/src/calendar/index.ts +5 -9
  366. package/src/calendar/intl/index.ts +210 -0
  367. package/src/calendar/utils.ts +227 -0
  368. package/src/checkbox/createCheckbox.ts +13 -21
  369. package/src/checkbox/createCheckboxGroup.ts +86 -45
  370. package/src/checkbox/createCheckboxGroupItem.ts +16 -27
  371. package/src/checkbox/createCheckboxGroupState.ts +3 -22
  372. package/src/checkbox/index.ts +8 -10
  373. package/src/collections/index.ts +246 -0
  374. package/src/color/createColorArea.ts +458 -314
  375. package/src/color/createColorField.ts +186 -137
  376. package/src/color/createColorSlider.ts +444 -197
  377. package/src/color/createColorSwatch.ts +65 -40
  378. package/src/color/createColorWheel.ts +343 -208
  379. package/src/color/index.ts +24 -24
  380. package/src/color/types.ts +198 -116
  381. package/src/combobox/createComboBox.ts +727 -647
  382. package/src/combobox/index.ts +6 -6
  383. package/src/combobox/intl/index.ts +5 -5
  384. package/src/datepicker/createDateField.ts +192 -39
  385. package/src/datepicker/createDatePicker.ts +294 -63
  386. package/src/datepicker/createDatePickerGroup.ts +149 -0
  387. package/src/datepicker/createDateRangePicker.ts +294 -0
  388. package/src/datepicker/createDateSegment.ts +316 -75
  389. package/src/datepicker/createTimeField.ts +38 -34
  390. package/src/datepicker/createTimeSegment.ts +352 -0
  391. package/src/datepicker/index.ts +24 -11
  392. package/src/dialog/createDialog.ts +127 -120
  393. package/src/dialog/index.ts +2 -2
  394. package/src/dialog/types.ts +19 -19
  395. package/src/disclosure/createDisclosure.ts +138 -33
  396. package/src/disclosure/createDisclosureGroup.ts +8 -18
  397. package/src/disclosure/index.ts +2 -2
  398. package/src/dnd/createDrag.ts +218 -209
  399. package/src/dnd/createDraggableCollection.ts +96 -63
  400. package/src/dnd/createDraggableItem.ts +260 -243
  401. package/src/dnd/createDrop.ts +313 -321
  402. package/src/dnd/createDroppableCollection.ts +799 -293
  403. package/src/dnd/createDroppableItem.ts +215 -213
  404. package/src/dnd/index.ts +66 -47
  405. package/src/dnd/types.ts +86 -89
  406. package/src/dnd/utils.ts +281 -294
  407. package/src/focus/FocusScope.tsx +155 -164
  408. package/src/focus/createAutoFocus.ts +305 -321
  409. package/src/focus/createFocusRestore.ts +300 -313
  410. package/src/focus/createVirtualFocus.ts +380 -396
  411. package/src/focus/index.ts +4 -8
  412. package/src/form/createFormReset.ts +4 -4
  413. package/src/form/createFormValidation.ts +201 -224
  414. package/src/form/index.ts +8 -11
  415. package/src/grid/GridKeyboardDelegate.ts +30 -30
  416. package/src/grid/createGrid.ts +38 -36
  417. package/src/grid/createGridCell.ts +18 -18
  418. package/src/grid/createGridRow.ts +14 -14
  419. package/src/grid/index.ts +5 -5
  420. package/src/grid/types.ts +8 -8
  421. package/src/gridlist/createGridList.ts +45 -24
  422. package/src/gridlist/createGridListItem.ts +68 -23
  423. package/src/gridlist/createGridListSelectionCheckbox.ts +12 -9
  424. package/src/gridlist/index.ts +4 -4
  425. package/src/gridlist/types.ts +11 -7
  426. package/src/i18n/createCollator.ts +66 -79
  427. package/src/i18n/createDateFormatter.ts +75 -83
  428. package/src/i18n/createFilter.ts +118 -131
  429. package/src/i18n/createNumberFormatter.ts +50 -52
  430. package/src/i18n/createStringFormatter.ts +19 -15
  431. package/src/i18n/index.ts +37 -40
  432. package/src/i18n/locale.tsx +163 -188
  433. package/src/i18n/utils.ts +95 -99
  434. package/src/index.ts +114 -164
  435. package/src/interactions/FocusableProvider.tsx +3 -7
  436. package/src/interactions/PressEvent.ts +4 -4
  437. package/src/interactions/createFocus.ts +16 -11
  438. package/src/interactions/createFocusRing.ts +21 -19
  439. package/src/interactions/createFocusWithin.ts +24 -16
  440. package/src/interactions/createFocusable.ts +15 -16
  441. package/src/interactions/createHover.ts +70 -55
  442. package/src/interactions/createInteractionModality.ts +75 -82
  443. package/src/interactions/createKeyboard.ts +2 -2
  444. package/src/interactions/createLongPress.ts +174 -174
  445. package/src/interactions/createMove.ts +299 -289
  446. package/src/interactions/createPress.ts +168 -91
  447. package/src/interactions/index.ts +24 -16
  448. package/src/label/createField.ts +18 -19
  449. package/src/label/createLabel.ts +18 -30
  450. package/src/label/createLabels.ts +8 -12
  451. package/src/label/index.ts +5 -5
  452. package/src/landmark/createLandmark.ts +356 -377
  453. package/src/landmark/index.ts +8 -8
  454. package/src/link/createLink.ts +96 -54
  455. package/src/link/index.ts +1 -1
  456. package/src/listbox/createListBox.ts +319 -269
  457. package/src/listbox/createOption.ts +208 -151
  458. package/src/listbox/index.ts +8 -12
  459. package/src/live-announcer/announce.ts +295 -322
  460. package/src/live-announcer/index.ts +9 -9
  461. package/src/menu/createMenu.ts +434 -396
  462. package/src/menu/createMenuItem.ts +201 -149
  463. package/src/menu/createMenuTrigger.ts +88 -88
  464. package/src/menu/index.ts +9 -18
  465. package/src/meter/createMeter.ts +7 -20
  466. package/src/meter/index.ts +1 -1
  467. package/src/numberfield/createNumberField.ts +368 -268
  468. package/src/numberfield/index.ts +5 -5
  469. package/src/overlays/ariaHideOutside.ts +223 -219
  470. package/src/overlays/createInteractOutside.ts +152 -149
  471. package/src/overlays/createModal.tsx +238 -202
  472. package/src/overlays/createOverlay.ts +195 -155
  473. package/src/overlays/createOverlayTrigger.ts +85 -85
  474. package/src/overlays/createPreventScroll.ts +288 -266
  475. package/src/overlays/index.ts +37 -44
  476. package/src/popover/calculatePosition.ts +117 -119
  477. package/src/popover/createOverlayPosition.ts +52 -43
  478. package/src/popover/createPopover.ts +63 -24
  479. package/src/popover/index.ts +3 -3
  480. package/src/progress/createProgressBar.ts +36 -32
  481. package/src/progress/index.ts +1 -1
  482. package/src/radio/createRadio.ts +95 -73
  483. package/src/radio/createRadioGroup.ts +142 -62
  484. package/src/radio/createRadioGroupState.ts +7 -31
  485. package/src/radio/index.ts +3 -8
  486. package/src/searchfield/createSearchField.ts +269 -186
  487. package/src/searchfield/index.ts +2 -2
  488. package/src/select/createHiddenSelect.tsx +276 -236
  489. package/src/select/createSelect.ts +430 -395
  490. package/src/select/index.ts +9 -14
  491. package/src/selection/createTypeSelect.ts +11 -11
  492. package/src/selection/index.ts +1 -1
  493. package/src/separator/createSeparator.ts +20 -25
  494. package/src/separator/index.ts +1 -1
  495. package/src/slider/createSlider.ts +333 -349
  496. package/src/slider/index.ts +2 -2
  497. package/src/ssr/index.tsx +331 -370
  498. package/src/steplist/createStepList.ts +106 -0
  499. package/src/steplist/index.ts +8 -0
  500. package/src/switch/createSwitch.ts +9 -14
  501. package/src/switch/index.ts +1 -1
  502. package/src/table/createTable.ts +155 -86
  503. package/src/table/createTableCell.ts +17 -16
  504. package/src/table/createTableColumnHeader.ts +67 -20
  505. package/src/table/createTableColumnResize.ts +256 -0
  506. package/src/table/createTableHeaderRow.ts +7 -7
  507. package/src/table/createTableRow.ts +149 -29
  508. package/src/table/createTableRowGroup.ts +5 -7
  509. package/src/table/createTableSelectAllCheckbox.ts +12 -11
  510. package/src/table/createTableSelectionCheckbox.ts +8 -8
  511. package/src/table/index.ts +14 -9
  512. package/src/table/types.ts +15 -7
  513. package/src/tabs/createTabs.ts +138 -127
  514. package/src/tabs/index.ts +1 -1
  515. package/src/tag/createTag.ts +171 -40
  516. package/src/tag/createTagGroup.ts +50 -39
  517. package/src/tag/index.ts +2 -6
  518. package/src/textfield/createTextField.ts +67 -35
  519. package/src/textfield/index.ts +1 -5
  520. package/src/toast/createToast.ts +34 -26
  521. package/src/toast/createToastRegion.ts +169 -27
  522. package/src/toast/index.ts +2 -6
  523. package/src/toggle/createToggle.ts +95 -53
  524. package/src/toggle/createToggleState.ts +2 -10
  525. package/src/toggle/index.ts +4 -5
  526. package/src/toolbar/createToolbar.ts +226 -169
  527. package/src/toolbar/index.ts +1 -1
  528. package/src/tooltip/createTooltip.ts +66 -79
  529. package/src/tooltip/createTooltipTrigger.ts +238 -222
  530. package/src/tooltip/index.ts +6 -6
  531. package/src/tree/createTree.ts +259 -246
  532. package/src/tree/createTreeItem.ts +282 -233
  533. package/src/tree/createTreeSelectionCheckbox.ts +71 -68
  534. package/src/tree/index.ts +16 -16
  535. package/src/tree/types.ts +95 -87
  536. package/src/utils/createDescription.ts +6 -23
  537. package/src/utils/dom.ts +61 -54
  538. package/src/utils/env.ts +53 -54
  539. package/src/utils/events.ts +7 -7
  540. package/src/utils/filterDOMProps.ts +49 -49
  541. package/src/utils/focus.ts +60 -68
  542. package/src/utils/geometry.ts +1 -4
  543. package/src/utils/globalListeners.ts +9 -9
  544. package/src/utils/index.ts +12 -22
  545. package/src/utils/mergeProps.ts +42 -15
  546. package/src/utils/platform.ts +16 -6
  547. package/src/utils/reactivity.ts +3 -3
  548. package/src/utils/textSelection.ts +16 -16
  549. package/src/visually-hidden/createVisuallyHidden.ts +127 -124
  550. package/src/visually-hidden/index.ts +6 -6
  551. package/dist/i18n/NumberFormatter.d.ts +0 -43
  552. package/dist/i18n/NumberFormatter.d.ts.map +0 -1
  553. package/dist/index.ssr.js +0 -15875
  554. package/dist/index.ssr.js.map +0 -7
  555. package/src/i18n/NumberFormatter.ts +0 -266
@@ -1,377 +1,356 @@
1
- /**
2
- * createLandmark - SolidJS implementation of React Aria's useLandmark
3
- *
4
- * Provides landmark navigation in an application. Call this with a role and label
5
- * to register a landmark navigable with the F6 key.
6
- *
7
- * ARIA landmarks help screen reader users navigate between major sections of a page.
8
- * The F6 key (or Shift+F6) cycles through all registered landmarks.
9
- */
10
-
11
- import type { JSX, Accessor } from 'solid-js';
12
- import { createEffect, onCleanup } from 'solid-js';
13
- import { access, type MaybeAccessor } from '../utils';
14
- import { filterDOMProps } from '../utils';
15
-
16
- // ============================================
17
- // TYPES
18
- // ============================================
19
-
20
- /** ARIA landmark roles */
21
- export type AriaLandmarkRole =
22
- | 'main'
23
- | 'region'
24
- | 'search'
25
- | 'navigation'
26
- | 'form'
27
- | 'banner'
28
- | 'contentinfo'
29
- | 'complementary';
30
-
31
- export interface AriaLandmarkProps {
32
- /** The ARIA landmark role. */
33
- role: AriaLandmarkRole;
34
- /**
35
- * A human-readable label for the landmark.
36
- * Required when multiple landmarks with the same role exist on a page.
37
- */
38
- 'aria-label'?: string;
39
- /** Identifies the element(s) that labels the landmark. */
40
- 'aria-labelledby'?: string;
41
- /** The element's unique identifier. */
42
- id?: string;
43
- /**
44
- * A custom focus handler called when this landmark receives focus via F6 navigation.
45
- * Use this to focus a specific element within the landmark instead of the container.
46
- */
47
- focus?: () => void;
48
- }
49
-
50
- export interface LandmarkAria<T extends HTMLElement = HTMLElement> {
51
- /** Props to spread on the landmark element. */
52
- landmarkProps: JSX.HTMLAttributes<T>;
53
- }
54
-
55
- export interface LandmarkController {
56
- /** Focus the next landmark in DOM order. */
57
- focusNext: () => void;
58
- /** Focus the previous landmark in DOM order. */
59
- focusPrevious: () => void;
60
- /** Focus the main landmark. */
61
- focusMain: () => void;
62
- /** Navigate to a specific landmark by role. If multiple exist, the first one is focused. */
63
- navigate: (role: AriaLandmarkRole) => void;
64
- }
65
-
66
- // ============================================
67
- // INTERNAL: Landmark Entry
68
- // ============================================
69
-
70
- interface LandmarkEntry {
71
- ref: HTMLElement;
72
- role: AriaLandmarkRole;
73
- label?: string;
74
- focus?: () => void;
75
- lastFocused?: HTMLElement;
76
- }
77
-
78
- // ============================================
79
- // LANDMARK MANAGER (Singleton)
80
- // ============================================
81
-
82
- /**
83
- * Manages all registered landmarks and handles F6 keyboard navigation.
84
- */
85
- class LandmarkManager {
86
- private landmarks: LandmarkEntry[] = [];
87
- private currentIndex = -1;
88
- private listening = false;
89
-
90
- constructor() {
91
- if (typeof window !== 'undefined') {
92
- this.startListening();
93
- }
94
- }
95
-
96
- private startListening() {
97
- if (this.listening) return;
98
- this.listening = true;
99
-
100
- window.addEventListener('keydown', this.handleKeyDown.bind(this), true);
101
- }
102
-
103
- private handleKeyDown(event: KeyboardEvent) {
104
- // F6 to navigate landmarks
105
- if (event.key === 'F6') {
106
- event.preventDefault();
107
- if (event.shiftKey) {
108
- this.focusPrevious();
109
- } else {
110
- this.focusNext();
111
- }
112
- }
113
- }
114
-
115
- register(entry: LandmarkEntry): void {
116
- // Insert in DOM order using compareDocumentPosition
117
- const index = this.findInsertionIndex(entry.ref);
118
- this.landmarks.splice(index, 0, entry);
119
-
120
- // Validate: if multiple landmarks have the same role, they should have different labels
121
- this.validateLabels();
122
- }
123
-
124
- unregister(ref: HTMLElement): void {
125
- const index = this.landmarks.findIndex((l) => l.ref === ref);
126
- if (index !== -1) {
127
- this.landmarks.splice(index, 1);
128
- // Adjust currentIndex if needed
129
- if (this.currentIndex >= this.landmarks.length) {
130
- this.currentIndex = this.landmarks.length - 1;
131
- }
132
- }
133
- }
134
-
135
- private findInsertionIndex(ref: HTMLElement): number {
136
- // Binary search for insertion point based on DOM order
137
- let low = 0;
138
- let high = this.landmarks.length;
139
-
140
- while (low < high) {
141
- const mid = Math.floor((low + high) / 2);
142
- const comparison = this.landmarks[mid].ref.compareDocumentPosition(ref);
143
-
144
- // Node.DOCUMENT_POSITION_FOLLOWING = 4
145
- if (comparison & Node.DOCUMENT_POSITION_FOLLOWING) {
146
- low = mid + 1;
147
- } else {
148
- high = mid;
149
- }
150
- }
151
-
152
- return low;
153
- }
154
-
155
- private validateLabels(): void {
156
- // Group landmarks by role
157
- const roleGroups = new Map<AriaLandmarkRole, LandmarkEntry[]>();
158
- for (const landmark of this.landmarks) {
159
- const group = roleGroups.get(landmark.role) || [];
160
- group.push(landmark);
161
- roleGroups.set(landmark.role, group);
162
- }
163
-
164
- // Warn if multiple landmarks with the same role lack unique labels
165
- for (const [role, group] of roleGroups) {
166
- if (group.length > 1) {
167
- const labels = group.map((l) => l.label);
168
- const uniqueLabels = new Set(labels.filter(Boolean));
169
- if (uniqueLabels.size < group.length) {
170
- console.warn(
171
- `Multiple landmarks with role "${role}" exist. Each should have a unique aria-label or aria-labelledby.`
172
- );
173
- }
174
- }
175
- }
176
- }
177
-
178
- focusNext(): void {
179
- if (this.landmarks.length === 0) return;
180
-
181
- // Find the currently focused landmark
182
- const activeElement = document.activeElement;
183
- this.currentIndex = this.findCurrentLandmarkIndex(activeElement);
184
-
185
- // Move to next
186
- this.currentIndex = (this.currentIndex + 1) % this.landmarks.length;
187
- this.focusLandmark(this.landmarks[this.currentIndex]);
188
- }
189
-
190
- focusPrevious(): void {
191
- if (this.landmarks.length === 0) return;
192
-
193
- // Find the currently focused landmark
194
- const activeElement = document.activeElement;
195
- this.currentIndex = this.findCurrentLandmarkIndex(activeElement);
196
-
197
- // Move to previous
198
- this.currentIndex =
199
- (this.currentIndex - 1 + this.landmarks.length) % this.landmarks.length;
200
- this.focusLandmark(this.landmarks[this.currentIndex]);
201
- }
202
-
203
- focusMain(): void {
204
- const main = this.landmarks.find((l) => l.role === 'main');
205
- if (main) {
206
- this.focusLandmark(main);
207
- }
208
- }
209
-
210
- navigate(role: AriaLandmarkRole): void {
211
- const landmark = this.landmarks.find((l) => l.role === role);
212
- if (landmark) {
213
- this.focusLandmark(landmark);
214
- }
215
- }
216
-
217
- private findCurrentLandmarkIndex(activeElement: Element | null): number {
218
- if (!activeElement) return -1;
219
-
220
- // Check if active element is within any landmark
221
- for (let i = 0; i < this.landmarks.length; i++) {
222
- if (this.landmarks[i].ref.contains(activeElement)) {
223
- // Store the last focused element for this landmark
224
- if (activeElement instanceof HTMLElement) {
225
- this.landmarks[i].lastFocused = activeElement;
226
- }
227
- return i;
228
- }
229
- }
230
-
231
- return -1;
232
- }
233
-
234
- private focusLandmark(landmark: LandmarkEntry): void {
235
- // If a custom focus handler is provided, use it
236
- if (landmark.focus) {
237
- landmark.focus();
238
- return;
239
- }
240
-
241
- // If we previously focused an element in this landmark, try to restore it
242
- if (landmark.lastFocused && landmark.ref.contains(landmark.lastFocused)) {
243
- landmark.lastFocused.focus();
244
- return;
245
- }
246
-
247
- // Try to find the first focusable element
248
- const focusable = this.findFirstFocusable(landmark.ref);
249
- if (focusable) {
250
- focusable.focus();
251
- return;
252
- }
253
-
254
- // Fallback: make the landmark itself focusable and focus it
255
- if (!landmark.ref.hasAttribute('tabindex')) {
256
- landmark.ref.setAttribute('tabindex', '-1');
257
- }
258
- landmark.ref.focus();
259
- }
260
-
261
- private findFirstFocusable(container: HTMLElement): HTMLElement | null {
262
- const focusableSelectors = [
263
- 'a[href]',
264
- 'button:not([disabled])',
265
- 'input:not([disabled])',
266
- 'select:not([disabled])',
267
- 'textarea:not([disabled])',
268
- '[tabindex]:not([tabindex="-1"])',
269
- ].join(', ');
270
-
271
- return container.querySelector<HTMLElement>(focusableSelectors);
272
- }
273
-
274
- getController(): LandmarkController {
275
- return {
276
- focusNext: () => this.focusNext(),
277
- focusPrevious: () => this.focusPrevious(),
278
- focusMain: () => this.focusMain(),
279
- navigate: (role) => this.navigate(role),
280
- };
281
- }
282
- }
283
-
284
- // Global singleton instance
285
- let landmarkManager: LandmarkManager | null = null;
286
-
287
- function getLandmarkManager(): LandmarkManager {
288
- if (!landmarkManager) {
289
- landmarkManager = new LandmarkManager();
290
- }
291
- return landmarkManager;
292
- }
293
-
294
- // ============================================
295
- // CREATE LANDMARK
296
- // ============================================
297
-
298
- /**
299
- * Provides landmark navigation in an application.
300
- * Call this with a role and label to register a landmark navigable with F6.
301
- *
302
- * @example
303
- * ```tsx
304
- * function Navigation(props) {
305
- * let ref: HTMLElement;
306
- * const { landmarkProps } = createLandmark({
307
- * role: 'navigation',
308
- * 'aria-label': 'Main navigation'
309
- * });
310
- *
311
- * return (
312
- * <nav {...landmarkProps} ref={ref}>
313
- * {props.children}
314
- * </nav>
315
- * );
316
- * }
317
- * ```
318
- */
319
- export function createLandmark<T extends HTMLElement = HTMLElement>(
320
- props: MaybeAccessor<AriaLandmarkProps>,
321
- ref: Accessor<T | undefined>
322
- ): LandmarkAria<T> {
323
- // Register with the landmark manager
324
- createEffect(() => {
325
- const element = ref();
326
- if (!element) return;
327
-
328
- const p = access(props);
329
- const entry: LandmarkEntry = {
330
- ref: element,
331
- role: p.role,
332
- label: p['aria-label'],
333
- focus: p.focus,
334
- };
335
-
336
- const manager = getLandmarkManager();
337
- manager.register(entry);
338
-
339
- onCleanup(() => {
340
- manager.unregister(element);
341
- });
342
- });
343
-
344
- const getLandmarkProps = (): JSX.HTMLAttributes<T> => {
345
- const p = access(props);
346
- const domProps = filterDOMProps(p as unknown as Record<string, unknown>, { labelable: true });
347
-
348
- return {
349
- ...domProps,
350
- role: p.role,
351
- };
352
- };
353
-
354
- return {
355
- get landmarkProps() {
356
- return getLandmarkProps();
357
- },
358
- };
359
- }
360
-
361
- // ============================================
362
- // LANDMARK CONTROLLER
363
- // ============================================
364
-
365
- /**
366
- * Returns a controller for programmatic landmark navigation.
367
- *
368
- * @example
369
- * ```tsx
370
- * const controller = getLandmarkController();
371
- * controller.focusMain(); // Focus the main landmark
372
- * controller.focusNext(); // Focus the next landmark
373
- * ```
374
- */
375
- export function getLandmarkController(): LandmarkController {
376
- return getLandmarkManager().getController();
377
- }
1
+ /**
2
+ * createLandmark - SolidJS implementation of React Aria's useLandmark
3
+ *
4
+ * Provides landmark navigation in an application. Call this with a role and label
5
+ * to register a landmark navigable with the F6 key.
6
+ *
7
+ * ARIA landmarks help screen reader users navigate between major sections of a page.
8
+ * The F6 key (or Shift+F6) cycles through all registered landmarks.
9
+ */
10
+
11
+ import type { JSX, Accessor } from "solid-js";
12
+ import { createEffect, onCleanup } from "solid-js";
13
+ import { access, type MaybeAccessor } from "../utils";
14
+ import { filterDOMProps } from "../utils";
15
+
16
+ /** ARIA landmark roles */
17
+ export type AriaLandmarkRole =
18
+ | "main"
19
+ | "region"
20
+ | "search"
21
+ | "navigation"
22
+ | "form"
23
+ | "banner"
24
+ | "contentinfo"
25
+ | "complementary";
26
+
27
+ export interface AriaLandmarkProps {
28
+ /** The ARIA landmark role. */
29
+ role: AriaLandmarkRole;
30
+ /**
31
+ * A human-readable label for the landmark.
32
+ * Required when multiple landmarks with the same role exist on a page.
33
+ */
34
+ "aria-label"?: string;
35
+ /** Identifies the element(s) that labels the landmark. */
36
+ "aria-labelledby"?: string;
37
+ /** The element's unique identifier. */
38
+ id?: string;
39
+ /**
40
+ * A custom focus handler called when this landmark receives focus via F6 navigation.
41
+ * Use this to focus a specific element within the landmark instead of the container.
42
+ */
43
+ focus?: () => void;
44
+ }
45
+
46
+ export interface LandmarkAria<T extends HTMLElement = HTMLElement> {
47
+ /** Props to spread on the landmark element. */
48
+ landmarkProps: JSX.HTMLAttributes<T>;
49
+ }
50
+
51
+ export interface LandmarkController {
52
+ /** Focus the next landmark in DOM order. */
53
+ focusNext: () => void;
54
+ /** Focus the previous landmark in DOM order. */
55
+ focusPrevious: () => void;
56
+ /** Focus the main landmark. */
57
+ focusMain: () => void;
58
+ /** Navigate to a specific landmark by role. If multiple exist, the first one is focused. */
59
+ navigate: (role: AriaLandmarkRole) => void;
60
+ }
61
+
62
+ interface LandmarkEntry {
63
+ ref: HTMLElement;
64
+ role: AriaLandmarkRole;
65
+ label?: string;
66
+ focus?: () => void;
67
+ lastFocused?: HTMLElement;
68
+ }
69
+
70
+ /**
71
+ * Manages all registered landmarks and handles F6 keyboard navigation.
72
+ */
73
+ class LandmarkManager {
74
+ private landmarks: LandmarkEntry[] = [];
75
+ private currentIndex = -1;
76
+ private listening = false;
77
+
78
+ constructor() {
79
+ if (typeof window !== "undefined") {
80
+ this.startListening();
81
+ }
82
+ }
83
+
84
+ private startListening() {
85
+ if (this.listening) return;
86
+ this.listening = true;
87
+
88
+ window.addEventListener("keydown", this.handleKeyDown.bind(this), true);
89
+ }
90
+
91
+ private handleKeyDown(event: KeyboardEvent) {
92
+ // F6 to navigate landmarks
93
+ if (event.key === "F6") {
94
+ event.preventDefault();
95
+ if (event.shiftKey) {
96
+ this.focusPrevious();
97
+ } else {
98
+ this.focusNext();
99
+ }
100
+ }
101
+ }
102
+
103
+ register(entry: LandmarkEntry): void {
104
+ // Insert in DOM order using compareDocumentPosition
105
+ const index = this.findInsertionIndex(entry.ref);
106
+ this.landmarks.splice(index, 0, entry);
107
+
108
+ // Validate: if multiple landmarks have the same role, they should have different labels
109
+ this.validateLabels();
110
+ }
111
+
112
+ unregister(ref: HTMLElement): void {
113
+ const index = this.landmarks.findIndex((l) => l.ref === ref);
114
+ if (index !== -1) {
115
+ this.landmarks.splice(index, 1);
116
+ // Adjust currentIndex if needed
117
+ if (this.currentIndex >= this.landmarks.length) {
118
+ this.currentIndex = this.landmarks.length - 1;
119
+ }
120
+ }
121
+ }
122
+
123
+ private findInsertionIndex(ref: HTMLElement): number {
124
+ // Binary search for insertion point based on DOM order
125
+ let low = 0;
126
+ let high = this.landmarks.length;
127
+
128
+ while (low < high) {
129
+ const mid = Math.floor((low + high) / 2);
130
+ const comparison = this.landmarks[mid].ref.compareDocumentPosition(ref);
131
+
132
+ // Node.DOCUMENT_POSITION_FOLLOWING = 4
133
+ if (comparison & Node.DOCUMENT_POSITION_FOLLOWING) {
134
+ low = mid + 1;
135
+ } else {
136
+ high = mid;
137
+ }
138
+ }
139
+
140
+ return low;
141
+ }
142
+
143
+ private validateLabels(): void {
144
+ // Group landmarks by role
145
+ const roleGroups = new Map<AriaLandmarkRole, LandmarkEntry[]>();
146
+ for (const landmark of this.landmarks) {
147
+ const group = roleGroups.get(landmark.role) || [];
148
+ group.push(landmark);
149
+ roleGroups.set(landmark.role, group);
150
+ }
151
+
152
+ // Warn if multiple landmarks with the same role lack unique labels
153
+ for (const [role, group] of roleGroups) {
154
+ if (group.length > 1) {
155
+ const labels = group.map((l) => l.label);
156
+ const uniqueLabels = new Set(labels.filter(Boolean));
157
+ if (uniqueLabels.size < group.length) {
158
+ console.warn(
159
+ `Multiple landmarks with role "${role}" exist. Each should have a unique aria-label or aria-labelledby.`,
160
+ );
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ focusNext(): void {
167
+ if (this.landmarks.length === 0) return;
168
+
169
+ // Find the currently focused landmark
170
+ const activeElement = document.activeElement;
171
+ this.currentIndex = this.findCurrentLandmarkIndex(activeElement);
172
+
173
+ // Move to next
174
+ this.currentIndex = (this.currentIndex + 1) % this.landmarks.length;
175
+ this.focusLandmark(this.landmarks[this.currentIndex]);
176
+ }
177
+
178
+ focusPrevious(): void {
179
+ if (this.landmarks.length === 0) return;
180
+
181
+ // Find the currently focused landmark
182
+ const activeElement = document.activeElement;
183
+ this.currentIndex = this.findCurrentLandmarkIndex(activeElement);
184
+
185
+ // Move to previous
186
+ this.currentIndex = (this.currentIndex - 1 + this.landmarks.length) % this.landmarks.length;
187
+ this.focusLandmark(this.landmarks[this.currentIndex]);
188
+ }
189
+
190
+ focusMain(): void {
191
+ const main = this.landmarks.find((l) => l.role === "main");
192
+ if (main) {
193
+ this.focusLandmark(main);
194
+ }
195
+ }
196
+
197
+ navigate(role: AriaLandmarkRole): void {
198
+ const landmark = this.landmarks.find((l) => l.role === role);
199
+ if (landmark) {
200
+ this.focusLandmark(landmark);
201
+ }
202
+ }
203
+
204
+ private findCurrentLandmarkIndex(activeElement: Element | null): number {
205
+ if (!activeElement) return -1;
206
+
207
+ // Check if active element is within any landmark
208
+ for (let i = 0; i < this.landmarks.length; i++) {
209
+ if (this.landmarks[i].ref.contains(activeElement)) {
210
+ // Store the last focused element for this landmark
211
+ if (activeElement instanceof HTMLElement) {
212
+ this.landmarks[i].lastFocused = activeElement;
213
+ }
214
+ return i;
215
+ }
216
+ }
217
+
218
+ return -1;
219
+ }
220
+
221
+ private focusLandmark(landmark: LandmarkEntry): void {
222
+ // If a custom focus handler is provided, use it
223
+ if (landmark.focus) {
224
+ landmark.focus();
225
+ return;
226
+ }
227
+
228
+ // If we previously focused an element in this landmark, try to restore it
229
+ if (landmark.lastFocused && landmark.ref.contains(landmark.lastFocused)) {
230
+ landmark.lastFocused.focus();
231
+ return;
232
+ }
233
+
234
+ // Try to find the first focusable element
235
+ const focusable = this.findFirstFocusable(landmark.ref);
236
+ if (focusable) {
237
+ focusable.focus();
238
+ return;
239
+ }
240
+
241
+ // Fallback: make the landmark itself focusable and focus it
242
+ if (!landmark.ref.hasAttribute("tabindex")) {
243
+ landmark.ref.setAttribute("tabindex", "-1");
244
+ }
245
+ landmark.ref.focus();
246
+ }
247
+
248
+ private findFirstFocusable(container: HTMLElement): HTMLElement | null {
249
+ const focusableSelectors = [
250
+ "a[href]",
251
+ "button:not([disabled])",
252
+ "input:not([disabled])",
253
+ "select:not([disabled])",
254
+ "textarea:not([disabled])",
255
+ '[tabindex]:not([tabindex="-1"])',
256
+ ].join(", ");
257
+
258
+ return container.querySelector<HTMLElement>(focusableSelectors);
259
+ }
260
+
261
+ getController(): LandmarkController {
262
+ return {
263
+ focusNext: () => this.focusNext(),
264
+ focusPrevious: () => this.focusPrevious(),
265
+ focusMain: () => this.focusMain(),
266
+ navigate: (role) => this.navigate(role),
267
+ };
268
+ }
269
+ }
270
+
271
+ // Global singleton instance
272
+ let landmarkManager: LandmarkManager | null = null;
273
+
274
+ function getLandmarkManager(): LandmarkManager {
275
+ if (!landmarkManager) {
276
+ landmarkManager = new LandmarkManager();
277
+ }
278
+ return landmarkManager;
279
+ }
280
+
281
+ /**
282
+ * Provides landmark navigation in an application.
283
+ * Call this with a role and label to register a landmark navigable with F6.
284
+ *
285
+ * @example
286
+ * ```tsx
287
+ * function Navigation(props) {
288
+ * let ref: HTMLElement;
289
+ * const { landmarkProps } = createLandmark({
290
+ * role: 'navigation',
291
+ * 'aria-label': 'Main navigation'
292
+ * });
293
+ *
294
+ * return (
295
+ * <nav {...landmarkProps} ref={ref}>
296
+ * {props.children}
297
+ * </nav>
298
+ * );
299
+ * }
300
+ * ```
301
+ */
302
+ export function createLandmark<T extends HTMLElement = HTMLElement>(
303
+ props: MaybeAccessor<AriaLandmarkProps>,
304
+ ref: Accessor<T | undefined>,
305
+ ): LandmarkAria<T> {
306
+ // Register with the landmark manager
307
+ createEffect(() => {
308
+ const element = ref();
309
+ if (!element) return;
310
+
311
+ const p = access(props);
312
+ const entry: LandmarkEntry = {
313
+ ref: element,
314
+ role: p.role,
315
+ label: p["aria-label"],
316
+ focus: p.focus,
317
+ };
318
+
319
+ const manager = getLandmarkManager();
320
+ manager.register(entry);
321
+
322
+ onCleanup(() => {
323
+ manager.unregister(element);
324
+ });
325
+ });
326
+
327
+ const getLandmarkProps = (): JSX.HTMLAttributes<T> => {
328
+ const p = access(props);
329
+ const domProps = filterDOMProps(p as unknown as Record<string, unknown>, { labelable: true });
330
+
331
+ return {
332
+ ...domProps,
333
+ role: p.role,
334
+ };
335
+ };
336
+
337
+ return {
338
+ get landmarkProps() {
339
+ return getLandmarkProps();
340
+ },
341
+ };
342
+ }
343
+
344
+ /**
345
+ * Returns a controller for programmatic landmark navigation.
346
+ *
347
+ * @example
348
+ * ```tsx
349
+ * const controller = getLandmarkController();
350
+ * controller.focusMain(); // Focus the main landmark
351
+ * controller.focusNext(); // Focus the next landmark
352
+ * ```
353
+ */
354
+ export function getLandmarkController(): LandmarkController {
355
+ return getLandmarkManager().getController();
356
+ }