@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,54 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/useFormReset.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; the explicit `[ref]` effect dep array is preserved exactly. The listener is
|
|
4
|
+
// wired with native `addEventListener('reset')` exactly like upstream.
|
|
5
|
+
import { useEffect } from 'octane';
|
|
6
|
+
|
|
7
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
8
|
+
import { useEffectEvent } from './useEffectEvent';
|
|
9
|
+
|
|
10
|
+
type RefObject<T> = { current: T };
|
|
11
|
+
|
|
12
|
+
export function useFormReset<T>(
|
|
13
|
+
ref: RefObject<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null> | undefined,
|
|
14
|
+
initialValue: T,
|
|
15
|
+
onReset: (value: T) => void,
|
|
16
|
+
): void;
|
|
17
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
18
|
+
export function useFormReset<T>(
|
|
19
|
+
ref: RefObject<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null> | undefined,
|
|
20
|
+
initialValue: T,
|
|
21
|
+
onReset: (value: T) => void,
|
|
22
|
+
slot: symbol | undefined,
|
|
23
|
+
): void;
|
|
24
|
+
export function useFormReset(...args: any[]): void {
|
|
25
|
+
const [user, slotArg] = splitSlot(args);
|
|
26
|
+
const slot = slotArg ?? S('useFormReset');
|
|
27
|
+
const ref = user[0] as
|
|
28
|
+
| { current: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null }
|
|
29
|
+
| undefined;
|
|
30
|
+
const initialValue = user[1];
|
|
31
|
+
const onReset = user[2] as (value: any) => void;
|
|
32
|
+
|
|
33
|
+
let handleReset = useEffectEvent(
|
|
34
|
+
(e: Event) => {
|
|
35
|
+
if (onReset && !e.defaultPrevented) {
|
|
36
|
+
onReset(initialValue);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
subSlot(slot, 'handler'),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
useEffect(
|
|
43
|
+
() => {
|
|
44
|
+
let form = ref?.current?.form;
|
|
45
|
+
|
|
46
|
+
form?.addEventListener('reset', handleReset);
|
|
47
|
+
return () => {
|
|
48
|
+
form?.removeEventListener('reset', handleReset);
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
[ref],
|
|
52
|
+
subSlot(slot, 'listen'),
|
|
53
|
+
);
|
|
54
|
+
}
|
package/src/utils/useId.ts
CHANGED
|
@@ -125,6 +125,11 @@ export function mergeIds(idA: string, idB: string): string {
|
|
|
125
125
|
* @param depArray - When to recalculate if the id is in the DOM.
|
|
126
126
|
*/
|
|
127
127
|
export function useSlotId(depArray?: ReadonlyArray<any>): string;
|
|
128
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
129
|
+
export function useSlotId(
|
|
130
|
+
depArray: ReadonlyArray<any> | undefined,
|
|
131
|
+
slot: symbol | undefined,
|
|
132
|
+
): string;
|
|
128
133
|
export function useSlotId(...args: any[]): string {
|
|
129
134
|
const [user, slotArg] = splitSlot(args);
|
|
130
135
|
const slot = slotArg ?? S('useSlotId');
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/useLabels.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; otherwise verbatim.
|
|
4
|
+
import type { AriaLabelingProps, DOMProps } from '@react-types/shared';
|
|
5
|
+
|
|
6
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
7
|
+
import { useId } from './useId';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Merges aria-label and aria-labelledby into aria-labelledby when both exist.
|
|
11
|
+
*
|
|
12
|
+
* @param props - Aria label props.
|
|
13
|
+
* @param defaultLabel - Default value for aria-label when not present.
|
|
14
|
+
*/
|
|
15
|
+
export function useLabels(
|
|
16
|
+
props: DOMProps & AriaLabelingProps,
|
|
17
|
+
defaultLabel?: string,
|
|
18
|
+
): DOMProps & AriaLabelingProps;
|
|
19
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
20
|
+
export function useLabels(
|
|
21
|
+
props: DOMProps & AriaLabelingProps,
|
|
22
|
+
defaultLabel: string | undefined,
|
|
23
|
+
slot: symbol | undefined,
|
|
24
|
+
): DOMProps & AriaLabelingProps;
|
|
25
|
+
export function useLabels(...args: any[]): DOMProps & AriaLabelingProps {
|
|
26
|
+
const [user, slotArg] = splitSlot(args);
|
|
27
|
+
const slot = slotArg ?? S('useLabels');
|
|
28
|
+
const props = user[0] as DOMProps & AriaLabelingProps;
|
|
29
|
+
const defaultLabel = user[1] as string | undefined;
|
|
30
|
+
|
|
31
|
+
let { id, 'aria-label': label, 'aria-labelledby': labelledBy } = props;
|
|
32
|
+
|
|
33
|
+
// If there is both an aria-label and aria-labelledby,
|
|
34
|
+
// combine them by pointing to the element itself.
|
|
35
|
+
id = useId(id, subSlot(slot, 'id'));
|
|
36
|
+
if (labelledBy && label) {
|
|
37
|
+
let ids = new Set([id, ...labelledBy.trim().split(/\s+/)]);
|
|
38
|
+
labelledBy = [...ids].join(' ');
|
|
39
|
+
} else if (labelledBy) {
|
|
40
|
+
labelledBy = labelledBy.trim().split(/\s+/).join(' ');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// If no labels are provided, use the default
|
|
44
|
+
if (!label && !labelledBy && defaultLabel) {
|
|
45
|
+
label = defaultLabel;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
id,
|
|
50
|
+
'aria-label': label,
|
|
51
|
+
'aria-labelledby': labelledBy,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/useResizeObserver.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; the explicit `[ref, box]` dependency array is kept verbatim.
|
|
4
|
+
import type { RefObject } from '@react-types/shared';
|
|
5
|
+
import { useEffect } from 'octane';
|
|
6
|
+
import { useEffectEvent } from './useEffectEvent';
|
|
7
|
+
|
|
8
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
9
|
+
|
|
10
|
+
function hasResizeObserver() {
|
|
11
|
+
return typeof window.ResizeObserver !== 'undefined';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type useResizeObserverOptionsType<T> = {
|
|
15
|
+
ref: RefObject<T | undefined | null> | undefined;
|
|
16
|
+
box?: ResizeObserverBoxOptions;
|
|
17
|
+
onResize: () => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function useResizeObserver<T extends Element>(
|
|
21
|
+
options: useResizeObserverOptionsType<T>,
|
|
22
|
+
): void;
|
|
23
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
24
|
+
export function useResizeObserver<T extends Element>(
|
|
25
|
+
options: useResizeObserverOptionsType<T>,
|
|
26
|
+
slot: symbol | undefined,
|
|
27
|
+
): void;
|
|
28
|
+
export function useResizeObserver(...args: any[]): void {
|
|
29
|
+
const [user, slotArg] = splitSlot(args);
|
|
30
|
+
const slot = slotArg ?? S('useResizeObserver');
|
|
31
|
+
const options = user[0] as useResizeObserverOptionsType<Element>;
|
|
32
|
+
|
|
33
|
+
// Only call onResize from inside the effect, otherwise we'll void our assumption that
|
|
34
|
+
// useEffectEvents are safe to pass in.
|
|
35
|
+
const { ref, box, onResize } = options;
|
|
36
|
+
let onResizeEvent = useEffectEvent(onResize, subSlot(slot, 'onResize'));
|
|
37
|
+
|
|
38
|
+
useEffect(
|
|
39
|
+
() => {
|
|
40
|
+
let element = ref?.current;
|
|
41
|
+
if (!element) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!hasResizeObserver()) {
|
|
46
|
+
window.addEventListener('resize', onResizeEvent, false);
|
|
47
|
+
return () => {
|
|
48
|
+
window.removeEventListener('resize', onResizeEvent, false);
|
|
49
|
+
};
|
|
50
|
+
} else {
|
|
51
|
+
const resizeObserverInstance = new window.ResizeObserver((entries) => {
|
|
52
|
+
if (!entries.length) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onResizeEvent();
|
|
57
|
+
});
|
|
58
|
+
resizeObserverInstance.observe(element, { box });
|
|
59
|
+
|
|
60
|
+
return () => {
|
|
61
|
+
if (element) {
|
|
62
|
+
resizeObserverInstance.unobserve(element);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
[ref, box],
|
|
68
|
+
subSlot(slot, 'observe'),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/useSlot.ts).
|
|
2
|
+
// octane adaptations: React's `RefCallback` type is declared locally (octane refs are
|
|
3
|
+
// React-19-style callback refs passed as props); public-hook slot threading
|
|
4
|
+
// (splitSlot/subSlot) per the binding convention; the explicit `[]` dep arrays are
|
|
5
|
+
// preserved exactly.
|
|
6
|
+
import { useCallback, useRef, useState } from 'octane';
|
|
7
|
+
|
|
8
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
9
|
+
import { useId } from './useId';
|
|
10
|
+
import { useLayoutEffect } from './useLayoutEffect';
|
|
11
|
+
|
|
12
|
+
type RefCallback<T> = (instance: T | null) => void;
|
|
13
|
+
|
|
14
|
+
export function useSlot(initialState?: boolean | (() => boolean)): [RefCallback<any>, boolean];
|
|
15
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
16
|
+
export function useSlot(
|
|
17
|
+
initialState: boolean | (() => boolean) | undefined,
|
|
18
|
+
slot: symbol | undefined,
|
|
19
|
+
): [RefCallback<any>, boolean];
|
|
20
|
+
export function useSlot(...args: any[]): [RefCallback<any>, boolean] {
|
|
21
|
+
const [user, slotArg] = splitSlot(args);
|
|
22
|
+
const slot = slotArg ?? S('useSlot');
|
|
23
|
+
const initialState = (user[0] as boolean | (() => boolean) | undefined) ?? true;
|
|
24
|
+
|
|
25
|
+
// Initial state is typically based on the parent having an aria-label or aria-labelledby.
|
|
26
|
+
// If it does, this value should be false so that we don't update the state and cause a rerender when we go through the layoutEffect
|
|
27
|
+
let [hasSlot, setHasSlot] = useState(initialState, subSlot(slot, 'hasSlot'));
|
|
28
|
+
let hasRun = useRef(false, subSlot(slot, 'hasRun'));
|
|
29
|
+
|
|
30
|
+
// A callback ref which will run when the slotted element mounts.
|
|
31
|
+
// This should happen before the useLayoutEffect below.
|
|
32
|
+
let ref = useCallback(
|
|
33
|
+
(el: any) => {
|
|
34
|
+
hasRun.current = true;
|
|
35
|
+
setHasSlot(!!el);
|
|
36
|
+
},
|
|
37
|
+
[],
|
|
38
|
+
subSlot(slot, 'ref'),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// If the callback hasn't been called, then reset to false.
|
|
42
|
+
useLayoutEffect(
|
|
43
|
+
() => {
|
|
44
|
+
if (!hasRun.current) {
|
|
45
|
+
setHasSlot(false);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
[],
|
|
49
|
+
subSlot(slot, 'reset'),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return [ref, hasSlot];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface SlotAria {
|
|
56
|
+
id: string | undefined;
|
|
57
|
+
ref: RefCallback<any>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function useSlotId2(initialState?: boolean | (() => boolean)): SlotAria;
|
|
61
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
62
|
+
export function useSlotId2(
|
|
63
|
+
initialState: boolean | (() => boolean) | undefined,
|
|
64
|
+
slot: symbol | undefined,
|
|
65
|
+
): SlotAria;
|
|
66
|
+
export function useSlotId2(...args: any[]): SlotAria {
|
|
67
|
+
const [user, slotArg] = splitSlot(args);
|
|
68
|
+
const slot = slotArg ?? S('useSlotId2');
|
|
69
|
+
const initialState = (user[0] as boolean | (() => boolean) | undefined) ?? true;
|
|
70
|
+
|
|
71
|
+
let id = useId(subSlot(slot, 'id'));
|
|
72
|
+
let [ref, hasSlot] = useSlot(initialState, subSlot(slot, 'slot'));
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
id: hasSlot ? id : undefined,
|
|
76
|
+
ref,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/useUpdateEffect.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; the explicit dependency arrays (including the caller-supplied one) are
|
|
4
|
+
// preserved exactly.
|
|
5
|
+
import { useEffect, useRef } from 'octane';
|
|
6
|
+
|
|
7
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
8
|
+
import { useEffectEvent } from './useEffectEvent';
|
|
9
|
+
|
|
10
|
+
type EffectCallback = () => void | (() => void);
|
|
11
|
+
|
|
12
|
+
// Like useEffect, but only called for updates after the initial render.
|
|
13
|
+
export function useUpdateEffect(cb: EffectCallback, dependencies: any[]): void;
|
|
14
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
15
|
+
export function useUpdateEffect(
|
|
16
|
+
cb: EffectCallback,
|
|
17
|
+
dependencies: any[],
|
|
18
|
+
slot: symbol | undefined,
|
|
19
|
+
): void;
|
|
20
|
+
export function useUpdateEffect(...args: any[]): void {
|
|
21
|
+
const [user, slotArg] = splitSlot(args);
|
|
22
|
+
const slot = slotArg ?? S('useUpdateEffect');
|
|
23
|
+
const cb = user[0] as EffectCallback;
|
|
24
|
+
const dependencies = user[1] as any[];
|
|
25
|
+
|
|
26
|
+
const isInitialMount = useRef(true, subSlot(slot, 'initialMount'));
|
|
27
|
+
const lastDeps = useRef<any[] | null>(null, subSlot(slot, 'lastDeps'));
|
|
28
|
+
let cbEvent = useEffectEvent(cb, subSlot(slot, 'cb'));
|
|
29
|
+
|
|
30
|
+
useEffect(
|
|
31
|
+
() => {
|
|
32
|
+
isInitialMount.current = true;
|
|
33
|
+
return () => {
|
|
34
|
+
isInitialMount.current = false;
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
[],
|
|
38
|
+
subSlot(slot, 'mountFx'),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
useEffect(
|
|
42
|
+
() => {
|
|
43
|
+
let prevDeps = lastDeps.current;
|
|
44
|
+
if (isInitialMount.current) {
|
|
45
|
+
isInitialMount.current = false;
|
|
46
|
+
} else if (!prevDeps || dependencies.some((dep, i) => !Object.is(dep, prevDeps[i]))) {
|
|
47
|
+
cbEvent();
|
|
48
|
+
}
|
|
49
|
+
lastDeps.current = dependencies;
|
|
50
|
+
},
|
|
51
|
+
dependencies,
|
|
52
|
+
subSlot(slot, 'updateFx'),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/useUpdateLayoutEffect.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; explicit dependency arrays are kept verbatim (they retain React's exact
|
|
4
|
+
// behavior in octane).
|
|
5
|
+
import { useRef } from 'octane';
|
|
6
|
+
|
|
7
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
8
|
+
import { useLayoutEffect } from './useLayoutEffect';
|
|
9
|
+
|
|
10
|
+
// React's EffectCallback shape (octane does not export the type alias).
|
|
11
|
+
type EffectCallback = () => void | (() => void);
|
|
12
|
+
|
|
13
|
+
// Like useLayoutEffect, but only called for updates after the initial render.
|
|
14
|
+
export function useUpdateLayoutEffect(effect: EffectCallback, dependencies: any[]): void;
|
|
15
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
16
|
+
export function useUpdateLayoutEffect(
|
|
17
|
+
effect: EffectCallback,
|
|
18
|
+
dependencies: any[],
|
|
19
|
+
slot: symbol | undefined,
|
|
20
|
+
): void;
|
|
21
|
+
export function useUpdateLayoutEffect(...args: any[]): void {
|
|
22
|
+
const [user, slotArg] = splitSlot(args);
|
|
23
|
+
const slot = slotArg ?? S('useUpdateLayoutEffect');
|
|
24
|
+
const effect = user[0] as EffectCallback;
|
|
25
|
+
const dependencies = user[1] as any[];
|
|
26
|
+
|
|
27
|
+
const isInitialMount = useRef(true, subSlot(slot, 'initial'));
|
|
28
|
+
const lastDeps = useRef<any[] | null>(null, subSlot(slot, 'lastDeps'));
|
|
29
|
+
|
|
30
|
+
useLayoutEffect(
|
|
31
|
+
() => {
|
|
32
|
+
isInitialMount.current = true;
|
|
33
|
+
return () => {
|
|
34
|
+
isInitialMount.current = false;
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
[],
|
|
38
|
+
subSlot(slot, 'mountFlag'),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
useLayoutEffect(
|
|
42
|
+
() => {
|
|
43
|
+
if (isInitialMount.current) {
|
|
44
|
+
isInitialMount.current = false;
|
|
45
|
+
} else if (
|
|
46
|
+
!lastDeps.current ||
|
|
47
|
+
// NOTE: `lastDeps[i]` (not `.current[i]`) is upstream's exact expression — kept verbatim.
|
|
48
|
+
dependencies.some((dep, i) => !Object.is(dep, (lastDeps as any)[i]))
|
|
49
|
+
) {
|
|
50
|
+
effect();
|
|
51
|
+
}
|
|
52
|
+
lastDeps.current = dependencies;
|
|
53
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
|
+
},
|
|
55
|
+
dependencies,
|
|
56
|
+
subSlot(slot, 'update'),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/visually-hidden/VisuallyHidden.tsx).
|
|
2
|
+
// octane adaptations: the component is built with `createElement` (elementType may be a
|
|
3
|
+
// tag string or an octane component); React's CSSProperties → a structural style object;
|
|
4
|
+
// public-hook slot threading.
|
|
5
|
+
import type { DOMAttributes } from '@react-types/shared';
|
|
6
|
+
import { createElement, useMemo, useState } from 'octane';
|
|
7
|
+
|
|
8
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
9
|
+
import { mergeProps } from '../utils/mergeProps';
|
|
10
|
+
import { useFocusWithin } from '../interactions/useFocusWithin';
|
|
11
|
+
|
|
12
|
+
export interface VisuallyHiddenProps extends DOMAttributes {
|
|
13
|
+
/** The content to visually hide. */
|
|
14
|
+
children?: any;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The element type for the container.
|
|
18
|
+
*
|
|
19
|
+
* @default 'div'
|
|
20
|
+
*/
|
|
21
|
+
elementType?: string | ((props: any) => any);
|
|
22
|
+
|
|
23
|
+
/** Whether the element should become visible on focus, for example skip links. */
|
|
24
|
+
isFocusable?: boolean;
|
|
25
|
+
|
|
26
|
+
style?: Record<string, any>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const styles: Record<string, any> = {
|
|
30
|
+
border: 0,
|
|
31
|
+
clip: 'rect(0 0 0 0)',
|
|
32
|
+
clipPath: 'inset(50%)',
|
|
33
|
+
height: '1px',
|
|
34
|
+
margin: '-1px',
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
padding: 0,
|
|
37
|
+
position: 'absolute',
|
|
38
|
+
width: '1px',
|
|
39
|
+
whiteSpace: 'nowrap',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export interface VisuallyHiddenAria {
|
|
43
|
+
visuallyHiddenProps: DOMAttributes;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function useVisuallyHidden(props?: VisuallyHiddenProps): VisuallyHiddenAria;
|
|
47
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
48
|
+
export function useVisuallyHidden(
|
|
49
|
+
props: VisuallyHiddenProps | undefined,
|
|
50
|
+
slot: symbol | undefined,
|
|
51
|
+
): VisuallyHiddenAria;
|
|
52
|
+
export function useVisuallyHidden(...args: any[]): VisuallyHiddenAria {
|
|
53
|
+
const [user, slotArg] = splitSlot(args);
|
|
54
|
+
const slot = slotArg ?? S('useVisuallyHidden');
|
|
55
|
+
const props = (user[0] as VisuallyHiddenProps | undefined) ?? {};
|
|
56
|
+
|
|
57
|
+
let { style, isFocusable } = props;
|
|
58
|
+
|
|
59
|
+
let [isFocused, setFocused] = useState(false, subSlot(slot, 'focused'));
|
|
60
|
+
let { focusWithinProps } = useFocusWithin(
|
|
61
|
+
{
|
|
62
|
+
isDisabled: !isFocusable,
|
|
63
|
+
onFocusWithinChange: (val: boolean) => setFocused(val),
|
|
64
|
+
},
|
|
65
|
+
subSlot(slot, 'focusWithin'),
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// If focused, don't hide the element.
|
|
69
|
+
let combinedStyles = useMemo(
|
|
70
|
+
() => {
|
|
71
|
+
if (isFocused) {
|
|
72
|
+
return style;
|
|
73
|
+
} else if (style) {
|
|
74
|
+
return { ...styles, ...style };
|
|
75
|
+
} else {
|
|
76
|
+
return styles;
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
[isFocused],
|
|
80
|
+
subSlot(slot, 'styles'),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
visuallyHiddenProps: {
|
|
85
|
+
...focusWithinProps,
|
|
86
|
+
style: combinedStyles,
|
|
87
|
+
} as DOMAttributes,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function VisuallyHidden(props: VisuallyHiddenProps): any {
|
|
92
|
+
let { children, elementType: Element = 'div', isFocusable, style, ...otherProps } = props;
|
|
93
|
+
let { visuallyHiddenProps } = useVisuallyHidden(props, S('VisuallyHidden'));
|
|
94
|
+
|
|
95
|
+
return createElement(
|
|
96
|
+
Element as any,
|
|
97
|
+
mergeProps(otherProps, visuallyHiddenProps as any),
|
|
98
|
+
children,
|
|
99
|
+
);
|
|
100
|
+
}
|