@octanejs/aria 0.0.1 → 0.0.3
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,149 @@
|
|
|
1
|
+
// Ported from react-stately (source: .react-spectrum/packages/react-stately/src/tabs/useTabListState.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; upstream's intentionally dep-less useEffect becomes an explicit `null`
|
|
4
|
+
// (run after every render).
|
|
5
|
+
import type {
|
|
6
|
+
Collection,
|
|
7
|
+
CollectionBase,
|
|
8
|
+
CollectionStateBase,
|
|
9
|
+
Key,
|
|
10
|
+
Node,
|
|
11
|
+
SingleSelection,
|
|
12
|
+
} from '@react-types/shared';
|
|
13
|
+
import { useEffect, useRef } from 'octane';
|
|
14
|
+
|
|
15
|
+
import { S, splitSlot, subSlot } from '../../internal';
|
|
16
|
+
import {
|
|
17
|
+
type SingleSelectListState,
|
|
18
|
+
useSingleSelectListState,
|
|
19
|
+
} from '../list/useSingleSelectListState';
|
|
20
|
+
|
|
21
|
+
export interface TabListProps<T>
|
|
22
|
+
extends
|
|
23
|
+
CollectionBase<T>,
|
|
24
|
+
Omit<
|
|
25
|
+
SingleSelection,
|
|
26
|
+
'disallowEmptySelection' | 'selectedKey' | 'defaultSelectedKey' | 'onSelectionChange'
|
|
27
|
+
> {
|
|
28
|
+
/**
|
|
29
|
+
* Whether the TabList is disabled.
|
|
30
|
+
* Shows that a selection exists, but is not available in that circumstance.
|
|
31
|
+
*/
|
|
32
|
+
isDisabled?: boolean;
|
|
33
|
+
/** The currently selected key in the collection (controlled). */
|
|
34
|
+
selectedKey?: Key;
|
|
35
|
+
/** The initial selected keys in the collection (uncontrolled). */
|
|
36
|
+
defaultSelectedKey?: Key;
|
|
37
|
+
/** Handler that is called when the selection changes. */
|
|
38
|
+
onSelectionChange?: (key: Key) => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface TabListStateOptions<T>
|
|
42
|
+
extends Omit<TabListProps<T>, 'children'>, CollectionStateBase<T> {}
|
|
43
|
+
|
|
44
|
+
export interface TabListState<T> extends SingleSelectListState<T> {
|
|
45
|
+
/** Whether the tab list is disabled. */
|
|
46
|
+
isDisabled: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Provides state management for a Tabs component. Tabs include a TabList which tracks
|
|
51
|
+
* which tab is currently selected and displays the content associated with that Tab in a TabPanel.
|
|
52
|
+
*/
|
|
53
|
+
export function useTabListState<T extends object>(props: TabListStateOptions<T>): TabListState<T>;
|
|
54
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
55
|
+
export function useTabListState<T extends object>(
|
|
56
|
+
props: TabListStateOptions<T>,
|
|
57
|
+
slot: symbol | undefined,
|
|
58
|
+
): TabListState<T>;
|
|
59
|
+
export function useTabListState(...args: any[]): TabListState<any> {
|
|
60
|
+
const [user, slotArg] = splitSlot(args);
|
|
61
|
+
const slot = slotArg ?? S('useTabListState');
|
|
62
|
+
const props = user[0] as TabListStateOptions<any>;
|
|
63
|
+
|
|
64
|
+
let state = useSingleSelectListState<any>(
|
|
65
|
+
{
|
|
66
|
+
...props,
|
|
67
|
+
onSelectionChange: props.onSelectionChange
|
|
68
|
+
? (key: Key | null) => {
|
|
69
|
+
if (key != null) {
|
|
70
|
+
props.onSelectionChange?.(key);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
: undefined,
|
|
74
|
+
suppressTextValueWarning: true,
|
|
75
|
+
defaultSelectedKey:
|
|
76
|
+
props.defaultSelectedKey ??
|
|
77
|
+
findDefaultSelectedKey(
|
|
78
|
+
props.collection,
|
|
79
|
+
props.disabledKeys ? new Set(props.disabledKeys) : new Set(),
|
|
80
|
+
) ??
|
|
81
|
+
undefined,
|
|
82
|
+
},
|
|
83
|
+
subSlot(slot, 'list'),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
let { selectionManager, collection, selectedKey: currentSelectedKey } = state;
|
|
87
|
+
|
|
88
|
+
let lastSelectedKey = useRef(currentSelectedKey, subSlot(slot, 'lastSelected'));
|
|
89
|
+
useEffect(
|
|
90
|
+
() => {
|
|
91
|
+
// Ensure a tab is always selected (in case no selected key was specified or if selected item was deleted from collection)
|
|
92
|
+
let selectedKey = currentSelectedKey;
|
|
93
|
+
if (
|
|
94
|
+
props.selectedKey == null &&
|
|
95
|
+
(selectionManager.isEmpty || selectedKey == null || !collection.getItem(selectedKey))
|
|
96
|
+
) {
|
|
97
|
+
selectedKey = findDefaultSelectedKey(collection, state.disabledKeys);
|
|
98
|
+
if (selectedKey != null) {
|
|
99
|
+
// directly set selection because replace/toggle selection won't consider disabled keys
|
|
100
|
+
selectionManager.setSelectedKeys([selectedKey]);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// If the tablist doesn't have focus and the selected key changes or if there isn't a focused key yet, change focused key to the selected key if it exists.
|
|
105
|
+
if (
|
|
106
|
+
(selectedKey != null && selectionManager.focusedKey == null) ||
|
|
107
|
+
(!selectionManager.isFocused && selectedKey !== lastSelectedKey.current)
|
|
108
|
+
) {
|
|
109
|
+
selectionManager.setFocusedKey(selectedKey);
|
|
110
|
+
}
|
|
111
|
+
lastSelectedKey.current = selectedKey;
|
|
112
|
+
},
|
|
113
|
+
null,
|
|
114
|
+
subSlot(slot, 'ensureSelected'),
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
...state,
|
|
119
|
+
isDisabled: props.isDisabled || false,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function findDefaultSelectedKey<T>(
|
|
124
|
+
collection: Collection<Node<T>> | undefined,
|
|
125
|
+
disabledKeys: Set<Key>,
|
|
126
|
+
) {
|
|
127
|
+
let selectedKey: Key | null = null;
|
|
128
|
+
if (collection) {
|
|
129
|
+
selectedKey = collection.getFirstKey();
|
|
130
|
+
// loop over tabs until we find one that isn't disabled and select that
|
|
131
|
+
while (
|
|
132
|
+
selectedKey != null &&
|
|
133
|
+
(disabledKeys.has(selectedKey) || collection.getItem(selectedKey)?.props?.isDisabled) &&
|
|
134
|
+
selectedKey !== collection.getLastKey()
|
|
135
|
+
) {
|
|
136
|
+
selectedKey = collection.getKeyAfter(selectedKey);
|
|
137
|
+
}
|
|
138
|
+
// if this check is true, then every item is disabled, it makes more sense to default to the first key than the last
|
|
139
|
+
if (
|
|
140
|
+
selectedKey != null &&
|
|
141
|
+
(disabledKeys.has(selectedKey) || collection.getItem(selectedKey)?.props?.isDisabled) &&
|
|
142
|
+
selectedKey === collection.getLastKey()
|
|
143
|
+
) {
|
|
144
|
+
selectedKey = collection.getFirstKey();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return selectedKey;
|
|
149
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Ported from react-stately (source: .react-spectrum/packages/react-stately/src/toggle/useToggleGroupState.ts).
|
|
2
|
+
// Its import closure is confined to `useControlledState` + `@react-types/shared` (no
|
|
3
|
+
// list/selection modules), so it lands in Phase 1. octane adaptations: public-hook slot
|
|
4
|
+
// threading (splitSlot/subSlot) per the binding convention; explicit `Set<Key>` element
|
|
5
|
+
// types on the default-set constructions (strict inference); explicit useMemo dep arrays
|
|
6
|
+
// preserved exactly.
|
|
7
|
+
import type { Key } from '@react-types/shared';
|
|
8
|
+
import { useMemo } from 'octane';
|
|
9
|
+
|
|
10
|
+
import { S, splitSlot, subSlot } from '../../internal';
|
|
11
|
+
import { useControlledState } from '../utils/useControlledState';
|
|
12
|
+
|
|
13
|
+
export interface ToggleGroupProps {
|
|
14
|
+
/**
|
|
15
|
+
* Whether single or multiple selection is enabled.
|
|
16
|
+
*
|
|
17
|
+
* @default 'single'
|
|
18
|
+
*/
|
|
19
|
+
selectionMode?: 'single' | 'multiple';
|
|
20
|
+
/** Whether the collection allows empty selection. */
|
|
21
|
+
disallowEmptySelection?: boolean;
|
|
22
|
+
/** The currently selected keys in the collection (controlled). */
|
|
23
|
+
selectedKeys?: Iterable<Key>;
|
|
24
|
+
/** The initial selected keys in the collection (uncontrolled). */
|
|
25
|
+
defaultSelectedKeys?: Iterable<Key>;
|
|
26
|
+
/** Handler that is called when the selection changes. */
|
|
27
|
+
onSelectionChange?: (keys: Set<Key>) => void;
|
|
28
|
+
/** Whether all items are disabled. */
|
|
29
|
+
isDisabled?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ToggleGroupState {
|
|
33
|
+
/** Whether single or multiple selection is enabled. */
|
|
34
|
+
readonly selectionMode: 'single' | 'multiple';
|
|
35
|
+
|
|
36
|
+
/** Whether all items are disabled. */
|
|
37
|
+
readonly isDisabled: boolean;
|
|
38
|
+
|
|
39
|
+
/** A set of keys for items that are selected. */
|
|
40
|
+
readonly selectedKeys: Set<Key>;
|
|
41
|
+
|
|
42
|
+
/** Toggles the selected state for an item by its key. */
|
|
43
|
+
toggleKey(key: Key): void;
|
|
44
|
+
|
|
45
|
+
/** Sets whether the given key is selected. */
|
|
46
|
+
setSelected(key: Key, isSelected: boolean): void;
|
|
47
|
+
|
|
48
|
+
/** Replaces the set of selected keys. */
|
|
49
|
+
setSelectedKeys(keys: Set<Key>): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Manages state for a group of toggles.
|
|
54
|
+
* It supports both single and multiple selected items.
|
|
55
|
+
*/
|
|
56
|
+
export function useToggleGroupState(props: ToggleGroupProps): ToggleGroupState;
|
|
57
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
58
|
+
export function useToggleGroupState(
|
|
59
|
+
props: ToggleGroupProps,
|
|
60
|
+
slot: symbol | undefined,
|
|
61
|
+
): ToggleGroupState;
|
|
62
|
+
export function useToggleGroupState(...args: any[]): ToggleGroupState {
|
|
63
|
+
const [user, slotArg] = splitSlot(args);
|
|
64
|
+
const slot = slotArg ?? S('useToggleGroupState');
|
|
65
|
+
const props = user[0] as ToggleGroupProps;
|
|
66
|
+
|
|
67
|
+
let { selectionMode = 'single', disallowEmptySelection, isDisabled = false } = props;
|
|
68
|
+
let [selectedKeys, setSelectedKeys] = useControlledState(
|
|
69
|
+
useMemo(
|
|
70
|
+
() => (props.selectedKeys ? new Set(props.selectedKeys) : undefined),
|
|
71
|
+
[props.selectedKeys],
|
|
72
|
+
subSlot(slot, 'controlled'),
|
|
73
|
+
),
|
|
74
|
+
useMemo(
|
|
75
|
+
() => (props.defaultSelectedKeys ? new Set(props.defaultSelectedKeys) : new Set<Key>()),
|
|
76
|
+
[props.defaultSelectedKeys],
|
|
77
|
+
subSlot(slot, 'default'),
|
|
78
|
+
),
|
|
79
|
+
props.onSelectionChange,
|
|
80
|
+
subSlot(slot, 'keys'),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
selectionMode,
|
|
85
|
+
isDisabled,
|
|
86
|
+
selectedKeys,
|
|
87
|
+
setSelectedKeys,
|
|
88
|
+
toggleKey(key) {
|
|
89
|
+
let keys: Set<Key>;
|
|
90
|
+
if (selectionMode === 'multiple') {
|
|
91
|
+
keys = new Set(selectedKeys);
|
|
92
|
+
if (keys.has(key) && (!disallowEmptySelection || keys.size > 1)) {
|
|
93
|
+
keys.delete(key);
|
|
94
|
+
} else {
|
|
95
|
+
keys.add(key);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
keys = new Set(selectedKeys.has(key) && !disallowEmptySelection ? [] : [key]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setSelectedKeys(keys);
|
|
102
|
+
},
|
|
103
|
+
setSelected(key, isSelected) {
|
|
104
|
+
if (isSelected !== selectedKeys.has(key)) {
|
|
105
|
+
this.toggleKey(key);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Ported from react-stately (source: .react-spectrum/packages/react-stately/src/toggle/useToggleState.ts).
|
|
2
|
+
// octane adaptations: React's `ReactNode` children type → `any` (octane descriptors);
|
|
3
|
+
// `FocusableProps` comes from the ported interactions area (type-only — upstream's
|
|
4
|
+
// @react-types/shared version is typed over React synthetic events); public-hook slot
|
|
5
|
+
// threading (splitSlot/subSlot) per the binding convention. The public value-level
|
|
6
|
+
// `onChange` callback is unchanged (the onInput rule applies only to DOM wiring).
|
|
7
|
+
import type { InputBase, Validation } from '@react-types/shared';
|
|
8
|
+
import { useState } from 'octane';
|
|
9
|
+
|
|
10
|
+
import type { FocusableProps } from '../../interactions/useFocusable';
|
|
11
|
+
|
|
12
|
+
import { S, splitSlot, subSlot } from '../../internal';
|
|
13
|
+
import { useControlledState } from '../utils/useControlledState';
|
|
14
|
+
|
|
15
|
+
export interface ToggleStateOptions extends InputBase {
|
|
16
|
+
/**
|
|
17
|
+
* Whether the element should be selected (uncontrolled).
|
|
18
|
+
*/
|
|
19
|
+
defaultSelected?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the element should be selected (controlled).
|
|
22
|
+
*/
|
|
23
|
+
isSelected?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Handler that is called when the element's selection state changes.
|
|
26
|
+
*/
|
|
27
|
+
onChange?: (isSelected: boolean) => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ToggleProps extends ToggleStateOptions, Validation<boolean>, FocusableProps {
|
|
31
|
+
/**
|
|
32
|
+
* The label for the element.
|
|
33
|
+
*/
|
|
34
|
+
children?: any;
|
|
35
|
+
/**
|
|
36
|
+
* The value of the input element, used when submitting an HTML form. See
|
|
37
|
+
* [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefvalue).
|
|
38
|
+
*/
|
|
39
|
+
value?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ToggleState {
|
|
43
|
+
/** Whether the toggle is selected. */
|
|
44
|
+
readonly isSelected: boolean;
|
|
45
|
+
|
|
46
|
+
/** Whether the toggle is selected by default. */
|
|
47
|
+
readonly defaultSelected: boolean;
|
|
48
|
+
|
|
49
|
+
/** Updates selection state. */
|
|
50
|
+
setSelected(isSelected: boolean): void;
|
|
51
|
+
|
|
52
|
+
/** Toggle the selection state. */
|
|
53
|
+
toggle(): void;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Provides state management for toggle components like checkboxes and switches.
|
|
58
|
+
*/
|
|
59
|
+
export function useToggleState(props?: ToggleStateOptions): ToggleState;
|
|
60
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
61
|
+
export function useToggleState(
|
|
62
|
+
props: ToggleStateOptions | undefined,
|
|
63
|
+
slot: symbol | undefined,
|
|
64
|
+
): ToggleState;
|
|
65
|
+
export function useToggleState(...args: any[]): ToggleState {
|
|
66
|
+
const [user, slotArg] = splitSlot(args);
|
|
67
|
+
const slot = slotArg ?? S('useToggleState');
|
|
68
|
+
const props = (user[0] as ToggleStateOptions | undefined) ?? {};
|
|
69
|
+
|
|
70
|
+
let { isReadOnly } = props;
|
|
71
|
+
|
|
72
|
+
// have to provide an empty function so useControlledState doesn't throw a fit
|
|
73
|
+
// can't use useControlledState's prop calling because we need the event object from the change
|
|
74
|
+
let [isSelected, setSelected] = useControlledState(
|
|
75
|
+
props.isSelected,
|
|
76
|
+
props.defaultSelected || false,
|
|
77
|
+
props.onChange,
|
|
78
|
+
subSlot(slot, 'selected'),
|
|
79
|
+
);
|
|
80
|
+
let [initialValue] = useState(isSelected, subSlot(slot, 'initial'));
|
|
81
|
+
|
|
82
|
+
function updateSelected(value: boolean) {
|
|
83
|
+
if (!isReadOnly) {
|
|
84
|
+
setSelected(value);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function toggleState() {
|
|
89
|
+
if (!isReadOnly) {
|
|
90
|
+
setSelected(!isSelected);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
isSelected,
|
|
96
|
+
defaultSelected: props.defaultSelected ?? initialValue,
|
|
97
|
+
setSelected: updateSelected,
|
|
98
|
+
toggle: toggleState,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// Ported from react-stately (source: .react-spectrum/packages/react-stately/src/tooltip/useTooltipTriggerState.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; the module-level warmup/cooldown timers and global tooltip registry are
|
|
4
|
+
// ported verbatim; upstream's explicit useEffect dep arrays are kept verbatim with a
|
|
5
|
+
// trailing subSlot.
|
|
6
|
+
import { useEffect, useMemo, useRef } from 'octane';
|
|
7
|
+
|
|
8
|
+
import { S, splitSlot, subSlot } from '../../internal';
|
|
9
|
+
import {
|
|
10
|
+
type OverlayTriggerProps,
|
|
11
|
+
useOverlayTriggerState,
|
|
12
|
+
} from '../overlays/useOverlayTriggerState';
|
|
13
|
+
|
|
14
|
+
export interface TooltipTriggerProps extends OverlayTriggerProps {
|
|
15
|
+
/**
|
|
16
|
+
* Whether the tooltip should be disabled, independent from the trigger.
|
|
17
|
+
*/
|
|
18
|
+
isDisabled?: boolean;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The delay time for the tooltip to show up. [See
|
|
22
|
+
* guidelines](https://spectrum.adobe.com/page/tooltip/#Immediate-or-delayed-appearance).
|
|
23
|
+
*
|
|
24
|
+
* @default 1500
|
|
25
|
+
*/
|
|
26
|
+
delay?: number;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The delay time for the tooltip to close. [See
|
|
30
|
+
* guidelines](https://spectrum.adobe.com/page/tooltip/#Warmup-and-cooldown).
|
|
31
|
+
*
|
|
32
|
+
* @default 500
|
|
33
|
+
*/
|
|
34
|
+
closeDelay?: number;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* By default, opens for both focus and hover. Can be made to open only for focus.
|
|
38
|
+
*
|
|
39
|
+
* @default 'hover'
|
|
40
|
+
*/
|
|
41
|
+
trigger?: 'hover' | 'focus';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Whether the tooltip should close when the trigger is pressed.
|
|
45
|
+
*
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
shouldCloseOnPress?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const TOOLTIP_DELAY = 1500; // this seems to be a 1.5 second delay, check with design
|
|
52
|
+
const TOOLTIP_COOLDOWN = 500;
|
|
53
|
+
|
|
54
|
+
export interface TooltipTriggerState {
|
|
55
|
+
/** Whether the tooltip is currently showing. */
|
|
56
|
+
isOpen: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Shows the tooltip. By default, the tooltip becomes visible after a delay
|
|
59
|
+
* depending on a global warmup timer. The `immediate` option shows the
|
|
60
|
+
* tooltip immediately instead.
|
|
61
|
+
*/
|
|
62
|
+
open(immediate?: boolean): void;
|
|
63
|
+
/** Hides the tooltip. */
|
|
64
|
+
close(immediate?: boolean): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// octane adaptation: loose index type (upstream's `{}`) so the cleanup's truthiness
|
|
68
|
+
// check on a registry entry isn't flagged as an always-defined function.
|
|
69
|
+
let tooltips: Record<string, any> = {};
|
|
70
|
+
let tooltipId = 0;
|
|
71
|
+
let globalWarmedUp = false;
|
|
72
|
+
let globalWarmUpTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
73
|
+
let globalCooldownTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Manages state for a tooltip trigger. Tracks whether the tooltip is open, and provides
|
|
77
|
+
* methods to toggle this state. Ensures only one tooltip is open at a time and controls
|
|
78
|
+
* the delay for showing a tooltip.
|
|
79
|
+
*/
|
|
80
|
+
export function useTooltipTriggerState(props?: TooltipTriggerProps): TooltipTriggerState;
|
|
81
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
82
|
+
export function useTooltipTriggerState(
|
|
83
|
+
props: TooltipTriggerProps | undefined,
|
|
84
|
+
slot: symbol | undefined,
|
|
85
|
+
): TooltipTriggerState;
|
|
86
|
+
export function useTooltipTriggerState(...args: any[]): TooltipTriggerState {
|
|
87
|
+
const [user, slotArg] = splitSlot(args);
|
|
88
|
+
const slot = slotArg ?? S('useTooltipTriggerState');
|
|
89
|
+
const props = (user[0] as TooltipTriggerProps) ?? {};
|
|
90
|
+
|
|
91
|
+
let { delay = TOOLTIP_DELAY, closeDelay = TOOLTIP_COOLDOWN } = props;
|
|
92
|
+
let { isOpen, open, close } = useOverlayTriggerState(props, subSlot(slot, 'overlay'));
|
|
93
|
+
let id = useMemo(() => `${++tooltipId}`, [], subSlot(slot, 'id'));
|
|
94
|
+
let closeTimeout = useRef<ReturnType<typeof setTimeout> | null>(
|
|
95
|
+
null,
|
|
96
|
+
subSlot(slot, 'closeTimeout'),
|
|
97
|
+
);
|
|
98
|
+
let closeCallback = useRef<() => void>(close, subSlot(slot, 'closeCallback'));
|
|
99
|
+
|
|
100
|
+
let ensureTooltipEntry = () => {
|
|
101
|
+
tooltips[id] = hideTooltip;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
let closeOpenTooltips = () => {
|
|
105
|
+
for (let hideTooltipId in tooltips) {
|
|
106
|
+
if (hideTooltipId !== id) {
|
|
107
|
+
tooltips[hideTooltipId](true);
|
|
108
|
+
delete tooltips[hideTooltipId];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
let showTooltip = () => {
|
|
114
|
+
if (closeTimeout.current) {
|
|
115
|
+
clearTimeout(closeTimeout.current);
|
|
116
|
+
}
|
|
117
|
+
closeTimeout.current = null;
|
|
118
|
+
closeOpenTooltips();
|
|
119
|
+
ensureTooltipEntry();
|
|
120
|
+
globalWarmedUp = true;
|
|
121
|
+
open();
|
|
122
|
+
if (globalWarmUpTimeout) {
|
|
123
|
+
clearTimeout(globalWarmUpTimeout);
|
|
124
|
+
globalWarmUpTimeout = null;
|
|
125
|
+
}
|
|
126
|
+
if (globalCooldownTimeout) {
|
|
127
|
+
clearTimeout(globalCooldownTimeout);
|
|
128
|
+
globalCooldownTimeout = null;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
let hideTooltip = (immediate?: boolean) => {
|
|
133
|
+
if (immediate || closeDelay <= 0) {
|
|
134
|
+
if (closeTimeout.current) {
|
|
135
|
+
clearTimeout(closeTimeout.current);
|
|
136
|
+
}
|
|
137
|
+
closeTimeout.current = null;
|
|
138
|
+
closeCallback.current();
|
|
139
|
+
} else if (!closeTimeout.current) {
|
|
140
|
+
closeTimeout.current = setTimeout(() => {
|
|
141
|
+
closeTimeout.current = null;
|
|
142
|
+
closeCallback.current();
|
|
143
|
+
}, closeDelay);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (globalWarmUpTimeout) {
|
|
147
|
+
clearTimeout(globalWarmUpTimeout);
|
|
148
|
+
globalWarmUpTimeout = null;
|
|
149
|
+
}
|
|
150
|
+
if (globalWarmedUp) {
|
|
151
|
+
if (globalCooldownTimeout) {
|
|
152
|
+
clearTimeout(globalCooldownTimeout);
|
|
153
|
+
}
|
|
154
|
+
globalCooldownTimeout = setTimeout(
|
|
155
|
+
() => {
|
|
156
|
+
delete tooltips[id];
|
|
157
|
+
globalCooldownTimeout = null;
|
|
158
|
+
globalWarmedUp = false;
|
|
159
|
+
},
|
|
160
|
+
Math.max(TOOLTIP_COOLDOWN, closeDelay),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
let warmupTooltip = () => {
|
|
166
|
+
closeOpenTooltips();
|
|
167
|
+
ensureTooltipEntry();
|
|
168
|
+
if (!isOpen && !globalWarmedUp) {
|
|
169
|
+
if (globalWarmUpTimeout) {
|
|
170
|
+
clearTimeout(globalWarmUpTimeout);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
globalWarmUpTimeout = setTimeout(() => {
|
|
174
|
+
globalWarmUpTimeout = null;
|
|
175
|
+
globalWarmedUp = true;
|
|
176
|
+
showTooltip();
|
|
177
|
+
}, delay);
|
|
178
|
+
} else if (!isOpen) {
|
|
179
|
+
showTooltip();
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
useEffect(
|
|
184
|
+
() => {
|
|
185
|
+
closeCallback.current = close;
|
|
186
|
+
},
|
|
187
|
+
[close],
|
|
188
|
+
subSlot(slot, 'closeCallback'),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
useEffect(
|
|
192
|
+
() => {
|
|
193
|
+
return () => {
|
|
194
|
+
if (closeTimeout.current) {
|
|
195
|
+
clearTimeout(closeTimeout.current);
|
|
196
|
+
}
|
|
197
|
+
let tooltip = tooltips[id];
|
|
198
|
+
if (tooltip) {
|
|
199
|
+
delete tooltips[id];
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
[id],
|
|
204
|
+
subSlot(slot, 'cleanup'),
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
isOpen,
|
|
209
|
+
open: (immediate) => {
|
|
210
|
+
if (!immediate && delay > 0 && !closeTimeout.current) {
|
|
211
|
+
warmupTooltip();
|
|
212
|
+
} else {
|
|
213
|
+
showTooltip();
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
close: hideTooltip,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Ported from react-stately (source: .react-spectrum/packages/react-stately/src/tree/TreeCollection.ts).
|
|
2
|
+
// Verbatim (no React surface).
|
|
3
|
+
import type { Collection, Key, Node } from '@react-types/shared';
|
|
4
|
+
|
|
5
|
+
export class TreeCollection<T> implements Collection<Node<T>> {
|
|
6
|
+
private keyMap: Map<Key, Node<T>> = new Map();
|
|
7
|
+
private iterable: Iterable<Node<T>>;
|
|
8
|
+
private firstKey: Key | null = null;
|
|
9
|
+
private lastKey: Key | null = null;
|
|
10
|
+
|
|
11
|
+
constructor(nodes: Iterable<Node<T>>, { expandedKeys }: { expandedKeys?: Set<Key> } = {}) {
|
|
12
|
+
this.iterable = nodes;
|
|
13
|
+
expandedKeys = expandedKeys || new Set();
|
|
14
|
+
|
|
15
|
+
let visit = (node: Node<T>) => {
|
|
16
|
+
this.keyMap.set(node.key, node);
|
|
17
|
+
|
|
18
|
+
if (node.childNodes && (node.type === 'section' || expandedKeys.has(node.key))) {
|
|
19
|
+
for (let child of node.childNodes) {
|
|
20
|
+
visit(child);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
for (let node of nodes) {
|
|
26
|
+
visit(node);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let last: Node<T> | null = null;
|
|
30
|
+
let index = 0;
|
|
31
|
+
for (let [key, node] of this.keyMap) {
|
|
32
|
+
if (last) {
|
|
33
|
+
last.nextKey = key;
|
|
34
|
+
node.prevKey = last.key;
|
|
35
|
+
} else {
|
|
36
|
+
this.firstKey = key;
|
|
37
|
+
node.prevKey = undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (node.type === 'item') {
|
|
41
|
+
node.index = index++;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
last = node;
|
|
45
|
+
|
|
46
|
+
// Set nextKey as undefined since this might be the last node
|
|
47
|
+
// If it isn't the last node, last.nextKey will properly set at start of new loop
|
|
48
|
+
last.nextKey = undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.lastKey = last?.key ?? null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
*[Symbol.iterator](): IterableIterator<Node<T>> {
|
|
55
|
+
yield* this.iterable;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get size(): number {
|
|
59
|
+
return this.keyMap.size;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getKeys(): IterableIterator<Key> {
|
|
63
|
+
return this.keyMap.keys();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getKeyBefore(key: Key): Key | null {
|
|
67
|
+
let node = this.keyMap.get(key);
|
|
68
|
+
return node ? (node.prevKey ?? null) : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getKeyAfter(key: Key): Key | null {
|
|
72
|
+
let node = this.keyMap.get(key);
|
|
73
|
+
return node ? (node.nextKey ?? null) : null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getFirstKey(): Key | null {
|
|
77
|
+
return this.firstKey;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getLastKey(): Key | null {
|
|
81
|
+
return this.lastKey;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getItem(key: Key): Node<T> | null {
|
|
85
|
+
return this.keyMap.get(key) ?? null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
at(idx: number): Node<T> | null {
|
|
89
|
+
const keys = [...this.getKeys()];
|
|
90
|
+
return this.getItem(keys[idx]);
|
|
91
|
+
}
|
|
92
|
+
}
|