@octanejs/aria 0.0.1 → 0.0.4
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.
- package/package.json +6 -3
- package/src/breadcrumbs/useBreadcrumbItem.ts +95 -0
- package/src/breadcrumbs/useBreadcrumbs.ts +51 -0
- package/src/button/useButton.ts +273 -0
- package/src/button/useToggleButton.ts +131 -0
- package/src/button/useToggleButtonGroup.ts +131 -0
- package/src/checkbox/useCheckbox.ts +114 -0
- package/src/checkbox/useCheckboxGroup.ts +107 -0
- package/src/checkbox/useCheckboxGroupItem.ts +132 -0
- package/src/checkbox/utils.ts +15 -0
- package/src/combobox/useComboBox.ts +602 -0
- package/src/dialog/useDialog.ts +147 -0
- package/src/disclosure/useDisclosure.ts +180 -0
- package/src/focus/FocusRing.ts +69 -0
- package/src/focus/FocusScope.ts +1205 -0
- package/src/focus/useFocusRing.ts +125 -0
- package/src/focus/useHasTabbableChild.ts +82 -0
- package/src/focus/virtualFocus.ts +38 -0
- package/src/form/useFormValidation.ts +205 -0
- package/src/grid/useGridSelectionAnnouncement.ts +177 -0
- package/src/grid/useGridSelectionCheckbox.ts +86 -0
- package/src/grid/useHighlightSelectionDescription.ts +81 -0
- package/src/gridlist/useGridList.ts +236 -0
- package/src/gridlist/useGridListItem.ts +512 -0
- package/src/gridlist/useGridListSection.ts +78 -0
- package/src/gridlist/useGridListSelectionCheckbox.ts +47 -0
- package/src/gridlist/utils.ts +36 -0
- package/src/i18n/I18nProvider.ts +97 -0
- package/src/i18n/server.ts +115 -0
- package/src/i18n/useCollator.ts +42 -0
- package/src/i18n/useDateFormatter.ts +64 -0
- package/src/i18n/useDefaultLocale.ts +93 -0
- package/src/i18n/useFilter.ts +107 -0
- package/src/i18n/useListFormatter.ts +33 -0
- package/src/i18n/useLocalizedStringFormatter.ts +90 -0
- package/src/i18n/useNumberFormatter.ts +33 -0
- package/src/i18n/utils.ts +67 -0
- package/src/index.ts +268 -0
- package/src/intl/breadcrumbs/ar-AE.json +3 -0
- package/src/intl/breadcrumbs/bg-BG.json +3 -0
- package/src/intl/breadcrumbs/cs-CZ.json +3 -0
- package/src/intl/breadcrumbs/da-DK.json +3 -0
- package/src/intl/breadcrumbs/de-DE.json +3 -0
- package/src/intl/breadcrumbs/el-GR.json +3 -0
- package/src/intl/breadcrumbs/en-US.json +3 -0
- package/src/intl/breadcrumbs/es-ES.json +3 -0
- package/src/intl/breadcrumbs/et-EE.json +3 -0
- package/src/intl/breadcrumbs/fi-FI.json +3 -0
- package/src/intl/breadcrumbs/fr-FR.json +3 -0
- package/src/intl/breadcrumbs/he-IL.json +3 -0
- package/src/intl/breadcrumbs/hr-HR.json +3 -0
- package/src/intl/breadcrumbs/hu-HU.json +3 -0
- package/src/intl/breadcrumbs/index.ts +75 -0
- package/src/intl/breadcrumbs/it-IT.json +3 -0
- package/src/intl/breadcrumbs/ja-JP.json +3 -0
- package/src/intl/breadcrumbs/ko-KR.json +3 -0
- package/src/intl/breadcrumbs/lt-LT.json +3 -0
- package/src/intl/breadcrumbs/lv-LV.json +3 -0
- package/src/intl/breadcrumbs/nb-NO.json +3 -0
- package/src/intl/breadcrumbs/nl-NL.json +3 -0
- package/src/intl/breadcrumbs/pl-PL.json +3 -0
- package/src/intl/breadcrumbs/pt-BR.json +3 -0
- package/src/intl/breadcrumbs/pt-PT.json +3 -0
- package/src/intl/breadcrumbs/ro-RO.json +3 -0
- package/src/intl/breadcrumbs/ru-RU.json +3 -0
- package/src/intl/breadcrumbs/sk-SK.json +3 -0
- package/src/intl/breadcrumbs/sl-SI.json +3 -0
- package/src/intl/breadcrumbs/sr-SP.json +3 -0
- package/src/intl/breadcrumbs/sv-SE.json +3 -0
- package/src/intl/breadcrumbs/tr-TR.json +3 -0
- package/src/intl/breadcrumbs/uk-UA.json +3 -0
- package/src/intl/breadcrumbs/zh-CN.json +3 -0
- package/src/intl/breadcrumbs/zh-TW.json +3 -0
- package/src/intl/combobox/ar-AE.json +7 -0
- package/src/intl/combobox/bg-BG.json +7 -0
- package/src/intl/combobox/cs-CZ.json +7 -0
- package/src/intl/combobox/da-DK.json +7 -0
- package/src/intl/combobox/de-DE.json +7 -0
- package/src/intl/combobox/el-GR.json +7 -0
- package/src/intl/combobox/en-US.json +7 -0
- package/src/intl/combobox/es-ES.json +7 -0
- package/src/intl/combobox/et-EE.json +7 -0
- package/src/intl/combobox/fi-FI.json +7 -0
- package/src/intl/combobox/fr-FR.json +7 -0
- package/src/intl/combobox/he-IL.json +7 -0
- package/src/intl/combobox/hr-HR.json +7 -0
- package/src/intl/combobox/hu-HU.json +7 -0
- package/src/intl/combobox/index.ts +75 -0
- package/src/intl/combobox/it-IT.json +7 -0
- package/src/intl/combobox/ja-JP.json +7 -0
- package/src/intl/combobox/ko-KR.json +7 -0
- package/src/intl/combobox/lt-LT.json +7 -0
- package/src/intl/combobox/lv-LV.json +7 -0
- package/src/intl/combobox/nb-NO.json +7 -0
- package/src/intl/combobox/nl-NL.json +7 -0
- package/src/intl/combobox/pl-PL.json +7 -0
- package/src/intl/combobox/pt-BR.json +7 -0
- package/src/intl/combobox/pt-PT.json +7 -0
- package/src/intl/combobox/ro-RO.json +7 -0
- package/src/intl/combobox/ru-RU.json +7 -0
- package/src/intl/combobox/sk-SK.json +7 -0
- package/src/intl/combobox/sl-SI.json +7 -0
- package/src/intl/combobox/sr-SP.json +7 -0
- package/src/intl/combobox/sv-SE.json +7 -0
- package/src/intl/combobox/tr-TR.json +7 -0
- package/src/intl/combobox/uk-UA.json +7 -0
- package/src/intl/combobox/zh-CN.json +7 -0
- package/src/intl/combobox/zh-TW.json +7 -0
- package/src/intl/grid/ar-AE.json +8 -0
- package/src/intl/grid/bg-BG.json +8 -0
- package/src/intl/grid/cs-CZ.json +8 -0
- package/src/intl/grid/da-DK.json +8 -0
- package/src/intl/grid/de-DE.json +8 -0
- package/src/intl/grid/el-GR.json +8 -0
- package/src/intl/grid/en-US.json +8 -0
- package/src/intl/grid/es-ES.json +8 -0
- package/src/intl/grid/et-EE.json +8 -0
- package/src/intl/grid/fi-FI.json +8 -0
- package/src/intl/grid/fr-FR.json +8 -0
- package/src/intl/grid/he-IL.json +8 -0
- package/src/intl/grid/hr-HR.json +8 -0
- package/src/intl/grid/hu-HU.json +8 -0
- package/src/intl/grid/index.ts +75 -0
- package/src/intl/grid/it-IT.json +8 -0
- package/src/intl/grid/ja-JP.json +8 -0
- package/src/intl/grid/ko-KR.json +8 -0
- package/src/intl/grid/lt-LT.json +8 -0
- package/src/intl/grid/lv-LV.json +8 -0
- package/src/intl/grid/nb-NO.json +8 -0
- package/src/intl/grid/nl-NL.json +8 -0
- package/src/intl/grid/pl-PL.json +8 -0
- package/src/intl/grid/pt-BR.json +8 -0
- package/src/intl/grid/pt-PT.json +8 -0
- package/src/intl/grid/ro-RO.json +8 -0
- package/src/intl/grid/ru-RU.json +8 -0
- package/src/intl/grid/sk-SK.json +8 -0
- package/src/intl/grid/sl-SI.json +8 -0
- package/src/intl/grid/sr-SP.json +8 -0
- package/src/intl/grid/sv-SE.json +8 -0
- package/src/intl/grid/tr-TR.json +8 -0
- package/src/intl/grid/uk-UA.json +8 -0
- package/src/intl/grid/zh-CN.json +8 -0
- package/src/intl/grid/zh-TW.json +8 -0
- package/src/intl/gridlist/ar-AE.json +4 -0
- package/src/intl/gridlist/bg-BG.json +4 -0
- package/src/intl/gridlist/cs-CZ.json +4 -0
- package/src/intl/gridlist/da-DK.json +4 -0
- package/src/intl/gridlist/de-DE.json +4 -0
- package/src/intl/gridlist/el-GR.json +4 -0
- package/src/intl/gridlist/en-US.json +4 -0
- package/src/intl/gridlist/es-ES.json +4 -0
- package/src/intl/gridlist/et-EE.json +4 -0
- package/src/intl/gridlist/fi-FI.json +4 -0
- package/src/intl/gridlist/fr-FR.json +4 -0
- package/src/intl/gridlist/he-IL.json +4 -0
- package/src/intl/gridlist/hr-HR.json +4 -0
- package/src/intl/gridlist/hu-HU.json +4 -0
- package/src/intl/gridlist/index.ts +75 -0
- package/src/intl/gridlist/it-IT.json +4 -0
- package/src/intl/gridlist/ja-JP.json +4 -0
- package/src/intl/gridlist/ko-KR.json +4 -0
- package/src/intl/gridlist/lt-LT.json +4 -0
- package/src/intl/gridlist/lv-LV.json +4 -0
- package/src/intl/gridlist/nb-NO.json +4 -0
- package/src/intl/gridlist/nl-NL.json +4 -0
- package/src/intl/gridlist/pl-PL.json +4 -0
- package/src/intl/gridlist/pt-BR.json +4 -0
- package/src/intl/gridlist/pt-PT.json +4 -0
- package/src/intl/gridlist/ro-RO.json +4 -0
- package/src/intl/gridlist/ru-RU.json +4 -0
- package/src/intl/gridlist/sk-SK.json +4 -0
- package/src/intl/gridlist/sl-SI.json +4 -0
- package/src/intl/gridlist/sr-SP.json +4 -0
- package/src/intl/gridlist/sv-SE.json +4 -0
- package/src/intl/gridlist/tr-TR.json +4 -0
- package/src/intl/gridlist/uk-UA.json +4 -0
- package/src/intl/gridlist/zh-CN.json +4 -0
- package/src/intl/gridlist/zh-TW.json +4 -0
- package/src/intl/menu/ar-AE.json +3 -0
- package/src/intl/menu/bg-BG.json +3 -0
- package/src/intl/menu/cs-CZ.json +3 -0
- package/src/intl/menu/da-DK.json +3 -0
- package/src/intl/menu/de-DE.json +3 -0
- package/src/intl/menu/el-GR.json +3 -0
- package/src/intl/menu/en-US.json +3 -0
- package/src/intl/menu/es-ES.json +3 -0
- package/src/intl/menu/et-EE.json +3 -0
- package/src/intl/menu/fi-FI.json +3 -0
- package/src/intl/menu/fr-FR.json +3 -0
- package/src/intl/menu/he-IL.json +3 -0
- package/src/intl/menu/hr-HR.json +3 -0
- package/src/intl/menu/hu-HU.json +3 -0
- package/src/intl/menu/index.ts +75 -0
- package/src/intl/menu/it-IT.json +3 -0
- package/src/intl/menu/ja-JP.json +3 -0
- package/src/intl/menu/ko-KR.json +3 -0
- package/src/intl/menu/lt-LT.json +3 -0
- package/src/intl/menu/lv-LV.json +3 -0
- package/src/intl/menu/nb-NO.json +3 -0
- package/src/intl/menu/nl-NL.json +3 -0
- package/src/intl/menu/pl-PL.json +3 -0
- package/src/intl/menu/pt-BR.json +3 -0
- package/src/intl/menu/pt-PT.json +3 -0
- package/src/intl/menu/ro-RO.json +3 -0
- package/src/intl/menu/ru-RU.json +3 -0
- package/src/intl/menu/sk-SK.json +3 -0
- package/src/intl/menu/sl-SI.json +3 -0
- package/src/intl/menu/sr-SP.json +3 -0
- package/src/intl/menu/sv-SE.json +3 -0
- package/src/intl/menu/tr-TR.json +3 -0
- package/src/intl/menu/uk-UA.json +3 -0
- package/src/intl/menu/zh-CN.json +3 -0
- package/src/intl/menu/zh-TW.json +3 -0
- package/src/intl/numberfield/ar-AE.json +5 -0
- package/src/intl/numberfield/bg-BG.json +5 -0
- package/src/intl/numberfield/cs-CZ.json +5 -0
- package/src/intl/numberfield/da-DK.json +5 -0
- package/src/intl/numberfield/de-DE.json +5 -0
- package/src/intl/numberfield/el-GR.json +5 -0
- package/src/intl/numberfield/en-US.json +5 -0
- package/src/intl/numberfield/es-ES.json +5 -0
- package/src/intl/numberfield/et-EE.json +5 -0
- package/src/intl/numberfield/fi-FI.json +5 -0
- package/src/intl/numberfield/fr-FR.json +5 -0
- package/src/intl/numberfield/he-IL.json +5 -0
- package/src/intl/numberfield/hr-HR.json +5 -0
- package/src/intl/numberfield/hu-HU.json +5 -0
- package/src/intl/numberfield/index.ts +75 -0
- package/src/intl/numberfield/it-IT.json +5 -0
- package/src/intl/numberfield/ja-JP.json +5 -0
- package/src/intl/numberfield/ko-KR.json +5 -0
- package/src/intl/numberfield/lt-LT.json +5 -0
- package/src/intl/numberfield/lv-LV.json +5 -0
- package/src/intl/numberfield/nb-NO.json +5 -0
- package/src/intl/numberfield/nl-NL.json +5 -0
- package/src/intl/numberfield/pl-PL.json +5 -0
- package/src/intl/numberfield/pt-BR.json +5 -0
- package/src/intl/numberfield/pt-PT.json +5 -0
- package/src/intl/numberfield/ro-RO.json +5 -0
- package/src/intl/numberfield/ru-RU.json +5 -0
- package/src/intl/numberfield/sk-SK.json +5 -0
- package/src/intl/numberfield/sl-SI.json +5 -0
- package/src/intl/numberfield/sr-SP.json +5 -0
- package/src/intl/numberfield/sv-SE.json +5 -0
- package/src/intl/numberfield/tr-TR.json +5 -0
- package/src/intl/numberfield/uk-UA.json +5 -0
- package/src/intl/numberfield/zh-CN.json +5 -0
- package/src/intl/numberfield/zh-TW.json +5 -0
- package/src/intl/overlays/ar-AE.json +3 -0
- package/src/intl/overlays/bg-BG.json +3 -0
- package/src/intl/overlays/cs-CZ.json +3 -0
- package/src/intl/overlays/da-DK.json +3 -0
- package/src/intl/overlays/de-DE.json +3 -0
- package/src/intl/overlays/el-GR.json +3 -0
- package/src/intl/overlays/en-US.json +3 -0
- package/src/intl/overlays/es-ES.json +3 -0
- package/src/intl/overlays/et-EE.json +3 -0
- package/src/intl/overlays/fi-FI.json +3 -0
- package/src/intl/overlays/fr-FR.json +3 -0
- package/src/intl/overlays/he-IL.json +3 -0
- package/src/intl/overlays/hr-HR.json +3 -0
- package/src/intl/overlays/hu-HU.json +3 -0
- package/src/intl/overlays/index.ts +75 -0
- package/src/intl/overlays/it-IT.json +3 -0
- package/src/intl/overlays/ja-JP.json +3 -0
- package/src/intl/overlays/ko-KR.json +3 -0
- package/src/intl/overlays/lt-LT.json +3 -0
- package/src/intl/overlays/lv-LV.json +3 -0
- package/src/intl/overlays/nb-NO.json +3 -0
- package/src/intl/overlays/nl-NL.json +3 -0
- package/src/intl/overlays/pl-PL.json +3 -0
- package/src/intl/overlays/pt-BR.json +3 -0
- package/src/intl/overlays/pt-PT.json +3 -0
- package/src/intl/overlays/ro-RO.json +3 -0
- package/src/intl/overlays/ru-RU.json +3 -0
- package/src/intl/overlays/sk-SK.json +3 -0
- package/src/intl/overlays/sl-SI.json +3 -0
- package/src/intl/overlays/sr-SP.json +3 -0
- package/src/intl/overlays/sv-SE.json +3 -0
- package/src/intl/overlays/tr-TR.json +3 -0
- package/src/intl/overlays/uk-UA.json +3 -0
- package/src/intl/overlays/zh-CN.json +3 -0
- package/src/intl/overlays/zh-TW.json +3 -0
- package/src/intl/searchfield/ar-AE.json +3 -0
- package/src/intl/searchfield/bg-BG.json +3 -0
- package/src/intl/searchfield/cs-CZ.json +3 -0
- package/src/intl/searchfield/da-DK.json +3 -0
- package/src/intl/searchfield/de-DE.json +3 -0
- package/src/intl/searchfield/el-GR.json +3 -0
- package/src/intl/searchfield/en-US.json +3 -0
- package/src/intl/searchfield/es-ES.json +3 -0
- package/src/intl/searchfield/et-EE.json +3 -0
- package/src/intl/searchfield/fi-FI.json +3 -0
- package/src/intl/searchfield/fr-FR.json +3 -0
- package/src/intl/searchfield/he-IL.json +3 -0
- package/src/intl/searchfield/hr-HR.json +3 -0
- package/src/intl/searchfield/hu-HU.json +3 -0
- package/src/intl/searchfield/index.ts +75 -0
- package/src/intl/searchfield/it-IT.json +3 -0
- package/src/intl/searchfield/ja-JP.json +3 -0
- package/src/intl/searchfield/ko-KR.json +3 -0
- package/src/intl/searchfield/lt-LT.json +3 -0
- package/src/intl/searchfield/lv-LV.json +3 -0
- package/src/intl/searchfield/nb-NO.json +3 -0
- package/src/intl/searchfield/nl-NL.json +3 -0
- package/src/intl/searchfield/pl-PL.json +3 -0
- package/src/intl/searchfield/pt-BR.json +3 -0
- package/src/intl/searchfield/pt-PT.json +3 -0
- package/src/intl/searchfield/ro-RO.json +3 -0
- package/src/intl/searchfield/ru-RU.json +3 -0
- package/src/intl/searchfield/sk-SK.json +3 -0
- package/src/intl/searchfield/sl-SI.json +3 -0
- package/src/intl/searchfield/sr-SP.json +3 -0
- package/src/intl/searchfield/sv-SE.json +3 -0
- package/src/intl/searchfield/tr-TR.json +3 -0
- package/src/intl/searchfield/uk-UA.json +3 -0
- package/src/intl/searchfield/zh-CN.json +3 -0
- package/src/intl/searchfield/zh-TW.json +3 -0
- package/src/intl/spinbutton/ar-AE.json +3 -0
- package/src/intl/spinbutton/bg-BG.json +3 -0
- package/src/intl/spinbutton/cs-CZ.json +3 -0
- package/src/intl/spinbutton/da-DK.json +3 -0
- package/src/intl/spinbutton/de-DE.json +3 -0
- package/src/intl/spinbutton/el-GR.json +3 -0
- package/src/intl/spinbutton/en-US.json +3 -0
- package/src/intl/spinbutton/es-ES.json +3 -0
- package/src/intl/spinbutton/et-EE.json +3 -0
- package/src/intl/spinbutton/fi-FI.json +3 -0
- package/src/intl/spinbutton/fr-FR.json +3 -0
- package/src/intl/spinbutton/he-IL.json +3 -0
- package/src/intl/spinbutton/hr-HR.json +3 -0
- package/src/intl/spinbutton/hu-HU.json +3 -0
- package/src/intl/spinbutton/index.ts +75 -0
- package/src/intl/spinbutton/it-IT.json +3 -0
- package/src/intl/spinbutton/ja-JP.json +3 -0
- package/src/intl/spinbutton/ko-KR.json +3 -0
- package/src/intl/spinbutton/lt-LT.json +3 -0
- package/src/intl/spinbutton/lv-LV.json +3 -0
- package/src/intl/spinbutton/nb-NO.json +3 -0
- package/src/intl/spinbutton/nl-NL.json +3 -0
- package/src/intl/spinbutton/pl-PL.json +3 -0
- package/src/intl/spinbutton/pt-BR.json +3 -0
- package/src/intl/spinbutton/pt-PT.json +3 -0
- package/src/intl/spinbutton/ro-RO.json +3 -0
- package/src/intl/spinbutton/ru-RU.json +3 -0
- package/src/intl/spinbutton/sk-SK.json +3 -0
- package/src/intl/spinbutton/sl-SI.json +3 -0
- package/src/intl/spinbutton/sr-SP.json +3 -0
- package/src/intl/spinbutton/sv-SE.json +3 -0
- package/src/intl/spinbutton/tr-TR.json +3 -0
- package/src/intl/spinbutton/uk-UA.json +3 -0
- package/src/intl/spinbutton/zh-CN.json +3 -0
- package/src/intl/spinbutton/zh-TW.json +3 -0
- package/src/intl/tag/ar-AE.json +4 -0
- package/src/intl/tag/bg-BG.json +4 -0
- package/src/intl/tag/cs-CZ.json +4 -0
- package/src/intl/tag/da-DK.json +4 -0
- package/src/intl/tag/de-DE.json +4 -0
- package/src/intl/tag/el-GR.json +4 -0
- package/src/intl/tag/en-US.json +4 -0
- package/src/intl/tag/es-ES.json +4 -0
- package/src/intl/tag/et-EE.json +4 -0
- package/src/intl/tag/fi-FI.json +4 -0
- package/src/intl/tag/fr-FR.json +4 -0
- package/src/intl/tag/he-IL.json +4 -0
- package/src/intl/tag/hr-HR.json +4 -0
- package/src/intl/tag/hu-HU.json +4 -0
- package/src/intl/tag/index.ts +75 -0
- package/src/intl/tag/it-IT.json +4 -0
- package/src/intl/tag/ja-JP.json +4 -0
- package/src/intl/tag/ko-KR.json +4 -0
- package/src/intl/tag/lt-LT.json +4 -0
- package/src/intl/tag/lv-LV.json +4 -0
- package/src/intl/tag/nb-NO.json +4 -0
- package/src/intl/tag/nl-NL.json +4 -0
- package/src/intl/tag/pl-PL.json +4 -0
- package/src/intl/tag/pt-BR.json +4 -0
- package/src/intl/tag/pt-PT.json +4 -0
- package/src/intl/tag/ro-RO.json +4 -0
- package/src/intl/tag/ru-RU.json +4 -0
- package/src/intl/tag/sk-SK.json +4 -0
- package/src/intl/tag/sl-SI.json +4 -0
- package/src/intl/tag/sr-SP.json +4 -0
- package/src/intl/tag/sv-SE.json +4 -0
- package/src/intl/tag/tr-TR.json +4 -0
- package/src/intl/tag/uk-UA.json +4 -0
- package/src/intl/tag/zh-CN.json +4 -0
- package/src/intl/tag/zh-TW.json +4 -0
- package/src/label/useField.ts +67 -0
- package/src/label/useLabel.ts +78 -0
- package/src/link/useLink.ts +108 -0
- package/src/listbox/useListBox.ts +224 -0
- package/src/listbox/useListBoxSection.ts +74 -0
- package/src/listbox/useOption.ts +212 -0
- package/src/listbox/utils.ts +38 -0
- package/src/live-announcer/LiveAnnouncer.ts +172 -0
- package/src/menu/useMenu.ts +139 -0
- package/src/menu/useMenuItem.ts +453 -0
- package/src/menu/useMenuSection.ts +70 -0
- package/src/menu/useMenuTrigger.ts +189 -0
- package/src/menu/useSafelyMouseToSubmenu.ts +236 -0
- package/src/menu/useSubmenuTrigger.ts +357 -0
- package/src/menu/utils.ts +16 -0
- package/src/meter/useMeter.ts +43 -0
- package/src/numberfield/useNumberField.ts +572 -0
- package/src/overlays/DismissButton.ts +50 -0
- package/src/overlays/Overlay.ts +106 -0
- package/src/overlays/PortalProvider.ts +37 -0
- package/src/overlays/ariaHideOutside.ts +299 -0
- package/src/overlays/calculatePosition.ts +856 -0
- package/src/overlays/useCloseOnScroll.ts +75 -0
- package/src/overlays/useModal.ts +224 -0
- package/src/overlays/useModalOverlay.ts +103 -0
- package/src/overlays/useOverlay.ts +199 -0
- package/src/overlays/useOverlayPosition.ts +462 -0
- package/src/overlays/useOverlayTrigger.ts +94 -0
- package/src/overlays/usePopover.ts +170 -0
- package/src/overlays/usePreventScroll.ts +316 -0
- package/src/progress/useProgressBar.ts +115 -0
- package/src/radio/useRadio.ts +219 -0
- package/src/radio/useRadioGroup.ts +184 -0
- package/src/radio/utils.ts +15 -0
- package/src/searchfield/useSearchField.ts +156 -0
- package/src/select/HiddenSelect.ts +261 -0
- package/src/select/useSelect.ts +332 -0
- package/src/selection/DOMLayoutDelegate.ts +51 -0
- package/src/selection/ListKeyboardDelegate.ts +392 -0
- package/src/selection/useSelectableCollection.ts +750 -0
- package/src/selection/useSelectableItem.ts +499 -0
- package/src/selection/useSelectableList.ts +132 -0
- package/src/selection/useTypeSelect.ts +192 -0
- package/src/selection/utils.ts +50 -0
- package/src/separator/useSeparator.ts +41 -0
- package/src/slider/useSlider.ts +277 -0
- package/src/slider/useSliderThumb.ts +375 -0
- package/src/slider/utils.ts +20 -0
- package/src/spinbutton/useSpinButton.ts +380 -0
- package/src/stately/checkbox/useCheckboxGroupState.ts +177 -0
- package/src/stately/collections/CollectionBuilder.ts +332 -0
- package/src/stately/collections/Item.ts +78 -0
- package/src/stately/collections/Section.ts +52 -0
- package/src/stately/collections/getChildNodes.ts +94 -0
- package/src/stately/collections/getItemCount.ts +29 -0
- package/src/stately/collections/types.ts +20 -0
- package/src/stately/collections/useCollection.ts +54 -0
- package/src/stately/combobox/useComboBoxState.ts +763 -0
- package/src/stately/disclosure/useDisclosureGroupState.ts +108 -0
- package/src/stately/disclosure/useDisclosureState.ts +84 -0
- package/src/stately/form/useFormValidationState.ts +331 -0
- package/src/stately/index.ts +111 -0
- package/src/stately/list/ListCollection.ts +104 -0
- package/src/stately/list/useListState.ts +178 -0
- package/src/stately/list/useSingleSelectListState.ts +101 -0
- package/src/stately/menu/useMenuTriggerState.ts +120 -0
- package/src/stately/menu/useSubmenuTriggerState.ts +116 -0
- package/src/stately/numberfield/useNumberFieldState.ts +430 -0
- package/src/stately/overlays/useOverlayTriggerState.ts +85 -0
- package/src/stately/radio/useRadioGroupState.ts +150 -0
- package/src/stately/searchfield/useSearchFieldState.ts +79 -0
- package/src/stately/select/useSelectState.ts +322 -0
- package/src/stately/selection/Selection.ts +23 -0
- package/src/stately/selection/SelectionManager.ts +541 -0
- package/src/stately/selection/types.ts +117 -0
- package/src/stately/selection/useMultipleSelectionState.ts +178 -0
- package/src/stately/slider/useSliderState.ts +458 -0
- package/src/stately/tabs/useTabListState.ts +149 -0
- package/src/stately/toggle/useToggleGroupState.ts +109 -0
- package/src/stately/toggle/useToggleState.ts +100 -0
- package/src/stately/tooltip/useTooltipTriggerState.ts +218 -0
- package/src/stately/tree/TreeCollection.ts +92 -0
- package/src/stately/tree/useTreeState.ts +121 -0
- package/src/stately/utils/useControlledState.ts +7 -0
- package/src/switch/useSwitch.ts +77 -0
- package/src/tabs/TabsKeyboardDelegate.ts +99 -0
- package/src/tabs/useTab.ts +117 -0
- package/src/tabs/useTabList.ts +105 -0
- package/src/tabs/useTabPanel.ts +75 -0
- package/src/tabs/utils.ts +32 -0
- package/src/tag/useTag.ts +162 -0
- package/src/tag/useTagGroup.ts +192 -0
- package/src/textfield/useFormattedTextField.ts +203 -0
- package/src/textfield/useTextField.ts +248 -0
- package/src/toggle/useToggle.ts +265 -0
- package/src/toolbar/useToolbar.ts +147 -0
- package/src/tooltip/useTooltip.ts +64 -0
- package/src/tooltip/useTooltipTrigger.ts +187 -0
- package/src/utils/filterDOMProps.ts +121 -0
- package/src/utils/getScrollParent.ts +16 -0
- package/src/utils/getScrollParents.ts +20 -0
- package/src/utils/keyboard.ts +38 -0
- package/src/utils/scrollIntoView.ts +178 -0
- package/src/utils/useDeepMemo.ts +30 -0
- package/src/utils/useFormReset.ts +54 -0
- package/src/utils/useId.ts +5 -0
- package/src/utils/useLabels.ts +53 -0
- package/src/utils/useResizeObserver.ts +70 -0
- package/src/utils/useSlot.ts +78 -0
- package/src/utils/useUpdateEffect.ts +54 -0
- package/src/utils/useUpdateLayoutEffect.ts +58 -0
- package/src/visually-hidden/VisuallyHidden.ts +100 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/label/useField.ts).
|
|
2
|
+
import type { DOMAttributes, HelpTextProps, Validation } from '@react-types/shared';
|
|
3
|
+
|
|
4
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
5
|
+
import { LabelAria, LabelAriaProps, useLabel } from './useLabel';
|
|
6
|
+
import { mergeProps } from '../utils/mergeProps';
|
|
7
|
+
import { useSlotId } from '../utils/useId';
|
|
8
|
+
|
|
9
|
+
export interface AriaFieldProps
|
|
10
|
+
extends LabelAriaProps, HelpTextProps, Omit<Validation<any>, 'isRequired'> {}
|
|
11
|
+
|
|
12
|
+
export interface FieldAria extends LabelAria {
|
|
13
|
+
/** Props for the description element, if any. */
|
|
14
|
+
descriptionProps: DOMAttributes;
|
|
15
|
+
/** Props for the error message element, if any. */
|
|
16
|
+
errorMessageProps: DOMAttributes;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Provides the accessibility implementation for input fields. Fields accept user input, gain
|
|
21
|
+
* context from their label, and may display a description or error message.
|
|
22
|
+
*
|
|
23
|
+
* @param props - Props for the Field.
|
|
24
|
+
*/
|
|
25
|
+
export function useField(props: AriaFieldProps): FieldAria;
|
|
26
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
27
|
+
export function useField(props: AriaFieldProps, slot: symbol | undefined): FieldAria;
|
|
28
|
+
export function useField(...args: any[]): FieldAria {
|
|
29
|
+
const [user, slotArg] = splitSlot(args);
|
|
30
|
+
const slot = slotArg ?? S('useField');
|
|
31
|
+
const props = user[0] as AriaFieldProps;
|
|
32
|
+
|
|
33
|
+
let { description, errorMessage, isInvalid, validationState } = props;
|
|
34
|
+
let { labelProps, fieldProps } = useLabel(props, subSlot(slot, 'label'));
|
|
35
|
+
|
|
36
|
+
let descriptionId = useSlotId(
|
|
37
|
+
[Boolean(description), Boolean(errorMessage), isInvalid, validationState],
|
|
38
|
+
subSlot(slot, 'descriptionId'),
|
|
39
|
+
);
|
|
40
|
+
let errorMessageId = useSlotId(
|
|
41
|
+
[Boolean(description), Boolean(errorMessage), isInvalid, validationState],
|
|
42
|
+
subSlot(slot, 'errorMessageId'),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
fieldProps = mergeProps(fieldProps, {
|
|
46
|
+
'aria-describedby':
|
|
47
|
+
[
|
|
48
|
+
descriptionId,
|
|
49
|
+
// Use aria-describedby for error message because aria-errormessage is unsupported using VoiceOver or NVDA. See https://github.com/adobe/react-spectrum/issues/1346#issuecomment-740136268
|
|
50
|
+
errorMessageId,
|
|
51
|
+
props['aria-describedby'],
|
|
52
|
+
]
|
|
53
|
+
.filter(Boolean)
|
|
54
|
+
.join(' ') || undefined,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
labelProps,
|
|
59
|
+
fieldProps,
|
|
60
|
+
descriptionProps: {
|
|
61
|
+
id: descriptionId,
|
|
62
|
+
},
|
|
63
|
+
errorMessageProps: {
|
|
64
|
+
id: errorMessageId,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/label/useLabel.ts).
|
|
2
|
+
// octane adaptations: React's ElementType/LabelHTMLAttributes → local structural types;
|
|
3
|
+
// the dev-only missing-label console.warn is not ported (repo policy).
|
|
4
|
+
import type {
|
|
5
|
+
AriaLabelingProps,
|
|
6
|
+
DOMAttributes,
|
|
7
|
+
DOMProps,
|
|
8
|
+
LabelableProps,
|
|
9
|
+
} from '@react-types/shared';
|
|
10
|
+
|
|
11
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
12
|
+
import { useId } from '../utils/useId';
|
|
13
|
+
import { useLabels } from '../utils/useLabels';
|
|
14
|
+
|
|
15
|
+
export interface LabelAriaProps extends LabelableProps, DOMProps, AriaLabelingProps {
|
|
16
|
+
/**
|
|
17
|
+
* The HTML element used to render the label, e.g. 'label', or 'span'.
|
|
18
|
+
*
|
|
19
|
+
* @default 'label'
|
|
20
|
+
*/
|
|
21
|
+
labelElementType?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface LabelAria {
|
|
25
|
+
/** Props to apply to the label container element. */
|
|
26
|
+
labelProps: DOMAttributes & { htmlFor?: string };
|
|
27
|
+
/** Props to apply to the field container element being labeled. */
|
|
28
|
+
fieldProps: AriaLabelingProps & DOMProps;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Provides the accessibility implementation for labels and their associated elements.
|
|
33
|
+
* Labels provide context for user inputs.
|
|
34
|
+
*
|
|
35
|
+
* @param props - The props for labels and fields.
|
|
36
|
+
*/
|
|
37
|
+
export function useLabel(props: LabelAriaProps): LabelAria;
|
|
38
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
39
|
+
export function useLabel(props: LabelAriaProps, slot: symbol | undefined): LabelAria;
|
|
40
|
+
export function useLabel(...args: any[]): LabelAria {
|
|
41
|
+
const [user, slotArg] = splitSlot(args);
|
|
42
|
+
const slot = slotArg ?? S('useLabel');
|
|
43
|
+
const props = user[0] as LabelAriaProps;
|
|
44
|
+
|
|
45
|
+
let {
|
|
46
|
+
id,
|
|
47
|
+
label,
|
|
48
|
+
'aria-labelledby': ariaLabelledby,
|
|
49
|
+
'aria-label': ariaLabel,
|
|
50
|
+
labelElementType = 'label',
|
|
51
|
+
} = props;
|
|
52
|
+
|
|
53
|
+
id = useId(id, subSlot(slot, 'id'));
|
|
54
|
+
let labelId = useId(subSlot(slot, 'labelId'));
|
|
55
|
+
let labelProps = {};
|
|
56
|
+
if (label) {
|
|
57
|
+
ariaLabelledby = ariaLabelledby ? `${labelId} ${ariaLabelledby}` : labelId;
|
|
58
|
+
labelProps = {
|
|
59
|
+
id: labelId,
|
|
60
|
+
htmlFor: labelElementType === 'label' ? id : undefined,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let fieldProps = useLabels(
|
|
65
|
+
{
|
|
66
|
+
id,
|
|
67
|
+
'aria-label': ariaLabel,
|
|
68
|
+
'aria-labelledby': ariaLabelledby,
|
|
69
|
+
},
|
|
70
|
+
undefined,
|
|
71
|
+
subSlot(slot, 'fieldProps'),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
labelProps,
|
|
76
|
+
fieldProps,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/link/useLink.ts).
|
|
2
|
+
// octane adaptations: `FocusableProps` is the ported native-event version; the wrapped
|
|
3
|
+
// `onClick` receives the NATIVE MouseEvent; public-hook slot threading per convention.
|
|
4
|
+
import type {
|
|
5
|
+
AriaLabelingProps,
|
|
6
|
+
FocusableElement,
|
|
7
|
+
LinkDOMProps,
|
|
8
|
+
PressEvents,
|
|
9
|
+
RefObject,
|
|
10
|
+
} from '@react-types/shared';
|
|
11
|
+
|
|
12
|
+
// octane adaptation: structural prop bag (upstream's DOMAttributes drags React handler
|
|
13
|
+
// types; the wrapped onClick is a native MouseEvent handler).
|
|
14
|
+
type DOMAttributes = Record<string, any>;
|
|
15
|
+
|
|
16
|
+
import type { FocusableProps } from '../interactions/useFocusable';
|
|
17
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
18
|
+
import { filterDOMProps } from '../utils/filterDOMProps';
|
|
19
|
+
import { handleLinkClick, useLinkProps, useRouter } from '../utils/openLink';
|
|
20
|
+
import { mergeProps } from '../utils/mergeProps';
|
|
21
|
+
import { useFocusable } from '../interactions/useFocusable';
|
|
22
|
+
import { usePress } from '../interactions/usePress';
|
|
23
|
+
|
|
24
|
+
export interface LinkProps extends Omit<PressEvents, 'onClick'>, FocusableProps {}
|
|
25
|
+
|
|
26
|
+
export interface AriaLinkProps extends LinkProps, LinkDOMProps, AriaLabelingProps {}
|
|
27
|
+
|
|
28
|
+
export interface AriaLinkOptions extends AriaLinkProps {
|
|
29
|
+
/** Whether the link is disabled. */
|
|
30
|
+
isDisabled?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The HTML element used to render the link, e.g. 'a', or 'span'.
|
|
33
|
+
*
|
|
34
|
+
* @default 'a'
|
|
35
|
+
*/
|
|
36
|
+
elementType?: string;
|
|
37
|
+
/** Handler called on the native click event (octane native MouseEvent). */
|
|
38
|
+
onClick?: (e: MouseEvent) => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface LinkAria {
|
|
42
|
+
/** Props for the link element. */
|
|
43
|
+
linkProps: DOMAttributes;
|
|
44
|
+
/** Whether the link is currently pressed. */
|
|
45
|
+
isPressed: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function useLink(props: AriaLinkOptions, ref: RefObject<FocusableElement | null>): LinkAria;
|
|
49
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
50
|
+
export function useLink(
|
|
51
|
+
props: AriaLinkOptions,
|
|
52
|
+
ref: RefObject<FocusableElement | null>,
|
|
53
|
+
slot: symbol | undefined,
|
|
54
|
+
): LinkAria;
|
|
55
|
+
export function useLink(...args: any[]): LinkAria {
|
|
56
|
+
const [user, slotArg] = splitSlot(args);
|
|
57
|
+
const slot = slotArg ?? S('useLink');
|
|
58
|
+
const props = user[0] as AriaLinkOptions;
|
|
59
|
+
const ref = user[1] as RefObject<FocusableElement | null>;
|
|
60
|
+
|
|
61
|
+
let {
|
|
62
|
+
elementType = 'a',
|
|
63
|
+
onPress,
|
|
64
|
+
onPressStart,
|
|
65
|
+
onPressEnd,
|
|
66
|
+
onClick,
|
|
67
|
+
isDisabled,
|
|
68
|
+
...otherProps
|
|
69
|
+
} = props;
|
|
70
|
+
|
|
71
|
+
let linkProps: DOMAttributes = {};
|
|
72
|
+
if (elementType !== 'a') {
|
|
73
|
+
linkProps = {
|
|
74
|
+
role: 'link',
|
|
75
|
+
tabIndex: !isDisabled ? 0 : undefined,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
let { focusableProps } = useFocusable(props, ref, subSlot(slot, 'focusable'));
|
|
79
|
+
let { pressProps, isPressed } = usePress(
|
|
80
|
+
{
|
|
81
|
+
onPress,
|
|
82
|
+
onPressStart,
|
|
83
|
+
onPressEnd,
|
|
84
|
+
onClick,
|
|
85
|
+
isDisabled,
|
|
86
|
+
ref,
|
|
87
|
+
},
|
|
88
|
+
subSlot(slot, 'press'),
|
|
89
|
+
);
|
|
90
|
+
let domProps = filterDOMProps(otherProps as any, { labelable: true });
|
|
91
|
+
let interactionHandlers = mergeProps(focusableProps, pressProps);
|
|
92
|
+
let router = useRouter();
|
|
93
|
+
let routerLinkProps = useLinkProps(props);
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
isPressed, // Used to indicate press state for visual
|
|
97
|
+
linkProps: mergeProps(domProps, routerLinkProps, {
|
|
98
|
+
...interactionHandlers,
|
|
99
|
+
...linkProps,
|
|
100
|
+
'aria-disabled': isDisabled || undefined,
|
|
101
|
+
'aria-current': (props as any)['aria-current'],
|
|
102
|
+
onClick: (e: MouseEvent) => {
|
|
103
|
+
(pressProps as any).onClick?.(e);
|
|
104
|
+
handleLinkClick(e, router, props.href, props.routerOptions);
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/listbox/useListBox.ts).
|
|
2
|
+
// octane adaptations:
|
|
3
|
+
// - `FocusEvents` handler props are the ported NATIVE-event versions (from useFocus);
|
|
4
|
+
// `DOMAttributes` is a local structural prop-bag alias (upstream's is typed over React's
|
|
5
|
+
// synthetic handlers); `ReactNode` label → `any` (octane descriptors).
|
|
6
|
+
// - `ListState` type from the ported stately list state.
|
|
7
|
+
// - Public-hook slot threading (splitSlot/subSlot) per the binding convention.
|
|
8
|
+
import type {
|
|
9
|
+
AriaLabelingProps,
|
|
10
|
+
CollectionBase,
|
|
11
|
+
DOMProps,
|
|
12
|
+
FocusStrategy,
|
|
13
|
+
Key,
|
|
14
|
+
KeyboardDelegate,
|
|
15
|
+
LayoutDelegate,
|
|
16
|
+
MultipleSelection,
|
|
17
|
+
Orientation,
|
|
18
|
+
RefObject,
|
|
19
|
+
SelectionBehavior,
|
|
20
|
+
} from '@react-types/shared';
|
|
21
|
+
import { filterDOMProps } from '../utils/filterDOMProps';
|
|
22
|
+
import type { FocusEvents } from '../interactions/useFocus';
|
|
23
|
+
import { listData } from './utils';
|
|
24
|
+
import type { ListState } from '../stately/list/useListState';
|
|
25
|
+
import { mergeProps } from '../utils/mergeProps';
|
|
26
|
+
import { useFocusWithin } from '../interactions/useFocusWithin';
|
|
27
|
+
import { useId } from '../utils/useId';
|
|
28
|
+
import { useLabel } from '../label/useLabel';
|
|
29
|
+
import { useSelectableList } from '../selection/useSelectableList';
|
|
30
|
+
|
|
31
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
32
|
+
|
|
33
|
+
// octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
|
|
34
|
+
// handler types along).
|
|
35
|
+
type DOMAttributes = Record<string, any>;
|
|
36
|
+
|
|
37
|
+
export interface ListBoxProps<T> extends CollectionBase<T>, MultipleSelection, FocusEvents {
|
|
38
|
+
/** Whether to auto focus the listbox or an option. */
|
|
39
|
+
autoFocus?: boolean | FocusStrategy;
|
|
40
|
+
/** Whether focus should wrap around when the end/start is reached. */
|
|
41
|
+
shouldFocusWrap?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface AriaListBoxPropsBase<T> extends ListBoxProps<T>, DOMProps, AriaLabelingProps {
|
|
45
|
+
/**
|
|
46
|
+
* Whether pressing the escape key should clear selection in the listbox or not.
|
|
47
|
+
*
|
|
48
|
+
* Most experiences should not modify this option as it eliminates a keyboard user's ability to
|
|
49
|
+
* easily clear selection. Only use if the escape key is being handled externally or should not
|
|
50
|
+
* trigger selection clearing contextually.
|
|
51
|
+
*
|
|
52
|
+
* @default 'clearSelection'
|
|
53
|
+
*/
|
|
54
|
+
escapeKeyBehavior?: 'clearSelection' | 'none';
|
|
55
|
+
}
|
|
56
|
+
export interface AriaListBoxProps<T> extends AriaListBoxPropsBase<T> {
|
|
57
|
+
/**
|
|
58
|
+
* An optional visual label for the listbox.
|
|
59
|
+
*/
|
|
60
|
+
label?: any;
|
|
61
|
+
/** How multiple selection should behave in the collection. */
|
|
62
|
+
selectionBehavior?: SelectionBehavior;
|
|
63
|
+
/** Whether selection should occur on press up instead of press down. */
|
|
64
|
+
shouldSelectOnPressUp?: boolean;
|
|
65
|
+
/** Whether options should be focused when the user hovers over them. */
|
|
66
|
+
shouldFocusOnHover?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Handler that is called when a user performs an action on an item. The exact user event depends
|
|
69
|
+
* on the collection's `selectionBehavior` prop and the interaction modality.
|
|
70
|
+
*/
|
|
71
|
+
onAction?: (key: Key) => void;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ListBoxAria {
|
|
75
|
+
/** Props for the listbox element. */
|
|
76
|
+
listBoxProps: DOMAttributes;
|
|
77
|
+
/** Props for the listbox's visual label element (if any). */
|
|
78
|
+
labelProps: DOMAttributes;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface AriaListBoxOptions<T> extends Omit<AriaListBoxProps<T>, 'children'> {
|
|
82
|
+
/** Whether the listbox uses virtual scrolling. */
|
|
83
|
+
isVirtualized?: boolean;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* An optional keyboard delegate implementation for type to select,
|
|
87
|
+
* to override the default.
|
|
88
|
+
*/
|
|
89
|
+
keyboardDelegate?: KeyboardDelegate;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A delegate object that provides layout information for items in the collection.
|
|
93
|
+
* By default this uses the DOM, but this can be overridden to implement things like
|
|
94
|
+
* virtualized scrolling.
|
|
95
|
+
*/
|
|
96
|
+
layoutDelegate?: LayoutDelegate;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Whether the listbox items should use virtual focus instead of being focused directly.
|
|
100
|
+
*/
|
|
101
|
+
shouldUseVirtualFocus?: boolean;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The behavior of links in the collection.
|
|
105
|
+
* - 'action': link behaves like onAction.
|
|
106
|
+
* - 'selection': link follows selection interactions (e.g. if URL drives selection).
|
|
107
|
+
* - 'override': links override all other interactions (link items are not selectable).
|
|
108
|
+
*
|
|
109
|
+
* @default 'override'
|
|
110
|
+
*/
|
|
111
|
+
linkBehavior?: 'action' | 'selection' | 'override';
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The primary orientation of the items. Usually this is the direction that the collection
|
|
115
|
+
* scrolls.
|
|
116
|
+
*
|
|
117
|
+
* @default 'vertical'
|
|
118
|
+
*/
|
|
119
|
+
orientation?: Orientation;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Provides the behavior and accessibility implementation for a listbox component.
|
|
124
|
+
* A listbox displays a list of options and allows a user to select one or more of them.
|
|
125
|
+
*
|
|
126
|
+
* @param props - Props for the listbox.
|
|
127
|
+
* @param state - State for the listbox, as returned by `useListState`.
|
|
128
|
+
*/
|
|
129
|
+
export function useListBox<T>(
|
|
130
|
+
props: AriaListBoxOptions<T>,
|
|
131
|
+
state: ListState<T>,
|
|
132
|
+
ref: RefObject<HTMLElement | null>,
|
|
133
|
+
): ListBoxAria;
|
|
134
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
135
|
+
export function useListBox<T>(
|
|
136
|
+
props: AriaListBoxOptions<T>,
|
|
137
|
+
state: ListState<T>,
|
|
138
|
+
ref: RefObject<HTMLElement | null>,
|
|
139
|
+
slot: symbol | undefined,
|
|
140
|
+
): ListBoxAria;
|
|
141
|
+
export function useListBox(...args: any[]): ListBoxAria {
|
|
142
|
+
const [user, slotArg] = splitSlot(args);
|
|
143
|
+
const slot = slotArg ?? S('useListBox');
|
|
144
|
+
const props = user[0] as AriaListBoxOptions<unknown>;
|
|
145
|
+
const state = user[1] as ListState<unknown>;
|
|
146
|
+
const ref = user[2] as RefObject<HTMLElement | null>;
|
|
147
|
+
|
|
148
|
+
let domProps = filterDOMProps(props, { labelable: true });
|
|
149
|
+
// Use props instead of state here. We don't want this to change due to long press.
|
|
150
|
+
let selectionBehavior = props.selectionBehavior || 'toggle';
|
|
151
|
+
let orientation = props.orientation || 'vertical';
|
|
152
|
+
let linkBehavior =
|
|
153
|
+
props.linkBehavior || (selectionBehavior === 'replace' ? 'action' : 'override');
|
|
154
|
+
if (selectionBehavior === 'toggle' && linkBehavior === 'action') {
|
|
155
|
+
// linkBehavior="action" does not work with selectionBehavior="toggle" because there is no way
|
|
156
|
+
// to initiate selection (checkboxes are not allowed inside a listbox). Link items will not be
|
|
157
|
+
// selectable in this configuration.
|
|
158
|
+
linkBehavior = 'override';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let { listProps } = useSelectableList(
|
|
162
|
+
{
|
|
163
|
+
...props,
|
|
164
|
+
ref,
|
|
165
|
+
selectionManager: state.selectionManager,
|
|
166
|
+
collection: state.collection,
|
|
167
|
+
disabledKeys: state.disabledKeys,
|
|
168
|
+
linkBehavior,
|
|
169
|
+
},
|
|
170
|
+
subSlot(slot, 'list'),
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
let { focusWithinProps } = useFocusWithin(
|
|
174
|
+
{
|
|
175
|
+
onFocusWithin: props.onFocus,
|
|
176
|
+
onBlurWithin: props.onBlur,
|
|
177
|
+
onFocusWithinChange: props.onFocusChange,
|
|
178
|
+
},
|
|
179
|
+
subSlot(slot, 'focusWithin'),
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
// Share list id and some props with child options.
|
|
183
|
+
let id = useId(props.id, subSlot(slot, 'id'));
|
|
184
|
+
listData.set(state, {
|
|
185
|
+
id,
|
|
186
|
+
shouldUseVirtualFocus: props.shouldUseVirtualFocus,
|
|
187
|
+
shouldSelectOnPressUp: props.shouldSelectOnPressUp,
|
|
188
|
+
shouldFocusOnHover: props.shouldFocusOnHover,
|
|
189
|
+
isVirtualized: props.isVirtualized,
|
|
190
|
+
onAction: props.onAction,
|
|
191
|
+
linkBehavior,
|
|
192
|
+
// @ts-ignore
|
|
193
|
+
UNSTABLE_itemBehavior: (props as any)['UNSTABLE_itemBehavior'],
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
let { labelProps, fieldProps } = useLabel(
|
|
197
|
+
{
|
|
198
|
+
...props,
|
|
199
|
+
id,
|
|
200
|
+
// listbox is not an HTML input element so it
|
|
201
|
+
// shouldn't be labeled by a <label> element.
|
|
202
|
+
labelElementType: 'span',
|
|
203
|
+
},
|
|
204
|
+
subSlot(slot, 'label'),
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
labelProps,
|
|
209
|
+
listBoxProps: mergeProps(
|
|
210
|
+
domProps,
|
|
211
|
+
focusWithinProps,
|
|
212
|
+
state.selectionManager.selectionMode === 'multiple'
|
|
213
|
+
? {
|
|
214
|
+
'aria-multiselectable': 'true',
|
|
215
|
+
}
|
|
216
|
+
: {},
|
|
217
|
+
{
|
|
218
|
+
role: 'listbox',
|
|
219
|
+
'aria-orientation': orientation,
|
|
220
|
+
...mergeProps(fieldProps, listProps),
|
|
221
|
+
},
|
|
222
|
+
),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/listbox/useListBoxSection.ts).
|
|
2
|
+
// octane adaptations: `ReactNode` heading → `any` (octane descriptors); the heading's
|
|
3
|
+
// `onMouseDown` receives the NATIVE MouseEvent; `DOMAttributes` is a local structural
|
|
4
|
+
// prop-bag alias; public-hook slot threading (splitSlot/subSlot) per the binding convention.
|
|
5
|
+
import { useId } from '../utils/useId';
|
|
6
|
+
|
|
7
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
8
|
+
|
|
9
|
+
// octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
|
|
10
|
+
// handler types along).
|
|
11
|
+
type DOMAttributes = Record<string, any>;
|
|
12
|
+
|
|
13
|
+
export interface AriaListBoxSectionProps {
|
|
14
|
+
/** The heading for the section. */
|
|
15
|
+
heading?: any;
|
|
16
|
+
/** An accessibility label for the section. Required if `heading` is not present. */
|
|
17
|
+
'aria-label'?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ListBoxSectionAria {
|
|
21
|
+
/** Props for the wrapper list item. */
|
|
22
|
+
itemProps: DOMAttributes;
|
|
23
|
+
|
|
24
|
+
/** Props for the heading element, if any. */
|
|
25
|
+
headingProps: DOMAttributes;
|
|
26
|
+
|
|
27
|
+
/** Props for the group element. */
|
|
28
|
+
groupProps: DOMAttributes;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Provides the behavior and accessibility implementation for a section in a listbox.
|
|
33
|
+
* See `useListBox` for more details about listboxes.
|
|
34
|
+
*
|
|
35
|
+
* @param props - Props for the section.
|
|
36
|
+
*/
|
|
37
|
+
export function useListBoxSection(props: AriaListBoxSectionProps): ListBoxSectionAria;
|
|
38
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
39
|
+
export function useListBoxSection(
|
|
40
|
+
props: AriaListBoxSectionProps,
|
|
41
|
+
slot: symbol | undefined,
|
|
42
|
+
): ListBoxSectionAria;
|
|
43
|
+
export function useListBoxSection(...args: any[]): ListBoxSectionAria {
|
|
44
|
+
const [user, slotArg] = splitSlot(args);
|
|
45
|
+
const slot = slotArg ?? S('useListBoxSection');
|
|
46
|
+
const props = user[0] as AriaListBoxSectionProps;
|
|
47
|
+
|
|
48
|
+
let { heading, 'aria-label': ariaLabel } = props;
|
|
49
|
+
let headingId = useId(subSlot(slot, 'headingId'));
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
itemProps: {
|
|
53
|
+
role: 'presentation',
|
|
54
|
+
},
|
|
55
|
+
headingProps: heading
|
|
56
|
+
? {
|
|
57
|
+
// Technically, listbox cannot contain headings according to ARIA.
|
|
58
|
+
// We hide the heading from assistive technology, using role="presentation",
|
|
59
|
+
// and only use it as a visual label for the nested group.
|
|
60
|
+
id: headingId,
|
|
61
|
+
role: 'presentation',
|
|
62
|
+
onMouseDown: (e: MouseEvent) => {
|
|
63
|
+
// Prevent DOM focus from moving on mouse down when using virtual focus
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
: {},
|
|
68
|
+
groupProps: {
|
|
69
|
+
role: 'group',
|
|
70
|
+
'aria-label': ariaLabel,
|
|
71
|
+
'aria-labelledby': heading ? headingId : undefined,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|