@astryxdesign/core 0.1.2 → 0.1.3-canary.6d57c8d
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/CHANGELOG.md +165 -0
- package/README.md +12 -12
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +2 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +0 -1
- package/dist/Calendar/Calendar.d.ts +5 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +82 -43
- package/dist/Calendar/hooks/index.d.ts +0 -2
- package/dist/Calendar/hooks/index.d.ts.map +1 -1
- package/dist/Calendar/hooks/index.js +1 -2
- package/dist/Calendar/index.d.ts +3 -3
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +3 -9
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +3 -11
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +17 -3
- package/dist/Center/Center.d.ts +11 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +9 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +0 -1
- package/dist/Chat/ChatMessageList.d.ts +14 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +2 -0
- package/dist/Chat/useTriggerMenu.d.ts +8 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +51 -9
- package/dist/CheckboxList/CheckboxList.d.ts +13 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +39 -9
- package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +0 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +9 -5
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +51 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +4 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +93 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +167 -99
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +42 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +78 -15
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +12 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +42 -14
- package/dist/Field/Field.d.ts +19 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -0
- package/dist/Field/FieldLabel.d.ts +21 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +41 -26
- package/dist/FileInput/FileInput.d.ts +22 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +56 -10
- package/dist/Grid/Grid.d.ts +11 -1
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +32 -6
- package/dist/InputGroup/InputGroup.d.ts +4 -3
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +16 -6
- package/dist/InputGroup/InputGroupContext.d.ts +4 -0
- package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupContext.js +2 -2
- package/dist/InputGroup/groupStyles.d.ts +1 -1
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +3 -3
- package/dist/InputGroup/index.d.ts +1 -0
- package/dist/InputGroup/index.d.ts.map +1 -1
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +33 -1
- package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +8 -4
- package/dist/Layer/useLayer.d.ts +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +64 -9
- package/dist/Layout/Layout.d.ts +4 -11
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +10 -11
- package/dist/Layout/LayoutFooter.d.ts +2 -2
- package/dist/Layout/LayoutFooter.d.ts.map +1 -1
- package/dist/Layout/LayoutHeader.d.ts +2 -2
- package/dist/Layout/LayoutHeader.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.d.ts +2 -2
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.d.ts +51 -0
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +63 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -2
- package/dist/Link/Link.d.ts +16 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +18 -7
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MoreMenu/MoreMenu.d.ts +1 -7
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +0 -2
- package/dist/MultiSelector/MultiSelector.d.ts +27 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +141 -42
- package/dist/MultiSelector/hooks.d.ts +12 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +14 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +34 -3
- package/dist/NumberInput/NumberInput.d.ts +23 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +62 -12
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +15 -1
- package/dist/Popover/Popover.d.ts +18 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +5 -2
- package/dist/Popover/usePopover.d.ts +38 -3
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +24 -9
- package/dist/PowerSearch/PowerSearch.d.ts +11 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +6 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +3 -5
- package/dist/RadioList/RadioList.d.ts +20 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +105 -9
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +78 -44
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
- package/dist/Selector/Selector.d.ts +24 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +122 -43
- package/dist/Selector/hooks.d.ts +8 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +14 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +2 -0
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +8 -2
- package/dist/Slider/Slider.d.ts +21 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +36 -9
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +38 -23
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +25 -1
- package/dist/Stack/StackItem.d.ts +12 -23
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +8 -1
- package/dist/Switch/Switch.d.ts +23 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -11
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +6 -0
- package/dist/TabList/TabList.d.ts +16 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +87 -10
- package/dist/TabList/TabListContext.d.ts +5 -0
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +5 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +11 -8
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +10 -1
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +10 -10
- package/dist/Table/TableHeaderCell.d.ts +8 -1
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.js +16 -16
- package/dist/Table/index.d.ts +2 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -2
- package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +8 -3
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/tableContextMenu.d.ts +33 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +133 -0
- package/dist/Table/types.d.ts +66 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +22 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +41 -9
- package/dist/TextInput/TextInput.d.ts +23 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +55 -10
- package/dist/TimeInput/TimeInput.d.ts +23 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +147 -76
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +14 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +131 -3
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +26 -4
- package/dist/Toolbar/Toolbar.d.ts +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +51 -7
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +56 -9
- package/dist/TopNav/TopNavHeading.d.ts +7 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +8 -0
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +72 -2
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +51 -12
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
- package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +13 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +69 -6
- package/dist/Typeahead/Typeahead.d.ts +26 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +65 -29
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
- package/dist/VisuallyHidden/index.d.ts +11 -0
- package/dist/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/VisuallyHidden/index.js +13 -0
- package/dist/astryx.css +18 -0
- package/dist/astryx.umd.js +55 -55
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/focusableSelector.d.ts +22 -0
- package/dist/hooks/focusableSelector.d.ts.map +1 -0
- package/dist/hooks/focusableSelector.js +24 -0
- package/dist/hooks/index.d.ts +12 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -2
- package/dist/hooks/useAnnounce.d.ts +40 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -0
- package/dist/hooks/useAnnounce.js +142 -0
- package/dist/hooks/useClickableContainer.d.ts +16 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +16 -4
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +4 -4
- package/dist/hooks/useFocusTrap.d.ts +18 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +87 -3
- package/dist/hooks/useGridFocus.d.ts +88 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +261 -62
- package/dist/hooks/useKeyboardHint.d.ts +82 -0
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHint.js +220 -0
- package/dist/hooks/useListFocus.d.ts +78 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +305 -52
- package/dist/hooks/useLongPress.d.ts +21 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -0
- package/dist/hooks/useLongPress.js +89 -0
- package/dist/hooks/useTreeFocus.d.ts +157 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -0
- package/dist/hooks/useTreeFocus.js +337 -0
- package/dist/hooks/useTypeahead.d.ts +63 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +117 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/utils/dateTypes.d.ts +12 -0
- package/dist/utils/dateTypes.d.ts.map +1 -1
- package/dist/utils/dateTypes.js +41 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/inputAria.d.ts +29 -0
- package/dist/utils/inputAria.d.ts.map +1 -0
- package/dist/utils/inputAria.js +30 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -2
- package/docs.mjs +2 -2
- package/package.json +12 -8
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.tsx +3 -16
- package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
- package/src/ButtonGroup/ButtonGroup.tsx +0 -1
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +168 -30
- package/src/Calendar/Calendar.tsx +121 -66
- package/src/Calendar/hooks/index.ts +0 -6
- package/src/Calendar/index.ts +1 -3
- package/src/Calendar/styles.ts +4 -9
- package/src/Carousel/Carousel.doc.mjs +7 -1
- package/src/Carousel/Carousel.test.tsx +20 -0
- package/src/Carousel/Carousel.tsx +16 -1
- package/src/Center/Center.doc.mjs +12 -2
- package/src/Center/Center.tsx +28 -3
- package/src/Chat/ChatComposerInput.test.tsx +26 -7
- package/src/Chat/ChatComposerInput.tsx +0 -1
- package/src/Chat/ChatDictationButton.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.doc.mjs +8 -0
- package/src/Chat/ChatMessageList.test.tsx +18 -0
- package/src/Chat/ChatMessageList.tsx +16 -0
- package/src/Chat/useTriggerMenu.tsx +22 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
- package/src/CheckboxInput/CheckboxInput.tsx +78 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxList.test.tsx +192 -26
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/CheckboxList/CheckboxListItem.tsx +0 -3
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +121 -0
- package/src/Citation/Citation.tsx +15 -3
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +63 -33
- package/src/CommandPalette/CommandPalette.test.tsx +47 -1
- package/src/CommandPalette/CommandPalette.tsx +9 -21
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +155 -1
- package/src/ContextMenu/ContextMenu.tsx +113 -16
- package/src/DateInput/DateInput.doc.mjs +286 -56
- package/src/DateInput/DateInput.test.tsx +248 -2
- package/src/DateInput/DateInput.tsx +196 -100
- package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
- package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
- package/src/DateRangeInput/DateRangeInput.tsx +63 -5
- package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
- package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
- package/src/DateTimeInput/DateTimeInput.tsx +125 -17
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.tsx +12 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
- package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
- package/src/DropdownMenu/DropdownMenu.tsx +52 -18
- package/src/Field/Field.doc.mjs +59 -18
- package/src/Field/Field.test.tsx +32 -0
- package/src/Field/Field.tsx +23 -5
- package/src/Field/FieldLabel.tsx +55 -17
- package/src/FileInput/FileInput.doc.mjs +17 -0
- package/src/FileInput/FileInput.test.tsx +283 -49
- package/src/FileInput/FileInput.tsx +76 -4
- package/src/Grid/Grid.doc.mjs +17 -4
- package/src/Grid/Grid.test.tsx +43 -30
- package/src/Grid/Grid.tsx +38 -3
- package/src/Icon/Icon.doc.mjs +3 -3
- package/src/InputGroup/InputGroup.doc.mjs +111 -23
- package/src/InputGroup/InputGroup.test.tsx +257 -60
- package/src/InputGroup/InputGroup.tsx +23 -5
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/groupStyles.ts +7 -1
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +35 -3
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +5 -0
- package/src/Layer/useLayer.test.tsx +111 -0
- package/src/Layer/useLayer.tsx +90 -9
- package/src/Layout/Layout.tsx +8 -16
- package/src/Layout/LayoutFooter.doc.mjs +4 -4
- package/src/Layout/LayoutFooter.tsx +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +4 -4
- package/src/Layout/LayoutHeader.tsx +3 -3
- package/src/Layout/LayoutPanel.tsx +3 -3
- package/src/Layout/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -0
- package/src/Lightbox/Lightbox.test.tsx +53 -5
- package/src/Lightbox/Lightbox.tsx +9 -4
- package/src/Link/Link.doc.mjs +14 -0
- package/src/Link/Link.test.tsx +50 -0
- package/src/Link/Link.tsx +39 -4
- package/src/Markdown/Markdown.test.tsx +11 -0
- package/src/Markdown/Markdown.tsx +7 -0
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +30 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +194 -48
- package/src/MultiSelector/hooks.ts +27 -0
- package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
- package/src/NavMenu/NavHeadingMenu.tsx +50 -3
- package/src/NumberInput/NumberInput.doc.mjs +17 -0
- package/src/NumberInput/NumberInput.test.tsx +242 -40
- package/src/NumberInput/NumberInput.tsx +89 -11
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +117 -5
- package/src/Pagination/Pagination.tsx +21 -1
- package/src/Popover/Popover.doc.mjs +26 -0
- package/src/Popover/Popover.test.tsx +121 -0
- package/src/Popover/Popover.tsx +23 -2
- package/src/Popover/usePopover.doc.mjs +9 -3
- package/src/Popover/usePopover.tsx +70 -12
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +97 -1
- package/src/PowerSearch/PowerSearch.tsx +16 -3
- package/src/ProgressBar/ProgressBar.test.tsx +34 -26
- package/src/ProgressBar/ProgressBar.tsx +3 -4
- package/src/RadioList/RadioList.doc.mjs +9 -0
- package/src/RadioList/RadioList.test.tsx +252 -16
- package/src/RadioList/RadioList.tsx +166 -10
- package/src/RadioList/RadioListItem.tsx +14 -2
- package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
- package/src/SegmentedControl/SegmentedControl.tsx +102 -54
- package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +26 -0
- package/src/Selector/Selector.test.tsx +387 -15
- package/src/Selector/Selector.tsx +175 -67
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +48 -0
- package/src/SideNav/SideNavHeading.tsx +8 -2
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +15 -0
- package/src/Slider/Slider.test.tsx +155 -2
- package/src/Slider/Slider.tsx +53 -5
- package/src/Spinner/Spinner.tsx +7 -1
- package/src/Stack/Stack.doc.mjs +77 -0
- package/src/Stack/Stack.test.tsx +55 -5
- package/src/Stack/Stack.tsx +73 -24
- package/src/Stack/StackItem.test.tsx +23 -0
- package/src/Stack/StackItem.tsx +20 -23
- package/src/Switch/Switch.doc.mjs +15 -0
- package/src/Switch/Switch.test.tsx +162 -27
- package/src/Switch/Switch.tsx +61 -21
- package/src/TabList/Tab.tsx +6 -0
- package/src/TabList/TabList.doc.mjs +6 -0
- package/src/TabList/TabList.test.tsx +251 -0
- package/src/TabList/TabList.tsx +103 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +21 -17
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.test.tsx +10 -0
- package/src/Table/Table.tsx +8 -0
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/index.ts +3 -2
- package/src/Table/plugins/pagination/paginateData.ts +10 -3
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
- package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +74 -0
- package/src/Table/useTableColumnResize.doc.mjs +3 -3
- package/src/Table/useTableStickyColumns.doc.mjs +2 -2
- package/src/Text/Text.doc.mjs +18 -18
- package/src/TextArea/TextArea.doc.mjs +17 -0
- package/src/TextArea/TextArea.test.tsx +167 -35
- package/src/TextArea/TextArea.tsx +62 -15
- package/src/TextInput/TextInput.doc.mjs +17 -0
- package/src/TextInput/TextInput.test.tsx +168 -34
- package/src/TextInput/TextInput.tsx +77 -9
- package/src/Thumbnail/Thumbnail.doc.mjs +4 -4
- package/src/TimeInput/TimeInput.doc.mjs +340 -60
- package/src/TimeInput/TimeInput.test.tsx +255 -7
- package/src/TimeInput/TimeInput.tsx +176 -70
- package/src/Timestamp/Timestamp.doc.mjs +19 -19
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +214 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +37 -1
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +68 -0
- package/src/Tooltip/useTooltip.tsx +55 -8
- package/src/TopNav/TopNav.test.tsx +50 -0
- package/src/TopNav/TopNavHeading.tsx +17 -1
- package/src/TreeList/TreeList.test.tsx +295 -6
- package/src/TreeList/TreeList.tsx +73 -1
- package/src/TreeList/TreeListItem.tsx +51 -5
- package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
- package/src/Typeahead/BaseTypeahead.tsx +93 -9
- package/src/Typeahead/Typeahead.doc.mjs +141 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +105 -33
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
- package/src/VisuallyHidden/index.ts +15 -0
- package/src/docs-script.test.mjs +50 -0
- package/src/hooks/focusableSelector.ts +25 -0
- package/src/hooks/index.ts +28 -2
- package/src/hooks/useAnnounce.test.tsx +101 -0
- package/src/hooks/useAnnounce.ts +168 -0
- package/src/hooks/useClickableContainer.ts +16 -4
- package/src/hooks/useEntryAnimation.ts +16 -4
- package/src/hooks/useFocusTrap.test.tsx +132 -0
- package/src/hooks/useFocusTrap.ts +98 -4
- package/src/hooks/useGridFocus.doc.mjs +40 -2
- package/src/hooks/useGridFocus.test.tsx +132 -0
- package/src/hooks/useGridFocus.ts +343 -67
- package/src/hooks/useKeyboardHint.doc.mjs +101 -0
- package/src/hooks/useKeyboardHint.test.tsx +70 -0
- package/src/hooks/useKeyboardHint.tsx +332 -0
- package/src/hooks/useListFocus.doc.mjs +50 -10
- package/src/hooks/useListFocus.test.tsx +375 -0
- package/src/hooks/useListFocus.ts +395 -57
- package/src/hooks/useLongPress.test.tsx +134 -0
- package/src/hooks/useLongPress.ts +119 -0
- package/src/hooks/useTreeFocus.doc.mjs +140 -0
- package/src/hooks/useTreeFocus.test.tsx +214 -0
- package/src/hooks/useTreeFocus.ts +559 -0
- package/src/hooks/useTypeahead.test.tsx +109 -0
- package/src/hooks/useTypeahead.ts +183 -0
- package/src/index.ts +1 -0
- package/src/theme/derivedVarRegistry.test.ts +10 -5
- package/src/utils/dateTypes.test.ts +40 -0
- package/src/utils/dateTypes.ts +40 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/inputAria.test.ts +39 -0
- package/src/utils/inputAria.ts +58 -0
- package/src/utils/timeParser.test.ts +10 -0
- package/src/utils/timeParser.ts +5 -2
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
- package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
- package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
|
@@ -8,10 +8,35 @@ export interface UseGridFocusOptions {
|
|
|
8
8
|
*/
|
|
9
9
|
columns: number;
|
|
10
10
|
/**
|
|
11
|
-
* Selector for
|
|
11
|
+
* Selector for cells within the grid. This should match ALL grid cell
|
|
12
|
+
* positions in DOM order (including disabled/empty ones) so the hook can
|
|
13
|
+
* preserve the true grid geometry when computing rows and columns.
|
|
14
|
+
*
|
|
15
|
+
* Use {@link UseGridFocusOptions.isCellFocusable} to distinguish cells that
|
|
16
|
+
* can receive focus from those that cannot (disabled or empty). Navigation
|
|
17
|
+
* moves to a target row/column and, if that cell is not focusable, continues
|
|
18
|
+
* in the same direction to the next focusable cell — the geometry is never
|
|
19
|
+
* collapsed to only-focusable cells.
|
|
20
|
+
*
|
|
12
21
|
* @default 'button:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
13
22
|
*/
|
|
14
23
|
cellSelector?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Predicate determining whether a cell matched by {@link cellSelector} can
|
|
26
|
+
* receive focus. When omitted, every matched cell is considered focusable
|
|
27
|
+
* (backwards-compatible behavior).
|
|
28
|
+
*
|
|
29
|
+
* @param cell A cell element matched by `cellSelector`.
|
|
30
|
+
*/
|
|
31
|
+
isCellFocusable?: (cell: HTMLElement) => boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Resolves the element to focus for a given cell. Useful when the cell is a
|
|
34
|
+
* wrapper element (e.g. a `role="gridcell"` div) whose focusable content is a
|
|
35
|
+
* descendant (e.g. a `<button>`). When omitted, the cell itself is focused.
|
|
36
|
+
*
|
|
37
|
+
* @param cell A cell element matched by `cellSelector`.
|
|
38
|
+
*/
|
|
39
|
+
getFocusTarget?: (cell: HTMLElement) => HTMLElement | null;
|
|
15
40
|
/**
|
|
16
41
|
* Callback when navigation would go before the first cell.
|
|
17
42
|
* Useful for navigating to previous month in calendars.
|
|
@@ -34,6 +59,32 @@ export interface UseGridFocusOptions {
|
|
|
34
59
|
* Callback for Page Down key (e.g., next month).
|
|
35
60
|
*/
|
|
36
61
|
onPageDown?: () => void;
|
|
62
|
+
/**
|
|
63
|
+
* Whether the grid is in a right-to-left context. When true, ArrowLeft and
|
|
64
|
+
* ArrowRight are swapped so horizontal navigation follows visual direction.
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
isRtl?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Roving-tabindex ownership. When true, the hook manages a single tab stop
|
|
70
|
+
* across the grid: exactly one focusable cell carries `tabindex="0"` and the
|
|
71
|
+
* rest `tabindex="-1"`. The tab stop is stamped on mount and repaired
|
|
72
|
+
* whenever cells mount/unmount or toggle focusable, and moves with arrow
|
|
73
|
+
* navigation. Attach the returned {@link UseGridFocusReturn.handleFocus} to
|
|
74
|
+
* the container's `onFocus` to keep the stop in sync after clicks or
|
|
75
|
+
* programmatic focus.
|
|
76
|
+
*
|
|
77
|
+
* The tab stop is stamped on the resolved focus target (see
|
|
78
|
+
* {@link UseGridFocusOptions.getFocusTarget}), not the cell wrapper, so it
|
|
79
|
+
* works when the focusable element is a descendant of the cell. An existing
|
|
80
|
+
* `tabindex="0"` on a focus target is honored, letting the caller seed which
|
|
81
|
+
* cell is initially tabbable.
|
|
82
|
+
*
|
|
83
|
+
* When false (the default), the hook only *moves* focus (`.focus()`) and
|
|
84
|
+
* never touches `tabindex` — the caller owns tab-stop management.
|
|
85
|
+
* @default false
|
|
86
|
+
*/
|
|
87
|
+
hasRovingTabIndex?: boolean;
|
|
37
88
|
}
|
|
38
89
|
/**
|
|
39
90
|
* Return type for useGridFocus hook
|
|
@@ -47,6 +98,12 @@ export interface UseGridFocusReturn<T extends HTMLElement = HTMLElement> {
|
|
|
47
98
|
* Key down handler to attach to the grid container.
|
|
48
99
|
*/
|
|
49
100
|
handleKeyDown: (e: React.KeyboardEvent) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Focus handler to attach to the container's `onFocus`. Keeps the roving tab
|
|
103
|
+
* stop in sync when `hasRovingTabIndex` is enabled; a no-op otherwise, so it
|
|
104
|
+
* is always safe to attach.
|
|
105
|
+
*/
|
|
106
|
+
handleFocus: (e: React.FocusEvent) => void;
|
|
50
107
|
/**
|
|
51
108
|
* Focus a specific cell by index.
|
|
52
109
|
*/
|
|
@@ -71,6 +128,18 @@ export interface UseGridFocusReturn<T extends HTMLElement = HTMLElement> {
|
|
|
71
128
|
* - Ctrl+End: Move to last cell in grid
|
|
72
129
|
* - Page Up/Down: Custom callbacks (e.g., month navigation)
|
|
73
130
|
*
|
|
131
|
+
* The hook enumerates ALL cells matched by `cellSelector` in DOM order and
|
|
132
|
+
* computes row/column over that full set, preserving the true grid geometry
|
|
133
|
+
* even when some cells are disabled or empty. When a move lands on a
|
|
134
|
+
* non-focusable cell (per `isCellFocusable`), it continues in the same
|
|
135
|
+
* direction to the next focusable cell.
|
|
136
|
+
*
|
|
137
|
+
* By default the hook only *moves* focus and leaves `tabindex` management to
|
|
138
|
+
* the caller. Opt into {@link UseGridFocusOptions.hasRovingTabIndex} for a hook
|
|
139
|
+
* that owns a single tab stop (roving tabindex) across the grid — stamping and
|
|
140
|
+
* repairing it as cells mount/unmount or toggle focusable, and moving it with
|
|
141
|
+
* arrow navigation.
|
|
142
|
+
*
|
|
74
143
|
* @example
|
|
75
144
|
* ```
|
|
76
145
|
* const {gridRef, handleKeyDown} = useGridFocus({
|
|
@@ -83,6 +152,24 @@ export interface UseGridFocusReturn<T extends HTMLElement = HTMLElement> {
|
|
|
83
152
|
* {cells.map(cell => <button role="gridcell">{cell}</button>)}
|
|
84
153
|
* </div>
|
|
85
154
|
* ```
|
|
155
|
+
*
|
|
156
|
+
* Roving-tabindex grid (e.g. a date picker where the cell is a wrapper around
|
|
157
|
+
* a focusable button):
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```
|
|
161
|
+
* const {gridRef, handleKeyDown, handleFocus} = useGridFocus({
|
|
162
|
+
* columns: 7,
|
|
163
|
+
* cellSelector: '[role="gridcell"]',
|
|
164
|
+
* isCellFocusable: cell => cell.querySelector('button:not([disabled])') != null,
|
|
165
|
+
* getFocusTarget: cell => cell.querySelector('button'),
|
|
166
|
+
* hasRovingTabIndex: true,
|
|
167
|
+
* });
|
|
168
|
+
*
|
|
169
|
+
* <div ref={gridRef} role="grid" onKeyDown={handleKeyDown} onFocus={handleFocus}>
|
|
170
|
+
* {cells}
|
|
171
|
+
* </div>
|
|
172
|
+
* ```
|
|
86
173
|
*/
|
|
87
174
|
export declare function useGridFocus<T extends HTMLElement = HTMLElement>(options: UseGridFocusOptions): UseGridFocusReturn<T>;
|
|
88
175
|
//# sourceMappingURL=useGridFocus.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGridFocus.d.ts","sourceRoot":"","sources":["../../src/hooks/useGridFocus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useGridFocus.d.ts","sourceRoot":"","sources":["../../src/hooks/useGridFocus.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC;IAEjD;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,WAAW,GAAG,IAAI,CAAC;IAE3D;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAE5D;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAE3D;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IAExB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IACrE;;OAEG;IACH,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEnC;;OAEG;IACH,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;IAEhD;;;;OAIG;IACH,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAC9D,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CAAC,CAAC,CAAC,CAuYvB"}
|
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useGridFocus.ts
|
|
7
|
-
* @input Uses React useCallback, useRef
|
|
7
|
+
* @input Uses React useCallback, useRef, useIsomorphicLayoutEffect
|
|
8
8
|
* @output Exports useGridFocus hook for grid keyboard navigation
|
|
9
9
|
* @position Core hook; used by Calendar for date grid navigation
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update:
|
|
12
12
|
* - /packages/core/src/hooks/index.ts
|
|
13
|
-
* - /packages/core/src/hooks/useGridFocus.test.
|
|
13
|
+
* - /packages/core/src/hooks/useGridFocus.test.tsx
|
|
14
14
|
*/
|
|
15
15
|
import { useCallback, useRef } from 'react';
|
|
16
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Configuration for grid focus behavior
|
|
@@ -33,6 +34,18 @@ import { useCallback, useRef } from 'react';
|
|
|
33
34
|
* - Ctrl+End: Move to last cell in grid
|
|
34
35
|
* - Page Up/Down: Custom callbacks (e.g., month navigation)
|
|
35
36
|
*
|
|
37
|
+
* The hook enumerates ALL cells matched by `cellSelector` in DOM order and
|
|
38
|
+
* computes row/column over that full set, preserving the true grid geometry
|
|
39
|
+
* even when some cells are disabled or empty. When a move lands on a
|
|
40
|
+
* non-focusable cell (per `isCellFocusable`), it continues in the same
|
|
41
|
+
* direction to the next focusable cell.
|
|
42
|
+
*
|
|
43
|
+
* By default the hook only *moves* focus and leaves `tabindex` management to
|
|
44
|
+
* the caller. Opt into {@link UseGridFocusOptions.hasRovingTabIndex} for a hook
|
|
45
|
+
* that owns a single tab stop (roving tabindex) across the grid — stamping and
|
|
46
|
+
* repairing it as cells mount/unmount or toggle focusable, and moving it with
|
|
47
|
+
* arrow navigation.
|
|
48
|
+
*
|
|
36
49
|
* @example
|
|
37
50
|
* ```
|
|
38
51
|
* const {gridRef, handleKeyDown} = useGridFocus({
|
|
@@ -45,20 +58,43 @@ import { useCallback, useRef } from 'react';
|
|
|
45
58
|
* {cells.map(cell => <button role="gridcell">{cell}</button>)}
|
|
46
59
|
* </div>
|
|
47
60
|
* ```
|
|
61
|
+
*
|
|
62
|
+
* Roving-tabindex grid (e.g. a date picker where the cell is a wrapper around
|
|
63
|
+
* a focusable button):
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```
|
|
67
|
+
* const {gridRef, handleKeyDown, handleFocus} = useGridFocus({
|
|
68
|
+
* columns: 7,
|
|
69
|
+
* cellSelector: '[role="gridcell"]',
|
|
70
|
+
* isCellFocusable: cell => cell.querySelector('button:not([disabled])') != null,
|
|
71
|
+
* getFocusTarget: cell => cell.querySelector('button'),
|
|
72
|
+
* hasRovingTabIndex: true,
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
* <div ref={gridRef} role="grid" onKeyDown={handleKeyDown} onFocus={handleFocus}>
|
|
76
|
+
* {cells}
|
|
77
|
+
* </div>
|
|
78
|
+
* ```
|
|
48
79
|
*/
|
|
49
80
|
export function useGridFocus(options) {
|
|
50
81
|
const {
|
|
51
82
|
columns,
|
|
52
83
|
cellSelector = 'button:not([disabled]), [tabindex]:not([tabindex="-1"])',
|
|
84
|
+
isCellFocusable,
|
|
85
|
+
getFocusTarget,
|
|
53
86
|
onNavigateBefore,
|
|
54
87
|
onNavigateAfter,
|
|
55
88
|
onPageUp,
|
|
56
|
-
onPageDown
|
|
89
|
+
onPageDown,
|
|
90
|
+
isRtl = false,
|
|
91
|
+
hasRovingTabIndex = false
|
|
57
92
|
} = options;
|
|
58
93
|
const gridRef = useRef(null);
|
|
59
94
|
|
|
60
95
|
/**
|
|
61
|
-
* Get all
|
|
96
|
+
* Get all cells in the grid, in DOM order. This includes disabled and empty
|
|
97
|
+
* cells so the true grid geometry is preserved.
|
|
62
98
|
*/
|
|
63
99
|
const getCells = useCallback(() => {
|
|
64
100
|
if (!gridRef.current) {
|
|
@@ -68,7 +104,114 @@ export function useGridFocus(options) {
|
|
|
68
104
|
}, [cellSelector]);
|
|
69
105
|
|
|
70
106
|
/**
|
|
71
|
-
*
|
|
107
|
+
* Whether a cell can receive focus.
|
|
108
|
+
*/
|
|
109
|
+
const cellFocusable = useCallback(cell => {
|
|
110
|
+
if (!cell) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
return isCellFocusable ? isCellFocusable(cell) : true;
|
|
114
|
+
}, [isCellFocusable]);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Resolve the element that should actually receive focus for a cell.
|
|
118
|
+
*/
|
|
119
|
+
const resolveFocusTarget = useCallback(cell => {
|
|
120
|
+
if (!cell) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
return getFocusTarget ? getFocusTarget(cell) : cell;
|
|
124
|
+
}, [getFocusTarget]);
|
|
125
|
+
|
|
126
|
+
// --- Roving tabindex ownership (opt-in via `hasRovingTabIndex`) -------------
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Set `tabindex` on an element, but only when it differs (avoids redundant
|
|
130
|
+
* DOM writes). Uses setAttribute so the value reflects even for elements
|
|
131
|
+
* (like `<button>`) whose default tabIndex is already 0.
|
|
132
|
+
*/
|
|
133
|
+
const setTabIndex = useCallback((el, value) => {
|
|
134
|
+
if (el.getAttribute('tabindex') !== String(value)) {
|
|
135
|
+
el.setAttribute('tabindex', String(value));
|
|
136
|
+
}
|
|
137
|
+
}, []);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The resolved focus targets of all focusable cells, in DOM order. These are
|
|
141
|
+
* the elements that carry the roving tab stop (a descendant of each cell when
|
|
142
|
+
* `getFocusTarget` is provided, otherwise the cell itself).
|
|
143
|
+
*/
|
|
144
|
+
const getFocusTargets = useCallback(() => {
|
|
145
|
+
return getCells().filter(cell => cellFocusable(cell)).map(cell => resolveFocusTarget(cell)).filter(el => el !== null);
|
|
146
|
+
}, [getCells, cellFocusable, resolveFocusTarget]);
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Stamp the roving tab stop: exactly one focus target is tabbable (0), the
|
|
150
|
+
* rest are -1. Prefer keeping the currently-tabbable target if it is still
|
|
151
|
+
* focusable; otherwise promote the first focusable one (tab-stop repair).
|
|
152
|
+
*/
|
|
153
|
+
const syncTabStops = useCallback(() => {
|
|
154
|
+
const targets = getFocusTargets();
|
|
155
|
+
if (targets.length === 0) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const current = targets.find(el => el.getAttribute('tabindex') === '0');
|
|
159
|
+
const tabbable = current ?? targets[0];
|
|
160
|
+
for (const el of targets) {
|
|
161
|
+
setTabIndex(el, el === tabbable ? 0 : -1);
|
|
162
|
+
}
|
|
163
|
+
}, [getFocusTargets, setTabIndex]);
|
|
164
|
+
|
|
165
|
+
// Keep the tab stop valid across renders (cells added/removed, focusability
|
|
166
|
+
// toggled). Runs after every commit but only when roving tabindex is on.
|
|
167
|
+
useIsomorphicLayoutEffect(() => {
|
|
168
|
+
if (hasRovingTabIndex) {
|
|
169
|
+
syncTabStops();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Move the roving tab stop so `target` becomes the sole tabbable focus
|
|
175
|
+
* target, then focus it. No-op on tab stops unless roving tabindex is on.
|
|
176
|
+
*/
|
|
177
|
+
const focusTarget = useCallback(target => {
|
|
178
|
+
if (!target) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (hasRovingTabIndex) {
|
|
182
|
+
for (const el of getFocusTargets()) {
|
|
183
|
+
setTabIndex(el, el === target ? 0 : -1);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
target.focus();
|
|
187
|
+
}, [hasRovingTabIndex, getFocusTargets, setTabIndex]);
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Focus a cell by resolving and focusing its target, moving the roving tab
|
|
191
|
+
* stop when enabled.
|
|
192
|
+
*/
|
|
193
|
+
const focusCellWithStop = useCallback(cell => {
|
|
194
|
+
const target = resolveFocusTarget(cell);
|
|
195
|
+
if (!target) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
focusTarget(target);
|
|
199
|
+
return true;
|
|
200
|
+
}, [resolveFocusTarget, focusTarget]);
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Keep the roving stop pointing at whatever ended up focused (e.g. a click
|
|
204
|
+
* or programmatic focus) so the next Tab behaves correctly. No-op unless
|
|
205
|
+
* roving tabindex is enabled.
|
|
206
|
+
*/
|
|
207
|
+
const handleFocus = useCallback(() => {
|
|
208
|
+
if (hasRovingTabIndex) {
|
|
209
|
+
syncTabStops();
|
|
210
|
+
}
|
|
211
|
+
}, [hasRovingTabIndex, syncTabStops]);
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get the currently focused cell index within the full cell set.
|
|
72
215
|
*/
|
|
73
216
|
const getCurrentIndex = useCallback(() => {
|
|
74
217
|
const cells = getCells();
|
|
@@ -77,27 +220,25 @@ export function useGridFocus(options) {
|
|
|
77
220
|
}, [getCells]);
|
|
78
221
|
|
|
79
222
|
/**
|
|
80
|
-
*
|
|
81
|
-
* Returns
|
|
223
|
+
* Find the next focusable cell starting at `startIndex`, moving by `step`.
|
|
224
|
+
* Returns the index of the focusable cell, or -1 if none exists in range
|
|
225
|
+
* (i.e. we ran off the start/end of the grid).
|
|
82
226
|
*/
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return;
|
|
227
|
+
const findFocusableInDirection = useCallback((cells, startIndex, step) => {
|
|
228
|
+
let index = startIndex;
|
|
229
|
+
while (index >= 0 && index < cells.length) {
|
|
230
|
+
if (cellFocusable(cells[index])) {
|
|
231
|
+
return index;
|
|
232
|
+
}
|
|
233
|
+
index += step;
|
|
91
234
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
cells[index]?.focus();
|
|
97
|
-
}, [getCells, onNavigateBefore, onNavigateAfter]);
|
|
235
|
+
return -1;
|
|
236
|
+
}, [cellFocusable]);
|
|
98
237
|
|
|
99
238
|
/**
|
|
100
|
-
*
|
|
239
|
+
* Focus a cell by index, clamping to valid range. Skips non-focusable cells
|
|
240
|
+
* toward the nearest edge. Used by public focus helpers (no navigation
|
|
241
|
+
* callbacks).
|
|
101
242
|
*/
|
|
102
243
|
const focusCell = useCallback(index => {
|
|
103
244
|
const cells = getCells();
|
|
@@ -105,86 +246,143 @@ export function useGridFocus(options) {
|
|
|
105
246
|
return;
|
|
106
247
|
}
|
|
107
248
|
const clampedIndex = Math.max(0, Math.min(index, cells.length - 1));
|
|
108
|
-
|
|
109
|
-
|
|
249
|
+
// Prefer the requested cell; otherwise search forward, then backward.
|
|
250
|
+
let target = findFocusableInDirection(cells, clampedIndex, 1);
|
|
251
|
+
if (target === -1) {
|
|
252
|
+
target = findFocusableInDirection(cells, clampedIndex, -1);
|
|
253
|
+
}
|
|
254
|
+
if (target !== -1) {
|
|
255
|
+
focusCellWithStop(cells[target]);
|
|
256
|
+
}
|
|
257
|
+
}, [getCells, findFocusableInDirection, focusCellWithStop]);
|
|
110
258
|
|
|
111
259
|
/**
|
|
112
|
-
* Focus the first cell.
|
|
260
|
+
* Focus the first focusable cell.
|
|
113
261
|
*/
|
|
114
262
|
const focusFirst = useCallback(() => {
|
|
115
263
|
const cells = getCells();
|
|
116
|
-
cells
|
|
117
|
-
|
|
264
|
+
const index = findFocusableInDirection(cells, 0, 1);
|
|
265
|
+
if (index !== -1) {
|
|
266
|
+
focusCellWithStop(cells[index]);
|
|
267
|
+
}
|
|
268
|
+
}, [getCells, findFocusableInDirection, focusCellWithStop]);
|
|
118
269
|
|
|
119
270
|
/**
|
|
120
|
-
* Focus the last cell.
|
|
271
|
+
* Focus the last focusable cell.
|
|
121
272
|
*/
|
|
122
273
|
const focusLast = useCallback(() => {
|
|
123
274
|
const cells = getCells();
|
|
124
|
-
cells
|
|
125
|
-
|
|
275
|
+
const index = findFocusableInDirection(cells, cells.length - 1, -1);
|
|
276
|
+
if (index !== -1) {
|
|
277
|
+
focusCellWithStop(cells[index]);
|
|
278
|
+
}
|
|
279
|
+
}, [getCells, findFocusableInDirection, focusCellWithStop]);
|
|
126
280
|
|
|
127
281
|
/**
|
|
128
282
|
* Handle keyboard navigation.
|
|
129
283
|
*/
|
|
130
284
|
const handleKeyDown = useCallback(e => {
|
|
285
|
+
const cells = getCells();
|
|
286
|
+
if (cells.length === 0) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
131
289
|
const currentIndex = getCurrentIndex();
|
|
132
290
|
if (currentIndex === -1) {
|
|
133
291
|
return;
|
|
134
292
|
}
|
|
135
|
-
const cells = getCells();
|
|
136
293
|
const currentRow = Math.floor(currentIndex / columns);
|
|
137
294
|
const currentCol = currentIndex % columns;
|
|
138
295
|
const totalRows = Math.ceil(cells.length / columns);
|
|
139
296
|
let handled = true;
|
|
140
|
-
|
|
297
|
+
|
|
298
|
+
// In RTL, ArrowLeft/ArrowRight are swapped so horizontal navigation
|
|
299
|
+
// follows visual direction. Vertical keys (Up/Down) are unaffected.
|
|
300
|
+
let key = e.key;
|
|
301
|
+
if (isRtl) {
|
|
302
|
+
if (key === 'ArrowLeft') {
|
|
303
|
+
key = 'ArrowRight';
|
|
304
|
+
} else if (key === 'ArrowRight') {
|
|
305
|
+
key = 'ArrowLeft';
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
switch (key) {
|
|
141
309
|
case 'ArrowRight':
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
310
|
+
{
|
|
311
|
+
// Move right, skipping non-focusable cells in the same direction.
|
|
312
|
+
const target = findFocusableInDirection(cells, currentIndex + 1, 1);
|
|
313
|
+
if (target !== -1) {
|
|
314
|
+
focusCellWithStop(cells[target]);
|
|
315
|
+
} else {
|
|
316
|
+
onNavigateAfter?.((currentCol + 1) % columns, 1);
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
145
320
|
case 'ArrowLeft':
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
321
|
+
{
|
|
322
|
+
const target = findFocusableInDirection(cells, currentIndex - 1, -1);
|
|
323
|
+
if (target !== -1) {
|
|
324
|
+
focusCellWithStop(cells[target]);
|
|
325
|
+
} else {
|
|
326
|
+
onNavigateBefore?.(currentCol === 0 ? columns - 1 : currentCol - 1, 1);
|
|
327
|
+
}
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
149
330
|
case 'ArrowDown':
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
331
|
+
{
|
|
332
|
+
if (currentRow < totalRows - 1) {
|
|
333
|
+
// Move to the same column one row down, then continue downward
|
|
334
|
+
// (by whole rows) to the next focusable cell in that column.
|
|
335
|
+
const target = findFocusableInDirection(cells, currentIndex + columns, columns);
|
|
336
|
+
if (target !== -1) {
|
|
337
|
+
focusCellWithStop(cells[target]);
|
|
338
|
+
} else {
|
|
339
|
+
onNavigateAfter?.(currentCol, columns);
|
|
340
|
+
}
|
|
155
341
|
} else {
|
|
156
|
-
|
|
157
|
-
focusCellInternal(cells.length - 1, currentCol, columns);
|
|
342
|
+
onNavigateAfter?.(currentCol, columns);
|
|
158
343
|
}
|
|
159
|
-
|
|
160
|
-
onNavigateAfter?.(currentCol, columns);
|
|
344
|
+
break;
|
|
161
345
|
}
|
|
162
|
-
break;
|
|
163
346
|
case 'ArrowUp':
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
347
|
+
{
|
|
348
|
+
if (currentRow > 0) {
|
|
349
|
+
const target = findFocusableInDirection(cells, currentIndex - columns, -columns);
|
|
350
|
+
if (target !== -1) {
|
|
351
|
+
focusCellWithStop(cells[target]);
|
|
352
|
+
} else {
|
|
353
|
+
onNavigateBefore?.(currentCol, columns);
|
|
354
|
+
}
|
|
355
|
+
} else {
|
|
356
|
+
onNavigateBefore?.(currentCol, columns);
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
169
359
|
}
|
|
170
|
-
break;
|
|
171
360
|
case 'Home':
|
|
172
361
|
if (e.ctrlKey || e.metaKey) {
|
|
173
|
-
// Ctrl+Home: first cell in grid
|
|
362
|
+
// Ctrl+Home: first focusable cell in grid
|
|
174
363
|
focusFirst();
|
|
175
364
|
} else {
|
|
176
|
-
// Home: first cell in current row
|
|
177
|
-
|
|
365
|
+
// Home: first focusable cell in current row (searching rightward)
|
|
366
|
+
const rowStart = currentRow * columns;
|
|
367
|
+
const rowEnd = Math.min(rowStart + columns - 1, cells.length - 1);
|
|
368
|
+
const target = findFocusableInDirection(cells, rowStart, 1);
|
|
369
|
+
if (target !== -1 && target <= rowEnd) {
|
|
370
|
+
focusCellWithStop(cells[target]);
|
|
371
|
+
}
|
|
178
372
|
}
|
|
179
373
|
break;
|
|
180
374
|
case 'End':
|
|
181
375
|
if (e.ctrlKey || e.metaKey) {
|
|
182
|
-
// Ctrl+End: last cell in grid
|
|
376
|
+
// Ctrl+End: last focusable cell in grid
|
|
183
377
|
focusLast();
|
|
184
378
|
} else {
|
|
185
|
-
// End: last cell in current row
|
|
186
|
-
const
|
|
187
|
-
|
|
379
|
+
// End: last focusable cell in current row (searching leftward)
|
|
380
|
+
const rowStart = currentRow * columns;
|
|
381
|
+
const rowEnd = Math.min(rowStart + columns - 1, cells.length - 1);
|
|
382
|
+
const target = findFocusableInDirection(cells, rowEnd, -1);
|
|
383
|
+
if (target !== -1 && target >= rowStart) {
|
|
384
|
+
focusCellWithStop(cells[target]);
|
|
385
|
+
}
|
|
188
386
|
}
|
|
189
387
|
break;
|
|
190
388
|
case 'PageUp':
|
|
@@ -200,10 +398,11 @@ export function useGridFocus(options) {
|
|
|
200
398
|
e.preventDefault();
|
|
201
399
|
e.stopPropagation();
|
|
202
400
|
}
|
|
203
|
-
}, [columns,
|
|
401
|
+
}, [columns, findFocusableInDirection, focusCellWithStop, focusFirst, focusLast, getCells, getCurrentIndex, isRtl, onNavigateAfter, onNavigateBefore, onPageDown, onPageUp]);
|
|
204
402
|
return {
|
|
205
403
|
gridRef,
|
|
206
404
|
handleKeyDown,
|
|
405
|
+
handleFocus,
|
|
207
406
|
focusCell,
|
|
208
407
|
focusFirst,
|
|
209
408
|
focusLast
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file useKeyboardHint.tsx
|
|
3
|
+
* @input Uses React, StyleX, Kbd, useLayer
|
|
4
|
+
* @output Exports useKeyboardHint hook — ephemeral arrow-key navigation hint
|
|
5
|
+
* @position Core hook; shows sighted keyboard users how to navigate composite
|
|
6
|
+
* widgets that use roving tabindex (single Tab stop, arrows inside)
|
|
7
|
+
*
|
|
8
|
+
* SYNC: When modified, update:
|
|
9
|
+
* - /packages/core/src/hooks/index.ts
|
|
10
|
+
* - /packages/core/src/hooks/useKeyboardHint.doc.mjs
|
|
11
|
+
* - /apps/storybook/stories/useKeyboardHint.stories.tsx
|
|
12
|
+
* - /packages/cli/templates/blocks/components/Hooks/useKeyboardHintHookUsage.tsx
|
|
13
|
+
*/
|
|
14
|
+
import React, { type ReactNode } from 'react';
|
|
15
|
+
export type KeyboardHintOrientation = 'horizontal' | 'vertical' | 'both';
|
|
16
|
+
export interface UseKeyboardHintOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Orientation of the arrow-key navigation. Controls which arrow icons are
|
|
19
|
+
* shown in the hint badge.
|
|
20
|
+
* - `'horizontal'` → ← →
|
|
21
|
+
* - `'vertical'` → ↑ ↓
|
|
22
|
+
* - `'both'` → ← → ↑ ↓
|
|
23
|
+
* @default 'horizontal'
|
|
24
|
+
*/
|
|
25
|
+
orientation?: KeyboardHintOrientation;
|
|
26
|
+
/**
|
|
27
|
+
* Milliseconds before the hint auto-dismisses after appearing.
|
|
28
|
+
* @default 3000
|
|
29
|
+
*/
|
|
30
|
+
dismissAfterMs?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the hint is enabled. Set to false to disable for a specific
|
|
33
|
+
* instance (e.g. when the widget is read-only or the user has dismissed
|
|
34
|
+
* globally).
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
isEnabled?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface UseKeyboardHintReturn {
|
|
40
|
+
/**
|
|
41
|
+
* The popover hint element to render inside your component tree (portals to
|
|
42
|
+
* top layer via `popover="manual"`). Render unconditionally — it manages its
|
|
43
|
+
* own visibility.
|
|
44
|
+
*/
|
|
45
|
+
hintElement: ReactNode;
|
|
46
|
+
/**
|
|
47
|
+
* Attach to the composite container's `onFocus`. Shows the hint on the first
|
|
48
|
+
* keyboard-focus (`:focus-visible`) entry from outside.
|
|
49
|
+
*/
|
|
50
|
+
onFocus: (e: React.FocusEvent) => void;
|
|
51
|
+
/**
|
|
52
|
+
* Attach to the composite container's `onBlur`. Hides the hint when focus
|
|
53
|
+
* leaves the composite entirely.
|
|
54
|
+
*/
|
|
55
|
+
onBlur: (e: React.FocusEvent) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Attach to the composite container's `onKeyDown`. Dismisses the hint on the
|
|
58
|
+
* first arrow press (the user discovered the interaction).
|
|
59
|
+
*/
|
|
60
|
+
onKeyDown: (e: React.KeyboardEvent) => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Shows an ephemeral visual hint ("← → to navigate") anchored to the focused
|
|
64
|
+
* item when a composite widget first receives keyboard focus. Teaches sighted
|
|
65
|
+
* keyboard users that arrows navigate within the group.
|
|
66
|
+
*
|
|
67
|
+
* The hint renders in the top layer (popover="manual") and is CSS-anchor-
|
|
68
|
+
* positioned to the currently focused element, so it is never clipped by
|
|
69
|
+
* overflow containers. It auto-dismisses on first arrow press, timeout, or
|
|
70
|
+
* blur, and does not re-show for that instance.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```
|
|
74
|
+
* const hint = useKeyboardHint({orientation: 'horizontal'});
|
|
75
|
+
* <div role="toolbar" onFocus={hint.onFocus} onBlur={hint.onBlur} onKeyDown={hint.onKeyDown}>
|
|
76
|
+
* {children}
|
|
77
|
+
* {hint.hintElement}
|
|
78
|
+
* </div>
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function useKeyboardHint(options?: UseKeyboardHintOptions): UseKeyboardHintReturn;
|
|
82
|
+
//# sourceMappingURL=useKeyboardHint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeyboardHint.d.ts","sourceRoot":"","sources":["../../src/hooks/useKeyboardHint.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAAiC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAgB5E,MAAM,MAAM,uBAAuB,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,uBAAuB,CAAC;IAEtC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,WAAW,EAAE,SAAS,CAAC;IAEvB;;;OAGG;IACH,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAEvC;;;OAGG;IACH,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAEtC;;;OAGG;IACH,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;CAC7C;AAkED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CA6JvB"}
|