@astryxdesign/core 0.1.8 → 0.1.9-canary.02ef052
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 +100 -0
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
- package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts +58 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +240 -53
- package/dist/Avatar/AvatarStatusDot.d.ts +35 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -0
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +33 -4
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +215 -6
- package/dist/Breadcrumbs/index.d.ts +6 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +10 -1
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +33 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +30 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +80 -11
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +3 -3
- package/dist/Calendar/styles.d.ts +30 -31
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +30 -31
- package/dist/Card/Card.d.ts +8 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +28 -2
- package/dist/Carousel/Carousel.d.ts +4 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +46 -16
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +46 -7
- package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +11 -1
- package/dist/Chat/ChatComposerInput.d.ts +20 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +36 -4
- package/dist/Chat/ChatContext.d.ts +33 -0
- package/dist/Chat/ChatContext.d.ts.map +1 -1
- package/dist/Chat/ChatContext.js +16 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +4 -2
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +4 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +7 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +27 -11
- package/dist/Chat/index.d.ts +2 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/index.js +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +2 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +22 -8
- package/dist/Chat/useSpeechRecognition.d.ts +0 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +1 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.js +5 -5
- package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +11 -1
- package/dist/Citation/Citation.d.ts +22 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +20 -6
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +5 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +22 -9
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +2 -2
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +45 -4
- package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
- package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +6 -1
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +14 -5
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +3 -1
- package/dist/DateInput/DateInput.d.ts +56 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -21
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +23 -20
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +33 -19
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +57 -6
- package/dist/Dialog/DialogContext.d.ts +7 -0
- package/dist/Dialog/DialogContext.d.ts.map +1 -1
- package/dist/Dialog/DialogContext.js +2 -2
- package/dist/Dialog/DialogHeader.d.ts +5 -2
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +6 -1
- package/dist/Divider/Divider.js +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +22 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +5 -3
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
- package/dist/DropdownMenu/index.d.ts +10 -0
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +13 -0
- package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +33 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemRoles.js +10 -1
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -6
- package/dist/Field/Field.d.ts +3 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +6 -4
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +43 -16
- package/dist/Field/inputStyles.stylex.d.ts +1 -0
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +18 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +60 -6
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +54 -35
- package/dist/HoverCard/HoverCard.d.ts +9 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/useHoverCard.d.ts +8 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +17 -6
- package/dist/Icon/Icon.d.ts +22 -3
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- package/dist/Item/Item.d.ts +6 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +22 -1
- package/dist/Layer/useLayer.d.ts +6 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +2 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +19 -13
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +6 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +104 -50
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +10 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +22 -17
- package/dist/Outline/Outline.d.ts +0 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +0 -1
- package/dist/OverflowList/OverflowList.d.ts +20 -3
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +29 -4
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +3 -9
- package/dist/PowerSearch/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.js +4 -4
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
- package/dist/SelectableCard/SelectableCard.d.ts +9 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +16 -13
- package/dist/Selector/Selector.d.ts +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +65 -19
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +5 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +13 -10
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts +1 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +12 -10
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +106 -36
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/Switch/Switch.d.ts +8 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +160 -91
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +33 -6
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
- package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/index.js +3 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts +13 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +7 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +105 -12
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +18 -19
- package/dist/TextInput/TextInput.d.ts +10 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +20 -17
- package/dist/Thumbnail/Thumbnail.d.ts +26 -5
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +97 -54
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
- package/dist/TimeInput/TimeInput.d.ts +10 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +32 -21
- package/dist/Timestamp/Timestamp.d.ts +3 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +8 -6
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +2 -5
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- package/dist/Token/Token.d.ts +30 -3
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +17 -2
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +10 -3
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +20 -6
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
- package/dist/TopNav/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeList.d.ts +12 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +3 -0
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +18 -10
- package/dist/TreeList/TreeListItem.d.ts +8 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +59 -21
- package/dist/TreeList/TreeListTypes.d.ts +25 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/TreeList/index.d.ts +2 -2
- package/dist/TreeList/index.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +20 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -1
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +20 -10
- package/dist/astryx.css +61 -39
- package/dist/astryx.umd.js +53 -53
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/docs-types.d.ts +8 -0
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.d.ts +47 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -0
- package/dist/hooks/computeOverflow.js +213 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -1
- package/dist/hooks/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- package/dist/hooks/useDevWarning.d.ts +18 -0
- package/dist/hooks/useDevWarning.d.ts.map +1 -0
- package/dist/hooks/useDevWarning.js +49 -0
- package/dist/hooks/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useInputStatusIcon.d.ts +38 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
- package/dist/hooks/useInputStatusIcon.js +158 -0
- package/dist/hooks/useListFocus.d.ts +39 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +54 -9
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +36 -25
- package/dist/i18n/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +51 -0
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
- package/dist/utils/devWarning.d.ts +42 -0
- package/dist/utils/devWarning.d.ts.map +1 -0
- package/dist/utils/devWarning.js +88 -0
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +65 -3
- package/dist/utils/rtlStyles.d.ts +24 -0
- package/dist/utils/rtlStyles.d.ts.map +1 -0
- package/dist/utils/rtlStyles.js +27 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/locales/en.json +104 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +78 -0
- package/package.json +6 -1
- package/src/AppShell/AppShell.tsx +6 -0
- package/src/AppShell/AppShellMobileContext.tsx +8 -0
- package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
- package/src/Avatar/Avatar.doc.mjs +64 -5
- package/src/Avatar/Avatar.test.tsx +374 -1
- package/src/Avatar/Avatar.tsx +367 -69
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +180 -21
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +141 -1
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -0
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +53 -9
- package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +335 -2
- package/src/Breadcrumbs/index.ts +31 -0
- package/src/Button/Button.doc.mjs +9 -4
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +27 -3
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
- package/src/ButtonGroup/ButtonGroup.tsx +32 -0
- package/src/Calendar/Calendar.doc.mjs +12 -1
- package/src/Calendar/Calendar.test.tsx +362 -19
- package/src/Calendar/Calendar.tsx +111 -32
- package/src/Calendar/dayCellUtils.test.ts +23 -18
- package/src/Calendar/dayCellUtils.ts +3 -3
- package/src/Calendar/styles.ts +33 -39
- package/src/Card/Card.doc.mjs +9 -0
- package/src/Card/Card.test.tsx +21 -3
- package/src/Card/Card.tsx +35 -2
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Carousel/Carousel.test.tsx +53 -0
- package/src/Carousel/Carousel.tsx +59 -10
- package/src/Chat/ChatComposer.doc.mjs +12 -3
- package/src/Chat/ChatComposer.test.tsx +115 -0
- package/src/Chat/ChatComposer.tsx +73 -9
- package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
- package/src/Chat/ChatComposerDrawer.tsx +11 -1
- package/src/Chat/ChatComposerInput.doc.mjs +7 -0
- package/src/Chat/ChatComposerInput.test.tsx +103 -0
- package/src/Chat/ChatComposerInput.tsx +51 -5
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +11 -2
- package/src/Chat/ChatLayout.tsx +7 -5
- package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +11 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +33 -5
- package/src/Chat/index.ts +5 -1
- package/src/Chat/useChatStreamScroll.test.tsx +49 -0
- package/src/Chat/useChatStreamScroll.ts +27 -10
- package/src/Chat/useSpeechRecognition.ts +1 -1
- package/src/Chat/useTriggerMenu.tsx +4 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxInput/CheckboxInput.tsx +5 -5
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/CheckboxList/CheckboxList.test.tsx +81 -3
- package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
- package/src/CheckboxList/CheckboxListItem.tsx +41 -5
- package/src/Citation/Citation.doc.mjs +4 -3
- package/src/Citation/Citation.test.tsx +97 -0
- package/src/Citation/Citation.tsx +43 -11
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +13 -3
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +45 -10
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +7 -0
- package/src/Collapsible/Collapsible.tsx +16 -6
- package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +44 -3
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
- package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
- package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +235 -0
- package/src/ContextMenu/ContextMenu.tsx +13 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +41 -0
- package/src/DateInput/DateInput.test.tsx +338 -0
- package/src/DateInput/DateInput.tsx +119 -32
- package/src/DateInput/index.ts +1 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
- package/src/DateRangeInput/DateRangeInput.tsx +42 -30
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +147 -0
- package/src/DateTimeInput/DateTimeInput.tsx +58 -41
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.test.tsx +77 -4
- package/src/Dialog/Dialog.tsx +89 -5
- package/src/Dialog/DialogContext.ts +9 -2
- package/src/Dialog/DialogHeader.doc.mjs +2 -2
- package/src/Dialog/DialogHeader.tsx +9 -2
- package/src/Divider/Divider.tsx +2 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +229 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +9 -4
- package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +39 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/Field.tsx +20 -14
- package/src/Field/FieldLabel.tsx +9 -1
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +150 -40
- package/src/FieldStatus/FieldStatus.tsx +69 -5
- package/src/FileInput/FileInput.doc.mjs +23 -2
- package/src/FileInput/FileInput.test.tsx +135 -12
- package/src/FileInput/FileInput.tsx +65 -51
- package/src/HoverCard/HoverCard.doc.mjs +13 -0
- package/src/HoverCard/HoverCard.test.tsx +21 -2
- package/src/HoverCard/HoverCard.tsx +11 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +39 -5
- package/src/Icon/Icon.doc.mjs +16 -2
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +58 -5
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.test.tsx +40 -18
- package/src/Item/Item.tsx +38 -2
- package/src/Layer/useLayer.tsx +8 -0
- package/src/Lightbox/Lightbox.tsx +15 -7
- package/src/List/List.test.tsx +9 -8
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MobileNav/MobileNav.tsx +12 -1
- package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
- package/src/MobileNav/MobileNavToggle.tsx +9 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +24 -2
- package/src/MultiSelector/MultiSelector.test.tsx +498 -3
- package/src/MultiSelector/MultiSelector.tsx +149 -65
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +21 -0
- package/src/NumberInput/NumberInput.test.tsx +82 -7
- package/src/NumberInput/NumberInput.tsx +36 -28
- package/src/Outline/Outline.tsx +0 -1
- package/src/OverflowList/OverflowList.doc.mjs +39 -6
- package/src/OverflowList/OverflowList.test.tsx +111 -0
- package/src/OverflowList/OverflowList.tsx +48 -8
- package/src/Pagination/Pagination.tsx +11 -3
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +29 -0
- package/src/PowerSearch/PowerSearch.test.tsx +43 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +4 -4
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +46 -4
- package/src/SelectableCard/SelectableCard.tsx +29 -16
- package/src/Selector/Selector.doc.mjs +15 -0
- package/src/Selector/Selector.test.tsx +417 -0
- package/src/Selector/Selector.tsx +86 -21
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +15 -8
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.tsx +10 -4
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +314 -13
- package/src/Slider/Slider.tsx +117 -28
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +54 -1
- package/src/Switch/Switch.tsx +90 -33
- package/src/TabList/Tab.tsx +2 -2
- package/src/TabList/TabMenu.tsx +2 -2
- package/src/Table/BaseTable.tsx +37 -7
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +15 -8
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
- package/src/Table/plugins/rowStatus/index.ts +7 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +77 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +22 -1
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -1
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
- package/src/Table/plugins/tree/useTableTreeData.tsx +139 -8
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
- package/src/Table/types.ts +33 -0
- package/src/Table/useBaseTablePlugins.ts +10 -6
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +29 -0
- package/src/Table/useTableTreeState.doc.mjs +2 -2
- package/src/TextArea/TextArea.doc.mjs +21 -0
- package/src/TextArea/TextArea.test.tsx +32 -1
- package/src/TextArea/TextArea.tsx +27 -26
- package/src/TextInput/TextInput.doc.mjs +21 -0
- package/src/TextInput/TextInput.test.tsx +150 -0
- package/src/TextInput/TextInput.tsx +28 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +142 -42
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.doc.mjs +21 -0
- package/src/TimeInput/TimeInput.test.tsx +99 -1
- package/src/TimeInput/TimeInput.tsx +43 -31
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +32 -0
- package/src/Timestamp/Timestamp.tsx +28 -8
- package/src/Toast/useToast.tsx +7 -8
- package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
- package/src/Token/Token.test.tsx +21 -15
- package/src/Token/Token.tsx +31 -14
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +38 -2
- package/src/Tokenizer/Tokenizer.test.tsx +206 -2
- package/src/Tokenizer/Tokenizer.tsx +30 -6
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- package/src/TopNav/TopNav.test.tsx +125 -1
- package/src/TopNav/TopNavHeading.tsx +24 -8
- package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
- package/src/TopNav/TopNavMegaMenu.tsx +10 -4
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.doc.mjs +28 -0
- package/src/TreeList/TreeList.test.tsx +272 -0
- package/src/TreeList/TreeList.tsx +23 -2
- package/src/TreeList/TreeListBranches.tsx +24 -8
- package/src/TreeList/TreeListItem.tsx +84 -22
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/Typeahead/BaseTypeahead.tsx +30 -15
- package/src/Typeahead/Typeahead.doc.mjs +13 -0
- package/src/Typeahead/Typeahead.test.tsx +50 -0
- package/src/Typeahead/Typeahead.tsx +11 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/authoring/doc.ts +1 -3
- package/src/doc-mjs.d.ts +19 -0
- package/src/docs-types.ts +5 -0
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useInputStatusIcon.test.tsx +162 -0
- package/src/hooks/useInputStatusIcon.tsx +224 -0
- package/src/hooks/useListFocus.doc.mjs +25 -3
- package/src/hooks/useListFocus.test.tsx +153 -1
- package/src/hooks/useListFocus.ts +102 -9
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/resolve.ts +9 -21
- package/src/i18n/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +107 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
- package/src/utils/devWarning.test.ts +56 -0
- package/src/utils/devWarning.ts +102 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/plainDate.test.ts +46 -6
- package/src/utils/plainDate.ts +69 -3
- package/src/utils/rtlStyles.ts +27 -0
- package/src/utils/types.ts +14 -0
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
* SYNC: When TopNavMenu changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
+
import {render, screen, fireEvent} from '@testing-library/react';
|
|
14
|
+
import userEvent from '@testing-library/user-event';
|
|
14
15
|
import {TopNavMenu} from './TopNavMenu';
|
|
15
16
|
|
|
16
17
|
const mockItems = [
|
|
@@ -32,10 +33,13 @@ describe('TopNavMenu', () => {
|
|
|
32
33
|
expect(screen.getByRole('button', {name: 'Products'})).toBeInTheDocument();
|
|
33
34
|
});
|
|
34
35
|
|
|
35
|
-
it('trigger
|
|
36
|
+
it('trigger announces a menu popup, not a dialog', () => {
|
|
36
37
|
render(<TopNavMenu label="Products" items={mockItems} />);
|
|
37
38
|
const trigger = screen.getByRole('button', {name: 'Products'});
|
|
38
|
-
|
|
39
|
+
// usePopover with role:'none' emits aria-haspopup="true" (the ARIA
|
|
40
|
+
// synonym for "menu") because the exposed semantics of the popup are its
|
|
41
|
+
// child role="menu", not a dialog.
|
|
42
|
+
expect(trigger).toHaveAttribute('aria-haspopup', 'true');
|
|
39
43
|
});
|
|
40
44
|
|
|
41
45
|
it('renders with custom items', () => {
|
|
@@ -57,3 +61,113 @@ describe('TopNavMenu', () => {
|
|
|
57
61
|
expect(screen.getByRole('button', {name: 'Menu'})).toBeInTheDocument();
|
|
58
62
|
});
|
|
59
63
|
});
|
|
64
|
+
|
|
65
|
+
describe('menu semantics (APG)', () => {
|
|
66
|
+
it('does not wrap the popup in a role="dialog" / aria-modal shell', () => {
|
|
67
|
+
render(<TopNavMenu label="Products" items={mockItems} />);
|
|
68
|
+
// The popup's exposed semantics are the role="menu" container itself —
|
|
69
|
+
// no dialog wrapper, no aria-modal.
|
|
70
|
+
expect(
|
|
71
|
+
screen.queryByRole('dialog', {hidden: true}),
|
|
72
|
+
).not.toBeInTheDocument();
|
|
73
|
+
expect(document.querySelector('[aria-modal]')).toBeNull();
|
|
74
|
+
expect(
|
|
75
|
+
screen.getByRole('menu', {name: 'Products', hidden: true}),
|
|
76
|
+
).toBeInTheDocument();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('keyboard navigation (APG menu pattern)', () => {
|
|
81
|
+
it('exposes exactly one tab stop among menu items (roving tabindex)', async () => {
|
|
82
|
+
const user = userEvent.setup();
|
|
83
|
+
render(<TopNavMenu label="Products" items={mockItems} />);
|
|
84
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
85
|
+
|
|
86
|
+
const items = screen.getAllByRole('menuitem', {hidden: true});
|
|
87
|
+
expect(items).toHaveLength(2);
|
|
88
|
+
const tabbable = items.filter(el => el.getAttribute('tabindex') === '0');
|
|
89
|
+
expect(tabbable).toHaveLength(1);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('moves focus with ArrowDown/ArrowUp and the tab stop follows', async () => {
|
|
93
|
+
const user = userEvent.setup();
|
|
94
|
+
render(<TopNavMenu label="Products" items={mockItems} />);
|
|
95
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
96
|
+
|
|
97
|
+
const menu = screen.getByRole('menu', {hidden: true});
|
|
98
|
+
const items = screen.getAllByRole('menuitem', {hidden: true});
|
|
99
|
+
items[0].focus();
|
|
100
|
+
|
|
101
|
+
fireEvent.keyDown(menu, {key: 'ArrowDown'});
|
|
102
|
+
expect(items[1]).toHaveFocus();
|
|
103
|
+
expect(items[1]).toHaveAttribute('tabindex', '0');
|
|
104
|
+
expect(items[0]).toHaveAttribute('tabindex', '-1');
|
|
105
|
+
|
|
106
|
+
fireEvent.keyDown(menu, {key: 'ArrowUp'});
|
|
107
|
+
expect(items[0]).toHaveFocus();
|
|
108
|
+
expect(items[0]).toHaveAttribute('tabindex', '0');
|
|
109
|
+
expect(items[1]).toHaveAttribute('tabindex', '-1');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('wraps focus at both ends', async () => {
|
|
113
|
+
const user = userEvent.setup();
|
|
114
|
+
render(<TopNavMenu label="Products" items={mockItems} />);
|
|
115
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
116
|
+
|
|
117
|
+
const menu = screen.getByRole('menu', {hidden: true});
|
|
118
|
+
const items = screen.getAllByRole('menuitem', {hidden: true});
|
|
119
|
+
|
|
120
|
+
items[1].focus();
|
|
121
|
+
fireEvent.keyDown(menu, {key: 'ArrowDown'});
|
|
122
|
+
expect(items[0]).toHaveFocus();
|
|
123
|
+
|
|
124
|
+
fireEvent.keyDown(menu, {key: 'ArrowUp'});
|
|
125
|
+
expect(items[1]).toHaveFocus();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('typeahead moves focus to the item matching the typed character', async () => {
|
|
129
|
+
const user = userEvent.setup();
|
|
130
|
+
render(<TopNavMenu label="Products" items={mockItems} />);
|
|
131
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
132
|
+
|
|
133
|
+
const menu = screen.getByRole('menu', {hidden: true});
|
|
134
|
+
fireEvent.keyDown(menu, {key: 'm'});
|
|
135
|
+
expect(
|
|
136
|
+
screen.getByRole('menuitem', {name: /Messaging/, hidden: true}),
|
|
137
|
+
).toHaveFocus();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('activates a focused onClick-only item with Enter', async () => {
|
|
141
|
+
const user = userEvent.setup();
|
|
142
|
+
const onClick = vi.fn();
|
|
143
|
+
render(<TopNavMenu label="Menu" items={[{title: 'Action', onClick}]} />);
|
|
144
|
+
await user.click(screen.getByRole('button', {name: 'Menu'}));
|
|
145
|
+
|
|
146
|
+
const item = screen.getByRole('menuitem', {hidden: true});
|
|
147
|
+
item.focus();
|
|
148
|
+
fireEvent.keyDown(item, {key: 'Enter'});
|
|
149
|
+
expect(onClick).toHaveBeenCalledOnce();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('still activates an item on click', async () => {
|
|
153
|
+
const user = userEvent.setup();
|
|
154
|
+
const onClick = vi.fn();
|
|
155
|
+
render(<TopNavMenu label="Menu" items={[{title: 'Action', onClick}]} />);
|
|
156
|
+
await user.click(screen.getByRole('button', {name: 'Menu'}));
|
|
157
|
+
|
|
158
|
+
await user.click(screen.getByRole('menuitem', {hidden: true}));
|
|
159
|
+
expect(onClick).toHaveBeenCalledOnce();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('closes the menu with Escape', async () => {
|
|
163
|
+
const user = userEvent.setup();
|
|
164
|
+
render(<TopNavMenu label="Products" items={mockItems} />);
|
|
165
|
+
const trigger = screen.getByRole('button', {name: 'Products'});
|
|
166
|
+
await user.click(trigger);
|
|
167
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
168
|
+
|
|
169
|
+
const menu = screen.getByRole('menu', {hidden: true});
|
|
170
|
+
fireEvent.keyDown(menu, {key: 'Escape'});
|
|
171
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
172
|
+
});
|
|
173
|
+
});
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file TopNavMenu.tsx
|
|
7
|
-
* @input Uses React, StyleX,
|
|
7
|
+
* @input Uses React, StyleX, usePopover, useMenuHover, useListFocus,
|
|
8
|
+
* useTypeahead, TopNavItem tokens
|
|
8
9
|
* @output Exports TopNavMenu component and related types
|
|
9
10
|
* @position Navigation item with hover-triggered overflow menu for TopNav
|
|
10
11
|
*
|
|
@@ -15,10 +16,18 @@
|
|
|
15
16
|
* - /packages/cli/templates/blocks/components/TopNav/ (showcase blocks)
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
|
-
import React, {
|
|
19
|
+
import React, {
|
|
20
|
+
useCallback,
|
|
21
|
+
useId,
|
|
22
|
+
useRef,
|
|
23
|
+
useState,
|
|
24
|
+
type ReactNode,
|
|
25
|
+
} from 'react';
|
|
19
26
|
import * as stylex from '@stylexjs/stylex';
|
|
20
27
|
import {usePopover} from '../Popover/usePopover';
|
|
21
28
|
import {useMenuHover} from '../hooks/useMenuHover';
|
|
29
|
+
import {useListFocus} from '../hooks/useListFocus';
|
|
30
|
+
import {useTypeahead} from '../hooks/useTypeahead';
|
|
22
31
|
import {getIcon} from '../Icon/globalIconRegistry';
|
|
23
32
|
import {mergeProps, mergeRefs} from '../utils';
|
|
24
33
|
import type {BaseProps} from '../BaseProps';
|
|
@@ -332,7 +341,10 @@ export function TopNavMenu({
|
|
|
332
341
|
const triggerButtonRef = useRef<HTMLButtonElement | null>(null);
|
|
333
342
|
|
|
334
343
|
const popover = usePopover({
|
|
335
|
-
|
|
344
|
+
// The popup's own role="menu" is the exposed semantics; a modal dialog
|
|
345
|
+
// wrapper would announce an unnamed dialog around the menu and make the
|
|
346
|
+
// trigger claim aria-haspopup="dialog" for menu content (see TabMenu).
|
|
347
|
+
role: 'none',
|
|
336
348
|
xstyle: styles.menuOffset,
|
|
337
349
|
});
|
|
338
350
|
|
|
@@ -353,6 +365,65 @@ export function TopNavMenu({
|
|
|
353
365
|
ref,
|
|
354
366
|
);
|
|
355
367
|
|
|
368
|
+
// The desktop popup is a composite menu widget per the APG menu pattern:
|
|
369
|
+
// a single roving tab stop with ArrowUp/ArrowDown traversal (wrapping),
|
|
370
|
+
// Home/End, and first-character typeahead. The hook owns item tabindex —
|
|
371
|
+
// items render tabIndex={-1} and exactly one is promoted to 0. The
|
|
372
|
+
// composition mirrors NavHeadingMenu.
|
|
373
|
+
const {listRef, handleKeyDown, handleFocus, focusItem} =
|
|
374
|
+
useListFocus<HTMLDivElement>({
|
|
375
|
+
itemSelector: '[role="menuitem"]',
|
|
376
|
+
hasRovingTabIndex: true,
|
|
377
|
+
onEscape: popover.hide,
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// First-character typeahead over the menu items (menus-11).
|
|
381
|
+
const getMenuItems = useCallback(
|
|
382
|
+
(): HTMLElement[] =>
|
|
383
|
+
listRef.current
|
|
384
|
+
? Array.from(
|
|
385
|
+
listRef.current.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
|
386
|
+
)
|
|
387
|
+
: [],
|
|
388
|
+
[listRef],
|
|
389
|
+
);
|
|
390
|
+
const typeahead = useTypeahead({
|
|
391
|
+
getItemLabels: () => getMenuItems().map(el => el.textContent),
|
|
392
|
+
onMatch: focusItem,
|
|
393
|
+
getCurrentIndex: () =>
|
|
394
|
+
getMenuItems().findIndex(
|
|
395
|
+
el =>
|
|
396
|
+
el === document.activeElement || el.contains(document.activeElement),
|
|
397
|
+
),
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// Extend useListFocus with Enter/Space activation. Items rendered without an
|
|
401
|
+
// `href` are `<div role="menuitem">` elements, which have no native keyboard
|
|
402
|
+
// activation — without this, Enter/Space on a focused onClick-only item does
|
|
403
|
+
// nothing. Anchor items (with `href`) already activate on Enter natively.
|
|
404
|
+
const menuKeyDown = useCallback(
|
|
405
|
+
(e: React.KeyboardEvent) => {
|
|
406
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
407
|
+
const focused = document.activeElement as HTMLElement | null;
|
|
408
|
+
if (focused?.getAttribute('role') === 'menuitem') {
|
|
409
|
+
e.preventDefault();
|
|
410
|
+
focused.click();
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (typeahead.onKeyDown(e)) {
|
|
415
|
+
e.preventDefault();
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
handleKeyDown(e);
|
|
419
|
+
},
|
|
420
|
+
[handleKeyDown, typeahead],
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
// Menu container carries both the hover hook's ref (for its open/close
|
|
424
|
+
// focus management) and the list-focus ref (for roving tabindex/typeahead).
|
|
425
|
+
const setMenuRef = mergeRefs<HTMLDivElement>(menuRef, listRef);
|
|
426
|
+
|
|
356
427
|
// Mobile bar: hide menus entirely
|
|
357
428
|
if (renderMode === 'mobile-bar') {
|
|
358
429
|
return null;
|
|
@@ -437,10 +508,15 @@ export function TopNavMenu({
|
|
|
437
508
|
</button>
|
|
438
509
|
{popover.render(
|
|
439
510
|
<div
|
|
440
|
-
ref={
|
|
511
|
+
ref={setMenuRef}
|
|
441
512
|
role="menu"
|
|
442
513
|
aria-label={label}
|
|
443
514
|
{...contentProps}
|
|
515
|
+
// After the contentProps spread so the full APG composition (roving
|
|
516
|
+
// tabindex + typeahead + Enter/Space activation) replaces the hover
|
|
517
|
+
// hook's basic arrow-key handler.
|
|
518
|
+
onKeyDown={menuKeyDown}
|
|
519
|
+
onFocus={handleFocus}
|
|
444
520
|
{...stylex.props(styles.menuContainer)}>
|
|
445
521
|
{items.map(item => {
|
|
446
522
|
const Element = item.href ? 'a' : 'div';
|
|
@@ -448,7 +524,9 @@ export function TopNavMenu({
|
|
|
448
524
|
<Element
|
|
449
525
|
key={getMenuItemKey(item)}
|
|
450
526
|
role="menuitem"
|
|
451
|
-
|
|
527
|
+
// Single tab stop: useListFocus owns the roving tabindex and
|
|
528
|
+
// promotes exactly one item to 0.
|
|
529
|
+
tabIndex={-1}
|
|
452
530
|
href={item.href}
|
|
453
531
|
onClick={item.onClick}
|
|
454
532
|
{...stylex.props(styles.menuItem)}>
|
|
@@ -26,6 +26,12 @@ export const docs = {
|
|
|
26
26
|
targets: [
|
|
27
27
|
{className: 'astryx-tree-list', visualProps: ['density']},
|
|
28
28
|
{className: 'astryx-tree-list-item', visualProps: ['density'], states: ['selected', 'disabled']},
|
|
29
|
+
{className: 'astryx-tree-list-chevron', states: ['state']},
|
|
30
|
+
{className: 'astryx-tree-list-item-label', states: ['selected']},
|
|
31
|
+
{className: 'astryx-tree-list-guide'},
|
|
32
|
+
],
|
|
33
|
+
vars: [
|
|
34
|
+
{name: '--tree-list-indent', description: 'Per-level indentation step. Each nesting level indents its rows by this distance, and the guide lines follow it so they stay aligned. Set it on the `tree-list` target to retune the metric (e.g. `var(--spacing-5)` for a wider indent).', default: 'var(--spacing-4)'},
|
|
29
35
|
],
|
|
30
36
|
},
|
|
31
37
|
components: [
|
|
@@ -47,6 +53,13 @@ export const docs = {
|
|
|
47
53
|
description: 'Spacing density for items.',
|
|
48
54
|
default: "'balanced'",
|
|
49
55
|
},
|
|
56
|
+
{
|
|
57
|
+
name: 'variant',
|
|
58
|
+
type: "'lineGuides' | 'noGuides'",
|
|
59
|
+
description:
|
|
60
|
+
'Visual treatment of the hierarchy guide lines. lineGuides shows connector lines; noGuides hides them, keeping indentation. Orthogonal to density.',
|
|
61
|
+
default: "'lineGuides'",
|
|
62
|
+
},
|
|
50
63
|
{
|
|
51
64
|
name: 'header',
|
|
52
65
|
type: 'ReactNode',
|
|
@@ -90,6 +103,12 @@ export const docsZh = {
|
|
|
90
103
|
targets: [
|
|
91
104
|
{className: 'astryx-tree-list', visualProps: ['density']},
|
|
92
105
|
{className: 'astryx-tree-list-item', visualProps: ['density'], states: ['selected', 'disabled']},
|
|
106
|
+
{className: 'astryx-tree-list-chevron', states: ['state']},
|
|
107
|
+
{className: 'astryx-tree-list-item-label', states: ['selected']},
|
|
108
|
+
{className: 'astryx-tree-list-guide'},
|
|
109
|
+
],
|
|
110
|
+
vars: [
|
|
111
|
+
{name: '--tree-list-indent', description: '每级缩进步长。每个嵌套层级的行按此距离缩进,引导线随之对齐。在 `tree-list` 目标上设置以调整该度量(例如用 `var(--spacing-5)` 获得更宽的缩进)。', default: 'var(--spacing-4)'},
|
|
93
112
|
],
|
|
94
113
|
},
|
|
95
114
|
components: [
|
|
@@ -112,6 +131,13 @@ export const docsZh = {
|
|
|
112
131
|
description: '项目的间距密度。',
|
|
113
132
|
default: "'balanced'",
|
|
114
133
|
},
|
|
134
|
+
{
|
|
135
|
+
name: 'variant',
|
|
136
|
+
type: "'lineGuides' | 'noGuides'",
|
|
137
|
+
description:
|
|
138
|
+
'层级引导线的视觉呈现。lineGuides 显示连接线;noGuides 隐藏连接线并保留缩进。与 density 正交。',
|
|
139
|
+
default: "'lineGuides'",
|
|
140
|
+
},
|
|
115
141
|
{
|
|
116
142
|
name: 'header',
|
|
117
143
|
type: 'ReactNode',
|
|
@@ -156,6 +182,7 @@ export const docsDense = {
|
|
|
156
182
|
propDescriptions: {
|
|
157
183
|
items: 'Recursive tree item data w/ id, label, optional children + isExpanded.',
|
|
158
184
|
density: 'Spacing density for items.',
|
|
185
|
+
variant: 'Guide-line treatment: lineGuides shows connectors, noGuides hides them (indent kept). Orthogonal to density.',
|
|
159
186
|
header: 'Header content, linked to tree via aria-labelledby.',
|
|
160
187
|
xstyle: 'StyleX styles for layout. Must be stylex.create() value.',
|
|
161
188
|
},
|
|
@@ -167,6 +194,7 @@ export const docsDense = {
|
|
|
167
194
|
propDescriptions: {
|
|
168
195
|
items: 'Recursive tree item data w/ id, label, optional children + isExpanded.',
|
|
169
196
|
density: 'Spacing density for items.',
|
|
197
|
+
variant: 'Guide-line treatment: lineGuides shows connectors, noGuides hides them (indent kept). Orthogonal to density.',
|
|
170
198
|
header: 'Header content, linked to tree via aria-labelledby.',
|
|
171
199
|
xstyle: 'StyleX styles for layout. Must be stylex.create() value.',
|
|
172
200
|
},
|
|
@@ -14,6 +14,8 @@ import {render, screen, fireEvent} from '@testing-library/react';
|
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {TreeList} from './TreeList';
|
|
16
16
|
import type {TreeListItemData} from './TreeListTypes';
|
|
17
|
+
import {defineTheme} from '../theme/defineTheme';
|
|
18
|
+
import {generateThemeCSSFlat} from '../theme/generateThemeRules';
|
|
17
19
|
|
|
18
20
|
const simpleItems: TreeListItemData[] = [
|
|
19
21
|
{id: 'a', label: 'Item A'},
|
|
@@ -393,6 +395,155 @@ describe('TreeList', () => {
|
|
|
393
395
|
expect(screen.getByRole('tree')).toBeInTheDocument();
|
|
394
396
|
});
|
|
395
397
|
|
|
398
|
+
// ===========================================================================
|
|
399
|
+
// Variant (guide lines)
|
|
400
|
+
// ===========================================================================
|
|
401
|
+
|
|
402
|
+
describe('variant', () => {
|
|
403
|
+
it('renders guide lines by default', () => {
|
|
404
|
+
const {container} = render(<TreeList items={nestedItemsExpanded} />);
|
|
405
|
+
expect(container.querySelector('.astryx-tree-list-guide')).not.toBeNull();
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it("variant='lineGuides' renders guide lines (explicit == default)", () => {
|
|
409
|
+
const {container} = render(
|
|
410
|
+
<TreeList items={nestedItemsExpanded} variant="lineGuides" />,
|
|
411
|
+
);
|
|
412
|
+
expect(container.querySelector('.astryx-tree-list-guide')).not.toBeNull();
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it("variant='noGuides' renders NO guide lines", () => {
|
|
416
|
+
const {container} = render(
|
|
417
|
+
<TreeList items={nestedItemsExpanded} variant="noGuides" />,
|
|
418
|
+
);
|
|
419
|
+
expect(container.querySelector('.astryx-tree-list-guide')).toBeNull();
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it("variant='noGuides' preserves the tree structure and items", () => {
|
|
423
|
+
render(<TreeList items={nestedItemsExpanded} variant="noGuides" />);
|
|
424
|
+
// Rows, roles, and nesting are all intact — only the connectors are gone.
|
|
425
|
+
expect(screen.getByRole('tree')).toBeInTheDocument();
|
|
426
|
+
expect(screen.getAllByRole('treeitem')).toHaveLength(4);
|
|
427
|
+
expect(screen.getByText('Parent')).toBeInTheDocument();
|
|
428
|
+
expect(screen.getByText('Child 1')).toBeInTheDocument();
|
|
429
|
+
expect(screen.getByText('Child 2')).toBeInTheDocument();
|
|
430
|
+
expect(screen.getByText('Sibling')).toBeInTheDocument();
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it("variant='noGuides' preserves per-level indentation on the rows", () => {
|
|
434
|
+
// Indentation lives on the row's margin-inline-start (not the guide
|
|
435
|
+
// element), so it must survive when the connectors are suppressed. The
|
|
436
|
+
// per-row distance is published as the `--_tree-indent` custom property
|
|
437
|
+
// (not an inline longhand — see #4308), so the theme layer can override
|
|
438
|
+
// the `margin-inline-start` declaration. A deeper row is indented more
|
|
439
|
+
// than a shallower one.
|
|
440
|
+
const {container} = render(
|
|
441
|
+
<TreeList items={deepItems} variant="noGuides" />,
|
|
442
|
+
);
|
|
443
|
+
const indentOf = (text: string): string => {
|
|
444
|
+
const li = screen.getByText(text).closest('li')!;
|
|
445
|
+
const styled = li.querySelector('[style*="--_tree-indent"]');
|
|
446
|
+
return styled?.getAttribute('style') ?? '';
|
|
447
|
+
};
|
|
448
|
+
// Guides are gone…
|
|
449
|
+
expect(container.querySelector('.astryx-tree-list-guide')).toBeNull();
|
|
450
|
+
// …but each level still publishes an indent distance, and the level
|
|
451
|
+
// multiplier grows with depth (0, 1, 2).
|
|
452
|
+
expect(indentOf('Root')).toContain('--_tree-indent');
|
|
453
|
+
expect(indentOf('Mid')).toContain('--_tree-indent');
|
|
454
|
+
expect(indentOf('Leaf')).toContain('--_tree-indent');
|
|
455
|
+
const level = (text: string): number => {
|
|
456
|
+
const m = /calc\((\d+)/.exec(indentOf(text));
|
|
457
|
+
return m ? Number(m[1]) : NaN;
|
|
458
|
+
};
|
|
459
|
+
expect(level('Mid')).toBeGreaterThan(level('Root'));
|
|
460
|
+
expect(level('Leaf')).toBeGreaterThan(level('Mid'));
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
// ===========================================================================
|
|
465
|
+
// Guide theme target
|
|
466
|
+
// ===========================================================================
|
|
467
|
+
|
|
468
|
+
describe('guide theme target', () => {
|
|
469
|
+
it('renders the astryx-tree-list-guide target on the connector lines', () => {
|
|
470
|
+
const {container} = render(<TreeList items={nestedItemsExpanded} />);
|
|
471
|
+
const guide = container.querySelector('.astryx-tree-list-guide');
|
|
472
|
+
// A dedicated, stable target so a theme can recolor or hide the guides
|
|
473
|
+
// without hiding the built-in connectors and reimplementing them.
|
|
474
|
+
expect(guide).not.toBeNull();
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('exposes tree-list-guide as a themeable defineTheme target', () => {
|
|
478
|
+
// jsdom cannot resolve the @layer cascade, so the generated CSS is what
|
|
479
|
+
// proves a theme override reaches the guide element.
|
|
480
|
+
const theme = defineTheme({
|
|
481
|
+
name: 'tree-list-guide-test',
|
|
482
|
+
components: {
|
|
483
|
+
'tree-list-guide': {
|
|
484
|
+
base: {backgroundColor: 'var(--color-accent)'},
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
const css = generateThemeCSSFlat(theme);
|
|
489
|
+
expect(css).toContain('.astryx-tree-list-guide {');
|
|
490
|
+
expect(css).toContain('background-color: var(--color-accent)');
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it('lets a theme hide the guides via display: none on the target', () => {
|
|
494
|
+
// Hiding the guides is done through the theme target, not a prop — the
|
|
495
|
+
// theme rule lands in @layer astryx-theme, above StyleX's base layer.
|
|
496
|
+
const theme = defineTheme({
|
|
497
|
+
name: 'tree-list-guide-hidden-test',
|
|
498
|
+
components: {
|
|
499
|
+
'tree-list-guide': {
|
|
500
|
+
base: {display: 'none'},
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
});
|
|
504
|
+
const css = generateThemeCSSFlat(theme);
|
|
505
|
+
expect(css).toContain('.astryx-tree-list-guide {');
|
|
506
|
+
expect(css).toContain('display: none');
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// ===========================================================================
|
|
511
|
+
// Indent lever (--tree-list-indent)
|
|
512
|
+
// ===========================================================================
|
|
513
|
+
|
|
514
|
+
describe('indent lever', () => {
|
|
515
|
+
it('lets a theme retune the indent step via the tree-list target', () => {
|
|
516
|
+
// The per-level step is a public, themeable var (default --spacing-4) set
|
|
517
|
+
// on the tree-list root, so a theme can retune the indent metric (e.g. to
|
|
518
|
+
// --spacing-5) via defineTheme. jsdom cannot resolve the @layer cascade,
|
|
519
|
+
// so the generated CSS is what proves the override reaches the lever.
|
|
520
|
+
const theme = defineTheme({
|
|
521
|
+
name: 'tree-list-indent-test',
|
|
522
|
+
components: {
|
|
523
|
+
'tree-list': {
|
|
524
|
+
base: {'--tree-list-indent': 'var(--spacing-5)'},
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
});
|
|
528
|
+
const css = generateThemeCSSFlat(theme);
|
|
529
|
+
expect(css).toContain('.astryx-tree-list {');
|
|
530
|
+
expect(css).toContain('--tree-list-indent: var(--spacing-5)');
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it('rows consume the indent step in their published indent distance', () => {
|
|
534
|
+
// Each row's --_tree-indent is calc(level * var(--tree-list-indent)),
|
|
535
|
+
// so retuning the step scales every level uniformly.
|
|
536
|
+
render(<TreeList items={deepItems} variant="noGuides" />);
|
|
537
|
+
const indentOf = (text: string): string => {
|
|
538
|
+
const li = screen.getByText(text).closest('li')!;
|
|
539
|
+
const styled = li.querySelector('[style*="--_tree-indent"]');
|
|
540
|
+
return styled?.getAttribute('style') ?? '';
|
|
541
|
+
};
|
|
542
|
+
expect(indentOf('Mid')).toContain('var(--tree-list-indent)');
|
|
543
|
+
expect(indentOf('Leaf')).toContain('var(--tree-list-indent)');
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
|
|
396
547
|
// ===========================================================================
|
|
397
548
|
// xds class name
|
|
398
549
|
// ===========================================================================
|
|
@@ -403,6 +554,127 @@ describe('TreeList', () => {
|
|
|
403
554
|
expect(root.className).toContain('astryx-tree-list');
|
|
404
555
|
});
|
|
405
556
|
|
|
557
|
+
// ===========================================================================
|
|
558
|
+
// Chevron theme target
|
|
559
|
+
// ===========================================================================
|
|
560
|
+
|
|
561
|
+
describe('chevron theme target', () => {
|
|
562
|
+
it('renders the astryx-tree-list-chevron target on the toggle button', () => {
|
|
563
|
+
render(<TreeList items={nestedItems} />);
|
|
564
|
+
const toggle = screen
|
|
565
|
+
.getByText('Parent')
|
|
566
|
+
.closest('li')!
|
|
567
|
+
.querySelector('[data-tree-toggle]')!;
|
|
568
|
+
|
|
569
|
+
// Dedicated, stable theme target on the expand/collapse control, so a
|
|
570
|
+
// theme can restyle the chevron without a fragile [data-tree-toggle] hook.
|
|
571
|
+
expect(toggle).toHaveClass('astryx-tree-list-chevron');
|
|
572
|
+
// Open/closed state is reflected so a theme can target each state alone.
|
|
573
|
+
expect(toggle).toHaveAttribute('data-state', 'collapsed');
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
it('reflects the expanded state on the toggle when open', () => {
|
|
577
|
+
render(<TreeList items={nestedItemsExpanded} />);
|
|
578
|
+
const toggle = screen
|
|
579
|
+
.getByText('Parent')
|
|
580
|
+
.closest('li')!
|
|
581
|
+
.querySelector('[data-tree-toggle]')!;
|
|
582
|
+
|
|
583
|
+
expect(toggle).toHaveClass('astryx-tree-list-chevron');
|
|
584
|
+
expect(toggle).toHaveAttribute('data-state', 'expanded');
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
it('keeps the functional data-tree-toggle hook alongside the new target', () => {
|
|
588
|
+
// The theme target is additive — the toggle is still a real <button> and
|
|
589
|
+
// still carries the functional activation attribute TreeList relies on.
|
|
590
|
+
render(<TreeList items={nestedItems} />);
|
|
591
|
+
const toggle = screen
|
|
592
|
+
.getByText('Parent')
|
|
593
|
+
.closest('li')!
|
|
594
|
+
.querySelector('[data-tree-toggle]')!;
|
|
595
|
+
expect(toggle.tagName).toBe('BUTTON');
|
|
596
|
+
expect(toggle).toHaveAttribute('data-tree-toggle');
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
it('exposes tree-list-chevron as a themeable defineTheme target', () => {
|
|
600
|
+
// The generated CSS is what proves the target is reachable by a theme:
|
|
601
|
+
// jsdom cannot resolve the @layer cascade, so the DOM-class assertions
|
|
602
|
+
// above and this generation assertion together cover the seam.
|
|
603
|
+
const theme = defineTheme({
|
|
604
|
+
name: 'tree-list-chevron-test',
|
|
605
|
+
components: {
|
|
606
|
+
'tree-list-chevron': {
|
|
607
|
+
base: {color: 'var(--color-accent)'},
|
|
608
|
+
'state:expanded': {color: 'var(--color-text-primary)'},
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
const css = generateThemeCSSFlat(theme);
|
|
613
|
+
expect(css).toContain('.astryx-tree-list-chevron {');
|
|
614
|
+
expect(css).toContain('color: var(--color-accent)');
|
|
615
|
+
expect(css).toContain('.astryx-tree-list-chevron.expanded');
|
|
616
|
+
expect(css).toContain('color: var(--color-text-primary)');
|
|
617
|
+
});
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
// ===========================================================================
|
|
621
|
+
// Item label theme target
|
|
622
|
+
// ===========================================================================
|
|
623
|
+
|
|
624
|
+
describe('item label theme target', () => {
|
|
625
|
+
it('renders the astryx-tree-list-item-label target on the label span', () => {
|
|
626
|
+
render(<TreeList items={simpleItems} />);
|
|
627
|
+
const label = screen.getByText('Item A');
|
|
628
|
+
|
|
629
|
+
// Dedicated, stable theme target on the label text, so a theme can style
|
|
630
|
+
// just the label without a fragile `button:not([data-tree-toggle]) > span`
|
|
631
|
+
// structural selector.
|
|
632
|
+
expect(label).toHaveClass('astryx-tree-list-item-label');
|
|
633
|
+
// A non-selected item's label carries no selected reflection.
|
|
634
|
+
expect(label).not.toHaveAttribute('data-selected');
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
it('reflects the selected state on the selected item label', () => {
|
|
638
|
+
render(
|
|
639
|
+
<TreeList items={[{id: 'a', label: 'Item A', isSelected: true}]} />,
|
|
640
|
+
);
|
|
641
|
+
const label = screen.getByText('Item A');
|
|
642
|
+
expect(label).toHaveClass('astryx-tree-list-item-label');
|
|
643
|
+
expect(label).toHaveAttribute('data-selected', 'selected');
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
it('keeps the label linked to its row via aria-labelledby', () => {
|
|
647
|
+
// The theme target is additive — the label still owns the id the
|
|
648
|
+
// interactive row references for its accessible name.
|
|
649
|
+
render(
|
|
650
|
+
<TreeList items={[{id: 'a', label: 'Item A', onClick: () => {}}]} />,
|
|
651
|
+
);
|
|
652
|
+
const label = screen.getByText('Item A');
|
|
653
|
+
const action = screen.getByRole('button');
|
|
654
|
+
expect(action).toHaveAttribute('aria-labelledby', label.id);
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
it('exposes tree-list-item-label as a themeable defineTheme target', () => {
|
|
658
|
+
// The generated CSS is what proves the target is reachable by a theme:
|
|
659
|
+
// jsdom cannot resolve the @layer cascade, so the DOM-class assertions
|
|
660
|
+
// above and this generation assertion together cover the seam.
|
|
661
|
+
const theme = defineTheme({
|
|
662
|
+
name: 'tree-list-item-label-test',
|
|
663
|
+
components: {
|
|
664
|
+
'tree-list-item-label': {
|
|
665
|
+
base: {color: 'var(--color-text-primary)'},
|
|
666
|
+
selected: {fontWeight: 'var(--font-weight-bold)'},
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
});
|
|
670
|
+
const css = generateThemeCSSFlat(theme);
|
|
671
|
+
expect(css).toContain('.astryx-tree-list-item-label {');
|
|
672
|
+
expect(css).toContain('color: var(--color-text-primary)');
|
|
673
|
+
expect(css).toContain('.astryx-tree-list-item-label.selected');
|
|
674
|
+
expect(css).toContain('font-weight: var(--font-weight-bold)');
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
|
|
406
678
|
// ===========================================================================
|
|
407
679
|
// APG structural ARIA (aria-level / aria-posinset / aria-setsize)
|
|
408
680
|
// ===========================================================================
|