@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,178 @@
|
|
|
1
|
+
// Ported from react-stately (source: .react-spectrum/packages/react-stately/src/selection/useMultipleSelectionState.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 type {
|
|
6
|
+
DisabledBehavior,
|
|
7
|
+
FocusStrategy,
|
|
8
|
+
Key,
|
|
9
|
+
MultipleSelection,
|
|
10
|
+
SelectionBehavior,
|
|
11
|
+
SelectionMode,
|
|
12
|
+
} from '@react-types/shared';
|
|
13
|
+
import { useEffect, useMemo, useRef, useState } from 'octane';
|
|
14
|
+
|
|
15
|
+
import { S, splitSlot, subSlot } from '../../internal';
|
|
16
|
+
import type { MultipleSelectionState } from './types';
|
|
17
|
+
import { Selection } from './Selection';
|
|
18
|
+
import { useControlledState } from '../utils/useControlledState';
|
|
19
|
+
|
|
20
|
+
function equalSets(setA: any, setB: any): boolean {
|
|
21
|
+
if (setA.size !== setB.size) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (let item of setA) {
|
|
26
|
+
if (!setB.has(item)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface MultipleSelectionStateProps extends MultipleSelection {
|
|
35
|
+
/**
|
|
36
|
+
* How multiple selection should behave in the collection.
|
|
37
|
+
*
|
|
38
|
+
* @default 'toggle'
|
|
39
|
+
*/
|
|
40
|
+
selectionBehavior?: SelectionBehavior;
|
|
41
|
+
/** Whether onSelectionChange should fire even if the new set of keys is the same as the last. */
|
|
42
|
+
allowDuplicateSelectionEvents?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether `disabledKeys` applies to all interactions, or only selection.
|
|
45
|
+
*
|
|
46
|
+
* @default 'all'
|
|
47
|
+
*/
|
|
48
|
+
disabledBehavior?: DisabledBehavior;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Manages state for multiple selection and focus in a collection.
|
|
53
|
+
*/
|
|
54
|
+
export function useMultipleSelectionState(
|
|
55
|
+
props: MultipleSelectionStateProps,
|
|
56
|
+
): MultipleSelectionState;
|
|
57
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
58
|
+
export function useMultipleSelectionState(
|
|
59
|
+
props: MultipleSelectionStateProps,
|
|
60
|
+
slot: symbol | undefined,
|
|
61
|
+
): MultipleSelectionState;
|
|
62
|
+
export function useMultipleSelectionState(...args: any[]): MultipleSelectionState {
|
|
63
|
+
const [user, slotArg] = splitSlot(args);
|
|
64
|
+
const slot = slotArg ?? S('useMultipleSelectionState');
|
|
65
|
+
const props = user[0] as MultipleSelectionStateProps;
|
|
66
|
+
|
|
67
|
+
let {
|
|
68
|
+
selectionMode = 'none' as SelectionMode,
|
|
69
|
+
disallowEmptySelection = false,
|
|
70
|
+
allowDuplicateSelectionEvents,
|
|
71
|
+
selectionBehavior: selectionBehaviorProp = 'toggle',
|
|
72
|
+
disabledBehavior = 'all',
|
|
73
|
+
} = props;
|
|
74
|
+
|
|
75
|
+
// We want synchronous updates to `isFocused` and `focusedKey` after their setters are called.
|
|
76
|
+
// But we also need to trigger a react re-render. So, we have both a ref (sync) and state (async).
|
|
77
|
+
let isFocusedRef = useRef(false, subSlot(slot, 'focusedRef'));
|
|
78
|
+
let [, setFocused] = useState(false, subSlot(slot, 'focused'));
|
|
79
|
+
let focusedKeyRef = useRef<Key | null>(null, subSlot(slot, 'focusedKeyRef'));
|
|
80
|
+
let childFocusStrategyRef = useRef<FocusStrategy | null>(null, subSlot(slot, 'childFocus'));
|
|
81
|
+
let [, setFocusedKey] = useState<Key | null>(null, subSlot(slot, 'focusedKey'));
|
|
82
|
+
let selectedKeysProp = useMemo(
|
|
83
|
+
() => convertSelection(props.selectedKeys),
|
|
84
|
+
[props.selectedKeys],
|
|
85
|
+
subSlot(slot, 'selectedProp'),
|
|
86
|
+
);
|
|
87
|
+
let defaultSelectedKeys = useMemo(
|
|
88
|
+
() => convertSelection(props.defaultSelectedKeys, new Selection()),
|
|
89
|
+
[props.defaultSelectedKeys],
|
|
90
|
+
subSlot(slot, 'defaultSelected'),
|
|
91
|
+
);
|
|
92
|
+
let [selectedKeys, setSelectedKeys] = useControlledState(
|
|
93
|
+
selectedKeysProp,
|
|
94
|
+
defaultSelectedKeys!,
|
|
95
|
+
props.onSelectionChange,
|
|
96
|
+
subSlot(slot, 'selected'),
|
|
97
|
+
);
|
|
98
|
+
let disabledKeysProp = useMemo(
|
|
99
|
+
() => (props.disabledKeys ? new Set(props.disabledKeys) : new Set<Key>()),
|
|
100
|
+
[props.disabledKeys],
|
|
101
|
+
subSlot(slot, 'disabled'),
|
|
102
|
+
);
|
|
103
|
+
let [selectionBehavior, setSelectionBehavior] = useState(
|
|
104
|
+
selectionBehaviorProp,
|
|
105
|
+
subSlot(slot, 'behavior'),
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// If the selectionBehavior prop is set to replace, but the current state is toggle (e.g. due to long press
|
|
109
|
+
// to enter selection mode on touch), and the selection becomes empty, reset the selection behavior.
|
|
110
|
+
if (
|
|
111
|
+
selectionBehaviorProp === 'replace' &&
|
|
112
|
+
selectionBehavior === 'toggle' &&
|
|
113
|
+
typeof selectedKeys === 'object' &&
|
|
114
|
+
selectedKeys.size === 0
|
|
115
|
+
) {
|
|
116
|
+
setSelectionBehavior('replace');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// If the selectionBehavior prop changes, update the state as well.
|
|
120
|
+
let lastSelectionBehavior = useRef(selectionBehaviorProp, subSlot(slot, 'lastBehavior'));
|
|
121
|
+
useEffect(
|
|
122
|
+
() => {
|
|
123
|
+
if (selectionBehaviorProp !== lastSelectionBehavior.current) {
|
|
124
|
+
setSelectionBehavior(selectionBehaviorProp);
|
|
125
|
+
lastSelectionBehavior.current = selectionBehaviorProp;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
[selectionBehaviorProp],
|
|
129
|
+
subSlot(slot, 'behaviorSync'),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
selectionMode,
|
|
134
|
+
disallowEmptySelection,
|
|
135
|
+
selectionBehavior,
|
|
136
|
+
setSelectionBehavior,
|
|
137
|
+
get isFocused() {
|
|
138
|
+
return isFocusedRef.current;
|
|
139
|
+
},
|
|
140
|
+
setFocused(f) {
|
|
141
|
+
isFocusedRef.current = f;
|
|
142
|
+
setFocused(f);
|
|
143
|
+
},
|
|
144
|
+
get focusedKey() {
|
|
145
|
+
return focusedKeyRef.current;
|
|
146
|
+
},
|
|
147
|
+
get childFocusStrategy() {
|
|
148
|
+
return childFocusStrategyRef.current;
|
|
149
|
+
},
|
|
150
|
+
setFocusedKey(k, childFocusStrategy = 'first') {
|
|
151
|
+
focusedKeyRef.current = k;
|
|
152
|
+
childFocusStrategyRef.current = childFocusStrategy;
|
|
153
|
+
setFocusedKey(k);
|
|
154
|
+
},
|
|
155
|
+
selectedKeys,
|
|
156
|
+
setSelectedKeys(keys) {
|
|
157
|
+
if (allowDuplicateSelectionEvents || !equalSets(keys, selectedKeys)) {
|
|
158
|
+
// `keys` is contextually the shared Selection type ('all' | Set<Key>) while the
|
|
159
|
+
// controlled tuple is inferred over the local Selection class; the runtime value
|
|
160
|
+
// is always accepted, so narrow the type at the verbatim call.
|
|
161
|
+
setSelectedKeys(keys as 'all' | Selection);
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
disabledKeys: disabledKeysProp,
|
|
165
|
+
disabledBehavior,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function convertSelection(
|
|
170
|
+
selection: 'all' | Iterable<Key> | null | undefined,
|
|
171
|
+
defaultValue?: Selection,
|
|
172
|
+
): 'all' | Selection | undefined {
|
|
173
|
+
if (!selection) {
|
|
174
|
+
return defaultValue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return selection === 'all' ? 'all' : new Selection(selection);
|
|
178
|
+
}
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
// Ported from react-stately (source: .react-spectrum/packages/react-stately/src/slider/useSliderState.ts).
|
|
2
|
+
// octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
|
|
3
|
+
// convention; public value-level callbacks (onChange/onChangeEnd) are unchanged (the
|
|
4
|
+
// onInput rule applies only to DOM wiring); upstream's untyped `createOnChange` params
|
|
5
|
+
// are typed `any`; explicit dependency arrays are kept verbatim (they retain React's
|
|
6
|
+
// exact behavior in octane).
|
|
7
|
+
import { clamp, snapValueToStep } from '../utils/number';
|
|
8
|
+
|
|
9
|
+
import type { LabelableProps, Orientation, RangeInputBase, ValueBase } from '@react-types/shared';
|
|
10
|
+
import { useCallback, useMemo, useRef, useState } from 'octane';
|
|
11
|
+
|
|
12
|
+
import { S, splitSlot, subSlot } from '../../internal';
|
|
13
|
+
import { useControlledState } from '../utils/useControlledState';
|
|
14
|
+
|
|
15
|
+
export interface SliderProps<T = number | number[]>
|
|
16
|
+
extends RangeInputBase<number>, ValueBase<T>, LabelableProps {
|
|
17
|
+
/**
|
|
18
|
+
* The orientation of the Slider.
|
|
19
|
+
*
|
|
20
|
+
* @default 'horizontal'
|
|
21
|
+
*/
|
|
22
|
+
orientation?: Orientation;
|
|
23
|
+
/** Whether the whole Slider is disabled. */
|
|
24
|
+
isDisabled?: boolean;
|
|
25
|
+
/** Fired when the slider stops moving, due to being let go. */
|
|
26
|
+
onChangeEnd?: (value: T) => void;
|
|
27
|
+
// These are duplicated from ValueBase to define defaults for the docs.
|
|
28
|
+
/**
|
|
29
|
+
* The slider's minimum value.
|
|
30
|
+
*
|
|
31
|
+
* @default 0
|
|
32
|
+
*/
|
|
33
|
+
minValue?: number;
|
|
34
|
+
/**
|
|
35
|
+
* The slider's maximum value.
|
|
36
|
+
*
|
|
37
|
+
* @default 100
|
|
38
|
+
*/
|
|
39
|
+
maxValue?: number;
|
|
40
|
+
/**
|
|
41
|
+
* The slider's step value.
|
|
42
|
+
*
|
|
43
|
+
* @default 1
|
|
44
|
+
*/
|
|
45
|
+
step?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface SliderState {
|
|
49
|
+
/**
|
|
50
|
+
* Values managed by the slider by thumb index.
|
|
51
|
+
*/
|
|
52
|
+
readonly values: number[];
|
|
53
|
+
/**
|
|
54
|
+
* The default values for each thumb.
|
|
55
|
+
*/
|
|
56
|
+
readonly defaultValues: number[];
|
|
57
|
+
/**
|
|
58
|
+
* Get the value for the specified thumb.
|
|
59
|
+
*
|
|
60
|
+
* @param index
|
|
61
|
+
*/
|
|
62
|
+
getThumbValue(index: number): number;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Sets the value for the specified thumb.
|
|
66
|
+
* The actual value set will be clamped and rounded according to min/max/step.
|
|
67
|
+
*
|
|
68
|
+
* @param index
|
|
69
|
+
* @param value
|
|
70
|
+
*/
|
|
71
|
+
setThumbValue(index: number, value: number): void;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Sets value for the specified thumb by percent offset (between 0 and 1).
|
|
75
|
+
*
|
|
76
|
+
* @param index
|
|
77
|
+
* @param percent
|
|
78
|
+
*/
|
|
79
|
+
setThumbPercent(index: number, percent: number): void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Whether the specific thumb is being dragged.
|
|
83
|
+
*
|
|
84
|
+
* @param index
|
|
85
|
+
*/
|
|
86
|
+
isThumbDragging(index: number): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Set is dragging on the specified thumb.
|
|
89
|
+
*
|
|
90
|
+
* @param index
|
|
91
|
+
* @param dragging
|
|
92
|
+
*/
|
|
93
|
+
setThumbDragging(index: number, dragging: boolean): void;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Currently-focused thumb index.
|
|
97
|
+
*/
|
|
98
|
+
readonly focusedThumb: number | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Set focused true on specified thumb. This will remove focus from
|
|
101
|
+
* any thumb that had it before.
|
|
102
|
+
*
|
|
103
|
+
* @param index
|
|
104
|
+
*/
|
|
105
|
+
setFocusedThumb(index: number | undefined): void;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Returns the specified thumb's value as a percentage from 0 to 1.
|
|
109
|
+
*
|
|
110
|
+
* @param index
|
|
111
|
+
*/
|
|
112
|
+
getThumbPercent(index: number): number;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Returns the value as a percent between the min and max of the slider.
|
|
116
|
+
*
|
|
117
|
+
* @param index
|
|
118
|
+
*/
|
|
119
|
+
getValuePercent(value: number): number;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Returns the string label for the specified thumb's value, per props.formatOptions.
|
|
123
|
+
*
|
|
124
|
+
* @param index
|
|
125
|
+
*/
|
|
126
|
+
getThumbValueLabel(index: number): string;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Returns the string label for the value, per props.formatOptions.
|
|
130
|
+
*
|
|
131
|
+
* @param value
|
|
132
|
+
*/
|
|
133
|
+
getFormattedValue(value?: number | number[]): string;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Returns the min allowed value for the specified thumb.
|
|
137
|
+
*
|
|
138
|
+
* @param index
|
|
139
|
+
*/
|
|
140
|
+
getThumbMinValue(index: number): number;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Returns the max allowed value for the specified thumb.
|
|
144
|
+
*
|
|
145
|
+
* @param index
|
|
146
|
+
*/
|
|
147
|
+
getThumbMaxValue(index: number): number;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Converts a percent along track (between 0 and 1) to the corresponding value.
|
|
151
|
+
*
|
|
152
|
+
* @param percent
|
|
153
|
+
*/
|
|
154
|
+
getPercentValue(percent: number): number;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Returns if the specified thumb is editable.
|
|
158
|
+
*
|
|
159
|
+
* @param index
|
|
160
|
+
*/
|
|
161
|
+
isThumbEditable(index: number): boolean;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Set the specified thumb's editable state.
|
|
165
|
+
*
|
|
166
|
+
* @param index
|
|
167
|
+
* @param editable
|
|
168
|
+
*/
|
|
169
|
+
setThumbEditable(index: number, editable: boolean): void;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Increments the value of the thumb by the step or page amount.
|
|
173
|
+
*/
|
|
174
|
+
incrementThumb(index: number, stepSize?: number): void;
|
|
175
|
+
/**
|
|
176
|
+
* Decrements the value of the thumb by the step or page amount.
|
|
177
|
+
*/
|
|
178
|
+
decrementThumb(index: number, stepSize?: number): void;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The step amount for the slider.
|
|
182
|
+
*/
|
|
183
|
+
readonly step: number;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The page size for the slider, used to do a bigger step.
|
|
187
|
+
*/
|
|
188
|
+
readonly pageSize: number;
|
|
189
|
+
|
|
190
|
+
/** The orientation of the slider. */
|
|
191
|
+
readonly orientation: Orientation;
|
|
192
|
+
|
|
193
|
+
/** Whether the slider is disabled. */
|
|
194
|
+
readonly isDisabled: boolean;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const DEFAULT_MIN_VALUE = 0;
|
|
198
|
+
const DEFAULT_MAX_VALUE = 100;
|
|
199
|
+
const DEFAULT_STEP_VALUE = 1;
|
|
200
|
+
|
|
201
|
+
export interface SliderStateOptions<T> extends SliderProps<T> {
|
|
202
|
+
numberFormatter: Intl.NumberFormat;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Provides state management for a slider component. Stores values for all thumbs,
|
|
207
|
+
* formats values for localization, and provides methods to update the position
|
|
208
|
+
* of any thumbs.
|
|
209
|
+
*
|
|
210
|
+
* @param props
|
|
211
|
+
*/
|
|
212
|
+
export function useSliderState<T extends number | number[]>(
|
|
213
|
+
props: SliderStateOptions<T>,
|
|
214
|
+
): SliderState;
|
|
215
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
216
|
+
export function useSliderState<T extends number | number[]>(
|
|
217
|
+
props: SliderStateOptions<T>,
|
|
218
|
+
slot: symbol | undefined,
|
|
219
|
+
): SliderState;
|
|
220
|
+
export function useSliderState(...args: any[]): SliderState {
|
|
221
|
+
const [user, slotArg] = splitSlot(args);
|
|
222
|
+
const slot = slotArg ?? S('useSliderState');
|
|
223
|
+
const props = user[0] as SliderStateOptions<any>;
|
|
224
|
+
|
|
225
|
+
const {
|
|
226
|
+
isDisabled = false,
|
|
227
|
+
minValue = DEFAULT_MIN_VALUE,
|
|
228
|
+
maxValue = DEFAULT_MAX_VALUE,
|
|
229
|
+
numberFormatter: formatter,
|
|
230
|
+
step = DEFAULT_STEP_VALUE,
|
|
231
|
+
orientation = 'horizontal',
|
|
232
|
+
} = props;
|
|
233
|
+
|
|
234
|
+
// Page step should be at least equal to step and always a multiple of the step.
|
|
235
|
+
let pageSize = useMemo(
|
|
236
|
+
() => {
|
|
237
|
+
let calcPageSize = (maxValue - minValue) / 10;
|
|
238
|
+
calcPageSize = snapValueToStep(calcPageSize, 0, calcPageSize + step, step);
|
|
239
|
+
return Math.max(calcPageSize, step);
|
|
240
|
+
},
|
|
241
|
+
[step, maxValue, minValue],
|
|
242
|
+
subSlot(slot, 'pageSize'),
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
let restrictValues = useCallback(
|
|
246
|
+
(values: number[] | undefined) =>
|
|
247
|
+
values?.map((val, idx) => {
|
|
248
|
+
let min = idx === 0 ? minValue : values[idx - 1];
|
|
249
|
+
let max = idx === values.length - 1 ? maxValue : values[idx + 1];
|
|
250
|
+
return snapValueToStep(val, min, max, step);
|
|
251
|
+
}),
|
|
252
|
+
[minValue, maxValue, step],
|
|
253
|
+
subSlot(slot, 'restrict'),
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
let value = useMemo(
|
|
257
|
+
() => restrictValues(convertValue(props.value)),
|
|
258
|
+
[props.value, restrictValues],
|
|
259
|
+
subSlot(slot, 'value'),
|
|
260
|
+
);
|
|
261
|
+
let defaultValue = useMemo(
|
|
262
|
+
() => restrictValues(convertValue(props.defaultValue) ?? [minValue])!,
|
|
263
|
+
[props.defaultValue, minValue, restrictValues],
|
|
264
|
+
subSlot(slot, 'defaultValue'),
|
|
265
|
+
);
|
|
266
|
+
let onChange = createOnChange(props.value, props.defaultValue, props.onChange);
|
|
267
|
+
let onChangeEnd = createOnChange(props.value, props.defaultValue, props.onChangeEnd);
|
|
268
|
+
|
|
269
|
+
const [values, setValuesState] = useControlledState<number[]>(
|
|
270
|
+
value,
|
|
271
|
+
defaultValue,
|
|
272
|
+
onChange,
|
|
273
|
+
subSlot(slot, 'values'),
|
|
274
|
+
);
|
|
275
|
+
let [initialValues] = useState(values, subSlot(slot, 'initial'));
|
|
276
|
+
const [isDraggings, setDraggingsState] = useState<boolean[]>(
|
|
277
|
+
new Array(values.length).fill(false),
|
|
278
|
+
subSlot(slot, 'draggings'),
|
|
279
|
+
);
|
|
280
|
+
const isEditablesRef = useRef<boolean[]>(
|
|
281
|
+
new Array(values.length).fill(true),
|
|
282
|
+
subSlot(slot, 'editables'),
|
|
283
|
+
);
|
|
284
|
+
const [focusedIndex, setFocusedIndex] = useState<number | undefined>(
|
|
285
|
+
undefined,
|
|
286
|
+
subSlot(slot, 'focusedIndex'),
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
const valuesRef = useRef<number[]>(values, subSlot(slot, 'valuesRef'));
|
|
290
|
+
const isDraggingsRef = useRef<boolean[]>(isDraggings, subSlot(slot, 'draggingsRef'));
|
|
291
|
+
|
|
292
|
+
let setValues = (values: number[]) => {
|
|
293
|
+
valuesRef.current = values;
|
|
294
|
+
setValuesState(values);
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
let setDraggings = (draggings: boolean[]) => {
|
|
298
|
+
isDraggingsRef.current = draggings;
|
|
299
|
+
setDraggingsState(draggings);
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
function getValuePercent(value: number) {
|
|
303
|
+
return (value - minValue) / (maxValue - minValue);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function getThumbMinValue(index: number) {
|
|
307
|
+
return index === 0 ? minValue : values[index - 1];
|
|
308
|
+
}
|
|
309
|
+
function getThumbMaxValue(index: number) {
|
|
310
|
+
return index === values.length - 1 ? maxValue : values[index + 1];
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function isThumbEditable(index: number) {
|
|
314
|
+
return isEditablesRef.current[index];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function setThumbEditable(index: number, editable: boolean) {
|
|
318
|
+
isEditablesRef.current[index] = editable;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function updateValue(index: number, value: number) {
|
|
322
|
+
if (isDisabled || !isThumbEditable(index)) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const thisMin = getThumbMinValue(index);
|
|
326
|
+
const thisMax = getThumbMaxValue(index);
|
|
327
|
+
|
|
328
|
+
// Round value to multiple of step, clamp value between min and max
|
|
329
|
+
value = snapValueToStep(value, thisMin, thisMax, step);
|
|
330
|
+
let newValues = replaceIndex(valuesRef.current, index, value);
|
|
331
|
+
setValues(newValues);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function updateDragging(index: number, dragging: boolean) {
|
|
335
|
+
if (isDisabled || !isThumbEditable(index)) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (dragging) {
|
|
339
|
+
valuesRef.current = values;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const wasDragging = isDraggingsRef.current[index];
|
|
343
|
+
isDraggingsRef.current = replaceIndex(isDraggingsRef.current, index, dragging);
|
|
344
|
+
setDraggings(isDraggingsRef.current);
|
|
345
|
+
|
|
346
|
+
// Call onChangeEnd if no handles are dragging.
|
|
347
|
+
if (onChangeEnd && wasDragging && !isDraggingsRef.current.some(Boolean)) {
|
|
348
|
+
onChangeEnd(valuesRef.current);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
let listFormatRef = useRef<Intl.ListFormat | null>(null, subSlot(slot, 'listFormat'));
|
|
353
|
+
|
|
354
|
+
function getFormattedValue(valueParam: number | number[] = values) {
|
|
355
|
+
if (typeof valueParam === 'number') {
|
|
356
|
+
valueParam = [valueParam];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
switch (valueParam.length) {
|
|
360
|
+
case 0:
|
|
361
|
+
return '';
|
|
362
|
+
case 1:
|
|
363
|
+
return formatter.format(valueParam[0]);
|
|
364
|
+
case 2:
|
|
365
|
+
return formatter.formatRange(valueParam[0], valueParam[1]);
|
|
366
|
+
default: {
|
|
367
|
+
let formatted = valueParam.map((value) => formatter.format(value));
|
|
368
|
+
let listFormat = listFormatRef.current;
|
|
369
|
+
if (
|
|
370
|
+
!listFormat ||
|
|
371
|
+
listFormat.resolvedOptions().locale !== formatter.resolvedOptions().locale
|
|
372
|
+
) {
|
|
373
|
+
listFormat = listFormatRef.current = new Intl.ListFormat(
|
|
374
|
+
formatter.resolvedOptions().locale,
|
|
375
|
+
{ type: 'unit' },
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
return listFormat.format(formatted);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function setThumbPercent(index: number, percent: number) {
|
|
384
|
+
updateValue(index, getPercentValue(percent));
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function getRoundedValue(value: number) {
|
|
388
|
+
return Math.round((value - minValue) / step) * step + minValue;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function getPercentValue(percent: number) {
|
|
392
|
+
const val = percent * (maxValue - minValue) + minValue;
|
|
393
|
+
return clamp(getRoundedValue(val), minValue, maxValue);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function incrementThumb(index: number, stepSize: number = 1) {
|
|
397
|
+
let s = Math.max(stepSize, step);
|
|
398
|
+
updateValue(index, snapValueToStep(values[index] + s, minValue, maxValue, step));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function decrementThumb(index: number, stepSize: number = 1) {
|
|
402
|
+
let s = Math.max(stepSize, step);
|
|
403
|
+
updateValue(index, snapValueToStep(values[index] - s, minValue, maxValue, step));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return {
|
|
407
|
+
values: values,
|
|
408
|
+
defaultValues: props.defaultValue !== undefined ? defaultValue : initialValues,
|
|
409
|
+
getThumbValue: (index: number) => values[index],
|
|
410
|
+
setThumbValue: updateValue,
|
|
411
|
+
setThumbPercent,
|
|
412
|
+
isThumbDragging: (index: number) => isDraggings[index],
|
|
413
|
+
setThumbDragging: updateDragging,
|
|
414
|
+
focusedThumb: focusedIndex,
|
|
415
|
+
setFocusedThumb: setFocusedIndex,
|
|
416
|
+
getThumbPercent: (index: number) => getValuePercent(values[index]),
|
|
417
|
+
getValuePercent,
|
|
418
|
+
getThumbValueLabel: (index: number) => getFormattedValue(values[index]),
|
|
419
|
+
getFormattedValue,
|
|
420
|
+
getThumbMinValue,
|
|
421
|
+
getThumbMaxValue,
|
|
422
|
+
getPercentValue,
|
|
423
|
+
isThumbEditable,
|
|
424
|
+
setThumbEditable,
|
|
425
|
+
incrementThumb,
|
|
426
|
+
decrementThumb,
|
|
427
|
+
step,
|
|
428
|
+
pageSize,
|
|
429
|
+
orientation,
|
|
430
|
+
isDisabled,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function replaceIndex<T>(array: T[], index: number, value: T) {
|
|
435
|
+
if (array[index] === value) {
|
|
436
|
+
return array;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return [...array.slice(0, index), value, ...array.slice(index + 1)];
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function convertValue(value?: number | number[]) {
|
|
443
|
+
if (value == null) {
|
|
444
|
+
return undefined;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return Array.isArray(value) ? value : [value];
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function createOnChange(value: any, defaultValue: any, onChange: any) {
|
|
451
|
+
return (newValue: number[]) => {
|
|
452
|
+
if (typeof value === 'number' || typeof defaultValue === 'number') {
|
|
453
|
+
onChange?.(newValue[0]);
|
|
454
|
+
} else {
|
|
455
|
+
onChange?.(newValue);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
}
|