@astryxdesign/core 0.1.1 → 0.1.2-canary.04e71b2
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 +105 -0
- package/README.md +131 -13
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
- package/dist/Banner/Banner.d.ts +7 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +9 -2
- 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 +12 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +53 -17
- 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/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.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -1
- 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/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +49 -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 +59 -8
- 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/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +7 -1
- 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 +8 -0
- package/dist/HoverCard/HoverCard.d.ts +2 -2
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +18 -6
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -3
- package/dist/InputGroup/InputGroup.d.ts +2 -2
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +14 -5
- 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/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 +34 -2
- package/dist/Layer/anchorName.d.ts +20 -0
- package/dist/Layer/anchorName.d.ts.map +1 -0
- package/dist/Layer/anchorName.js +36 -0
- 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 +29 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +55 -11
- 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 +17 -2
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +20 -9
- package/dist/Link/LinkProvider.d.ts +1 -0
- package/dist/Link/LinkProvider.d.ts.map +1 -1
- package/dist/Link/LinkProvider.js +1 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +18 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +13 -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 +25 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +103 -22
- 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 +46 -28
- package/dist/Popover/usePopover.d.ts +25 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +18 -6
- 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 +22 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +84 -23
- 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/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 +38 -11
- 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 +86 -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 +38 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +36 -7
- 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/TableRow.d.ts +6 -1
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +15 -7
- package/dist/Table/index.d.ts +4 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +3 -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/plugins/stickyColumns/index.d.ts +3 -0
- package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/index.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +369 -0
- 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 +161 -5
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +1 -1
- package/dist/Text/text.stylex.d.ts +2 -2
- package/dist/Text/text.stylex.js +2 -2
- 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 +53 -10
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +28 -3
- 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 +132 -3
- package/dist/ToggleButton/ToggleButton.d.ts +7 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +34 -57
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +27 -5
- 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 +57 -9
- 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 +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +67 -6
- package/dist/Typeahead/Typeahead.d.ts +24 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +29 -5
- 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 +40 -1
- package/dist/astryx.umd.js +147 -0
- package/dist/astryx.umd.js.map +7 -0
- 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/theme/generateThemeRules.js +1 -1
- package/dist/theme/syntax/SyntaxTheme.d.ts +1 -1
- package/dist/theme/syntax/SyntaxTheme.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -2
- package/dist/theme/syntax/presets.d.ts +1 -1
- package/dist/theme/syntax/presets.d.ts.map +1 -1
- package/dist/theme/syntax/presets.js +1 -1
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.js +1 -1
- package/dist/theme/types.d.ts +1 -1
- 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/package.json +15 -5
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +16 -7
- package/src/Banner/Banner.tsx +9 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.doc.mjs +6 -0
- package/src/Button/Button.test.tsx +105 -11
- package/src/Button/Button.tsx +76 -21
- 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/ChatComposer.doc.mjs +3 -0
- package/src/Chat/ChatComposerDrawer.doc.mjs +12 -0
- 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 +3 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -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 +169 -16
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +117 -0
- package/src/Citation/Citation.tsx +9 -1
- package/src/ClickableCard/ClickableCard.doc.mjs +15 -0
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +61 -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 +281 -56
- package/src/DateInput/DateInput.test.tsx +188 -2
- package/src/DateInput/DateInput.tsx +89 -10
- 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/EmptyState/EmptyState.test.tsx +4 -2
- package/src/EmptyState/EmptyState.tsx +6 -2
- 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 +14 -4
- package/src/Grid/Grid.tsx +20 -0
- package/src/HoverCard/HoverCard.doc.mjs +3 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -2
- package/src/HoverCard/HoverCard.tsx +20 -16
- package/src/HoverCard/useHoverCard.tsx +13 -10
- package/src/Icon/Icon.doc.mjs +8 -0
- package/src/InputGroup/InputGroup.doc.mjs +2 -2
- package/src/InputGroup/InputGroup.test.tsx +98 -60
- package/src/InputGroup/InputGroup.tsx +21 -4
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +37 -12
- package/src/Layer/anchorName.test.ts +146 -0
- package/src/Layer/anchorName.ts +46 -0
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +12 -2
- package/src/Layer/useLayer.tsx +100 -15
- package/src/Layout/Layout.doc.mjs +1 -1
- 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 -2
- 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 +52 -2
- package/src/Link/Link.tsx +42 -7
- package/src/Link/LinkProvider.tsx +1 -0
- package/src/List/List.doc.mjs +7 -0
- package/src/Markdown/Markdown.doc.mjs +2 -0
- package/src/Markdown/Markdown.test.tsx +28 -26
- package/src/Markdown/Markdown.tsx +21 -6
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MobileNav/MobileNav.doc.mjs +8 -8
- package/src/MobileNav/MobileNav.tsx +13 -0
- package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +25 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +145 -21
- 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/OverflowList/OverflowList.doc.mjs +17 -0
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +250 -14
- package/src/Pagination/Pagination.tsx +54 -29
- package/src/Popover/usePopover.doc.mjs +7 -3
- package/src/Popover/usePopover.tsx +49 -6
- 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 +45 -27
- 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/Resizable/Resizable.doc.mjs +1 -1
- package/src/Section/Section.doc.mjs +11 -0
- 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 +15 -0
- package/src/Selector/Selector.doc.mjs +25 -0
- package/src/Selector/Selector.test.tsx +322 -15
- package/src/Selector/Selector.tsx +126 -40
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +16 -0
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.doc.mjs +11 -1
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +19 -0
- package/src/Slider/Slider.test.tsx +158 -18
- package/src/Slider/Slider.tsx +54 -6
- 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 +12 -0
- package/src/TabList/TabList.test.tsx +208 -0
- package/src/TabList/TabList.tsx +102 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +72 -41
- package/src/Table/Table.doc.mjs +14 -0
- package/src/Table/Table.test.tsx +39 -30
- package/src/Table/Table.tsx +27 -1
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/TableRow.tsx +37 -7
- package/src/Table/index.ts +6 -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/plugins/stickyColumns/index.ts +4 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +407 -0
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +175 -4
- package/src/Table/useBaseTablePlugins.ts +1 -0
- package/src/Table/useTableColumnResize.doc.mjs +96 -0
- package/src/Table/useTableStickyColumns.doc.mjs +59 -0
- package/src/Text/Heading.doc.mjs +15 -2
- package/src/Text/Text.doc.mjs +7 -1
- package/src/Text/text.stylex.ts +2 -2
- 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/TimeInput/TimeInput.doc.mjs +335 -60
- package/src/TimeInput/TimeInput.test.tsx +144 -7
- package/src/TimeInput/TimeInput.tsx +74 -5
- package/src/Timestamp/Timestamp.doc.mjs +9 -0
- package/src/Timestamp/Timestamp.test.tsx +44 -18
- package/src/Timestamp/Timestamp.tsx +30 -10
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +204 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/ToggleButton/ToggleButton.doc.mjs +9 -3
- package/src/ToggleButton/ToggleButton.test.tsx +39 -18
- package/src/ToggleButton/ToggleButton.tsx +46 -83
- package/src/Tokenizer/Tokenizer.doc.mjs +15 -0
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +41 -2
- package/src/Toolbar/Toolbar.doc.mjs +65 -5
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +81 -0
- package/src/Tooltip/useTooltip.tsx +57 -11
- 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 +86 -9
- package/src/Typeahead/Typeahead.doc.mjs +136 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +52 -1
- 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/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/useImageMode.test.ts +133 -0
- 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 +4 -0
- package/src/theme/generateThemeRules.test.ts +7 -8
- package/src/theme/generateThemeRules.ts +1 -1
- package/src/theme/syntax/SyntaxTheme.tsx +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +20 -11
- package/src/theme/syntax/presets.ts +5 -2
- package/src/theme/syntax/tokens.ts +1 -1
- package/src/theme/types.ts +1 -1
- 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
|
@@ -37,6 +37,13 @@ import {
|
|
|
37
37
|
typeScaleVars,
|
|
38
38
|
} from '../theme/tokens.stylex';
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Grace period (ms) before hiding on pointer-leave when no explicit `hideDelay`
|
|
42
|
+
* is set, so the pointer can travel across the small gap from the trigger onto
|
|
43
|
+
* the tooltip surface without the tooltip disappearing (WCAG 1.4.13 hoverable).
|
|
44
|
+
*/
|
|
45
|
+
const HOVER_BRIDGE_DELAY = 100;
|
|
46
|
+
|
|
40
47
|
const styles = stylex.create({
|
|
41
48
|
// Base container styles - inverted colors for high contrast
|
|
42
49
|
container: {
|
|
@@ -233,9 +240,7 @@ function isFocusable(element: HTMLElement): boolean {
|
|
|
233
240
|
* {tooltip.renderTooltip('Helpful tooltip text')}
|
|
234
241
|
* ```
|
|
235
242
|
*/
|
|
236
|
-
export function useTooltip(
|
|
237
|
-
options: TooltipOptions = {},
|
|
238
|
-
): TooltipReturn {
|
|
243
|
+
export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
|
|
239
244
|
const {
|
|
240
245
|
placement = 'above',
|
|
241
246
|
alignment = 'center',
|
|
@@ -293,21 +298,29 @@ export function useTooltip(
|
|
|
293
298
|
}, delay);
|
|
294
299
|
}, [isEnabled, isOpen, clearTimeouts, layer, delay]);
|
|
295
300
|
|
|
296
|
-
// Schedule hide with delay (suppressed when isOpen is true)
|
|
301
|
+
// Schedule hide with delay (suppressed when isOpen is true).
|
|
302
|
+
// A small hover bridge (when hideDelay is 0) lets the pointer travel from the
|
|
303
|
+
// trigger onto the tooltip surface without the tooltip vanishing — required
|
|
304
|
+
// for WCAG 1.4.13 (Content on Hover or Focus: hoverable).
|
|
297
305
|
const scheduleHide = useCallback(() => {
|
|
298
306
|
if (isOpen === true) {
|
|
299
307
|
return;
|
|
300
308
|
}
|
|
301
309
|
clearTimeouts();
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
layer.hide();
|
|
305
|
-
}, hideDelay);
|
|
306
|
-
} else {
|
|
310
|
+
const effectiveHideDelay = hideDelay > 0 ? hideDelay : HOVER_BRIDGE_DELAY;
|
|
311
|
+
hideTimeoutRef.current = setTimeout(() => {
|
|
307
312
|
layer.hide();
|
|
308
|
-
}
|
|
313
|
+
}, effectiveHideDelay);
|
|
309
314
|
}, [isOpen, clearTimeouts, layer, hideDelay]);
|
|
310
315
|
|
|
316
|
+
// Cancel a pending hide (e.g. the pointer entered the tooltip surface).
|
|
317
|
+
const cancelHide = useCallback(() => {
|
|
318
|
+
if (hideTimeoutRef.current) {
|
|
319
|
+
clearTimeout(hideTimeoutRef.current);
|
|
320
|
+
hideTimeoutRef.current = null;
|
|
321
|
+
}
|
|
322
|
+
}, []);
|
|
323
|
+
|
|
311
324
|
// Event handlers
|
|
312
325
|
const handleMouseEnter = useCallback(() => {
|
|
313
326
|
// Suppress tooltips on touch devices — hover is simulated and eats a tap
|
|
@@ -422,6 +435,32 @@ export function useTooltip(
|
|
|
422
435
|
}
|
|
423
436
|
}, [isOpen, clearTimeouts, layer]);
|
|
424
437
|
|
|
438
|
+
// Dismiss on Escape (WCAG 1.4.13 — dismissible). Uncontrolled tooltips only;
|
|
439
|
+
// a controlled tooltip's visibility is owned by the consumer. The listener is
|
|
440
|
+
// mounted for the lifetime of an uncontrolled tooltip rather than gated on
|
|
441
|
+
// `layer.isOpen` (React state, which can lag a frame behind the DOM) —
|
|
442
|
+
// `layer.hide()` self-guards and no-ops when the layer is already closed.
|
|
443
|
+
// Guarded against IME composition-cancel.
|
|
444
|
+
useEffect(() => {
|
|
445
|
+
if (isOpen !== undefined) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
449
|
+
if (e.key !== 'Escape') {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
if (e.isComposing || e.keyCode === 229) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
clearTimeouts();
|
|
456
|
+
layer.hide();
|
|
457
|
+
};
|
|
458
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
459
|
+
return () => {
|
|
460
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
461
|
+
};
|
|
462
|
+
}, [isOpen, layer, clearTimeouts]);
|
|
463
|
+
|
|
425
464
|
// Render function that wraps layer.render with tooltip styling
|
|
426
465
|
const renderTooltip = useCallback(
|
|
427
466
|
(children: ReactNode, props?: ContextRenderProps): ReactNode => {
|
|
@@ -429,8 +468,15 @@ export function useTooltip(
|
|
|
429
468
|
const renderProps = {
|
|
430
469
|
placement: renderPlacement,
|
|
431
470
|
alignment: props?.alignment ?? alignment,
|
|
471
|
+
role: 'tooltip',
|
|
432
472
|
xstyle: [popoverXstyle, layerAnimations[renderPlacement]],
|
|
433
473
|
className: themeProps('tooltip').className,
|
|
474
|
+
// Keep the tooltip open while the pointer is over the surface itself
|
|
475
|
+
// (WCAG 1.4.13 hoverable). These sit on the layer container — the
|
|
476
|
+
// element the user actually hovers — not the inner content div, since
|
|
477
|
+
// mouseenter/leave do not bubble.
|
|
478
|
+
onMouseEnter: cancelHide,
|
|
479
|
+
onMouseLeave: scheduleHide,
|
|
434
480
|
};
|
|
435
481
|
|
|
436
482
|
return layer.render(
|
|
@@ -438,7 +484,7 @@ export function useTooltip(
|
|
|
438
484
|
renderProps,
|
|
439
485
|
);
|
|
440
486
|
},
|
|
441
|
-
[layer, placement, alignment, popoverXstyle],
|
|
487
|
+
[layer, placement, alignment, popoverXstyle, cancelHide, scheduleHide],
|
|
442
488
|
);
|
|
443
489
|
|
|
444
490
|
return {
|
|
@@ -61,6 +61,44 @@ const deepItems: TreeListItemData[] = [
|
|
|
61
61
|
},
|
|
62
62
|
];
|
|
63
63
|
|
|
64
|
+
// APG keyboard fixtures (module-level to satisfy no-unstable-default-props).
|
|
65
|
+
const flatItems: TreeListItemData[] = [
|
|
66
|
+
{id: 'a', label: 'Apple'},
|
|
67
|
+
{id: 'b', label: 'Banana'},
|
|
68
|
+
{id: 'c', label: 'Cherry'},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const withDisabledItems: TreeListItemData[] = [
|
|
72
|
+
{id: 'a', label: 'Apple'},
|
|
73
|
+
{id: 'b', label: 'Banana', isDisabled: true},
|
|
74
|
+
{id: 'c', label: 'Cherry'},
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
const collapsedParentItems: TreeListItemData[] = [
|
|
78
|
+
{
|
|
79
|
+
id: 'parent',
|
|
80
|
+
label: 'Parent',
|
|
81
|
+
children: [
|
|
82
|
+
{id: 'child-1', label: 'Child 1'},
|
|
83
|
+
{id: 'child-2', label: 'Child 2'},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
{id: 'sibling', label: 'Sibling'},
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
const expandedParentItems: TreeListItemData[] = [
|
|
90
|
+
{
|
|
91
|
+
id: 'parent',
|
|
92
|
+
label: 'Parent',
|
|
93
|
+
isExpanded: true,
|
|
94
|
+
children: [
|
|
95
|
+
{id: 'child-1', label: 'Child 1'},
|
|
96
|
+
{id: 'child-2', label: 'Child 2'},
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
{id: 'sibling', label: 'Sibling'},
|
|
100
|
+
];
|
|
101
|
+
|
|
64
102
|
describe('TreeList', () => {
|
|
65
103
|
// ===========================================================================
|
|
66
104
|
// Basic rendering
|
|
@@ -160,6 +198,26 @@ describe('TreeList', () => {
|
|
|
160
198
|
expect(item).not.toHaveAttribute('aria-expanded');
|
|
161
199
|
});
|
|
162
200
|
|
|
201
|
+
it('renders a keyboard-focusable toggle button for parents without onClick/href', () => {
|
|
202
|
+
render(<TreeList items={nestedItems} />);
|
|
203
|
+
const toggle = screen.getByRole('button', {name: 'Toggle children'});
|
|
204
|
+
expect(toggle).toBeInTheDocument();
|
|
205
|
+
expect(toggle).toHaveAttribute('aria-expanded', 'false');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('expands a parent from the keyboard via the toggle button', async () => {
|
|
209
|
+
const user = userEvent.setup();
|
|
210
|
+
render(<TreeList items={nestedItems} />);
|
|
211
|
+
// Collapsed: children are not rendered.
|
|
212
|
+
expect(screen.queryByText('Child 1')).not.toBeInTheDocument();
|
|
213
|
+
const toggle = screen.getByRole('button', {name: 'Toggle children'});
|
|
214
|
+
toggle.focus();
|
|
215
|
+
expect(toggle).toHaveFocus();
|
|
216
|
+
await user.keyboard('{Enter}');
|
|
217
|
+
expect(screen.getByText('Child 1')).toBeInTheDocument();
|
|
218
|
+
expect(toggle).toHaveAttribute('aria-expanded', 'true');
|
|
219
|
+
});
|
|
220
|
+
|
|
163
221
|
it('renders group role for nested children', () => {
|
|
164
222
|
render(<TreeList items={nestedItemsExpanded} />);
|
|
165
223
|
const groups = document.querySelectorAll('[role="group"]');
|
|
@@ -210,18 +268,14 @@ describe('TreeList', () => {
|
|
|
210
268
|
it('fires onClick when invisible button is clicked', async () => {
|
|
211
269
|
const user = userEvent.setup();
|
|
212
270
|
const onClick = vi.fn();
|
|
213
|
-
const items: TreeListItemData[] = [
|
|
214
|
-
{id: 'a', label: 'Clickable', onClick},
|
|
215
|
-
];
|
|
271
|
+
const items: TreeListItemData[] = [{id: 'a', label: 'Clickable', onClick}];
|
|
216
272
|
render(<TreeList items={items} />);
|
|
217
273
|
await user.click(screen.getByRole('button'));
|
|
218
274
|
expect(onClick).toHaveBeenCalledTimes(1);
|
|
219
275
|
});
|
|
220
276
|
|
|
221
277
|
it('renders an invisible anchor when href is provided', () => {
|
|
222
|
-
const items: TreeListItemData[] = [
|
|
223
|
-
{id: 'a', label: 'Link', href: '/docs'},
|
|
224
|
-
];
|
|
278
|
+
const items: TreeListItemData[] = [{id: 'a', label: 'Link', href: '/docs'}];
|
|
225
279
|
const {container} = render(<TreeList items={items} />);
|
|
226
280
|
const anchor = container.querySelector('a');
|
|
227
281
|
expect(anchor).toBeInTheDocument();
|
|
@@ -317,4 +371,239 @@ describe('TreeList', () => {
|
|
|
317
371
|
const root = screen.getByTestId('tree');
|
|
318
372
|
expect(root.className).toContain('astryx-tree-list');
|
|
319
373
|
});
|
|
374
|
+
|
|
375
|
+
// ===========================================================================
|
|
376
|
+
// APG structural ARIA (aria-level / aria-posinset / aria-setsize)
|
|
377
|
+
// ===========================================================================
|
|
378
|
+
|
|
379
|
+
it('sets aria-level, aria-posinset, and aria-setsize at the top level', () => {
|
|
380
|
+
render(<TreeList items={flatItems} />);
|
|
381
|
+
const apple = screen.getByText('Apple').closest('li');
|
|
382
|
+
expect(apple).toHaveAttribute('aria-level', '1');
|
|
383
|
+
expect(apple).toHaveAttribute('aria-posinset', '1');
|
|
384
|
+
expect(apple).toHaveAttribute('aria-setsize', '3');
|
|
385
|
+
|
|
386
|
+
const cherry = screen.getByText('Cherry').closest('li');
|
|
387
|
+
expect(cherry).toHaveAttribute('aria-posinset', '3');
|
|
388
|
+
expect(cherry).toHaveAttribute('aria-setsize', '3');
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('sets aria-level/posinset/setsize correctly at deeper levels', () => {
|
|
392
|
+
render(<TreeList items={expandedParentItems} />);
|
|
393
|
+
const parent = screen.getByText('Parent').closest('li');
|
|
394
|
+
expect(parent).toHaveAttribute('aria-level', '1');
|
|
395
|
+
expect(parent).toHaveAttribute('aria-setsize', '2');
|
|
396
|
+
|
|
397
|
+
const child1 = screen.getByText('Child 1').closest('li');
|
|
398
|
+
expect(child1).toHaveAttribute('aria-level', '2');
|
|
399
|
+
expect(child1).toHaveAttribute('aria-posinset', '1');
|
|
400
|
+
expect(child1).toHaveAttribute('aria-setsize', '2');
|
|
401
|
+
|
|
402
|
+
const child2 = screen.getByText('Child 2').closest('li');
|
|
403
|
+
expect(child2).toHaveAttribute('aria-level', '2');
|
|
404
|
+
expect(child2).toHaveAttribute('aria-posinset', '2');
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('sets aria-level across three depths', () => {
|
|
408
|
+
render(<TreeList items={deepItems} />);
|
|
409
|
+
expect(screen.getByText('Root').closest('li')).toHaveAttribute(
|
|
410
|
+
'aria-level',
|
|
411
|
+
'1',
|
|
412
|
+
);
|
|
413
|
+
expect(screen.getByText('Mid').closest('li')).toHaveAttribute(
|
|
414
|
+
'aria-level',
|
|
415
|
+
'2',
|
|
416
|
+
);
|
|
417
|
+
expect(screen.getByText('Leaf').closest('li')).toHaveAttribute(
|
|
418
|
+
'aria-level',
|
|
419
|
+
'3',
|
|
420
|
+
);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// ===========================================================================
|
|
424
|
+
// Roving tabindex
|
|
425
|
+
// ===========================================================================
|
|
426
|
+
|
|
427
|
+
it('makes exactly one treeitem tabbable by default (the first enabled)', () => {
|
|
428
|
+
render(<TreeList items={flatItems} />);
|
|
429
|
+
const treeitems = screen.getAllByRole('treeitem');
|
|
430
|
+
const tabbable = treeitems.filter(
|
|
431
|
+
el => el.getAttribute('tabindex') === '0',
|
|
432
|
+
);
|
|
433
|
+
expect(tabbable).toHaveLength(1);
|
|
434
|
+
expect(tabbable[0]).toBe(screen.getByText('Apple').closest('li'));
|
|
435
|
+
expect(screen.getByText('Banana').closest('li')).toHaveAttribute(
|
|
436
|
+
'tabindex',
|
|
437
|
+
'-1',
|
|
438
|
+
);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('defaults the tab stop to the selected item when one is selected', () => {
|
|
442
|
+
const items: TreeListItemData[] = [
|
|
443
|
+
{id: 'a', label: 'Apple'},
|
|
444
|
+
{id: 'b', label: 'Banana', isSelected: true},
|
|
445
|
+
{id: 'c', label: 'Cherry'},
|
|
446
|
+
];
|
|
447
|
+
render(<TreeList items={items} />);
|
|
448
|
+
expect(screen.getByText('Banana').closest('li')).toHaveAttribute(
|
|
449
|
+
'tabindex',
|
|
450
|
+
'0',
|
|
451
|
+
);
|
|
452
|
+
expect(screen.getByText('Apple').closest('li')).toHaveAttribute(
|
|
453
|
+
'tabindex',
|
|
454
|
+
'-1',
|
|
455
|
+
);
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
it('moves the single tab stop when focus moves via keyboard', async () => {
|
|
459
|
+
const user = userEvent.setup();
|
|
460
|
+
render(<TreeList items={flatItems} />);
|
|
461
|
+
const apple = screen.getByText('Apple').closest('li')!;
|
|
462
|
+
apple.focus();
|
|
463
|
+
await user.keyboard('{ArrowDown}');
|
|
464
|
+
const treeitems = screen.getAllByRole('treeitem');
|
|
465
|
+
const tabbable = treeitems.filter(
|
|
466
|
+
el => el.getAttribute('tabindex') === '0',
|
|
467
|
+
);
|
|
468
|
+
expect(tabbable).toHaveLength(1);
|
|
469
|
+
expect(tabbable[0]).toBe(screen.getByText('Banana').closest('li'));
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// ===========================================================================
|
|
473
|
+
// APG keyboard navigation
|
|
474
|
+
// ===========================================================================
|
|
475
|
+
|
|
476
|
+
it('ArrowDown / ArrowUp move focus between visible treeitems', async () => {
|
|
477
|
+
const user = userEvent.setup();
|
|
478
|
+
render(<TreeList items={flatItems} />);
|
|
479
|
+
const apple = screen.getByText('Apple').closest('li')!;
|
|
480
|
+
apple.focus();
|
|
481
|
+
await user.keyboard('{ArrowDown}');
|
|
482
|
+
expect(document.activeElement).toBe(
|
|
483
|
+
screen.getByText('Banana').closest('li'),
|
|
484
|
+
);
|
|
485
|
+
await user.keyboard('{ArrowDown}');
|
|
486
|
+
expect(document.activeElement).toBe(
|
|
487
|
+
screen.getByText('Cherry').closest('li'),
|
|
488
|
+
);
|
|
489
|
+
await user.keyboard('{ArrowUp}');
|
|
490
|
+
expect(document.activeElement).toBe(
|
|
491
|
+
screen.getByText('Banana').closest('li'),
|
|
492
|
+
);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it('ArrowDown / ArrowUp skip disabled treeitems', async () => {
|
|
496
|
+
const user = userEvent.setup();
|
|
497
|
+
render(<TreeList items={withDisabledItems} />);
|
|
498
|
+
const apple = screen.getByText('Apple').closest('li')!;
|
|
499
|
+
apple.focus();
|
|
500
|
+
await user.keyboard('{ArrowDown}');
|
|
501
|
+
// Banana is disabled → skipped, lands on Cherry.
|
|
502
|
+
expect(document.activeElement).toBe(
|
|
503
|
+
screen.getByText('Cherry').closest('li'),
|
|
504
|
+
);
|
|
505
|
+
await user.keyboard('{ArrowUp}');
|
|
506
|
+
expect(document.activeElement).toBe(
|
|
507
|
+
screen.getByText('Apple').closest('li'),
|
|
508
|
+
);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it('ArrowRight expands a collapsed parent, then enters the first child', async () => {
|
|
512
|
+
const user = userEvent.setup();
|
|
513
|
+
render(<TreeList items={collapsedParentItems} />);
|
|
514
|
+
const parent = screen.getByText('Parent').closest('li')!;
|
|
515
|
+
parent.focus();
|
|
516
|
+
expect(screen.queryByText('Child 1')).not.toBeInTheDocument();
|
|
517
|
+
await user.keyboard('{ArrowRight}');
|
|
518
|
+
// First ArrowRight expands.
|
|
519
|
+
expect(screen.getByText('Child 1')).toBeInTheDocument();
|
|
520
|
+
expect(document.activeElement).toBe(parent);
|
|
521
|
+
await user.keyboard('{ArrowRight}');
|
|
522
|
+
// Second ArrowRight moves into first child.
|
|
523
|
+
expect(document.activeElement).toBe(
|
|
524
|
+
screen.getByText('Child 1').closest('li'),
|
|
525
|
+
);
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
it('ArrowRight on a leaf is a no-op', async () => {
|
|
529
|
+
const user = userEvent.setup();
|
|
530
|
+
render(<TreeList items={flatItems} />);
|
|
531
|
+
const apple = screen.getByText('Apple').closest('li')!;
|
|
532
|
+
apple.focus();
|
|
533
|
+
await user.keyboard('{ArrowRight}');
|
|
534
|
+
expect(document.activeElement).toBe(apple);
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it('ArrowLeft collapses an expanded parent, then moves to parent', async () => {
|
|
538
|
+
const user = userEvent.setup();
|
|
539
|
+
render(<TreeList items={expandedParentItems} />);
|
|
540
|
+
const parent = screen.getByText('Parent').closest('li')!;
|
|
541
|
+
// Focus a child first.
|
|
542
|
+
const child1 = screen.getByText('Child 1').closest('li')!;
|
|
543
|
+
child1.focus();
|
|
544
|
+
await user.keyboard('{ArrowLeft}');
|
|
545
|
+
// Child is a leaf → ArrowLeft moves to parent.
|
|
546
|
+
expect(document.activeElement).toBe(parent);
|
|
547
|
+
await user.keyboard('{ArrowLeft}');
|
|
548
|
+
// Parent is expanded → ArrowLeft collapses it.
|
|
549
|
+
expect(screen.queryByText('Child 1')).not.toBeInTheDocument();
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
it('Home and End move to the first and last visible treeitems', async () => {
|
|
553
|
+
const user = userEvent.setup();
|
|
554
|
+
render(<TreeList items={flatItems} />);
|
|
555
|
+
const banana = screen.getByText('Banana').closest('li')!;
|
|
556
|
+
banana.focus();
|
|
557
|
+
await user.keyboard('{End}');
|
|
558
|
+
expect(document.activeElement).toBe(
|
|
559
|
+
screen.getByText('Cherry').closest('li'),
|
|
560
|
+
);
|
|
561
|
+
await user.keyboard('{Home}');
|
|
562
|
+
expect(document.activeElement).toBe(
|
|
563
|
+
screen.getByText('Apple').closest('li'),
|
|
564
|
+
);
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
it('Enter activates the item onClick', async () => {
|
|
568
|
+
const user = userEvent.setup();
|
|
569
|
+
const onClick = vi.fn();
|
|
570
|
+
const items: TreeListItemData[] = [{id: 'a', label: 'Apple', onClick}];
|
|
571
|
+
render(<TreeList items={items} />);
|
|
572
|
+
const apple = screen.getByText('Apple').closest('li')!;
|
|
573
|
+
apple.focus();
|
|
574
|
+
await user.keyboard('{Enter}');
|
|
575
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
it('Space activates the item onClick', async () => {
|
|
579
|
+
const user = userEvent.setup();
|
|
580
|
+
const onClick = vi.fn();
|
|
581
|
+
const items: TreeListItemData[] = [{id: 'a', label: 'Apple', onClick}];
|
|
582
|
+
render(<TreeList items={items} />);
|
|
583
|
+
const apple = screen.getByText('Apple').closest('li')!;
|
|
584
|
+
apple.focus();
|
|
585
|
+
await user.keyboard(' ');
|
|
586
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
it('Enter toggles expansion for a parent without its own action', async () => {
|
|
590
|
+
const user = userEvent.setup();
|
|
591
|
+
render(<TreeList items={collapsedParentItems} />);
|
|
592
|
+
const parent = screen.getByText('Parent').closest('li')!;
|
|
593
|
+
parent.focus();
|
|
594
|
+
expect(screen.queryByText('Child 1')).not.toBeInTheDocument();
|
|
595
|
+
await user.keyboard('{Enter}');
|
|
596
|
+
expect(screen.getByText('Child 1')).toBeInTheDocument();
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
it('typeahead moves focus to the next item matching typed characters', async () => {
|
|
600
|
+
const user = userEvent.setup();
|
|
601
|
+
render(<TreeList items={flatItems} />);
|
|
602
|
+
const apple = screen.getByText('Apple').closest('li')!;
|
|
603
|
+
apple.focus();
|
|
604
|
+
await user.keyboard('c');
|
|
605
|
+
expect(document.activeElement).toBe(
|
|
606
|
+
screen.getByText('Cherry').closest('li'),
|
|
607
|
+
);
|
|
608
|
+
});
|
|
320
609
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file TreeList.tsx
|
|
7
|
-
* @input Uses React, StyleX, theme tokens, TreeListItem, TreeListTypes
|
|
7
|
+
* @input Uses React, StyleX, theme tokens, TreeListItem, TreeListTypes, useTreeFocus
|
|
8
8
|
* @output Exports TreeList component, TreeListProps type
|
|
9
9
|
* @position Core implementation; consumed by index.ts
|
|
10
10
|
*
|
|
@@ -23,6 +23,7 @@ import type {BaseProps} from '../BaseProps';
|
|
|
23
23
|
import {TreeListItem} from './TreeListItem';
|
|
24
24
|
import type {TreeListItemData, TreeListDensity} from './TreeListTypes';
|
|
25
25
|
import {themeProps} from '../utils/themeProps';
|
|
26
|
+
import {useTreeFocus} from '../hooks/useTreeFocus';
|
|
26
27
|
|
|
27
28
|
// =============================================================================
|
|
28
29
|
// Types
|
|
@@ -97,6 +98,35 @@ function collectExpandedKeys(items: TreeListItemData[]): string[] {
|
|
|
97
98
|
return keys;
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Compute the initial roving-tabindex seed: the first selected enabled item in
|
|
103
|
+
* document order, else the first enabled item, else the first item. The hook
|
|
104
|
+
* (useTreeFocus with hasRovingTabIndex) takes ownership after mount — it
|
|
105
|
+
* preserves this seeded `tabindex="0"` on its repair pass and moves the stop
|
|
106
|
+
* with keyboard navigation.
|
|
107
|
+
*/
|
|
108
|
+
function findInitialTabbableId(items: TreeListItemData[]): string | undefined {
|
|
109
|
+
let firstEnabled: string | undefined;
|
|
110
|
+
const walk = (list: TreeListItemData[]): string | undefined => {
|
|
111
|
+
for (const item of list) {
|
|
112
|
+
if (item.isSelected && item.isDisabled !== true) {
|
|
113
|
+
return item.id;
|
|
114
|
+
}
|
|
115
|
+
if (firstEnabled == null && item.isDisabled !== true) {
|
|
116
|
+
firstEnabled = item.id;
|
|
117
|
+
}
|
|
118
|
+
if (item.children != null && item.children.length > 0) {
|
|
119
|
+
const selected = walk(item.children);
|
|
120
|
+
if (selected != null) {
|
|
121
|
+
return selected;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
};
|
|
127
|
+
return walk(items) ?? firstEnabled ?? items[0]?.id;
|
|
128
|
+
}
|
|
129
|
+
|
|
100
130
|
// =============================================================================
|
|
101
131
|
// Component
|
|
102
132
|
// =============================================================================
|
|
@@ -160,6 +190,42 @@ export function TreeList({
|
|
|
160
190
|
[expandedKeysFromProps],
|
|
161
191
|
);
|
|
162
192
|
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
// Roving tabindex + APG tree keyboard model (via useTreeFocus)
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
|
|
197
|
+
// The hook (hasRovingTabIndex) owns the tree's single tab stop: it repairs
|
|
198
|
+
// the stop on mount and moves it with keyboard navigation. We only seed the
|
|
199
|
+
// initially-tabbable treeitem in the render (selected item or first enabled);
|
|
200
|
+
// the hook's repair pass preserves that seeded `tabindex="0"`.
|
|
201
|
+
const initialTabbableId = useMemo(
|
|
202
|
+
() => findInitialTabbableId(items),
|
|
203
|
+
[items],
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// Enter/Space activation: prefer the treeitem's own inner action (link or
|
|
207
|
+
// button); return true when handled so the hook does not also toggle. Scoped
|
|
208
|
+
// to this treeitem's own row — never a descendant treeitem's action inside an
|
|
209
|
+
// expanded group.
|
|
210
|
+
const activateItem = useCallback((current: HTMLElement): boolean => {
|
|
211
|
+
const candidates = current.querySelectorAll<HTMLElement>(
|
|
212
|
+
'a[href], button:not([aria-label="Toggle children"])',
|
|
213
|
+
);
|
|
214
|
+
for (const candidate of candidates) {
|
|
215
|
+
if (candidate.closest('[role="treeitem"]') === current) {
|
|
216
|
+
candidate.click();
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
}, []);
|
|
222
|
+
|
|
223
|
+
const {treeRef, handleKeyDown, handleFocus} = useTreeFocus<HTMLUListElement>({
|
|
224
|
+
onToggleExpand: handleToggle,
|
|
225
|
+
onActivate: activateItem,
|
|
226
|
+
hasRovingTabIndex: true,
|
|
227
|
+
});
|
|
228
|
+
|
|
163
229
|
function renderItems(
|
|
164
230
|
items: TreeListItemData[],
|
|
165
231
|
nestedLevel: number,
|
|
@@ -206,6 +272,9 @@ export function TreeList({
|
|
|
206
272
|
onToggle={handleToggle}
|
|
207
273
|
density={density}
|
|
208
274
|
renderedChildren={renderedChildren}
|
|
275
|
+
posInSet={index + 1}
|
|
276
|
+
setSize={items.length}
|
|
277
|
+
isTabbable={item.id === initialTabbableId}
|
|
209
278
|
/>
|
|
210
279
|
);
|
|
211
280
|
});
|
|
@@ -227,8 +296,11 @@ export function TreeList({
|
|
|
227
296
|
</div>
|
|
228
297
|
)}
|
|
229
298
|
<ul
|
|
299
|
+
ref={treeRef}
|
|
230
300
|
role="tree"
|
|
231
301
|
aria-labelledby={header != null ? headerId : undefined}
|
|
302
|
+
onKeyDown={handleKeyDown}
|
|
303
|
+
onFocus={handleFocus}
|
|
232
304
|
{...stylex.props(styles.list)}>
|
|
233
305
|
{renderItems(items, 0, [])}
|
|
234
306
|
</ul>
|