@astryxdesign/core 0.3.0 → 0.4.0
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 +156 -0
- package/dist/AlertDialog/AlertDialog.d.ts +10 -2
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +22 -3
- package/dist/AppShell/AppShell.d.ts +2 -2
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +40 -9
- package/dist/AspectRatio/AspectRatio.d.ts +13 -0
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +9 -0
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +33 -20
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +2 -3
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +15 -14
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +21 -8
- package/dist/Breadcrumbs/index.d.ts +2 -1
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +1 -0
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +11 -15
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +2 -1
- package/dist/Calendar/styles.d.ts +0 -2
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +0 -2
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +8 -12
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +2 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +3 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +4 -3
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +17 -17
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +2 -6
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +36 -125
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -11
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +84 -67
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +35 -15
- package/dist/CommandPalette/CommandPaletteItem.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +6 -3
- package/dist/CommandPalette/CommandPaletteList.js +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +35 -33
- package/dist/ContextMenu/ContextMenu.d.ts +2 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +1 -1
- package/dist/ContextMenu/index.d.ts +2 -1
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +1 -0
- package/dist/DateInput/DateInput.d.ts +9 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +24 -23
- package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +11 -16
- package/dist/DateTimeInput/DateTimeInput.d.ts +9 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +22 -17
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +4 -4
- package/dist/DropdownMenu/DropdownMenu.d.ts +33 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +62 -20
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +8 -11
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +32 -31
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts +25 -0
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuDivider.js +66 -0
- package/dist/DropdownMenu/DropdownMenuItem.d.ts +15 -2
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +20 -8
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +5 -5
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +24 -67
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -8
- package/dist/DropdownMenu/index.d.ts +2 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +4 -0
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +35 -27
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +9 -5
- package/dist/Field/InputClearButton.d.ts +16 -3
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +15 -4
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +3 -19
- package/dist/Indicator/CheckIndicator.d.ts +25 -0
- package/dist/Indicator/CheckIndicator.d.ts.map +1 -0
- package/dist/Indicator/CheckIndicator.js +155 -0
- package/dist/Indicator/CheckboxIndicator.d.ts +22 -0
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -0
- package/dist/Indicator/CheckboxIndicator.js +173 -0
- package/dist/Indicator/RadioIndicator.d.ts +23 -0
- package/dist/Indicator/RadioIndicator.d.ts.map +1 -0
- package/dist/Indicator/RadioIndicator.js +137 -0
- package/dist/Indicator/index.d.ts +24 -0
- package/dist/Indicator/index.d.ts.map +1 -0
- package/dist/Indicator/index.js +26 -0
- package/dist/Indicator/indicator.markers.stylex.d.ts +16 -0
- package/dist/Indicator/indicator.markers.stylex.d.ts.map +1 -0
- package/dist/Indicator/indicator.markers.stylex.js +21 -0
- package/dist/Indicator/indicatorRegistry.d.ts +71 -0
- package/dist/Indicator/indicatorRegistry.d.ts.map +1 -0
- package/dist/Indicator/indicatorRegistry.js +93 -0
- package/dist/Indicator/types.d.ts +167 -0
- package/dist/Indicator/types.d.ts.map +1 -0
- package/dist/Indicator/types.js +1 -0
- package/dist/Indicator/useIndicator.d.ts +18 -0
- package/dist/Indicator/useIndicator.d.ts.map +1 -0
- package/dist/Indicator/useIndicator.js +30 -0
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -8
- package/dist/Layer/useLayer.d.ts +14 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +25 -2
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +56 -53
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +4 -5
- package/dist/MobileNav/MobileNav.js +8 -8
- package/dist/MoreMenu/MoreMenu.d.ts +14 -1
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +78 -75
- package/dist/NumberInput/NumberInput.d.ts +27 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +230 -42
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +2 -3
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +61 -63
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +6 -8
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +7 -0
- package/dist/ProgressBar/ProgressBar.d.ts +11 -4
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +96 -6
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +29 -84
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +2 -3
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -3
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +3 -11
- package/dist/Selector/Selector.d.ts +2 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +164 -94
- package/dist/Selector/hooks.d.ts +18 -6
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +57 -40
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +29 -14
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +56 -20
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +28 -22
- package/dist/Stack/stack.stylex.d.ts +3 -3
- package/dist/Switch/Switch.js +11 -10
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -3
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +41 -19
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +8 -0
- package/dist/Table/index.d.ts +1 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +22 -18
- package/dist/Table/plugins/rowExpansion/index.d.ts +1 -1
- package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/index.js +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +41 -76
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +94 -345
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +23 -4
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +29 -33
- package/dist/Table/tableContextMenu.d.ts.map +1 -1
- package/dist/Table/tableContextMenu.js +2 -1
- package/dist/Table/types.d.ts +11 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +16 -6
- package/dist/TextInput/TextInput.d.ts +10 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +13 -19
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +32 -26
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +7 -15
- package/dist/Timestamp/TimestampHoverCard.d.ts.map +1 -1
- package/dist/Timestamp/TimestampHoverCard.js +16 -34
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +20 -11
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +4 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +3 -19
- package/dist/TopNav/TopNav.d.ts.map +1 -1
- package/dist/TopNav/TopNav.js +6 -5
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +54 -16
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +3 -9
- package/dist/TopNav/TopNavMegaMenu.d.ts +7 -0
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +146 -60
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +22 -3
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +83 -38
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +13 -0
- package/dist/TreeList/TreeListBranches.d.ts +1 -1
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +14 -4
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +57 -30
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +16 -8
- package/dist/astryx.css +74 -85
- package/dist/astryx.umd.js +56 -56
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/containerReveal.stylex.d.ts +61 -0
- package/dist/hooks/containerReveal.stylex.d.ts.map +1 -0
- package/dist/hooks/containerReveal.stylex.js +63 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/useClipboard.d.ts +59 -0
- package/dist/hooks/useClipboard.d.ts.map +1 -0
- package/dist/hooks/useClipboard.js +106 -0
- package/dist/hooks/useContainerReveal.d.ts +14 -8
- package/dist/hooks/useContainerReveal.d.ts.map +1 -1
- package/dist/hooks/useContainerReveal.js +28 -69
- package/dist/hooks/useIndicatorFocusRing.d.ts +28 -0
- package/dist/hooks/useIndicatorFocusRing.d.ts.map +1 -0
- package/dist/hooks/useIndicatorFocusRing.js +96 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +12 -2
- package/dist/hooks/useScrollLock.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.js +33 -18
- package/dist/hooks/useStreamingText.d.ts +18 -3
- package/dist/hooks/useStreamingText.d.ts.map +1 -1
- package/dist/hooks/useStreamingText.js +47 -7
- package/dist/hooks/useTreeFocus.d.ts.map +1 -1
- package/dist/hooks/useTreeFocus.js +9 -3
- package/dist/hooks/useTypeahead.d.ts +3 -2
- package/dist/hooks/useTypeahead.d.ts.map +1 -1
- package/dist/hooks/useTypeahead.js +19 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/defineTheme.d.ts +16 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +8 -0
- package/dist/theme/derivedVarRegistry.d.ts +8 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +14 -13
- package/dist/theme/expandColorScale.d.ts +3 -1
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +17 -7
- package/dist/theme/expandTypeScale.d.ts.map +1 -1
- package/dist/theme/expandTypeScale.js +17 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +11 -0
- package/dist/theme/index.d.ts +1 -0
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/utils/focusOutline.stylex.d.ts +107 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -0
- package/dist/utils/focusOutline.stylex.js +130 -0
- package/dist/utils/focusReturn.d.ts +24 -0
- package/dist/utils/focusReturn.d.ts.map +1 -0
- package/dist/utils/focusReturn.js +29 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/mergeRefs.d.ts.map +1 -1
- package/dist/utils/mergeRefs.js +7 -5
- package/dist/utils/rtlStyles.d.ts +2 -2
- package/dist/utils/rtlStyles.js +2 -2
- package/dist/utils/themeProps.d.ts +20 -1
- package/dist/utils/themeProps.d.ts.map +1 -1
- package/dist/utils/themeProps.js +8 -2
- package/locales/en.json +12 -0
- package/locales/pseudo.json +9 -0
- package/package.json +7 -2
- package/src/AlertDialog/AlertDialog.doc.mjs +16 -3
- package/src/AlertDialog/AlertDialog.test.tsx +208 -1
- package/src/AlertDialog/AlertDialog.tsx +21 -3
- package/src/AppShell/AppShell.doc.mjs +11 -0
- package/src/AppShell/AppShell.test.tsx +139 -0
- package/src/AppShell/AppShell.tsx +32 -22
- package/src/AspectRatio/AspectRatio.doc.mjs +27 -3
- package/src/AspectRatio/AspectRatio.test.tsx +30 -0
- package/src/AspectRatio/AspectRatio.tsx +13 -0
- package/src/Avatar/Avatar.doc.mjs +2 -13
- package/src/Avatar/Avatar.test.tsx +33 -8
- package/src/Avatar/Avatar.tsx +52 -50
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -9
- package/src/Banner/Banner.tsx +9 -6
- package/src/Breadcrumbs/BreadcrumbItem.tsx +16 -6
- package/src/Breadcrumbs/index.ts +5 -1
- package/src/Button/Button.tsx +21 -41
- package/src/Calendar/Calendar.tsx +2 -1
- package/src/Calendar/styles.ts +0 -8
- package/src/Carousel/Carousel.doc.mjs +3 -0
- package/src/Carousel/Carousel.tsx +10 -6
- package/src/Chat/Chat.doc.mjs +2 -0
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatLayoutScrollButton.test.tsx +22 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +8 -1
- package/src/Chat/ChatSendButton.tsx +2 -3
- package/src/Chat/ChatToolCalls.test.tsx +35 -0
- package/src/Chat/ChatToolCalls.tsx +36 -16
- package/src/Chat/useTriggerMenu.tsx +2 -5
- package/src/CheckboxInput/CheckboxInput.doc.mjs +4 -2
- package/src/CheckboxInput/CheckboxInput.test.tsx +115 -0
- package/src/CheckboxInput/CheckboxInput.tsx +45 -202
- package/src/ClickableCard/ClickableCard.tsx +6 -11
- package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
- package/src/CodeBlock/CodeBlock.test.tsx +91 -0
- package/src/CodeBlock/CodeBlock.tsx +57 -80
- package/src/Collapsible/Collapsible.tsx +22 -18
- package/src/CommandPalette/CommandPalette.test.tsx +29 -0
- package/src/CommandPalette/CommandPaletteItem.tsx +7 -4
- package/src/CommandPalette/CommandPaletteList.tsx +2 -2
- package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
- package/src/ComplexSelector/ComplexSelector.test.tsx +64 -0
- package/src/ComplexSelector/ComplexSelector.tsx +46 -29
- package/src/ContextMenu/ContextMenu.doc.mjs +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +41 -0
- package/src/ContextMenu/ContextMenu.tsx +3 -3
- package/src/ContextMenu/index.ts +5 -1
- package/src/DateInput/DateInput.doc.mjs +18 -3
- package/src/DateInput/DateInput.test.tsx +93 -11
- package/src/DateInput/DateInput.tsx +41 -19
- package/src/DateRangeInput/DateRangeInput.doc.mjs +10 -2
- package/src/DateRangeInput/DateRangeInput.test.tsx +110 -14
- package/src/DateRangeInput/DateRangeInput.tsx +24 -12
- package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -2
- package/src/DateTimeInput/DateTimeInput.test.tsx +75 -0
- package/src/DateTimeInput/DateTimeInput.tsx +35 -8
- package/src/Dialog/Dialog.tsx +2 -9
- package/src/DropdownMenu/DropdownMenu.doc.mjs +5 -9
- package/src/DropdownMenu/DropdownMenu.test.tsx +534 -4
- package/src/DropdownMenu/DropdownMenu.tsx +113 -52
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +27 -30
- package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +34 -0
- package/src/DropdownMenu/DropdownMenuDivider.tsx +81 -0
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +39 -4
- package/src/DropdownMenu/DropdownMenuItem.tsx +48 -10
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +30 -76
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +25 -19
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +44 -14
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +1 -5
- package/src/DropdownMenu/index.ts +8 -1
- package/src/DropdownMenu/renderDropdownItems.tsx +33 -34
- package/src/EmptyState/EmptyState.doc.mjs +4 -0
- package/src/EmptyState/EmptyState.test.tsx +62 -0
- package/src/EmptyState/EmptyState.tsx +16 -6
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/InputClearButton.test.tsx +117 -0
- package/src/Field/InputClearButton.tsx +30 -3
- package/src/HoverCard/useHoverCard.tsx +2 -23
- package/src/Icon/Icon.doc.mjs +2 -1
- package/src/Indicator/CheckIndicator.tsx +174 -0
- package/src/Indicator/CheckboxIndicator.tsx +257 -0
- package/src/Indicator/Indicator.doc.mjs +344 -0
- package/src/Indicator/Indicator.test.tsx +393 -0
- package/src/Indicator/RadioIndicator.tsx +206 -0
- package/src/Indicator/index.ts +45 -0
- package/src/Indicator/indicator.markers.stylex.ts +19 -0
- package/src/Indicator/indicatorRegistry.test.tsx +106 -0
- package/src/Indicator/indicatorRegistry.ts +120 -0
- package/src/Indicator/types.ts +186 -0
- package/src/Indicator/useIndicator.ts +39 -0
- package/src/Item/Item.doc.mjs +1 -1
- package/src/Item/Item.tsx +7 -14
- package/src/Layer/useLayer.doc.mjs +2 -2
- package/src/Layer/useLayer.test.tsx +85 -0
- package/src/Layer/useLayer.tsx +39 -1
- package/src/Lightbox/Lightbox.doc.mjs +1 -1
- package/src/Lightbox/Lightbox.tsx +43 -38
- package/src/Link/Link.tsx +4 -11
- package/src/MobileNav/MobileNav.tsx +3 -3
- package/src/MoreMenu/MoreMenu.doc.mjs +31 -0
- package/src/MoreMenu/MoreMenu.test.tsx +68 -1
- package/src/MoreMenu/MoreMenu.tsx +19 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +9 -1
- package/src/MultiSelector/MultiSelector.test.tsx +255 -16
- package/src/MultiSelector/MultiSelector.tsx +103 -99
- package/src/NumberInput/NumberInput.doc.mjs +265 -50
- package/src/NumberInput/NumberInput.test.tsx +726 -21
- package/src/NumberInput/NumberInput.tsx +353 -59
- package/src/Outline/Outline.tsx +2 -5
- package/src/Pagination/Pagination.doc.mjs +1 -1
- package/src/Pagination/Pagination.test.tsx +22 -7
- package/src/Pagination/Pagination.tsx +38 -35
- package/src/Popover/Popover.tsx +6 -7
- package/src/PowerSearch/PowerSearch.tsx +1 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +42 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +7 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +27 -5
- package/src/ProgressBar/ProgressBar.test.tsx +224 -1
- package/src/ProgressBar/ProgressBar.tsx +124 -22
- package/src/RadioList/RadioList.doc.mjs +4 -2
- package/src/RadioList/RadioListItem.tsx +31 -130
- package/src/Resizable/ResizeHandle.tsx +2 -9
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -9
- package/src/SelectableCard/SelectableCard.tsx +4 -9
- package/src/Selector/Selector.doc.mjs +7 -4
- package/src/Selector/Selector.test.tsx +935 -25
- package/src/Selector/Selector.tsx +189 -106
- package/src/Selector/hooks.ts +77 -50
- package/src/SideNav/SideNav.test.tsx +46 -0
- package/src/SideNav/SideNav.tsx +1 -0
- package/src/SideNav/SideNavCollapseButton.tsx +15 -10
- package/src/SideNav/SideNavHeading.tsx +48 -10
- package/src/SideNav/SideNavItem.tsx +20 -12
- package/src/Stack/Stack.doc.mjs +110 -0
- package/src/StatusDot/StatusDot.doc.mjs +12 -3
- package/src/Switch/Switch.test.tsx +32 -0
- package/src/Switch/Switch.tsx +8 -8
- package/src/TabList/Tab.tsx +2 -9
- package/src/TabList/TabMenu.tsx +14 -21
- package/src/Table/BaseTable.tsx +11 -0
- package/src/Table/index.ts +1 -4
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +30 -14
- package/src/Table/plugins/rowExpansion/index.ts +1 -4
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +125 -175
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +115 -458
- package/src/Table/plugins/sortable/useTableSortable.tsx +2 -6
- package/src/Table/plugins/tree/useTableTreeData.tsx +43 -24
- package/src/Table/tableContextMenu.test.tsx +27 -0
- package/src/Table/tableContextMenu.tsx +1 -0
- package/src/Table/types.ts +11 -0
- package/src/Table/useTableGroupedRows.doc.mjs +1 -1
- package/src/Table/useTableRowExpansion.doc.mjs +43 -66
- package/src/TextArea/TextArea.doc.mjs +42 -2
- package/src/TextArea/TextArea.test.tsx +219 -0
- package/src/TextArea/TextArea.tsx +34 -7
- package/src/TextInput/TextInput.doc.mjs +18 -2
- package/src/TextInput/TextInput.test.tsx +189 -0
- package/src/TextInput/TextInput.tsx +25 -31
- package/src/Thumbnail/Thumbnail.tsx +2 -9
- package/src/TimeInput/TimeInput.doc.mjs +2 -2
- package/src/TimeInput/TimeInput.test.tsx +30 -3
- package/src/TimeInput/TimeInput.tsx +9 -26
- package/src/Timestamp/Timestamp.doc.mjs +4 -3
- package/src/Timestamp/TimestampHoverCard.tsx +13 -35
- package/src/Token/Token.tsx +5 -28
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.test.tsx +45 -3
- package/src/Tokenizer/Tokenizer.tsx +10 -2
- package/src/Tooltip/useTooltip.tsx +2 -23
- package/src/TopNav/TopNav.tsx +1 -3
- package/src/TopNav/TopNavHeading.tsx +42 -13
- package/src/TopNav/TopNavItem.tsx +3 -21
- package/src/TopNav/TopNavMegaMenu.test.tsx +433 -33
- package/src/TopNav/TopNavMegaMenu.tsx +118 -53
- package/src/TopNav/TopNavMegaMenuItem.tsx +2 -9
- package/src/TopNav/TopNavMenu.tsx +34 -37
- package/src/TreeList/TreeList.doc.mjs +5 -0
- package/src/TreeList/TreeList.test.tsx +206 -7
- package/src/TreeList/TreeList.tsx +22 -0
- package/src/TreeList/TreeListBranches.tsx +25 -2
- package/src/TreeList/TreeListItem.tsx +89 -52
- package/src/Typeahead/BaseTypeahead.tsx +19 -6
- package/src/Typeahead/Typeahead.doc.mjs +1 -0
- package/src/Typeahead/Typeahead.test.tsx +76 -3
- package/src/hooks/containerReveal.stylex.ts +102 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useClipboard.doc.mjs +87 -0
- package/src/hooks/useClipboard.test.tsx +151 -0
- package/src/hooks/useClipboard.ts +135 -0
- package/src/hooks/useContainerReveal.doc.mjs +7 -7
- package/src/hooks/useContainerReveal.test.tsx +42 -62
- package/src/hooks/useContainerReveal.ts +36 -91
- package/src/hooks/useImageMode.test.ts +1 -1
- package/src/hooks/useIndicatorFocusRing.tsx +120 -0
- package/src/hooks/useLongPress.test.tsx +18 -0
- package/src/hooks/useLongPress.ts +12 -2
- package/src/hooks/useScrollLock.test.ts +72 -0
- package/src/hooks/useScrollLock.ts +51 -19
- package/src/hooks/useStreamingText.test.ts +46 -1
- package/src/hooks/useStreamingText.ts +49 -7
- package/src/hooks/useTreeFocus.test.tsx +50 -0
- package/src/hooks/useTreeFocus.ts +14 -3
- package/src/hooks/useTypeahead.test.tsx +150 -0
- package/src/hooks/useTypeahead.ts +24 -9
- package/src/i18n/InternationalizationProvider.doc.mjs +7 -2
- package/src/index.ts +1 -0
- package/src/theme/defineTheme.ts +24 -0
- package/src/theme/derivedVarRegistry.test.ts +21 -1
- package/src/theme/derivedVarRegistry.ts +19 -6
- package/src/theme/expandColorScale.test.ts +14 -0
- package/src/theme/expandColorScale.ts +24 -9
- package/src/theme/expandTypeScale.test.ts +43 -0
- package/src/theme/expandTypeScale.ts +17 -0
- package/src/theme/generateThemeRules.test.ts +61 -20
- package/src/theme/generateThemeRules.ts +11 -0
- package/src/theme/index.ts +13 -0
- package/src/utils/focusOutline.stylex.ts +163 -0
- package/src/utils/focusReturn.test.ts +42 -0
- package/src/utils/focusReturn.ts +31 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/mergeRefs.test.ts +48 -0
- package/src/utils/mergeRefs.ts +12 -6
- package/src/utils/rtlStyles.ts +2 -2
- package/src/utils/themeProps.ts +26 -4
- package/dist/CheckboxInput/checkbox.markers.stylex.d.ts +0 -9
- package/dist/CheckboxInput/checkbox.markers.stylex.d.ts.map +0 -1
- package/dist/CheckboxInput/checkbox.markers.stylex.js +0 -14
- package/dist/RadioList/radio.markers.stylex.d.ts +0 -7
- package/dist/RadioList/radio.markers.stylex.d.ts.map +0 -1
- package/dist/RadioList/radio.markers.stylex.js +0 -12
- package/dist/hooks/containerReveal.pool.stylex.d.ts +0 -303
- package/dist/hooks/containerReveal.pool.stylex.d.ts.map +0 -1
- package/dist/hooks/containerReveal.pool.stylex.js +0 -292
- package/src/CheckboxInput/checkbox.markers.stylex.ts +0 -12
- package/src/RadioList/radio.markers.stylex.ts +0 -10
- package/src/hooks/containerReveal.pool.stylex.ts +0 -571
|
@@ -9,13 +9,65 @@
|
|
|
9
9
|
* SYNC: When TopNavMegaMenu changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi, beforeAll, afterAll, afterEach} from 'vitest';
|
|
13
|
+
import {render, screen, act, fireEvent} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {TopNavMegaMenu} from './TopNavMegaMenu';
|
|
16
16
|
import {TopNavMegaMenuItem} from './TopNavMegaMenuItem';
|
|
17
17
|
import {TopNavRenderContext} from './TopNavRenderContext';
|
|
18
18
|
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Popover API mock — jsdom implements no Popover API, so default-mode tests
|
|
21
|
+
// that actually open/close the panel install these shims on HTMLElement.
|
|
22
|
+
// =============================================================================
|
|
23
|
+
|
|
24
|
+
let originalMatches: typeof HTMLElement.prototype.matches;
|
|
25
|
+
|
|
26
|
+
function installPopoverApiMock() {
|
|
27
|
+
originalMatches = HTMLElement.prototype.matches;
|
|
28
|
+
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
29
|
+
// Model the browser's auto-popover stack: opening one auto popover evicts
|
|
30
|
+
// any currently open auto popover before showing the new one.
|
|
31
|
+
if (this.getAttribute('popover') === 'auto') {
|
|
32
|
+
document
|
|
33
|
+
.querySelectorAll<HTMLElement>('[popover="auto"][popover-open]')
|
|
34
|
+
.forEach(openPopover => {
|
|
35
|
+
if (openPopover === this) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
openPopover.removeAttribute('popover-open');
|
|
39
|
+
const closeEvent = new Event('toggle', {bubbles: false});
|
|
40
|
+
Object.defineProperty(closeEvent, 'newState', {value: 'closed'});
|
|
41
|
+
openPopover.dispatchEvent(closeEvent);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
this.setAttribute('popover-open', '');
|
|
45
|
+
const event = new Event('toggle', {bubbles: false});
|
|
46
|
+
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
47
|
+
this.dispatchEvent(event);
|
|
48
|
+
});
|
|
49
|
+
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
50
|
+
this.removeAttribute('popover-open');
|
|
51
|
+
const event = new Event('toggle', {bubbles: false});
|
|
52
|
+
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
53
|
+
this.dispatchEvent(event);
|
|
54
|
+
});
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
+
(HTMLElement.prototype as any).matches = function (
|
|
57
|
+
selector: string,
|
|
58
|
+
): boolean {
|
|
59
|
+
if (selector === ':popover-open') {
|
|
60
|
+
return this.hasAttribute('popover-open');
|
|
61
|
+
}
|
|
62
|
+
return originalMatches.call(this, selector);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function restorePopoverApiMock() {
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
+
(HTMLElement.prototype as any).matches = originalMatches;
|
|
69
|
+
}
|
|
70
|
+
|
|
19
71
|
// =============================================================================
|
|
20
72
|
// Default (desktop) mode
|
|
21
73
|
// =============================================================================
|
|
@@ -80,37 +132,8 @@ describe('TopNavMegaMenu — default mode', () => {
|
|
|
80
132
|
// =============================================================================
|
|
81
133
|
|
|
82
134
|
describe('TopNavMegaMenu — popup semantics', () => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
beforeAll(() => {
|
|
87
|
-
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
88
|
-
this.setAttribute('popover-open', '');
|
|
89
|
-
const event = new Event('toggle', {bubbles: false});
|
|
90
|
-
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
91
|
-
this.dispatchEvent(event);
|
|
92
|
-
});
|
|
93
|
-
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
94
|
-
this.removeAttribute('popover-open');
|
|
95
|
-
const event = new Event('toggle', {bubbles: false});
|
|
96
|
-
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
97
|
-
this.dispatchEvent(event);
|
|
98
|
-
});
|
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
|
-
(HTMLElement.prototype as any).matches = function (
|
|
101
|
-
selector: string,
|
|
102
|
-
): boolean {
|
|
103
|
-
if (selector === ':popover-open') {
|
|
104
|
-
return this.hasAttribute('popover-open');
|
|
105
|
-
}
|
|
106
|
-
return originalMatches.call(this, selector);
|
|
107
|
-
};
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
afterAll(() => {
|
|
111
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
112
|
-
(HTMLElement.prototype as any).matches = originalMatches;
|
|
113
|
-
});
|
|
135
|
+
beforeAll(installPopoverApiMock);
|
|
136
|
+
afterAll(restorePopoverApiMock);
|
|
114
137
|
|
|
115
138
|
it('trigger aria-controls resolves to the popup element', async () => {
|
|
116
139
|
const user = userEvent.setup();
|
|
@@ -223,6 +246,383 @@ describe('TopNavMegaMenu — popup semantics', () => {
|
|
|
223
246
|
});
|
|
224
247
|
});
|
|
225
248
|
|
|
249
|
+
// =============================================================================
|
|
250
|
+
// Hover → click guard (default mode) — issue #3121
|
|
251
|
+
//
|
|
252
|
+
// The trigger opens on hover and on click. A hover-open records a timestamp so
|
|
253
|
+
// the click that naturally follows a hover confirms and pins the panel for
|
|
254
|
+
// CLICK_GUARD_MS (the panel just appeared under the cursor) instead of toggling
|
|
255
|
+
// it shut. Deliberate clicks outside that window still toggle.
|
|
256
|
+
// =============================================================================
|
|
257
|
+
|
|
258
|
+
describe('TopNavMegaMenu — hover/click guard (default mode)', () => {
|
|
259
|
+
beforeAll(installPopoverApiMock);
|
|
260
|
+
afterAll(restorePopoverApiMock);
|
|
261
|
+
afterEach(() => {
|
|
262
|
+
vi.useRealTimers();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
function renderMenu() {
|
|
266
|
+
render(
|
|
267
|
+
<TopNavMegaMenu
|
|
268
|
+
label="Products"
|
|
269
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
270
|
+
/>,
|
|
271
|
+
);
|
|
272
|
+
return screen.getByRole('button', {name: 'Products'});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
it('keeps the panel open when a hover-open is immediately clicked', async () => {
|
|
276
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
277
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
278
|
+
const trigger = renderMenu();
|
|
279
|
+
|
|
280
|
+
// Hover opens the panel after the show delay (150ms).
|
|
281
|
+
await user.hover(trigger);
|
|
282
|
+
act(() => {
|
|
283
|
+
vi.advanceTimersByTime(200);
|
|
284
|
+
});
|
|
285
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
286
|
+
|
|
287
|
+
// The click that naturally follows the hover must NOT toggle it shut.
|
|
288
|
+
await user.click(trigger);
|
|
289
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
290
|
+
|
|
291
|
+
// It is still a click interaction, so it pins the panel just like a
|
|
292
|
+
// click-open. Leaving the trigger must not dismiss it.
|
|
293
|
+
await user.unhover(trigger);
|
|
294
|
+
act(() => {
|
|
295
|
+
vi.advanceTimersByTime(300);
|
|
296
|
+
});
|
|
297
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('closes on a click that lands well after the hover-open (past the guard)', async () => {
|
|
301
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
302
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
303
|
+
const trigger = renderMenu();
|
|
304
|
+
|
|
305
|
+
await user.hover(trigger);
|
|
306
|
+
act(() => {
|
|
307
|
+
vi.advanceTimersByTime(200);
|
|
308
|
+
});
|
|
309
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
310
|
+
|
|
311
|
+
// Past the guard window, a click is a deliberate dismissal.
|
|
312
|
+
act(() => {
|
|
313
|
+
vi.advanceTimersByTime(600);
|
|
314
|
+
});
|
|
315
|
+
await user.click(trigger);
|
|
316
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('toggles cleanly for click-only interaction (no hover, no guard)', async () => {
|
|
320
|
+
const user = userEvent.setup();
|
|
321
|
+
const trigger = renderMenu();
|
|
322
|
+
|
|
323
|
+
// A click with no preceding hover opens...
|
|
324
|
+
await user.click(trigger);
|
|
325
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
326
|
+
|
|
327
|
+
// ...and the next click closes — the guard only applies after a hover-open.
|
|
328
|
+
await user.click(trigger);
|
|
329
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('closes a hover-opened (transient) panel when the pointer leaves', async () => {
|
|
333
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
334
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
335
|
+
const trigger = renderMenu();
|
|
336
|
+
|
|
337
|
+
await user.hover(trigger);
|
|
338
|
+
act(() => {
|
|
339
|
+
vi.advanceTimersByTime(200);
|
|
340
|
+
});
|
|
341
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
342
|
+
|
|
343
|
+
// Leaving closes it after hideDelay (250ms) — hover opens are transient.
|
|
344
|
+
await user.unhover(trigger);
|
|
345
|
+
act(() => {
|
|
346
|
+
vi.advanceTimersByTime(300);
|
|
347
|
+
});
|
|
348
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('keeps a click-opened (pinned) panel open when the pointer leaves', async () => {
|
|
352
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
353
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
354
|
+
const trigger = renderMenu();
|
|
355
|
+
|
|
356
|
+
// A click pins the panel open (a deliberate open should persist).
|
|
357
|
+
await user.click(trigger);
|
|
358
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
359
|
+
|
|
360
|
+
await user.unhover(trigger);
|
|
361
|
+
act(() => {
|
|
362
|
+
vi.advanceTimersByTime(400);
|
|
363
|
+
});
|
|
364
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('re-entering the trigger cancels a pending hide', async () => {
|
|
368
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
369
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
370
|
+
const trigger = renderMenu();
|
|
371
|
+
|
|
372
|
+
await user.hover(trigger);
|
|
373
|
+
act(() => {
|
|
374
|
+
vi.advanceTimersByTime(200);
|
|
375
|
+
});
|
|
376
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
377
|
+
|
|
378
|
+
// Leave (schedules a hide), then return before hideDelay elapses.
|
|
379
|
+
await user.unhover(trigger);
|
|
380
|
+
act(() => {
|
|
381
|
+
vi.advanceTimersByTime(100);
|
|
382
|
+
});
|
|
383
|
+
await user.hover(trigger);
|
|
384
|
+
act(() => {
|
|
385
|
+
vi.advanceTimersByTime(300);
|
|
386
|
+
});
|
|
387
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('does not reopen when the pointer enters the panel after close', async () => {
|
|
391
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
392
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
393
|
+
const trigger = renderMenu();
|
|
394
|
+
const panel = screen.getByRole('group', {
|
|
395
|
+
name: 'Products',
|
|
396
|
+
hidden: true,
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
await user.click(trigger);
|
|
400
|
+
await user.click(trigger);
|
|
401
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
402
|
+
|
|
403
|
+
// The exit transition can leave the closed panel briefly hit-testable.
|
|
404
|
+
fireEvent.mouseEnter(panel);
|
|
405
|
+
act(() => {
|
|
406
|
+
vi.advanceTimersByTime(200);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('re-hovering an open panel does not refresh the click guard', async () => {
|
|
413
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
414
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
415
|
+
const trigger = renderMenu();
|
|
416
|
+
|
|
417
|
+
await user.hover(trigger);
|
|
418
|
+
act(() => {
|
|
419
|
+
vi.advanceTimersByTime(200);
|
|
420
|
+
});
|
|
421
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
422
|
+
|
|
423
|
+
// Wait past the guard window, re-hovering along the way. The re-hover must
|
|
424
|
+
// NOT re-stamp the guard timestamp (only a fresh open may), so the click
|
|
425
|
+
// below is still judged a deliberate close.
|
|
426
|
+
act(() => {
|
|
427
|
+
vi.advanceTimersByTime(600);
|
|
428
|
+
});
|
|
429
|
+
await user.hover(trigger);
|
|
430
|
+
act(() => {
|
|
431
|
+
vi.advanceTimersByTime(200);
|
|
432
|
+
});
|
|
433
|
+
await user.click(trigger);
|
|
434
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('opening a sibling mega menu closes the pinned menu through the native auto-popover stack', async () => {
|
|
438
|
+
vi.useFakeTimers({shouldAdvanceTime: true});
|
|
439
|
+
const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
|
|
440
|
+
render(
|
|
441
|
+
<>
|
|
442
|
+
<TopNavMegaMenu
|
|
443
|
+
label="Products"
|
|
444
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
445
|
+
/>
|
|
446
|
+
<TopNavMegaMenu
|
|
447
|
+
label="Solutions"
|
|
448
|
+
items={<TopNavMegaMenuItem title="Enterprise" href="/enterprise" />}
|
|
449
|
+
/>
|
|
450
|
+
</>,
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
const products = screen.getByRole('button', {name: 'Products'});
|
|
454
|
+
const solutions = screen.getByRole('button', {name: 'Solutions'});
|
|
455
|
+
|
|
456
|
+
await user.click(products);
|
|
457
|
+
expect(products).toHaveAttribute('aria-expanded', 'true');
|
|
458
|
+
|
|
459
|
+
await user.hover(solutions);
|
|
460
|
+
act(() => {
|
|
461
|
+
vi.advanceTimersByTime(200);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
expect(products).toHaveAttribute('aria-expanded', 'false');
|
|
465
|
+
expect(solutions).toHaveAttribute('aria-expanded', 'true');
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// =============================================================================
|
|
470
|
+
// Dismissal (default mode) — issue #3121
|
|
471
|
+
//
|
|
472
|
+
// The panel stays an *auto* popover for native light dismiss and stack
|
|
473
|
+
// exclusivity. `popoverTarget` makes the button its native invoker so trigger
|
|
474
|
+
// activation is not treated as an outside click before the guard can run.
|
|
475
|
+
// jsdom cannot exercise that native event ordering; these tests lock in the
|
|
476
|
+
// required wiring, while the end-to-end interaction is browser-verified in the
|
|
477
|
+
// PR's manual test plan.
|
|
478
|
+
// =============================================================================
|
|
479
|
+
|
|
480
|
+
describe('TopNavMegaMenu — dismissal (default mode)', () => {
|
|
481
|
+
beforeAll(installPopoverApiMock);
|
|
482
|
+
afterAll(restorePopoverApiMock);
|
|
483
|
+
|
|
484
|
+
function renderAndOpen() {
|
|
485
|
+
render(
|
|
486
|
+
<TopNavMegaMenu
|
|
487
|
+
label="Products"
|
|
488
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
489
|
+
/>,
|
|
490
|
+
);
|
|
491
|
+
return screen.getByRole('button', {name: 'Products'});
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
it('renders an auto popover and registers the trigger as its native invoker', () => {
|
|
495
|
+
const trigger = renderAndOpen();
|
|
496
|
+
const popup = document.getElementById(
|
|
497
|
+
trigger.getAttribute('aria-controls') as string,
|
|
498
|
+
);
|
|
499
|
+
expect(popup).toHaveAttribute('popover', 'auto');
|
|
500
|
+
expect(trigger).toHaveAttribute('popovertarget', popup?.id);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
it('prevents the native invoker toggle so the click guard owns activation', async () => {
|
|
504
|
+
const trigger = renderAndOpen();
|
|
505
|
+
|
|
506
|
+
const clickEvent = new MouseEvent('click', {
|
|
507
|
+
bubbles: true,
|
|
508
|
+
cancelable: true,
|
|
509
|
+
detail: 1,
|
|
510
|
+
});
|
|
511
|
+
fireEvent(trigger, clickEvent);
|
|
512
|
+
|
|
513
|
+
expect(clickEvent.defaultPrevented).toBe(true);
|
|
514
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
it('reconciles a browser-initiated native light dismiss', async () => {
|
|
518
|
+
const user = userEvent.setup();
|
|
519
|
+
const trigger = renderAndOpen();
|
|
520
|
+
|
|
521
|
+
await user.click(trigger);
|
|
522
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
523
|
+
|
|
524
|
+
const popup = document.getElementById(
|
|
525
|
+
trigger.getAttribute('aria-controls') as string,
|
|
526
|
+
) as HTMLElement;
|
|
527
|
+
popup.removeAttribute('popover-open');
|
|
528
|
+
const toggleEvent = new Event('toggle', {bubbles: false});
|
|
529
|
+
Object.defineProperty(toggleEvent, 'newState', {value: 'closed'});
|
|
530
|
+
fireEvent(popup, toggleEvent);
|
|
531
|
+
|
|
532
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// =============================================================================
|
|
537
|
+
// Keyboard (default mode) — issue #3121
|
|
538
|
+
//
|
|
539
|
+
// Keyboard activation always OPENS (never toggles the panel closed) and moves
|
|
540
|
+
// focus into the panel; Escape closes it and returns focus to the trigger.
|
|
541
|
+
// =============================================================================
|
|
542
|
+
|
|
543
|
+
describe('TopNavMegaMenu — keyboard (default mode)', () => {
|
|
544
|
+
beforeAll(installPopoverApiMock);
|
|
545
|
+
afterAll(restorePopoverApiMock);
|
|
546
|
+
|
|
547
|
+
it('opens on Enter (keyboard activation)', async () => {
|
|
548
|
+
const user = userEvent.setup();
|
|
549
|
+
render(
|
|
550
|
+
<TopNavMegaMenu
|
|
551
|
+
label="Products"
|
|
552
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
553
|
+
/>,
|
|
554
|
+
);
|
|
555
|
+
const trigger = screen.getByRole('button', {name: 'Products'});
|
|
556
|
+
trigger.focus();
|
|
557
|
+
|
|
558
|
+
await user.keyboard('{Enter}');
|
|
559
|
+
|
|
560
|
+
// aria-expanded is the observable signal. Enter also auto-focuses the first
|
|
561
|
+
// link (unlike pointer/hover opens, which keep focus on the trigger), but
|
|
562
|
+
// that focus landing is only verifiable in a real browser — jsdom renders
|
|
563
|
+
// the popover content display:none, so activeElement can't move onto it
|
|
564
|
+
// (browser-verified via the Playwright checks for #3121). Panel content
|
|
565
|
+
// presence is deliberately NOT asserted: useLayer renders it into the DOM
|
|
566
|
+
// even while closed, so such an assertion would be vacuous.
|
|
567
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
it('opens on Space', async () => {
|
|
571
|
+
const user = userEvent.setup();
|
|
572
|
+
render(
|
|
573
|
+
<TopNavMegaMenu
|
|
574
|
+
label="Products"
|
|
575
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
576
|
+
/>,
|
|
577
|
+
);
|
|
578
|
+
const trigger = screen.getByRole('button', {name: 'Products'});
|
|
579
|
+
trigger.focus();
|
|
580
|
+
|
|
581
|
+
await user.keyboard(' ');
|
|
582
|
+
|
|
583
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
it('keyboard activation never toggles an open panel closed', async () => {
|
|
587
|
+
const user = userEvent.setup();
|
|
588
|
+
render(
|
|
589
|
+
<TopNavMegaMenu
|
|
590
|
+
label="Products"
|
|
591
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
592
|
+
/>,
|
|
593
|
+
);
|
|
594
|
+
const trigger = screen.getByRole('button', {name: 'Products'});
|
|
595
|
+
|
|
596
|
+
// Open via pointer (focus stays on the trigger).
|
|
597
|
+
await user.click(trigger);
|
|
598
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
599
|
+
|
|
600
|
+
// Enter on an already-open panel keeps it open — no toggle-close.
|
|
601
|
+
trigger.focus();
|
|
602
|
+
await user.keyboard('{Enter}');
|
|
603
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
it('closes on Escape and returns focus to the trigger', async () => {
|
|
607
|
+
const user = userEvent.setup();
|
|
608
|
+
render(
|
|
609
|
+
<TopNavMegaMenu
|
|
610
|
+
label="Products"
|
|
611
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
612
|
+
/>,
|
|
613
|
+
);
|
|
614
|
+
const trigger = screen.getByRole('button', {name: 'Products'});
|
|
615
|
+
|
|
616
|
+
// Pointer open leaves focus on the trigger.
|
|
617
|
+
await user.click(trigger);
|
|
618
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
619
|
+
|
|
620
|
+
await user.keyboard('{Escape}');
|
|
621
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
622
|
+
expect(trigger).toHaveFocus();
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
|
|
226
626
|
// =============================================================================
|
|
227
627
|
// Mobile-bar mode — should be hidden
|
|
228
628
|
// =============================================================================
|