@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,106 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/overlays/Overlay.tsx).
|
|
2
|
+
// octane adaptations: `.tsx` → `.ts`, JSX → `createElement`; `ReactDOM.createPortal` →
|
|
3
|
+
// octane's `createPortal(children, container)` (see aria memory octane-portal-as-value);
|
|
4
|
+
// the plain-`.ts` `Overlay` component uses the S()/subSlot component-slot convention; the
|
|
5
|
+
// Provider descriptor keeps a stable `{ value, children }` shape; React's ReactNode/JSX/Context
|
|
6
|
+
// types → `any`; `useOverlayFocusContain` gets public-hook slot threading.
|
|
7
|
+
import { ClearPressResponder } from '../interactions/PressResponder';
|
|
8
|
+
import { FocusScope } from '../focus/FocusScope';
|
|
9
|
+
import { createContext, createElement, createPortal, useContext, useMemo, useState } from 'octane';
|
|
10
|
+
import { useIsSSR } from '../ssr/SSRProvider';
|
|
11
|
+
import { useLayoutEffect } from '../utils/useLayoutEffect';
|
|
12
|
+
import { useUNSAFE_PortalContext } from './PortalProvider';
|
|
13
|
+
|
|
14
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
15
|
+
|
|
16
|
+
export interface OverlayProps {
|
|
17
|
+
/**
|
|
18
|
+
* The container element in which the overlay portal will be placed.
|
|
19
|
+
*
|
|
20
|
+
* @default document.body
|
|
21
|
+
*/
|
|
22
|
+
portalContainer?: Element;
|
|
23
|
+
/** The overlay to render in the portal. */
|
|
24
|
+
children: any;
|
|
25
|
+
/**
|
|
26
|
+
* Disables default focus management for the overlay, including containment and restoration.
|
|
27
|
+
* This option should be used very carefully. When focus management is disabled, you must
|
|
28
|
+
* implement focus containment and restoration to ensure the overlay is keyboard accessible.
|
|
29
|
+
*/
|
|
30
|
+
disableFocusManagement?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether to contain focus within the overlay.
|
|
33
|
+
*/
|
|
34
|
+
shouldContainFocus?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the overlay is currently performing an exit animation. When true,
|
|
37
|
+
* focus is allowed to move outside.
|
|
38
|
+
*/
|
|
39
|
+
isExiting?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface OverlayContextValue {
|
|
43
|
+
contain: boolean;
|
|
44
|
+
setContain: (value: boolean | ((prev: boolean) => boolean)) => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const OverlayContext = createContext<OverlayContextValue | null>(null);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A container which renders an overlay such as a popover or modal in a portal,
|
|
51
|
+
* and provides a focus scope for the child elements.
|
|
52
|
+
*/
|
|
53
|
+
export function Overlay(props: OverlayProps): any {
|
|
54
|
+
const slot = S('Overlay');
|
|
55
|
+
let isSSR = useIsSSR(subSlot(slot, 'ssr'));
|
|
56
|
+
let { portalContainer = isSSR ? null : document.body, isExiting } = props;
|
|
57
|
+
let [contain, setContain] = useState(false, subSlot(slot, 'contain'));
|
|
58
|
+
let contextValue = useMemo(
|
|
59
|
+
() => ({ contain, setContain }),
|
|
60
|
+
[contain, setContain],
|
|
61
|
+
subSlot(slot, 'context'),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
let { getContainer } = useUNSAFE_PortalContext();
|
|
65
|
+
if (!props.portalContainer && getContainer) {
|
|
66
|
+
portalContainer = getContainer();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!portalContainer) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let contents = props.children;
|
|
74
|
+
if (!props.disableFocusManagement) {
|
|
75
|
+
contents = createElement(FocusScope, {
|
|
76
|
+
restoreFocus: true,
|
|
77
|
+
contain: (props.shouldContainFocus || contain) && !isExiting,
|
|
78
|
+
children: contents,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
contents = createElement(OverlayContext.Provider, {
|
|
83
|
+
value: contextValue as OverlayContextValue,
|
|
84
|
+
children: createElement(ClearPressResponder, { children: contents }),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return createPortal(contents, portalContainer);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** @private */
|
|
91
|
+
export function useOverlayFocusContain(): void;
|
|
92
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
93
|
+
export function useOverlayFocusContain(slot: symbol | undefined): void;
|
|
94
|
+
export function useOverlayFocusContain(...args: any[]): void {
|
|
95
|
+
const [, slotArg] = splitSlot(args);
|
|
96
|
+
const slot = slotArg ?? S('useOverlayFocusContain');
|
|
97
|
+
let ctx = useContext(OverlayContext);
|
|
98
|
+
let setContain = ctx?.setContain;
|
|
99
|
+
useLayoutEffect(
|
|
100
|
+
() => {
|
|
101
|
+
setContain?.(true);
|
|
102
|
+
},
|
|
103
|
+
[setContain],
|
|
104
|
+
subSlot(slot, 'contain'),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/overlays/PortalProvider.tsx).
|
|
2
|
+
// octane adaptations: `.tsx` → `.ts`, JSX → `createElement` with a stable `{ value, children }`
|
|
3
|
+
// Provider descriptor shape; React's `ReactNode`/`JSX.Element`/`React.Context` types → `any`;
|
|
4
|
+
// `useContext` is context-identity keyed, so it needs no slot threading.
|
|
5
|
+
import { createContext, createElement, useContext } from 'octane';
|
|
6
|
+
|
|
7
|
+
export interface PortalProviderProps {
|
|
8
|
+
/** Should return the element where we should portal to. Can clear the context by passing null. */
|
|
9
|
+
getContainer?: (() => HTMLElement | null) | null;
|
|
10
|
+
/**
|
|
11
|
+
* The content of the PortalProvider. Should contain all children that want to portal their
|
|
12
|
+
* overlays to the element returned by the provided `getContainer()`.
|
|
13
|
+
*/
|
|
14
|
+
children: any;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PortalProviderContextValue extends Omit<PortalProviderProps, 'children'> {}
|
|
18
|
+
|
|
19
|
+
export const PortalContext = createContext<PortalProviderContextValue>({});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Sets the portal container for all overlay elements rendered by its children.
|
|
23
|
+
*/
|
|
24
|
+
export function UNSAFE_PortalProvider(props: PortalProviderProps): any {
|
|
25
|
+
let { getContainer } = props;
|
|
26
|
+
let { getContainer: ctxGetContainer } = useUNSAFE_PortalContext();
|
|
27
|
+
return createElement(PortalContext.Provider, {
|
|
28
|
+
value: {
|
|
29
|
+
getContainer: getContainer === null ? undefined : (getContainer ?? ctxGetContainer),
|
|
30
|
+
},
|
|
31
|
+
children: props.children,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function useUNSAFE_PortalContext(): PortalProviderContextValue {
|
|
36
|
+
return useContext(PortalContext) ?? {};
|
|
37
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/overlays/ariaHideOutside.ts).
|
|
2
|
+
// octane adaptations: `shadowDOM` flag imported from the ported `../stately/flags` (upstream
|
|
3
|
+
// reads it from `react-stately/private/flags/flags`). No hooks here — a plain DOM utility, so
|
|
4
|
+
// no slot threading. Module-level ref-count map and observer stack are ported verbatim.
|
|
5
|
+
import { createShadowTreeWalker } from '../utils/shadowdom/ShadowTreeWalker';
|
|
6
|
+
|
|
7
|
+
import { getOwnerDocument, getOwnerWindow } from '../utils/domHelpers';
|
|
8
|
+
import { nodeContains } from '../utils/shadowdom/DOMFunctions';
|
|
9
|
+
import { shadowDOM } from '../stately/flags';
|
|
10
|
+
|
|
11
|
+
const supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;
|
|
12
|
+
|
|
13
|
+
function isAlwaysVisibleNode(node: HTMLElement | SVGElement): boolean {
|
|
14
|
+
return node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer !== undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface AriaHideOutsideOptions {
|
|
18
|
+
root?: Element;
|
|
19
|
+
shouldUseInert?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Keeps a ref count of all hidden elements. Added to when hiding an element, and
|
|
23
|
+
// subtracted from when showing it again. When it reaches zero, aria-hidden is removed.
|
|
24
|
+
let refCountMap = new WeakMap<Element, number>();
|
|
25
|
+
interface ObserverWrapper {
|
|
26
|
+
visibleNodes: Set<Element>;
|
|
27
|
+
hiddenNodes: Set<Element>;
|
|
28
|
+
observe: () => void;
|
|
29
|
+
disconnect: () => void;
|
|
30
|
+
}
|
|
31
|
+
let observerStack: Array<ObserverWrapper> = [];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Hides all elements in the DOM outside the given targets from screen readers using aria-hidden,
|
|
35
|
+
* and returns a function to revert these changes. In addition, changes to the DOM are watched
|
|
36
|
+
* and new elements outside the targets are automatically hidden.
|
|
37
|
+
*
|
|
38
|
+
* @param targets - The elements that should remain visible.
|
|
39
|
+
* @param root - Nothing will be hidden above this element.
|
|
40
|
+
* @returns - A function to restore all hidden elements.
|
|
41
|
+
*/
|
|
42
|
+
export function ariaHideOutside(targets: Element[], options?: AriaHideOutsideOptions | Element) {
|
|
43
|
+
let windowObj = getOwnerWindow(targets?.[0]);
|
|
44
|
+
let opts = options instanceof windowObj.Element ? { root: options } : options;
|
|
45
|
+
let root = opts?.root ?? document.body;
|
|
46
|
+
let shouldUseInert = opts?.shouldUseInert && supportsInert;
|
|
47
|
+
let visibleNodes = new Set<Element>(targets);
|
|
48
|
+
let hiddenNodes = new Set<Element>();
|
|
49
|
+
|
|
50
|
+
let getHidden = (element: Element) => {
|
|
51
|
+
return shouldUseInert && element instanceof windowObj.HTMLElement
|
|
52
|
+
? element.inert
|
|
53
|
+
: element.getAttribute('aria-hidden') === 'true';
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
let setHidden = (element: Element, hidden: boolean) => {
|
|
57
|
+
if (shouldUseInert && element instanceof windowObj.HTMLElement) {
|
|
58
|
+
element.inert = hidden;
|
|
59
|
+
} else if (hidden) {
|
|
60
|
+
element.setAttribute('aria-hidden', 'true');
|
|
61
|
+
} else {
|
|
62
|
+
element.removeAttribute('aria-hidden');
|
|
63
|
+
if (element instanceof windowObj.HTMLElement) {
|
|
64
|
+
// We only ever call setHidden with hidden = false when the nodeCount is 1 aka
|
|
65
|
+
// we are trying to make the element visible to screen readers again, so remove inert as well
|
|
66
|
+
element.inert = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
let shadowRootsToWatch = new Set<ShadowRoot>();
|
|
72
|
+
if (shadowDOM()) {
|
|
73
|
+
// find all shadow roots that are ancestors of the targets
|
|
74
|
+
// traverse upwards until the root is reached
|
|
75
|
+
for (let target of targets) {
|
|
76
|
+
let node = target;
|
|
77
|
+
while (node && node !== root) {
|
|
78
|
+
let root = node.getRootNode();
|
|
79
|
+
if ('shadowRoot' in root) {
|
|
80
|
+
shadowRootsToWatch.add(root.shadowRoot as ShadowRoot);
|
|
81
|
+
}
|
|
82
|
+
node = root.parentNode as Element;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let walk = (root: Element) => {
|
|
88
|
+
// Keep live announcer and top layer elements (e.g. toasts) visible.
|
|
89
|
+
for (let element of root.querySelectorAll(
|
|
90
|
+
'[data-live-announcer], [data-react-aria-top-layer]',
|
|
91
|
+
)) {
|
|
92
|
+
visibleNodes.add(element);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let acceptNode = (node: Element) => {
|
|
96
|
+
// Skip this node and its children if it is one of the target nodes, or a live announcer.
|
|
97
|
+
// Also skip children of already hidden nodes, as aria-hidden is recursive. An exception is
|
|
98
|
+
// made for elements with role="row" since VoiceOver on iOS has issues hiding elements with role="row".
|
|
99
|
+
// For that case we want to hide the cells inside as well (https://bugs.webkit.org/show_bug.cgi?id=222623).
|
|
100
|
+
if (
|
|
101
|
+
hiddenNodes.has(node) ||
|
|
102
|
+
visibleNodes.has(node) ||
|
|
103
|
+
(node.parentElement &&
|
|
104
|
+
hiddenNodes.has(node.parentElement) &&
|
|
105
|
+
node.parentElement.getAttribute('role') !== 'row')
|
|
106
|
+
) {
|
|
107
|
+
return NodeFilter.FILTER_REJECT;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Skip this node but continue to children if one of the targets is inside the node.
|
|
111
|
+
for (let target of visibleNodes) {
|
|
112
|
+
if (nodeContains(node, target)) {
|
|
113
|
+
return NodeFilter.FILTER_SKIP;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
let walker = createShadowTreeWalker(getOwnerDocument(root), root, NodeFilter.SHOW_ELEMENT, {
|
|
121
|
+
acceptNode,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// TreeWalker does not include the root.
|
|
125
|
+
let acceptRoot = acceptNode(root);
|
|
126
|
+
if (acceptRoot === NodeFilter.FILTER_ACCEPT) {
|
|
127
|
+
hide(root);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (acceptRoot !== NodeFilter.FILTER_REJECT) {
|
|
131
|
+
let node = walker.nextNode() as Element;
|
|
132
|
+
while (node != null) {
|
|
133
|
+
hide(node);
|
|
134
|
+
node = walker.nextNode() as Element;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
let hide = (node: Element) => {
|
|
140
|
+
let refCount = refCountMap.get(node) ?? 0;
|
|
141
|
+
|
|
142
|
+
// If already aria-hidden, and the ref count is zero, then this element
|
|
143
|
+
// was already hidden and there's nothing for us to do.
|
|
144
|
+
if (getHidden(node) && refCount === 0) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (refCount === 0) {
|
|
149
|
+
setHidden(node, true);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
hiddenNodes.add(node);
|
|
153
|
+
refCountMap.set(node, refCount + 1);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// If there is already a MutationObserver listening from a previous call,
|
|
157
|
+
// disconnect it so the new on takes over.
|
|
158
|
+
if (observerStack.length) {
|
|
159
|
+
observerStack[observerStack.length - 1].disconnect();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
walk(root);
|
|
163
|
+
|
|
164
|
+
let observer = new MutationObserver((changes) => {
|
|
165
|
+
for (let change of changes) {
|
|
166
|
+
if (change.type !== 'childList') {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// If the parent element of the added nodes is not within one of the targets,
|
|
171
|
+
// and not already inside a hidden node, hide all of the new children.
|
|
172
|
+
if (
|
|
173
|
+
change.target.isConnected &&
|
|
174
|
+
![...visibleNodes, ...hiddenNodes].some((node) => nodeContains(node, change.target))
|
|
175
|
+
) {
|
|
176
|
+
for (let node of change.addedNodes) {
|
|
177
|
+
if (
|
|
178
|
+
(node instanceof HTMLElement || node instanceof SVGElement) &&
|
|
179
|
+
isAlwaysVisibleNode(node)
|
|
180
|
+
) {
|
|
181
|
+
visibleNodes.add(node);
|
|
182
|
+
} else if (node instanceof Element) {
|
|
183
|
+
walk(node);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (shadowDOM()) {
|
|
189
|
+
// if any of the observed shadow roots were removed, stop observing them
|
|
190
|
+
for (let shadowRoot of shadowRootsToWatch) {
|
|
191
|
+
if (!shadowRoot.isConnected) {
|
|
192
|
+
observer.disconnect();
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
201
|
+
let shadowObservers = new Set<MutationObserver>();
|
|
202
|
+
if (shadowDOM()) {
|
|
203
|
+
for (let shadowRoot of shadowRootsToWatch) {
|
|
204
|
+
// Disconnect single target instead of all https://github.com/whatwg/dom/issues/126
|
|
205
|
+
let shadowObserver = new MutationObserver((changes) => {
|
|
206
|
+
for (let change of changes) {
|
|
207
|
+
if (change.type !== 'childList') {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// If the parent element of the added nodes is not within one of the targets,
|
|
212
|
+
// and not already inside a hidden node, hide all of the new children.
|
|
213
|
+
if (
|
|
214
|
+
change.target.isConnected &&
|
|
215
|
+
![...visibleNodes, ...hiddenNodes].some((node) => nodeContains(node, change.target))
|
|
216
|
+
) {
|
|
217
|
+
for (let node of change.addedNodes) {
|
|
218
|
+
if (
|
|
219
|
+
(node instanceof HTMLElement || node instanceof SVGElement) &&
|
|
220
|
+
isAlwaysVisibleNode(node)
|
|
221
|
+
) {
|
|
222
|
+
visibleNodes.add(node);
|
|
223
|
+
} else if (node instanceof Element) {
|
|
224
|
+
walk(node);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (shadowDOM()) {
|
|
230
|
+
// if any of the observed shadow roots were removed, stop observing them
|
|
231
|
+
for (let shadowRoot of shadowRootsToWatch) {
|
|
232
|
+
if (!shadowRoot.isConnected) {
|
|
233
|
+
observer.disconnect();
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
shadowObserver.observe(shadowRoot, { childList: true, subtree: true });
|
|
241
|
+
shadowObservers.add(shadowObserver);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
let observerWrapper: ObserverWrapper = {
|
|
246
|
+
visibleNodes,
|
|
247
|
+
hiddenNodes,
|
|
248
|
+
observe() {
|
|
249
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
250
|
+
},
|
|
251
|
+
disconnect() {
|
|
252
|
+
observer.disconnect();
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
observerStack.push(observerWrapper);
|
|
257
|
+
|
|
258
|
+
return (): void => {
|
|
259
|
+
observer.disconnect();
|
|
260
|
+
if (shadowDOM()) {
|
|
261
|
+
for (let shadowObserver of shadowObservers) {
|
|
262
|
+
shadowObserver.disconnect();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for (let node of hiddenNodes) {
|
|
267
|
+
let count = refCountMap.get(node);
|
|
268
|
+
if (count == null) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (count === 1) {
|
|
272
|
+
setHidden(node, false);
|
|
273
|
+
refCountMap.delete(node);
|
|
274
|
+
} else {
|
|
275
|
+
refCountMap.set(node, count - 1);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Remove this observer from the stack, and start the previous one.
|
|
280
|
+
if (observerWrapper === observerStack[observerStack.length - 1]) {
|
|
281
|
+
observerStack.pop();
|
|
282
|
+
if (observerStack.length) {
|
|
283
|
+
observerStack[observerStack.length - 1].observe();
|
|
284
|
+
}
|
|
285
|
+
} else {
|
|
286
|
+
observerStack.splice(observerStack.indexOf(observerWrapper), 1);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function keepVisible(element: Element): (() => void) | undefined {
|
|
292
|
+
let observer = observerStack[observerStack.length - 1];
|
|
293
|
+
if (observer && !observer.visibleNodes.has(element)) {
|
|
294
|
+
observer.visibleNodes.add(element);
|
|
295
|
+
return () => {
|
|
296
|
+
observer.visibleNodes.delete(element);
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|