@astryxdesign/core 0.2.0 → 0.3.0-canary.041a0ef
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 +110 -0
- package/README.md +5 -3
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.js +1 -1
- package/dist/AppShell/AppShell.d.ts +2 -20
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +25 -18
- package/dist/AppShell/index.d.ts +20 -1
- package/dist/AppShell/index.d.ts.map +1 -1
- package/dist/AppShell/index.js +14 -0
- package/dist/AspectRatio/AspectRatio.d.ts +1 -1
- package/dist/AspectRatio/AspectRatio.js +1 -1
- package/dist/Avatar/Avatar.d.ts +1 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +37 -24
- package/dist/Avatar/AvatarStatusDot.d.ts +2 -26
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +1 -22
- package/dist/Avatar/index.d.ts +26 -1
- package/dist/Avatar/index.d.ts.map +1 -1
- package/dist/Avatar/index.js +21 -0
- package/dist/AvatarGroup/AvatarGroup.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +4 -8
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +2 -2
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +9 -6
- package/dist/Badge/Badge.d.ts +2 -30
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +2 -17
- package/dist/Badge/index.d.ts +31 -2
- package/dist/Badge/index.d.ts.map +1 -1
- package/dist/Badge/index.js +15 -1
- package/dist/Banner/Banner.d.ts +2 -37
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +21 -48
- package/dist/Banner/index.d.ts +37 -1
- package/dist/Banner/index.d.ts.map +1 -1
- package/dist/Banner/index.js +27 -0
- package/dist/Blockquote/Blockquote.d.ts +1 -1
- package/dist/Blockquote/Blockquote.js +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +22 -8
- package/dist/Breadcrumbs/Breadcrumbs.d.ts +2 -18
- package/dist/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs/Breadcrumbs.js +1 -15
- package/dist/Breadcrumbs/index.d.ts +18 -1
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +14 -0
- package/dist/Button/Button.d.ts +3 -21
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +17 -34
- package/dist/Button/index.d.ts +21 -3
- package/dist/Button/index.d.ts.map +1 -1
- package/dist/Button/index.js +15 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +1 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +3 -2
- package/dist/Calendar/index.d.ts +1 -1
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +2 -4
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +2 -4
- package/dist/Calendar/utils.d.ts +0 -4
- package/dist/Calendar/utils.d.ts.map +1 -1
- package/dist/Calendar/utils.js +1 -8
- package/dist/Card/Card.d.ts +1 -1
- package/dist/Card/Card.js +1 -1
- package/dist/Carousel/Carousel.d.ts +54 -3
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +90 -27
- package/dist/Carousel/index.d.ts +1 -1
- package/dist/Carousel/index.d.ts.map +1 -1
- package/dist/Center/Center.d.ts +21 -4
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +11 -3
- package/dist/Chat/ChatComposer.d.ts +1 -1
- package/dist/Chat/ChatComposer.js +9 -9
- package/dist/Chat/ChatComposerDrawer.d.ts +1 -1
- package/dist/Chat/ChatComposerDrawer.js +5 -5
- package/dist/Chat/ChatComposerInput.d.ts +1 -1
- package/dist/Chat/ChatComposerInput.js +1 -1
- package/dist/Chat/ChatDictationButton.d.ts +1 -1
- package/dist/Chat/ChatDictationButton.js +1 -1
- package/dist/Chat/ChatLayout.d.ts +8 -1
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +15 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +2 -1
- package/dist/Chat/ChatMessage.d.ts +1 -1
- package/dist/Chat/ChatMessage.js +1 -1
- package/dist/Chat/ChatMessageBubble.d.ts +1 -1
- package/dist/Chat/ChatMessageBubble.js +1 -1
- package/dist/Chat/ChatMessageList.d.ts +1 -1
- package/dist/Chat/ChatMessageList.js +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +4 -2
- package/dist/Chat/ChatSystemMessage.d.ts +1 -1
- package/dist/Chat/ChatSystemMessage.js +1 -1
- package/dist/Chat/ChatTokenizedText.d.ts +1 -1
- package/dist/Chat/ChatTokenizedText.js +1 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +17 -17
- package/dist/CheckboxInput/CheckboxInput.d.ts +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +3 -3
- package/dist/CheckboxList/CheckboxList.d.ts +1 -1
- package/dist/CheckboxList/CheckboxList.js +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +20 -5
- package/dist/Citation/Citation.d.ts +1 -1
- package/dist/Citation/Citation.js +1 -1
- package/dist/ClickableCard/ClickableCard.d.ts +3 -3
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +6 -14
- package/dist/Code/Code.d.ts +2 -2
- package/dist/Code/Code.js +2 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +35 -18
- package/dist/Collapsible/Collapsible.d.ts +1 -1
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +36 -16
- package/dist/Collapsible/CollapsibleGroup.d.ts +1 -1
- package/dist/Collapsible/CollapsibleGroup.js +1 -1
- package/dist/Collapsible/CollapsibleGroupContext.js +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.js +1 -1
- package/dist/CommandPalette/CommandPaletteEmpty.js +1 -1
- package/dist/CommandPalette/CommandPaletteFooter.js +1 -1
- package/dist/CommandPalette/CommandPaletteGroup.js +1 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts +2 -2
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +4 -2
- package/dist/CommandPalette/CommandPaletteItem.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/CommandPalette/CommandPaletteList.js +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts +108 -0
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -0
- package/dist/ComplexSelector/ComplexSelector.js +310 -0
- package/dist/ComplexSelector/index.d.ts +7 -0
- package/dist/ComplexSelector/index.d.ts.map +1 -0
- package/dist/ComplexSelector/index.js +10 -0
- package/dist/ContextMenu/ContextMenu.d.ts +2 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +24 -6
- package/dist/DateInput/DateInput.d.ts +9 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +6 -3
- package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +6 -3
- package/dist/DateTimeInput/DateTimeInput.d.ts +9 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +6 -3
- package/dist/Dialog/Dialog.d.ts +33 -24
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +47 -31
- package/dist/Dialog/DialogHeader.d.ts +1 -1
- package/dist/Dialog/DialogHeader.js +1 -1
- package/dist/Dialog/index.d.ts +18 -1
- package/dist/Dialog/index.d.ts.map +1 -1
- package/dist/Dialog/index.js +14 -0
- package/dist/Divider/Divider.d.ts +2 -18
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +1 -15
- package/dist/Divider/index.d.ts +18 -1
- package/dist/Divider/index.d.ts.map +1 -1
- package/dist/Divider/index.js +14 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +28 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +75 -23
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +18 -12
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +38 -63
- package/dist/DropdownMenu/DropdownMenuItem.d.ts +8 -3
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +14 -5
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +6 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +14 -6
- package/dist/DropdownMenu/menuItemHover.d.ts +1 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemHover.js +1 -0
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +27 -16
- package/dist/EmptyState/EmptyState.d.ts +1 -1
- package/dist/EmptyState/EmptyState.js +1 -1
- package/dist/Field/Field.d.ts +1 -1
- package/dist/Field/Field.js +1 -1
- package/dist/Field/FieldLabel.d.ts +4 -3
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +48 -5
- package/dist/FieldStatus/FieldStatus.d.ts +1 -18
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +13 -17
- package/dist/FieldStatus/index.d.ts +19 -1
- package/dist/FieldStatus/index.d.ts.map +1 -1
- package/dist/FieldStatus/index.js +14 -0
- package/dist/FileInput/FileInput.js +1 -1
- package/dist/FormLayout/FormLayout.d.ts +1 -1
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +1 -1
- package/dist/Grid/Grid.d.ts +2 -10
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +1 -10
- package/dist/Grid/GridSpan.d.ts +1 -1
- package/dist/Grid/GridSpan.js +1 -1
- package/dist/HStack/HStack.d.ts +1 -1
- package/dist/HStack/HStack.js +1 -1
- package/dist/Heading/Heading.d.ts +2 -2
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +5 -4
- package/dist/HoverCard/HoverCard.d.ts +1 -1
- package/dist/HoverCard/HoverCard.js +1 -1
- package/dist/Icon/Icon.d.ts +1 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +4 -2
- package/dist/Icon/defaultIcons.d.ts.map +1 -1
- package/dist/Icon/defaultIcons.js +14 -0
- package/dist/Icon/globalIconRegistry.d.ts +48 -6
- package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
- package/dist/Icon/globalIconRegistry.js +74 -7
- package/dist/Icon/index.d.ts +4 -3
- package/dist/Icon/index.d.ts.map +1 -1
- package/dist/Icon/index.js +2 -1
- package/dist/Icon/useIcon.d.ts +14 -0
- package/dist/Icon/useIcon.d.ts.map +1 -0
- package/dist/Icon/useIcon.js +21 -0
- package/dist/IconButton/IconButton.d.ts +1 -1
- package/dist/IconButton/IconButton.js +1 -1
- package/dist/InputGroup/InputGroup.d.ts +1 -1
- package/dist/InputGroup/InputGroup.js +1 -1
- package/dist/InputGroup/InputGroupText.d.ts +1 -1
- package/dist/InputGroup/InputGroupText.js +1 -1
- package/dist/Item/Item.d.ts +17 -4
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +36 -15
- package/dist/Kbd/Kbd.d.ts +1 -1
- package/dist/Kbd/Kbd.js +1 -1
- package/dist/Layout/Layout.d.ts +1 -1
- package/dist/Layout/Layout.js +1 -1
- package/dist/Layout/LayoutContent.d.ts +1 -1
- package/dist/Layout/LayoutContent.js +1 -1
- package/dist/Layout/LayoutFooter.d.ts +1 -1
- package/dist/Layout/LayoutFooter.js +1 -1
- package/dist/Layout/LayoutHeader.d.ts +1 -1
- package/dist/Layout/LayoutHeader.js +1 -1
- package/dist/Layout/LayoutPanel.d.ts +1 -1
- package/dist/Layout/LayoutPanel.js +1 -1
- package/dist/Lightbox/Lightbox.d.ts +6 -4
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +173 -79
- package/dist/Link/Link.d.ts +1 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +5 -6
- package/dist/Link/LinkProvider.d.ts +2 -2
- package/dist/Link/LinkProvider.js +2 -2
- package/dist/List/List.d.ts +1 -1
- package/dist/List/List.js +1 -1
- package/dist/List/ListItem.d.ts +12 -2
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +3 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +35 -13
- package/dist/MetadataList/MetadataList.d.ts +2 -2
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +38 -12
- package/dist/MetadataList/MetadataListItem.d.ts +1 -1
- package/dist/MetadataList/MetadataListItem.js +1 -1
- package/dist/MobileNav/MobileNav.d.ts +1 -1
- package/dist/MobileNav/MobileNav.js +9 -9
- package/dist/MoreMenu/MoreMenu.d.ts +1 -1
- package/dist/MoreMenu/MoreMenu.js +3 -3
- package/dist/MultiSelector/MultiSelector.d.ts +13 -4
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +155 -54
- package/dist/NavIcon/NavIcon.d.ts +1 -1
- package/dist/NavIcon/NavIcon.js +1 -1
- package/dist/NavMenu/index.d.ts +0 -2
- package/dist/NavMenu/index.d.ts.map +1 -1
- package/dist/NavMenu/index.js +1 -3
- package/dist/NumberInput/NumberInput.d.ts +1 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +19 -7
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +3 -4
- package/dist/OverflowList/OverflowList.d.ts +1 -1
- package/dist/OverflowList/OverflowList.js +1 -1
- package/dist/Pagination/Pagination.d.ts +26 -21
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +204 -78
- package/dist/Pagination/index.d.ts +22 -1
- package/dist/Pagination/index.d.ts.map +1 -1
- package/dist/Pagination/index.js +14 -0
- package/dist/Popover/Popover.d.ts +20 -3
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +5 -1
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +14 -3
- package/dist/PowerSearch/PowerSearch.d.ts +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 +56 -22
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +169 -22
- package/dist/ProgressBar/ProgressBarMarkTooltip.d.ts +27 -0
- package/dist/ProgressBar/ProgressBarMarkTooltip.d.ts.map +1 -0
- package/dist/ProgressBar/ProgressBarMarkTooltip.js +35 -0
- package/dist/ProgressBar/index.d.ts +21 -1
- package/dist/ProgressBar/index.d.ts.map +1 -1
- package/dist/ProgressBar/index.js +14 -0
- package/dist/RadioList/RadioList.d.ts +1 -1
- package/dist/RadioList/RadioList.js +1 -1
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +2 -2
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +17 -14
- package/dist/Section/Section.d.ts +2 -19
- package/dist/Section/Section.d.ts.map +1 -1
- package/dist/Section/Section.js +1 -15
- package/dist/Section/index.d.ts +19 -1
- package/dist/Section/index.d.ts.map +1 -1
- package/dist/Section/index.js +14 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +6 -6
- package/dist/SelectableCard/SelectableCard.d.ts +4 -3
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +18 -14
- package/dist/Selector/Selector.d.ts +14 -4
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +247 -77
- 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 +1 -1
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +2 -2
- package/dist/SideNav/SideNavCollapseButton.d.ts +2 -2
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +30 -14
- package/dist/SideNav/SideNavHeading.d.ts +1 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +57 -20
- package/dist/SideNav/SideNavItem.d.ts +2 -2
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +30 -25
- package/dist/SideNav/SideNavSection.d.ts +1 -1
- package/dist/SideNav/SideNavSection.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +3 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +78 -68
- package/dist/Spinner/Spinner.d.ts +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +1 -1
- package/dist/Stack/Stack.js +1 -1
- package/dist/Stack/StackItem.d.ts +1 -1
- package/dist/Stack/StackItem.js +1 -1
- package/dist/Stack/stack.stylex.d.ts +3 -3
- package/dist/StatusDot/StatusDot.d.ts +1 -20
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +2 -17
- package/dist/StatusDot/index.d.ts +21 -1
- package/dist/StatusDot/index.d.ts.map +1 -1
- package/dist/StatusDot/index.js +14 -0
- package/dist/Switch/Switch.d.ts +2 -6
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +28 -20
- package/dist/TabList/Tab.d.ts +1 -1
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +3 -4
- package/dist/TabList/TabList.d.ts +1 -1
- package/dist/TabList/TabList.js +1 -1
- package/dist/TabList/TabMenu.d.ts +1 -1
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +52 -22
- package/dist/Table/BaseTable.d.ts +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +4 -7
- package/dist/Table/Table.d.ts +1 -1
- package/dist/Table/Table.js +1 -1
- package/dist/Table/TableCell.d.ts +1 -1
- package/dist/Table/TableCell.js +4 -2
- package/dist/Table/TableHeaderCell.d.ts +1 -1
- package/dist/Table/TableHeaderCell.js +4 -2
- package/dist/Table/TableRow.d.ts +1 -1
- package/dist/Table/TableRow.js +1 -1
- 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/useTableRowExpansion.d.ts +18 -3
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +55 -43
- 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 +11 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +65 -35
- package/dist/Table/tableContextMenu.d.ts.map +1 -1
- package/dist/Table/tableContextMenu.js +2 -1
- package/dist/Table/types.d.ts +5 -9
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Text/Text.d.ts +11 -2
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +26 -3
- package/dist/Text/index.d.ts +31 -1
- package/dist/Text/index.d.ts.map +1 -1
- package/dist/Text/index.js +23 -0
- package/dist/TextArea/TextArea.d.ts +1 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +111 -41
- package/dist/TextInput/TextInput.d.ts +1 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +4 -3
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +28 -16
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +3 -2
- package/dist/Timestamp/Timestamp.d.ts +26 -12
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +128 -65
- package/dist/Timestamp/TimestampHoverCard.d.ts +45 -0
- package/dist/Timestamp/TimestampHoverCard.d.ts.map +1 -0
- package/dist/Timestamp/TimestampHoverCard.js +228 -0
- package/dist/Timestamp/formatInstant.d.ts +3 -3
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +7 -2
- package/dist/Timestamp/tooltipEntries.d.ts +17 -2
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.js +4 -2
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +61 -9
- package/dist/ToggleButton/ToggleButton.d.ts +1 -1
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +4 -2
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- package/dist/Token/Token.d.ts +6 -28
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +84 -64
- package/dist/Token/TokenLink.d.ts +62 -0
- package/dist/Token/TokenLink.d.ts.map +1 -0
- package/dist/Token/TokenLink.js +76 -0
- package/dist/Token/index.d.ts +27 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Token/index.js +14 -0
- package/dist/Tokenizer/Tokenizer.d.ts +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +5 -3
- package/dist/Toolbar/Toolbar.d.ts +1 -1
- package/dist/Toolbar/Toolbar.js +1 -1
- package/dist/Tooltip/Tooltip.d.ts +1 -1
- package/dist/Tooltip/Tooltip.js +1 -1
- package/dist/TopNav/TopNav.d.ts +1 -1
- package/dist/TopNav/TopNav.d.ts.map +1 -1
- package/dist/TopNav/TopNav.js +7 -6
- package/dist/TopNav/TopNavHeading.d.ts +2 -8
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +56 -20
- package/dist/TopNav/TopNavItem.d.ts +1 -1
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +4 -10
- package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +89 -42
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +23 -4
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +84 -33
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +14 -1
- package/dist/TreeList/TreeListBranches.d.ts +1 -1
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +15 -5
- package/dist/TreeList/TreeListItem.d.ts +12 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +58 -30
- package/dist/TreeList/TreeListTypes.d.ts +1 -17
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/TreeList/index.d.ts +18 -1
- package/dist/TreeList/index.d.ts.map +1 -1
- package/dist/TreeList/index.js +14 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +10 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +17 -3
- package/dist/Typeahead/Typeahead.d.ts +1 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +9 -2
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.js +1 -1
- package/dist/VStack/VStack.d.ts +1 -1
- package/dist/VStack/VStack.js +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +1 -1
- package/dist/astryx.css +143 -46
- package/dist/astryx.umd.js +52 -56
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/containerReveal.pool.stylex.d.ts +303 -0
- package/dist/hooks/containerReveal.pool.stylex.d.ts.map +1 -0
- package/dist/hooks/containerReveal.pool.stylex.js +292 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/useContainerReveal.d.ts +83 -0
- package/dist/hooks/useContainerReveal.d.ts.map +1 -0
- package/dist/hooks/useContainerReveal.js +123 -0
- package/dist/hooks/useGridFocus.d.ts +8 -6
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useInputContainer.d.ts.map +1 -1
- package/dist/hooks/useInputContainer.js +29 -1
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +11 -0
- package/dist/hooks/useKeyboardHint.d.ts +2 -2
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
- package/dist/hooks/useKeyboardHint.js +5 -3
- package/dist/hooks/useListFocus.d.ts +8 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +12 -2
- 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 +13 -2
- 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/i18n/InternationalizationProvider.d.ts +6 -0
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/useDirection.d.ts.map +1 -1
- package/dist/i18n/useDirection.js +6 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/contrast.d.ts +45 -0
- package/dist/theme/contrast.d.ts.map +1 -0
- package/dist/theme/contrast.js +88 -0
- package/dist/theme/defineTheme.d.ts +9 -3
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +6 -4
- package/dist/theme/derivedVarRegistry.d.ts +8 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +5 -13
- package/dist/theme/expandColorScale.d.ts +32 -3
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +102 -13
- package/dist/theme/expandTypeScale.d.ts.map +1 -1
- package/dist/theme/expandTypeScale.js +17 -0
- package/dist/theme/generateThemeRules.d.ts +0 -6
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +11 -15
- package/dist/theme/index.d.ts +9 -7
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +4 -3
- package/dist/theme/themeRegistry.d.ts +32 -0
- package/dist/theme/themeRegistry.d.ts.map +1 -0
- package/dist/theme/themeRegistry.js +49 -0
- package/dist/theme/tokens.stylex.d.ts +0 -17
- package/dist/theme/tokens.stylex.d.ts.map +1 -1
- package/dist/theme/tokens.stylex.js +0 -22
- package/dist/theme/types.d.ts +10 -2
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/theme/useTheme.d.ts +9 -0
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +82 -27
- package/dist/utils/focusOutline.stylex.d.ts +74 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -0
- package/dist/utils/focusOutline.stylex.js +95 -0
- package/dist/utils/rtlStyles.d.ts +23 -2
- package/dist/utils/rtlStyles.d.ts.map +1 -1
- package/dist/utils/rtlStyles.js +28 -3
- package/groups.doc.mjs +2 -2
- package/locales/en.json +128 -0
- package/locales/pseudo.json +96 -0
- package/package.json +9 -13
- package/src/AlertDialog/AlertDialog.doc.mjs +3 -3
- package/src/AlertDialog/AlertDialog.tsx +1 -1
- package/src/AlertDialog/useImperativeAlertDialog.doc.mjs +1 -1
- package/src/AppShell/AppShell.doc.mjs +3 -3
- package/src/AppShell/AppShell.test.tsx +55 -0
- package/src/AppShell/AppShell.tsx +27 -22
- package/src/AppShell/index.ts +20 -1
- package/src/AppShell/useAppShellMobile.doc.mjs +2 -2
- package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
- package/src/AspectRatio/AspectRatio.tsx +1 -1
- package/src/Avatar/Avatar.doc.mjs +5 -16
- package/src/Avatar/Avatar.test.tsx +33 -8
- package/src/Avatar/Avatar.tsx +60 -53
- package/src/Avatar/AvatarStatusDot.doc.mjs +1 -1
- package/src/Avatar/AvatarStatusDot.tsx +2 -27
- package/src/Avatar/index.ts +26 -1
- package/src/AvatarGroup/AvatarGroup.doc.mjs +3 -3
- package/src/AvatarGroup/AvatarGroup.test.tsx +21 -1
- package/src/AvatarGroup/AvatarGroup.tsx +3 -7
- package/src/AvatarGroup/AvatarGroupOverflow.doc.mjs +1 -1
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +7 -12
- package/src/Badge/Badge.doc.mjs +3 -3
- package/src/Badge/Badge.tsx +2 -31
- package/src/Badge/index.ts +32 -6
- package/src/Banner/Banner.doc.mjs +3 -3
- package/src/Banner/Banner.tsx +17 -51
- package/src/Banner/index.ts +39 -7
- package/src/Blockquote/Blockquote.doc.mjs +3 -3
- package/src/Blockquote/Blockquote.tsx +1 -1
- package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +1 -1
- package/src/Breadcrumbs/BreadcrumbItem.tsx +17 -5
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +3 -3
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +1 -1
- package/src/Breadcrumbs/Breadcrumbs.tsx +2 -19
- package/src/Breadcrumbs/index.ts +19 -5
- package/src/Button/Button.doc.mjs +3 -3
- package/src/Button/Button.test.tsx +16 -0
- package/src/Button/Button.tsx +27 -64
- package/src/Button/index.ts +22 -7
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -3
- package/src/ButtonGroup/ButtonGroup.tsx +1 -1
- package/src/Calendar/Calendar.doc.mjs +3 -3
- package/src/Calendar/Calendar.test.tsx +22 -6
- package/src/Calendar/Calendar.tsx +3 -2
- package/src/Calendar/index.ts +1 -6
- package/src/Calendar/styles.ts +2 -10
- package/src/Calendar/utils.ts +0 -11
- package/src/Card/Card.doc.mjs +3 -3
- package/src/Card/Card.tsx +1 -1
- package/src/Carousel/Carousel.doc.mjs +13 -3
- package/src/Carousel/Carousel.test.tsx +232 -1
- package/src/Carousel/Carousel.tsx +154 -27
- package/src/Carousel/index.ts +1 -1
- package/src/Center/Center.doc.mjs +41 -3
- package/src/Center/Center.test.tsx +75 -0
- package/src/Center/Center.tsx +38 -3
- package/src/Chat/Chat.doc.mjs +3 -3
- package/src/Chat/ChatComposer.doc.mjs +1 -1
- package/src/Chat/ChatComposer.tsx +5 -5
- package/src/Chat/ChatComposerDrawer.doc.mjs +1 -1
- package/src/Chat/ChatComposerDrawer.tsx +5 -5
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.tsx +1 -1
- package/src/Chat/ChatComposerTokenElement.doc.mjs +1 -1
- package/src/Chat/ChatDictationButton.doc.mjs +3 -3
- package/src/Chat/ChatDictationButton.tsx +1 -1
- package/src/Chat/ChatLayout.doc.mjs +1 -1
- package/src/Chat/ChatLayout.test.tsx +57 -0
- package/src/Chat/ChatLayout.tsx +23 -2
- package/src/Chat/ChatLayoutScrollButton.doc.mjs +1 -1
- package/src/Chat/ChatLayoutScrollButton.test.tsx +22 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +2 -1
- package/src/Chat/ChatMessage.doc.mjs +1 -1
- package/src/Chat/ChatMessage.tsx +1 -1
- package/src/Chat/ChatMessageBubble.doc.mjs +1 -1
- package/src/Chat/ChatMessageBubble.tsx +1 -1
- package/src/Chat/ChatMessageList.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.tsx +1 -1
- package/src/Chat/ChatMessageMetadata.doc.mjs +1 -1
- package/src/Chat/ChatSendButton.doc.mjs +1 -1
- package/src/Chat/ChatSendButton.tsx +5 -3
- package/src/Chat/ChatSystemMessage.doc.mjs +1 -1
- package/src/Chat/ChatSystemMessage.tsx +1 -1
- package/src/Chat/ChatTokenizedText.doc.mjs +1 -1
- package/src/Chat/ChatTokenizedText.tsx +1 -1
- package/src/Chat/ChatToolCalls.doc.mjs +3 -3
- package/src/Chat/ChatToolCalls.test.tsx +35 -0
- package/src/Chat/ChatToolCalls.tsx +36 -16
- package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -3
- package/src/CheckboxInput/CheckboxInput.test.tsx +56 -0
- package/src/CheckboxInput/CheckboxInput.tsx +18 -3
- package/src/CheckboxList/CheckboxList.doc.mjs +3 -3
- package/src/CheckboxList/CheckboxList.test.tsx +94 -3
- package/src/CheckboxList/CheckboxList.tsx +1 -1
- package/src/CheckboxList/CheckboxListItem.doc.mjs +1 -1
- package/src/CheckboxList/CheckboxListItem.tsx +18 -11
- package/src/Citation/Citation.doc.mjs +2 -2
- package/src/Citation/Citation.tsx +1 -1
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
- package/src/ClickableCard/ClickableCard.tsx +9 -14
- package/src/Code/Code.tsx +2 -2
- package/src/CodeBlock/Code.doc.mjs +1 -1
- package/src/CodeBlock/CodeBlock.doc.mjs +3 -3
- package/src/CodeBlock/CodeBlock.test.tsx +17 -0
- package/src/CodeBlock/CodeBlock.tsx +18 -17
- package/src/Collapsible/Collapsible.doc.mjs +3 -3
- package/src/Collapsible/Collapsible.tsx +23 -19
- package/src/Collapsible/CollapsibleGroup.doc.mjs +1 -1
- package/src/Collapsible/CollapsibleGroup.tsx +1 -1
- package/src/Collapsible/CollapsibleGroupContext.tsx +1 -1
- package/src/Collapsible/useCollapsible.doc.mjs +2 -2
- package/src/CommandPalette/CommandPalette.doc.mjs +4 -4
- package/src/CommandPalette/CommandPalette.test.tsx +29 -0
- package/src/CommandPalette/CommandPalette.tsx +1 -1
- package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +1 -1
- package/src/CommandPalette/CommandPaletteEmpty.tsx +1 -1
- package/src/CommandPalette/CommandPaletteFooter.doc.mjs +1 -1
- package/src/CommandPalette/CommandPaletteFooter.tsx +1 -1
- package/src/CommandPalette/CommandPaletteGroup.doc.mjs +1 -1
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +6 -2
- package/src/CommandPalette/CommandPaletteGroup.tsx +1 -1
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +1 -1
- package/src/CommandPalette/CommandPaletteInput.tsx +5 -1
- package/src/CommandPalette/CommandPaletteItem.doc.mjs +1 -1
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/CommandPalette/CommandPaletteList.doc.mjs +1 -1
- package/src/CommandPalette/CommandPaletteList.tsx +1 -1
- package/src/ComplexSelector/ComplexSelector.doc.mjs +220 -0
- package/src/ComplexSelector/ComplexSelector.test.tsx +181 -0
- package/src/ComplexSelector/ComplexSelector.tsx +443 -0
- package/src/ComplexSelector/index.ts +17 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +38 -2
- package/src/ContextMenu/ContextMenu.tsx +27 -6
- package/src/ContextMenu/ContextMenuItem.doc.mjs +1 -1
- package/src/DateInput/DateInput.doc.mjs +19 -4
- package/src/DateInput/DateInput.test.tsx +79 -3
- package/src/DateInput/DateInput.tsx +23 -3
- package/src/DateRangeInput/DateRangeInput.doc.mjs +11 -3
- package/src/DateRangeInput/DateRangeInput.test.tsx +97 -2
- package/src/DateRangeInput/DateRangeInput.tsx +19 -2
- package/src/DateTimeInput/DateTimeInput.doc.mjs +19 -5
- package/src/DateTimeInput/DateTimeInput.test.tsx +81 -2
- package/src/DateTimeInput/DateTimeInput.tsx +19 -2
- package/src/Dialog/Dialog.doc.mjs +7 -5
- package/src/Dialog/Dialog.test.tsx +46 -3
- package/src/Dialog/Dialog.tsx +63 -53
- package/src/Dialog/DialogHeader.doc.mjs +1 -1
- package/src/Dialog/DialogHeader.tsx +1 -1
- package/src/Dialog/index.ts +18 -1
- package/src/Dialog/useImperativeDialog.doc.mjs +1 -1
- package/src/Divider/Divider.doc.mjs +3 -3
- package/src/Divider/Divider.tsx +2 -19
- package/src/Divider/index.ts +19 -5
- package/src/DropdownMenu/DropdownMenu.doc.mjs +22 -7
- package/src/DropdownMenu/DropdownMenu.test.tsx +405 -1
- package/src/DropdownMenu/DropdownMenu.tsx +117 -50
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +41 -64
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +25 -5
- package/src/DropdownMenu/DropdownMenuItem.tsx +34 -7
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +5 -13
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +11 -2
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +84 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +90 -15
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +24 -8
- package/src/DropdownMenu/menuItemHover.ts +1 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +31 -21
- package/src/EmptyState/EmptyState.doc.mjs +3 -3
- package/src/EmptyState/EmptyState.tsx +1 -1
- package/src/Field/Field.doc.mjs +7 -3
- package/src/Field/Field.tsx +1 -1
- package/src/Field/FieldLabel.doc.mjs +1 -1
- package/src/Field/FieldLabel.test.tsx +103 -0
- package/src/Field/FieldLabel.tsx +61 -5
- package/src/FieldStatus/FieldStatus.doc.mjs +3 -2
- package/src/FieldStatus/FieldStatus.test.tsx +61 -0
- package/src/FieldStatus/FieldStatus.tsx +16 -23
- package/src/FieldStatus/index.ts +20 -5
- package/src/FileInput/FileInput.doc.mjs +3 -3
- package/src/FileInput/FileInput.tsx +1 -1
- package/src/FormLayout/FormLayout.doc.mjs +3 -3
- package/src/FormLayout/FormLayout.tsx +2 -5
- package/src/Grid/Grid.doc.mjs +3 -8
- package/src/Grid/Grid.tsx +1 -25
- package/src/Grid/GridSpan.doc.mjs +1 -1
- package/src/Grid/GridSpan.tsx +1 -1
- package/src/HStack/HStack.tsx +1 -1
- package/src/Heading/Heading.tsx +4 -3
- package/src/HoverCard/HoverCard.doc.mjs +3 -3
- package/src/HoverCard/HoverCard.tsx +1 -1
- package/src/HoverCard/useHoverCard.doc.mjs +2 -2
- package/src/Icon/Icon.doc.mjs +8 -6
- package/src/Icon/Icon.test.tsx +23 -0
- package/src/Icon/Icon.tsx +4 -2
- package/src/Icon/defaultIcons.tsx +14 -0
- package/src/Icon/globalIconRegistry.test.tsx +87 -1
- package/src/Icon/globalIconRegistry.tsx +111 -9
- package/src/Icon/index.ts +9 -7
- package/src/Icon/useIcon.ts +23 -0
- package/src/IconButton/IconButton.doc.mjs +2 -2
- package/src/IconButton/IconButton.tsx +1 -1
- package/src/InputGroup/InputGroup.doc.mjs +2 -2
- package/src/InputGroup/InputGroup.tsx +1 -1
- package/src/InputGroup/InputGroupText.doc.mjs +1 -1
- package/src/InputGroup/InputGroupText.tsx +1 -1
- package/src/Item/Item.doc.mjs +8 -3
- package/src/Item/Item.test.tsx +88 -0
- package/src/Item/Item.tsx +65 -26
- package/src/Kbd/Kbd.doc.mjs +3 -3
- package/src/Kbd/Kbd.tsx +1 -1
- package/src/Layer/Layer.doc.mjs +2 -2
- package/src/Layer/useLayer.doc.mjs +2 -2
- package/src/Layout/Layout.doc.mjs +3 -3
- package/src/Layout/Layout.tsx +1 -1
- package/src/Layout/LayoutContent.doc.mjs +1 -1
- package/src/Layout/LayoutContent.tsx +1 -1
- package/src/Layout/LayoutFooter.doc.mjs +1 -1
- package/src/Layout/LayoutFooter.tsx +1 -1
- package/src/Layout/LayoutHeader.doc.mjs +1 -1
- package/src/Layout/LayoutHeader.tsx +1 -1
- package/src/Layout/LayoutPanel.doc.mjs +1 -1
- package/src/Layout/LayoutPanel.tsx +1 -1
- package/src/Lightbox/Lightbox.doc.mjs +6 -6
- package/src/Lightbox/Lightbox.test.tsx +211 -0
- package/src/Lightbox/Lightbox.tsx +152 -60
- package/src/Link/Link.doc.mjs +3 -3
- package/src/Link/Link.tsx +5 -12
- package/src/Link/LinkProvider.doc.mjs +2 -2
- package/src/Link/LinkProvider.tsx +2 -2
- package/src/List/List.doc.mjs +3 -3
- package/src/List/List.tsx +1 -1
- package/src/List/ListItem.doc.mjs +13 -1
- package/src/List/ListItem.tsx +14 -1
- package/src/Markdown/Markdown.doc.mjs +81 -1
- package/src/Markdown/Markdown.test.tsx +92 -0
- package/src/Markdown/Markdown.tsx +96 -68
- package/src/Markdown/parser.perf.test.ts +47 -35
- package/src/MetadataList/MetadataList.doc.mjs +3 -3
- package/src/MetadataList/MetadataList.test.tsx +82 -0
- package/src/MetadataList/MetadataList.tsx +45 -20
- package/src/MetadataList/MetadataListItem.doc.mjs +1 -1
- package/src/MetadataList/MetadataListItem.tsx +1 -1
- package/src/MobileNav/MobileNav.doc.mjs +3 -3
- package/src/MobileNav/MobileNav.tsx +4 -4
- package/src/MoreMenu/MoreMenu.doc.mjs +3 -3
- package/src/MoreMenu/MoreMenu.test.tsx +28 -1
- package/src/MoreMenu/MoreMenu.tsx +3 -3
- package/src/MultiSelector/MultiSelector.doc.mjs +37 -10
- package/src/MultiSelector/MultiSelector.test.tsx +396 -8
- package/src/MultiSelector/MultiSelector.tsx +254 -74
- package/src/NavIcon/NavIcon.doc.mjs +3 -3
- package/src/NavIcon/NavIcon.tsx +1 -1
- package/src/NavMenu/NavHeadingMenu.test.tsx +0 -16
- package/src/NavMenu/NavMenu.doc.mjs +2 -2
- package/src/NavMenu/index.ts +0 -4
- package/src/NumberInput/NumberInput.doc.mjs +5 -8
- package/src/NumberInput/NumberInput.test.tsx +117 -3
- package/src/NumberInput/NumberInput.tsx +30 -3
- package/src/Outline/Outline.doc.mjs +3 -3
- package/src/Outline/Outline.tsx +3 -6
- package/src/OverflowList/OverflowList.doc.mjs +3 -3
- package/src/OverflowList/OverflowList.tsx +1 -1
- package/src/Overlay/Overlay.doc.mjs +2 -2
- package/src/Pagination/Pagination.doc.mjs +55 -8
- package/src/Pagination/Pagination.test.tsx +582 -0
- package/src/Pagination/Pagination.tsx +249 -64
- package/src/Pagination/index.ts +22 -1
- package/src/Popover/Popover.doc.mjs +31 -3
- package/src/Popover/Popover.test.tsx +41 -0
- package/src/Popover/Popover.tsx +25 -2
- package/src/Popover/usePopover.doc.mjs +2 -2
- package/src/Popover/usePopover.tsx +10 -4
- package/src/PowerSearch/PowerSearch.doc.mjs +3 -3
- 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 +24 -3
- package/src/ProgressBar/ProgressBar.test.tsx +523 -2
- package/src/ProgressBar/ProgressBar.tsx +250 -25
- package/src/ProgressBar/ProgressBarMarkTooltip.tsx +43 -0
- package/src/ProgressBar/index.ts +22 -1
- package/src/RadioList/RadioList.doc.mjs +3 -3
- package/src/RadioList/RadioList.test.tsx +26 -4
- package/src/RadioList/RadioList.tsx +1 -1
- package/src/RadioList/RadioListItem.doc.mjs +1 -1
- package/src/RadioList/RadioListItem.tsx +9 -2
- package/src/Resizable/Resizable.doc.mjs +2 -2
- package/src/Resizable/ResizeHandle.test.tsx +52 -3
- package/src/Resizable/ResizeHandle.tsx +27 -22
- package/src/Resizable/useResizable.doc.mjs +2 -2
- package/src/Section/Section.doc.mjs +3 -3
- package/src/Section/Section.tsx +2 -20
- package/src/Section/index.ts +20 -5
- package/src/SegmentedControl/SegmentedControl.doc.mjs +3 -3
- package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
- package/src/SegmentedControl/SegmentedControl.tsx +1 -1
- package/src/SegmentedControl/SegmentedControlItem.doc.mjs +1 -1
- package/src/SegmentedControl/SegmentedControlItem.tsx +23 -12
- package/src/SelectableCard/SelectableCard.doc.mjs +4 -2
- package/src/SelectableCard/SelectableCard.test.tsx +55 -0
- package/src/SelectableCard/SelectableCard.tsx +23 -12
- package/src/Selector/Selector.doc.mjs +34 -11
- package/src/Selector/Selector.test.tsx +1176 -118
- package/src/Selector/Selector.tsx +345 -96
- package/src/Selector/SelectorOption.doc.mjs +1 -1
- package/src/Selector/hooks.ts +77 -50
- package/src/SideNav/SideNav.doc.mjs +3 -3
- package/src/SideNav/SideNav.test.tsx +46 -0
- package/src/SideNav/SideNav.tsx +2 -1
- package/src/SideNav/SideNavCollapseButton.doc.mjs +1 -1
- package/src/SideNav/SideNavCollapseButton.tsx +16 -10
- package/src/SideNav/SideNavHeading.doc.mjs +1 -1
- package/src/SideNav/SideNavHeading.tsx +49 -12
- package/src/SideNav/SideNavItem.doc.mjs +1 -1
- package/src/SideNav/SideNavItem.tsx +21 -14
- package/src/SideNav/SideNavSection.doc.mjs +1 -1
- package/src/SideNav/SideNavSection.tsx +1 -1
- package/src/Skeleton/Skeleton.doc.mjs +3 -3
- package/src/Skeleton/Skeleton.test.tsx +16 -0
- package/src/Skeleton/Skeleton.tsx +14 -2
- package/src/Slider/Slider.doc.mjs +3 -3
- package/src/Slider/Slider.tsx +9 -13
- package/src/Spinner/Spinner.doc.mjs +3 -3
- package/src/Spinner/Spinner.tsx +1 -1
- package/src/Stack/Stack.doc.mjs +113 -3
- package/src/Stack/Stack.tsx +1 -1
- package/src/Stack/StackItem.tsx +1 -1
- package/src/StatusDot/StatusDot.doc.mjs +15 -6
- package/src/StatusDot/StatusDot.tsx +2 -22
- package/src/StatusDot/index.ts +22 -5
- package/src/Switch/Switch.doc.mjs +5 -5
- package/src/Switch/Switch.test.tsx +71 -25
- package/src/Switch/Switch.tsx +63 -26
- package/src/TabList/Tab.doc.mjs +1 -1
- package/src/TabList/Tab.tsx +3 -10
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +21 -18
- package/src/TabList/TabList.tsx +1 -1
- package/src/TabList/TabMenu.doc.mjs +1 -1
- package/src/TabList/TabMenu.tsx +25 -24
- package/src/Table/BaseTable.tsx +4 -5
- package/src/Table/Table.doc.mjs +5 -5
- package/src/Table/Table.test.tsx +27 -49
- package/src/Table/Table.tsx +1 -1
- package/src/Table/TableCell.doc.mjs +1 -1
- package/src/Table/TableCell.tsx +2 -2
- package/src/Table/TableHeaderCell.doc.mjs +1 -1
- package/src/Table/TableHeaderCell.tsx +2 -2
- package/src/Table/TableRow.doc.mjs +1 -1
- package/src/Table/TableRow.tsx +1 -1
- package/src/Table/index.ts +1 -1
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +30 -14
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +72 -33
- package/src/Table/plugins/sortable/useTableSortable.tsx +2 -6
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +161 -2
- package/src/Table/plugins/tree/useTableTreeData.tsx +97 -25
- package/src/Table/tableContextMenu.test.tsx +27 -0
- package/src/Table/tableContextMenu.tsx +1 -0
- package/src/Table/types.ts +5 -9
- package/src/Table/useTableColumnResize.doc.mjs +1 -1
- package/src/Table/useTableColumnSettings.doc.mjs +1 -1
- package/src/Table/useTableFilterState.doc.mjs +1 -1
- package/src/Table/useTableFiltering.doc.mjs +1 -1
- package/src/Table/useTableGroupedRows.doc.mjs +2 -2
- package/src/Table/useTablePagination.doc.mjs +1 -1
- package/src/Table/useTableRowExpansion.doc.mjs +57 -4
- package/src/Table/useTableRowIndex.doc.mjs +2 -2
- package/src/Table/useTableRowStatus.doc.mjs +3 -3
- package/src/Table/useTableSelection.doc.mjs +1 -1
- package/src/Table/useTableSelectionState.doc.mjs +1 -1
- package/src/Table/useTableSortable.doc.mjs +1 -1
- package/src/Table/useTableStickyColumns.doc.mjs +1 -1
- package/src/Table/useTableTreeData.doc.mjs +10 -1
- package/src/Table/useTableTreeState.doc.mjs +1 -1
- package/src/Text/Heading.doc.mjs +4 -4
- package/src/Text/Text.doc.mjs +4 -4
- package/src/Text/Text.test.tsx +42 -0
- package/src/Text/Text.tsx +26 -2
- package/src/Text/index.ts +32 -6
- package/src/TextArea/TextArea.doc.mjs +31 -7
- package/src/TextArea/TextArea.test.tsx +186 -7
- package/src/TextArea/TextArea.tsx +156 -52
- package/src/TextInput/TextInput.doc.mjs +5 -5
- package/src/TextInput/TextInput.test.tsx +77 -0
- package/src/TextInput/TextInput.tsx +7 -3
- package/src/Thumbnail/Thumbnail.doc.mjs +2 -2
- package/src/Thumbnail/Thumbnail.test.tsx +24 -1
- package/src/Thumbnail/Thumbnail.tsx +29 -43
- package/src/TimeInput/TimeInput.doc.mjs +5 -5
- package/src/TimeInput/TimeInput.test.tsx +30 -3
- package/src/TimeInput/TimeInput.tsx +6 -2
- package/src/Timestamp/Timestamp.doc.mjs +30 -24
- package/src/Timestamp/Timestamp.test.tsx +438 -107
- package/src/Timestamp/Timestamp.tsx +167 -103
- package/src/Timestamp/TimestampHoverCard.tsx +283 -0
- package/src/Timestamp/formatInstant.ts +9 -4
- package/src/Timestamp/tooltipEntries.test.ts +9 -0
- package/src/Timestamp/tooltipEntries.ts +18 -2
- package/src/Toast/Toast.doc.mjs +3 -3
- package/src/Toast/ToastViewport.test.tsx +218 -8
- package/src/Toast/ToastViewport.tsx +71 -12
- package/src/Toast/useToast.doc.mjs +2 -2
- package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
- package/src/ToggleButton/ToggleButton.test.tsx +24 -0
- package/src/ToggleButton/ToggleButton.tsx +20 -2
- package/src/ToggleButton/ToggleButtonGroup.doc.mjs +1 -1
- package/src/ToggleButton/ToggleButtonGroup.tsx +3 -6
- package/src/Token/Token.doc.mjs +3 -3
- package/src/Token/Token.test.tsx +145 -0
- package/src/Token/Token.tsx +77 -86
- package/src/Token/TokenLink.tsx +107 -0
- package/src/Token/index.ts +28 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +5 -5
- package/src/Tokenizer/Tokenizer.test.tsx +45 -3
- package/src/Tokenizer/Tokenizer.tsx +11 -3
- package/src/Toolbar/Toolbar.doc.mjs +3 -3
- package/src/Toolbar/Toolbar.tsx +1 -1
- package/src/Tooltip/Tooltip.doc.mjs +3 -3
- package/src/Tooltip/Tooltip.tsx +1 -1
- package/src/Tooltip/useTooltip.doc.mjs +2 -2
- package/src/TopNav/TopNav.doc.mjs +3 -3
- package/src/TopNav/TopNav.test.tsx +2 -2
- package/src/TopNav/TopNav.tsx +2 -4
- package/src/TopNav/TopNavHeading.doc.mjs +1 -12
- package/src/TopNav/TopNavHeading.tsx +44 -25
- package/src/TopNav/TopNavItem.doc.mjs +1 -1
- package/src/TopNav/TopNavItem.tsx +4 -22
- package/src/TopNav/TopNavMegaMenu.doc.mjs +1 -1
- package/src/TopNav/TopNavMegaMenu.tsx +62 -30
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +1 -1
- package/src/TopNav/TopNavMegaMenuItem.doc.mjs +1 -1
- package/src/TopNav/TopNavMegaMenuItem.tsx +3 -10
- package/src/TopNav/TopNavMenu.doc.mjs +1 -1
- package/src/TopNav/TopNavMenu.tsx +34 -32
- package/src/TreeList/TreeList.doc.mjs +8 -3
- package/src/TreeList/TreeList.test.tsx +216 -13
- package/src/TreeList/TreeList.tsx +23 -1
- package/src/TreeList/TreeListBranches.tsx +26 -3
- package/src/TreeList/TreeListItem.tsx +90 -52
- package/src/TreeList/TreeListTypes.ts +1 -18
- package/src/TreeList/index.ts +19 -1
- package/src/Typeahead/BaseTypeahead.doc.mjs +1 -1
- package/src/Typeahead/BaseTypeahead.tsx +30 -2
- package/src/Typeahead/Typeahead.doc.mjs +4 -3
- package/src/Typeahead/Typeahead.test.tsx +138 -3
- package/src/Typeahead/Typeahead.tsx +7 -1
- package/src/Typeahead/TypeaheadItem.doc.mjs +1 -1
- package/src/Typeahead/TypeaheadItem.tsx +1 -1
- package/src/VStack/VStack.tsx +1 -1
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +3 -3
- package/src/VisuallyHidden/VisuallyHidden.tsx +1 -1
- package/src/__tests__/babelPluginAddExtensions.test.ts +190 -0
- package/src/__tests__/forcedColors.ts +60 -0
- package/src/__tests__/inputWidthContract.test.tsx +8 -1
- package/src/doc-mjs.d.ts +5 -2
- package/src/docPropLiterals.test.ts +1 -1
- package/src/docPropReferences.test.ts +1 -1
- package/src/hooks/containerReveal.pool.stylex.ts +571 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useClickableContainer.doc.mjs +2 -2
- package/src/hooks/useContainerReveal.doc.mjs +75 -0
- package/src/hooks/useContainerReveal.test.tsx +116 -0
- package/src/hooks/useContainerReveal.ts +181 -0
- package/src/hooks/useEntryAnimation.doc.mjs +2 -2
- package/src/hooks/useFocusTrap.doc.mjs +2 -2
- package/src/hooks/useGridFocus.doc.mjs +2 -2
- package/src/hooks/useGridFocus.ts +8 -6
- package/src/hooks/useHotkeys.doc.mjs +2 -2
- package/src/hooks/useImageMode.doc.mjs +2 -2
- package/src/hooks/useImageMode.test.ts +1 -1
- package/src/hooks/useInputContainer.doc.mjs +2 -2
- package/src/hooks/useInputContainer.test.tsx +180 -0
- package/src/hooks/useInputContainer.ts +36 -1
- package/src/hooks/useInputStatusIcon.test.tsx +59 -0
- package/src/hooks/useInputStatusIcon.tsx +12 -1
- package/src/hooks/useKeyboardHint.doc.mjs +2 -2
- package/src/hooks/useKeyboardHint.test.tsx +22 -0
- package/src/hooks/useKeyboardHint.tsx +7 -3
- package/src/hooks/useListFocus.doc.mjs +2 -2
- package/src/hooks/useListFocus.ts +8 -7
- package/src/hooks/useLongPress.test.tsx +18 -0
- package/src/hooks/useLongPress.ts +12 -2
- package/src/hooks/useMediaQuery.doc.mjs +2 -2
- package/src/hooks/useOverflow.doc.mjs +2 -2
- package/src/hooks/useScrollLock.doc.mjs +2 -2
- package/src/hooks/useScrollOverflow.doc.mjs +2 -2
- package/src/hooks/useStreamingText.doc.mjs +2 -2
- package/src/hooks/useStreamingText.test.ts +46 -1
- package/src/hooks/useStreamingText.ts +49 -7
- package/src/hooks/useTreeFocus.doc.mjs +2 -2
- package/src/hooks/useTreeFocus.test.tsx +53 -1
- package/src/hooks/useTreeFocus.ts +13 -2
- package/src/hooks/useTypeahead.test.tsx +150 -0
- package/src/hooks/useTypeahead.ts +24 -9
- package/src/i18n/InternationalizationProvider.doc.mjs +14 -2
- package/src/i18n/InternationalizationProvider.tsx +6 -0
- package/src/i18n/useDirection.ts +6 -3
- package/src/i18n/useTranslator.doc.mjs +2 -2
- package/src/index.ts +2 -18
- package/src/theme/MediaTheme.doc.mjs +2 -2
- package/src/theme/SyntaxTheme.doc.mjs +2 -2
- package/src/theme/Theme.doc.mjs +2 -2
- package/src/theme/Theme.tsx +3 -7
- package/src/theme/contrast.test.ts +94 -0
- package/src/theme/contrast.ts +99 -0
- package/src/theme/defineTheme.test.ts +29 -30
- package/src/theme/defineTheme.ts +11 -5
- package/src/theme/derivedVarRegistry.test.ts +8 -1
- package/src/theme/derivedVarRegistry.ts +15 -6
- package/src/theme/expandColorScale.test.ts +401 -1
- package/src/theme/expandColorScale.ts +143 -19
- package/src/theme/expandTypeScale.test.ts +43 -0
- package/src/theme/expandTypeScale.ts +17 -0
- package/src/theme/generateThemeRules.test.ts +41 -20
- package/src/theme/generateThemeRules.ts +11 -15
- package/src/theme/index.ts +11 -13
- package/src/theme/themeRegistry.test.ts +59 -0
- package/src/theme/themeRegistry.ts +53 -0
- package/src/theme/tokens.stylex.ts +0 -19
- package/src/theme/types.ts +14 -13
- package/src/theme/useTheme.doc.mjs +2 -2
- package/src/theme/useTheme.test.tsx +48 -3
- package/src/theme/useTheme.ts +100 -29
- package/src/utils/focusOutline.stylex.ts +128 -0
- package/src/utils/rtlStyles.ts +24 -2
- package/dist/NavMenu/NavMenuItem.d.ts +0 -13
- package/dist/NavMenu/NavMenuItem.d.ts.map +0 -1
- package/dist/NavMenu/NavMenuItem.js +0 -16
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +0 -9
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +0 -1
- package/dist/Thumbnail/thumbnail.markers.stylex.js +0 -14
- package/dist/authoring/doc.d.ts +0 -145
- package/dist/authoring/doc.d.ts.map +0 -1
- package/dist/authoring/doc.js +0 -100
- package/dist/authoring/index.d.ts +0 -29
- package/dist/authoring/index.d.ts.map +0 -1
- package/dist/authoring/index.js +0 -28
- package/dist/authoring/integration.d.ts +0 -35
- package/dist/authoring/integration.d.ts.map +0 -1
- package/dist/authoring/integration.js +0 -30
- package/dist/authoring/template.d.ts +0 -66
- package/dist/authoring/template.d.ts.map +0 -1
- package/dist/authoring/template.js +0 -55
- package/dist/config.d.ts +0 -80
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -40
- package/dist/docs-types.d.ts +0 -969
- package/dist/docs-types.d.ts.map +0 -1
- package/dist/docs-types.js +0 -1
- package/src/NavMenu/NavMenuItem.tsx +0 -19
- package/src/Thumbnail/thumbnail.markers.stylex.ts +0 -12
- package/src/authoring/doc.ts +0 -164
- package/src/authoring/index.test.ts +0 -52
- package/src/authoring/index.ts +0 -50
- package/src/authoring/integration.ts +0 -42
- package/src/authoring/template.ts +0 -74
- package/src/config.test.ts +0 -16
- package/src/config.ts +0 -92
- package/src/docs-types.ts +0 -1108
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Selector.test.tsx
|
|
5
5
|
* @input Uses vitest, @testing-library/react, @testing-library/user-event
|
|
6
|
-
* @output Unit tests for Selector
|
|
6
|
+
* @output Unit tests for Selector behavior and selected-item geometry
|
|
7
7
|
* @position Tests; validates Selector behavior
|
|
8
8
|
*
|
|
9
9
|
* SYNC: When Selector.tsx API changes, update these tests.
|
|
@@ -18,20 +18,24 @@ import {
|
|
|
18
18
|
within,
|
|
19
19
|
} from '@testing-library/react';
|
|
20
20
|
import userEvent from '@testing-library/user-event';
|
|
21
|
+
import {useState} from 'react';
|
|
21
22
|
import {Selector} from './Selector';
|
|
22
23
|
import {SelectorOption} from './SelectorOption';
|
|
23
24
|
import {Icon} from '../Icon';
|
|
24
25
|
import {InputGroup, InputGroupText} from '../InputGroup';
|
|
25
26
|
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
26
27
|
import {defineTheme} from '../theme/defineTheme';
|
|
27
|
-
import {
|
|
28
|
+
import {generateThemeCSS} from '../theme/generateThemeRules';
|
|
28
29
|
|
|
29
|
-
function
|
|
30
|
-
|
|
30
|
+
function generateThemeTestCSS(theme: Parameters<typeof generateThemeCSS>[0]) {
|
|
31
|
+
const {prose, component} = generateThemeCSS(theme);
|
|
32
|
+
return [prose, component].filter(Boolean).join('\n\n');
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
// Mock showPopover and hidePopover methods since they're not implemented in jsdom
|
|
34
36
|
beforeEach(() => {
|
|
37
|
+
// The live regions are a document-level singleton; start each test clean.
|
|
38
|
+
__resetLiveRegionsForTest();
|
|
35
39
|
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
36
40
|
this.setAttribute('popover-open', '');
|
|
37
41
|
const event = new Event('toggle', {bubbles: false});
|
|
@@ -66,6 +70,23 @@ const h = {hidden: true} as const;
|
|
|
66
70
|
|
|
67
71
|
const OPTIONS = ['Apple', 'Banana', 'Cherry'];
|
|
68
72
|
|
|
73
|
+
// Mirrors useTypeahead's default resetMs — how long the typed buffer survives.
|
|
74
|
+
const TYPEAHEAD_RESET_MS = 750;
|
|
75
|
+
|
|
76
|
+
const politeRegion = () =>
|
|
77
|
+
document.querySelector('[data-astryx-live-region="polite"]');
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Type onto an element with no awaits between keystrokes. Typeahead only
|
|
81
|
+
* accumulates while keys land inside the reset window, so an awaited
|
|
82
|
+
* `user.keyboard` per character would put CI stalls on the critical path.
|
|
83
|
+
*/
|
|
84
|
+
function type(text: string, element: HTMLElement) {
|
|
85
|
+
for (const key of text) {
|
|
86
|
+
fireEvent.keyDown(element, {key});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
69
90
|
function rect({
|
|
70
91
|
top,
|
|
71
92
|
bottom,
|
|
@@ -94,36 +115,103 @@ function rect({
|
|
|
94
115
|
};
|
|
95
116
|
}
|
|
96
117
|
|
|
97
|
-
function mockSelectorRects(
|
|
118
|
+
function mockSelectorRects({
|
|
119
|
+
anchor = rect({top: 160, bottom: 190, height: 30}),
|
|
120
|
+
trigger = rect({top: 160, bottom: 190, height: 30}),
|
|
121
|
+
listbox = rect({top: 190, bottom: 310, height: 120}),
|
|
122
|
+
selectedItem = rect({top: 220, bottom: 250, height: 30}),
|
|
123
|
+
listboxLayoutHeight = listbox.height,
|
|
124
|
+
selectedItemLayoutTop = selectedItem.top - listbox.top,
|
|
125
|
+
selectedItemLayoutHeight = selectedItem.height,
|
|
126
|
+
viewportHeight = 200,
|
|
127
|
+
}: {
|
|
128
|
+
anchor?: DOMRect;
|
|
129
|
+
trigger?: DOMRect;
|
|
130
|
+
listbox?: DOMRect;
|
|
131
|
+
selectedItem?: DOMRect;
|
|
132
|
+
listboxLayoutHeight?: number;
|
|
133
|
+
selectedItemLayoutTop?: number;
|
|
134
|
+
selectedItemLayoutHeight?: number;
|
|
135
|
+
viewportHeight?: number;
|
|
136
|
+
} = {}) {
|
|
98
137
|
const originalGetBoundingClientRect =
|
|
99
138
|
HTMLElement.prototype.getBoundingClientRect;
|
|
100
139
|
const originalInnerHeight = Object.getOwnPropertyDescriptor(
|
|
101
140
|
window,
|
|
102
141
|
'innerHeight',
|
|
103
142
|
);
|
|
143
|
+
const originalOffsetTop = Object.getOwnPropertyDescriptor(
|
|
144
|
+
HTMLElement.prototype,
|
|
145
|
+
'offsetTop',
|
|
146
|
+
);
|
|
147
|
+
const originalOffsetHeight = Object.getOwnPropertyDescriptor(
|
|
148
|
+
HTMLElement.prototype,
|
|
149
|
+
'offsetHeight',
|
|
150
|
+
);
|
|
104
151
|
HTMLElement.prototype.getBoundingClientRect = function () {
|
|
152
|
+
if (this.classList.contains('astryx-selector')) {
|
|
153
|
+
return anchor;
|
|
154
|
+
}
|
|
105
155
|
// The trigger is role="combobox" by default, or a plain button with
|
|
106
156
|
// aria-haspopup="listbox" in hasSearch mode — match either.
|
|
107
157
|
if (
|
|
108
158
|
this.getAttribute('role') === 'combobox' ||
|
|
109
159
|
this.getAttribute('aria-haspopup') === 'listbox'
|
|
110
160
|
) {
|
|
111
|
-
return
|
|
161
|
+
return trigger;
|
|
112
162
|
}
|
|
113
163
|
if (this.getAttribute('role') === 'listbox') {
|
|
114
|
-
return
|
|
164
|
+
return listbox;
|
|
115
165
|
}
|
|
116
166
|
if (this.id.endsWith('-item-1')) {
|
|
117
|
-
return
|
|
167
|
+
return selectedItem;
|
|
118
168
|
}
|
|
119
169
|
return originalGetBoundingClientRect.call(this);
|
|
120
170
|
};
|
|
171
|
+
Object.defineProperty(HTMLElement.prototype, 'offsetTop', {
|
|
172
|
+
configurable: true,
|
|
173
|
+
get() {
|
|
174
|
+
if (this.getAttribute('role') === 'listbox') {
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
177
|
+
if (this.id.endsWith('-item-1')) {
|
|
178
|
+
return selectedItemLayoutTop;
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
|
|
184
|
+
configurable: true,
|
|
185
|
+
get() {
|
|
186
|
+
if (this.getAttribute('role') === 'listbox') {
|
|
187
|
+
return listboxLayoutHeight;
|
|
188
|
+
}
|
|
189
|
+
if (this.id.endsWith('-item-1')) {
|
|
190
|
+
return selectedItemLayoutHeight;
|
|
191
|
+
}
|
|
192
|
+
return 0;
|
|
193
|
+
},
|
|
194
|
+
});
|
|
121
195
|
Object.defineProperty(window, 'innerHeight', {
|
|
122
|
-
value:
|
|
196
|
+
value: viewportHeight,
|
|
123
197
|
configurable: true,
|
|
124
198
|
});
|
|
125
199
|
return () => {
|
|
126
200
|
HTMLElement.prototype.getBoundingClientRect = originalGetBoundingClientRect;
|
|
201
|
+
if (originalOffsetTop) {
|
|
202
|
+
Object.defineProperty(
|
|
203
|
+
HTMLElement.prototype,
|
|
204
|
+
'offsetTop',
|
|
205
|
+
originalOffsetTop,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
if (originalOffsetHeight) {
|
|
209
|
+
Object.defineProperty(
|
|
210
|
+
HTMLElement.prototype,
|
|
211
|
+
'offsetHeight',
|
|
212
|
+
originalOffsetHeight,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
127
215
|
if (originalInnerHeight) {
|
|
128
216
|
Object.defineProperty(window, 'innerHeight', originalInnerHeight);
|
|
129
217
|
}
|
|
@@ -261,6 +349,81 @@ describe('Selector', () => {
|
|
|
261
349
|
}
|
|
262
350
|
});
|
|
263
351
|
|
|
352
|
+
it('aligns the selected item using untransformed layout geometry', async () => {
|
|
353
|
+
const restoreRects = mockSelectorRects({
|
|
354
|
+
anchor: rect({top: 160, bottom: 192, height: 32}),
|
|
355
|
+
trigger: rect({top: 166, bottom: 186, height: 20}),
|
|
356
|
+
// Simulate the 0.95 entry scale in visual rects while retaining the
|
|
357
|
+
// untransformed 120px list / 36px item offset used for positioning.
|
|
358
|
+
listbox: rect({top: 190, bottom: 304, height: 114}),
|
|
359
|
+
selectedItem: rect({
|
|
360
|
+
top: 224.2,
|
|
361
|
+
bottom: 254.6,
|
|
362
|
+
height: 30.4,
|
|
363
|
+
}),
|
|
364
|
+
listboxLayoutHeight: 120,
|
|
365
|
+
selectedItemLayoutTop: 36,
|
|
366
|
+
selectedItemLayoutHeight: 32,
|
|
367
|
+
viewportHeight: 900,
|
|
368
|
+
});
|
|
369
|
+
const user = userEvent.setup();
|
|
370
|
+
try {
|
|
371
|
+
render(
|
|
372
|
+
<Selector
|
|
373
|
+
label="Fruit"
|
|
374
|
+
options={OPTIONS}
|
|
375
|
+
value="Banana"
|
|
376
|
+
onChange={() => {}}
|
|
377
|
+
/>,
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
await user.click(screen.getByRole('combobox'));
|
|
381
|
+
const popover = screen
|
|
382
|
+
.getByRole('listbox', {hidden: true})
|
|
383
|
+
.closest('[popover]');
|
|
384
|
+
await waitFor(() => {
|
|
385
|
+
// 68px geometric alignment plus the 1px optical correction.
|
|
386
|
+
expect(popover?.getAttribute('style')).toContain(
|
|
387
|
+
'margin-block-start: -69px',
|
|
388
|
+
);
|
|
389
|
+
});
|
|
390
|
+
} finally {
|
|
391
|
+
restoreRects();
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it('adds the border inset only to input-variant dropdowns', async () => {
|
|
396
|
+
const user = userEvent.setup();
|
|
397
|
+
const {unmount} = render(
|
|
398
|
+
<Selector
|
|
399
|
+
label="Input fruit"
|
|
400
|
+
options={OPTIONS}
|
|
401
|
+
value="Banana"
|
|
402
|
+
onChange={() => {}}
|
|
403
|
+
/>,
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
await user.click(screen.getByRole('combobox'));
|
|
407
|
+
const inputDropdownClass = screen.getByRole('listbox', h).className;
|
|
408
|
+
unmount();
|
|
409
|
+
|
|
410
|
+
render(
|
|
411
|
+
<Selector
|
|
412
|
+
label="Ghost fruit"
|
|
413
|
+
options={OPTIONS}
|
|
414
|
+
value="Banana"
|
|
415
|
+
variant="ghost"
|
|
416
|
+
onChange={() => {}}
|
|
417
|
+
/>,
|
|
418
|
+
);
|
|
419
|
+
await user.click(screen.getByRole('combobox'));
|
|
420
|
+
const ghostDropdownClass = screen.getByRole('listbox', h).className;
|
|
421
|
+
|
|
422
|
+
// The bordered input gets one extra StyleX rule for its border-width
|
|
423
|
+
// correction; the borderless ghost keeps the base menu inset.
|
|
424
|
+
expect(inputDropdownClass).not.toBe(ghostDropdownClass);
|
|
425
|
+
});
|
|
426
|
+
|
|
264
427
|
it('does not apply selected-item overlay offset when placement is explicit', async () => {
|
|
265
428
|
const restoreRects = mockSelectorRects();
|
|
266
429
|
const user = userEvent.setup();
|
|
@@ -613,6 +776,28 @@ describe('Selector', () => {
|
|
|
613
776
|
expect(within(listbox).getByText('No results found')).toBeInTheDocument();
|
|
614
777
|
});
|
|
615
778
|
|
|
779
|
+
it('empty-state message is not exposed as a listbox child', async () => {
|
|
780
|
+
const user = userEvent.setup();
|
|
781
|
+
render(
|
|
782
|
+
<Selector
|
|
783
|
+
label="Fruit"
|
|
784
|
+
options={OPTIONS}
|
|
785
|
+
value="Apple"
|
|
786
|
+
onChange={() => {}}
|
|
787
|
+
hasSearch
|
|
788
|
+
/>,
|
|
789
|
+
);
|
|
790
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
791
|
+
await user.type(screen.getByRole('combobox', h), 'xyz');
|
|
792
|
+
|
|
793
|
+
// role="listbox" only permits option/group children — the visual
|
|
794
|
+
// empty-state message must be presentational (it is announced through
|
|
795
|
+
// the result-count live region instead).
|
|
796
|
+
const listbox = screen.getByRole('listbox', h);
|
|
797
|
+
const empty = within(listbox).getByText('No results found');
|
|
798
|
+
expect(empty).toHaveAttribute('role', 'presentation');
|
|
799
|
+
});
|
|
800
|
+
|
|
616
801
|
it('calls onChange when selecting a filtered option', async () => {
|
|
617
802
|
const user = userEvent.setup();
|
|
618
803
|
const onChange = vi.fn();
|
|
@@ -962,152 +1147,678 @@ describe('Selector', () => {
|
|
|
962
1147
|
});
|
|
963
1148
|
});
|
|
964
1149
|
|
|
965
|
-
describe('
|
|
966
|
-
it('
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
description="Where the alert should route"
|
|
971
|
-
status={{type: 'error', message: 'Destination is required'}}>
|
|
972
|
-
<InputGroupText>#</InputGroupText>
|
|
973
|
-
<Selector
|
|
974
|
-
label="Channel"
|
|
975
|
-
isLabelHidden
|
|
976
|
-
options={OPTIONS}
|
|
977
|
-
placeholder="Choose a channel"
|
|
978
|
-
/>
|
|
979
|
-
</InputGroup>,
|
|
980
|
-
);
|
|
1150
|
+
describe('typeahead', () => {
|
|
1151
|
+
it('selects the matching option by typing on the closed trigger', async () => {
|
|
1152
|
+
const user = userEvent.setup();
|
|
1153
|
+
const onChange = vi.fn();
|
|
1154
|
+
render(<Selector label="Fruit" options={OPTIONS} onChange={onChange} />);
|
|
981
1155
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
const trigger = screen.getByRole('combobox', {
|
|
985
|
-
name: 'Destination Channel',
|
|
986
|
-
});
|
|
987
|
-
const labelledByIDs =
|
|
988
|
-
trigger.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
1156
|
+
await user.tab();
|
|
1157
|
+
await user.keyboard('c');
|
|
989
1158
|
|
|
990
|
-
expect(
|
|
991
|
-
|
|
992
|
-
expect(
|
|
993
|
-
'
|
|
994
|
-
|
|
995
|
-
expect(trigger).toHaveAttribute(
|
|
996
|
-
'aria-describedby',
|
|
997
|
-
group.getAttribute('aria-describedby'),
|
|
1159
|
+
expect(onChange).toHaveBeenCalledWith('Cherry');
|
|
1160
|
+
// Native select parity: the value changes without opening the menu.
|
|
1161
|
+
expect(screen.getByRole('combobox')).toHaveAttribute(
|
|
1162
|
+
'aria-expanded',
|
|
1163
|
+
'false',
|
|
998
1164
|
);
|
|
999
|
-
expect(screen.getByText('#')).toBeInTheDocument();
|
|
1000
1165
|
});
|
|
1001
1166
|
|
|
1002
|
-
it('
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1167
|
+
it('cycles through options sharing a first letter on repeated presses', async () => {
|
|
1168
|
+
const user = userEvent.setup();
|
|
1169
|
+
function Harness() {
|
|
1170
|
+
const [value, setValue] = useState<string | undefined>(undefined);
|
|
1171
|
+
return (
|
|
1006
1172
|
<Selector
|
|
1007
|
-
label="
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
disabledMessage="Choose a project first"
|
|
1173
|
+
label="City"
|
|
1174
|
+
options={['Austin', 'Chicago', 'Cleveland', 'Columbus']}
|
|
1175
|
+
value={value}
|
|
1176
|
+
onChange={setValue}
|
|
1012
1177
|
/>
|
|
1013
|
-
|
|
1014
|
-
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
render(<Harness />);
|
|
1015
1181
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1182
|
+
await user.tab();
|
|
1183
|
+
await user.keyboard('c');
|
|
1184
|
+
expect(screen.getByRole('combobox')).toHaveTextContent('Chicago');
|
|
1185
|
+
await user.keyboard('c');
|
|
1186
|
+
expect(screen.getByRole('combobox')).toHaveTextContent('Cleveland');
|
|
1187
|
+
await user.keyboard('c');
|
|
1188
|
+
expect(screen.getByRole('combobox')).toHaveTextContent('Columbus');
|
|
1189
|
+
// Wraps back around past non-matching options.
|
|
1190
|
+
await user.keyboard('c');
|
|
1191
|
+
expect(screen.getByRole('combobox')).toHaveTextContent('Chicago');
|
|
1192
|
+
});
|
|
1020
1193
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1194
|
+
it('advances past the current selection on a fresh single-letter press', async () => {
|
|
1195
|
+
const user = userEvent.setup();
|
|
1196
|
+
function Harness() {
|
|
1197
|
+
const [value, setValue] = useState<string | undefined>('Chicago');
|
|
1198
|
+
return (
|
|
1199
|
+
<Selector
|
|
1200
|
+
label="City"
|
|
1201
|
+
options={['Austin', 'Chicago', 'Cleveland', 'Columbus']}
|
|
1202
|
+
value={value}
|
|
1203
|
+
onChange={setValue}
|
|
1204
|
+
/>
|
|
1205
|
+
);
|
|
1206
|
+
}
|
|
1207
|
+
render(<Harness />);
|
|
1208
|
+
|
|
1209
|
+
const trigger = screen.getByRole('combobox');
|
|
1210
|
+
await user.tab();
|
|
1211
|
+
// Native select parity: the selected option's own initial moves on to
|
|
1212
|
+
// the next match. Anchoring the search AT the selection instead of after
|
|
1213
|
+
// it re-matches the current value, and the duplicate-select guard then
|
|
1214
|
+
// swallows the keystroke entirely.
|
|
1215
|
+
type('c', trigger);
|
|
1216
|
+
|
|
1217
|
+
expect(trigger).toHaveTextContent('Cleveland');
|
|
1024
1218
|
});
|
|
1025
|
-
});
|
|
1026
1219
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1220
|
+
it('advances the highlight past the current one with the menu open', async () => {
|
|
1221
|
+
const user = userEvent.setup();
|
|
1029
1222
|
render(
|
|
1030
1223
|
<Selector
|
|
1031
|
-
label="
|
|
1032
|
-
options={
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
data-testid="fruit-selector"
|
|
1224
|
+
label="City"
|
|
1225
|
+
options={['Austin', 'Chicago', 'Cleveland', 'Columbus']}
|
|
1226
|
+
value="Chicago"
|
|
1227
|
+
onChange={() => {}}
|
|
1036
1228
|
/>,
|
|
1037
1229
|
);
|
|
1038
1230
|
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
fireEvent.mouseEnter(container);
|
|
1044
|
-
await waitFor(() => {
|
|
1045
|
-
expect(tooltip).toHaveAttribute('popover-open');
|
|
1046
|
-
});
|
|
1231
|
+
const trigger = screen.getByRole('combobox');
|
|
1232
|
+
await user.tab();
|
|
1233
|
+
await user.keyboard('{Enter}'); // opens with the highlight on Chicago
|
|
1234
|
+
type('c', trigger);
|
|
1047
1235
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1236
|
+
const activeId = trigger.getAttribute('aria-activedescendant');
|
|
1237
|
+
expect(document.getElementById(activeId ?? '')).toHaveTextContent(
|
|
1238
|
+
'Cleveland',
|
|
1239
|
+
);
|
|
1052
1240
|
});
|
|
1053
1241
|
|
|
1054
|
-
it('
|
|
1242
|
+
it('treats a space mid-buffer as part of the match, not as open', async () => {
|
|
1055
1243
|
const user = userEvent.setup();
|
|
1244
|
+
const onChange = vi.fn();
|
|
1056
1245
|
render(
|
|
1057
1246
|
<Selector
|
|
1058
|
-
label="
|
|
1059
|
-
options={
|
|
1060
|
-
|
|
1061
|
-
disabledMessage="You need the Editor role"
|
|
1247
|
+
label="State"
|
|
1248
|
+
options={['New Jersey', 'New York']}
|
|
1249
|
+
onChange={onChange}
|
|
1062
1250
|
/>,
|
|
1063
1251
|
);
|
|
1064
1252
|
|
|
1065
|
-
const
|
|
1253
|
+
const trigger = screen.getByRole('combobox');
|
|
1066
1254
|
await user.tab();
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1255
|
+
// Synchronous keydowns: the buffer only accumulates while keystrokes
|
|
1256
|
+
// land inside the TYPEAHEAD_RESET_MS window, and awaiting between them
|
|
1257
|
+
// would put a CI stall on the critical path.
|
|
1258
|
+
type('new y', trigger);
|
|
1259
|
+
|
|
1260
|
+
expect(onChange).toHaveBeenLastCalledWith('New York');
|
|
1261
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
1071
1262
|
});
|
|
1072
1263
|
|
|
1073
|
-
it('
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1264
|
+
it('opens and seeds the search input when typing on a closed hasSearch trigger', async () => {
|
|
1265
|
+
const user = userEvent.setup();
|
|
1266
|
+
render(<Selector label="Fruit" options={OPTIONS} hasSearch />);
|
|
1267
|
+
|
|
1268
|
+
await user.tab();
|
|
1269
|
+
await user.keyboard('c');
|
|
1270
|
+
|
|
1271
|
+
const search = screen.getByPlaceholderText('Search…');
|
|
1272
|
+
expect(search).toHaveValue('c');
|
|
1273
|
+
await waitFor(() => expect(search).toHaveFocus());
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1276
|
+
it('accumulates a multi-character prefix and resets it after the timeout', async () => {
|
|
1277
|
+
const user = userEvent.setup();
|
|
1278
|
+
const onChange = vi.fn();
|
|
1279
|
+
// Controlled: the committed value has to feed back in, or the match
|
|
1280
|
+
// anchor stays -1 for the whole test and never gets exercised.
|
|
1281
|
+
function Harness() {
|
|
1282
|
+
const [value, setValue] = useState<string | undefined>(undefined);
|
|
1283
|
+
return (
|
|
1284
|
+
<Selector
|
|
1285
|
+
label="Fruit"
|
|
1286
|
+
options={['Apple', 'Banana', 'Blueberry']}
|
|
1287
|
+
value={value}
|
|
1288
|
+
onChange={next => {
|
|
1289
|
+
setValue(next);
|
|
1290
|
+
onChange(next);
|
|
1291
|
+
}}
|
|
1292
|
+
/>
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
render(<Harness />);
|
|
1296
|
+
|
|
1297
|
+
const trigger = screen.getByRole('combobox');
|
|
1298
|
+
await user.tab();
|
|
1299
|
+
type('b', trigger);
|
|
1300
|
+
expect(trigger).toHaveTextContent('Banana');
|
|
1301
|
+
// Within the window the buffer accumulates: "bl" → Blueberry. A
|
|
1302
|
+
// multi-character buffer refines, so it may keep the current match.
|
|
1303
|
+
type('l', trigger);
|
|
1304
|
+
expect(trigger).toHaveTextContent('Blueberry');
|
|
1305
|
+
|
|
1306
|
+
// Past the window the buffer starts fresh: "a" → Apple. A surviving
|
|
1307
|
+
// buffer would search "bla" and match nothing, so only a real reset
|
|
1308
|
+
// gets here — worth the one real wait in the suite.
|
|
1309
|
+
await new Promise(resolve =>
|
|
1310
|
+
setTimeout(resolve, TYPEAHEAD_RESET_MS + 100),
|
|
1080
1311
|
);
|
|
1081
|
-
|
|
1312
|
+
type('a', trigger);
|
|
1313
|
+
expect(trigger).toHaveTextContent('Apple');
|
|
1082
1314
|
});
|
|
1083
1315
|
|
|
1084
|
-
it('
|
|
1085
|
-
|
|
1086
|
-
|
|
1316
|
+
it('skips disabled options when matching', async () => {
|
|
1317
|
+
const user = userEvent.setup();
|
|
1318
|
+
function Harness() {
|
|
1319
|
+
const [value, setValue] = useState<string | undefined>(undefined);
|
|
1320
|
+
return (
|
|
1321
|
+
<Selector
|
|
1322
|
+
label="Fruit"
|
|
1323
|
+
options={[{value: 'Cherry', disabled: true}, 'Coconut']}
|
|
1324
|
+
value={value}
|
|
1325
|
+
onChange={setValue}
|
|
1326
|
+
/>
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
render(<Harness />);
|
|
1330
|
+
|
|
1331
|
+
const trigger = screen.getByRole('combobox');
|
|
1332
|
+
await user.tab();
|
|
1333
|
+
type('c', trigger);
|
|
1334
|
+
expect(trigger).toHaveTextContent('Coconut');
|
|
1335
|
+
|
|
1336
|
+
// The skip has to survive cycling too: with Coconut current, the next
|
|
1337
|
+
// press wraps onto the disabled Cherry and must pass over it.
|
|
1338
|
+
type('c', trigger);
|
|
1339
|
+
expect(trigger).toHaveTextContent('Coconut');
|
|
1340
|
+
expect(trigger).not.toHaveTextContent('Cherry');
|
|
1087
1341
|
});
|
|
1088
1342
|
|
|
1089
|
-
it('
|
|
1343
|
+
it('moves the highlight without committing when typing with the menu open', async () => {
|
|
1344
|
+
const user = userEvent.setup();
|
|
1345
|
+
const onChange = vi.fn();
|
|
1090
1346
|
render(
|
|
1091
1347
|
<Selector
|
|
1092
|
-
label="
|
|
1093
|
-
options={
|
|
1094
|
-
|
|
1095
|
-
disabledMessage="You need the Editor role"
|
|
1348
|
+
label="City"
|
|
1349
|
+
options={['Austin', 'Chicago', 'Cleveland']}
|
|
1350
|
+
onChange={onChange}
|
|
1096
1351
|
/>,
|
|
1097
1352
|
);
|
|
1353
|
+
|
|
1354
|
+
await user.tab();
|
|
1355
|
+
await user.keyboard('{Enter}'); // open
|
|
1098
1356
|
const trigger = screen.getByRole('combobox');
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1357
|
+
|
|
1358
|
+
await user.keyboard('c');
|
|
1359
|
+
let activeId = trigger.getAttribute('aria-activedescendant');
|
|
1360
|
+
expect(document.getElementById(activeId ?? '')).toHaveTextContent(
|
|
1361
|
+
'Chicago',
|
|
1362
|
+
);
|
|
1363
|
+
|
|
1364
|
+
// Repeated press cycles the highlight, still without committing.
|
|
1365
|
+
await user.keyboard('c');
|
|
1366
|
+
activeId = trigger.getAttribute('aria-activedescendant');
|
|
1367
|
+
expect(document.getElementById(activeId ?? '')).toHaveTextContent(
|
|
1368
|
+
'Cleveland',
|
|
1369
|
+
);
|
|
1370
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
1371
|
+
// aria-activedescendant already announces each match, so announcing
|
|
1372
|
+
// again here would make a screen reader say every match twice.
|
|
1373
|
+
// useAnnounce writes its text in a rAF callback, so let a frame pass —
|
|
1374
|
+
// asserting before it runs would pass no matter what the code does.
|
|
1375
|
+
await new Promise(resolve => requestAnimationFrame(() => resolve(null)));
|
|
1376
|
+
expect(politeRegion()?.textContent ?? '').toBe('');
|
|
1377
|
+
|
|
1378
|
+
await user.keyboard('{Enter}');
|
|
1379
|
+
expect(onChange).toHaveBeenCalledWith('Cleveland');
|
|
1102
1380
|
});
|
|
1103
1381
|
|
|
1104
|
-
it('
|
|
1382
|
+
it('does not fire onChange when the only match is already selected', async () => {
|
|
1383
|
+
const user = userEvent.setup();
|
|
1384
|
+
const onChange = vi.fn();
|
|
1105
1385
|
render(
|
|
1106
1386
|
<Selector
|
|
1107
1387
|
label="Fruit"
|
|
1108
1388
|
options={OPTIONS}
|
|
1109
|
-
|
|
1110
|
-
|
|
1389
|
+
value="Cherry"
|
|
1390
|
+
onChange={onChange}
|
|
1391
|
+
/>,
|
|
1392
|
+
);
|
|
1393
|
+
|
|
1394
|
+
await user.tab();
|
|
1395
|
+
await user.keyboard('c');
|
|
1396
|
+
|
|
1397
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
1398
|
+
});
|
|
1399
|
+
|
|
1400
|
+
it('ignores printable keys pressed with ctrl or meta modifiers', async () => {
|
|
1401
|
+
const user = userEvent.setup();
|
|
1402
|
+
const onChange = vi.fn();
|
|
1403
|
+
render(<Selector label="Fruit" options={OPTIONS} onChange={onChange} />);
|
|
1404
|
+
|
|
1405
|
+
await user.tab();
|
|
1406
|
+
await user.keyboard('{Control>}c{/Control}{Meta>}b{/Meta}');
|
|
1407
|
+
|
|
1408
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
1409
|
+
});
|
|
1410
|
+
|
|
1411
|
+
it('announces the committed option to screen readers', async () => {
|
|
1412
|
+
const user = userEvent.setup();
|
|
1413
|
+
render(<Selector label="Fruit" options={OPTIONS} onChange={() => {}} />);
|
|
1414
|
+
|
|
1415
|
+
await user.tab();
|
|
1416
|
+
await user.keyboard('c');
|
|
1417
|
+
|
|
1418
|
+
// The trigger keeps focus and the menu never opens, so nothing else
|
|
1419
|
+
// prompts a re-read. The polite live region carries the new value.
|
|
1420
|
+
await waitFor(() => {
|
|
1421
|
+
expect(politeRegion()).toHaveTextContent('Cherry');
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
|
|
1425
|
+
it('does not select while focusable-disabled', async () => {
|
|
1426
|
+
const user = userEvent.setup();
|
|
1427
|
+
const onChange = vi.fn();
|
|
1428
|
+
render(
|
|
1429
|
+
<Selector
|
|
1430
|
+
label="Fruit"
|
|
1431
|
+
options={OPTIONS}
|
|
1432
|
+
onChange={onChange}
|
|
1433
|
+
isDisabled
|
|
1434
|
+
disabledMessage="Ask an admin"
|
|
1435
|
+
/>,
|
|
1436
|
+
);
|
|
1437
|
+
|
|
1438
|
+
// aria-disabled keeps the trigger focusable, so keydowns still arrive.
|
|
1439
|
+
screen.getByRole('combobox').focus();
|
|
1440
|
+
await user.keyboard('c');
|
|
1441
|
+
|
|
1442
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
|
+
it('cycles without duplicating changeAction while an action is pending', async () => {
|
|
1446
|
+
const user = userEvent.setup();
|
|
1447
|
+
const calls: string[] = [];
|
|
1448
|
+
render(
|
|
1449
|
+
<Selector
|
|
1450
|
+
label="City"
|
|
1451
|
+
options={['Chicago', 'Cleveland', 'Columbus']}
|
|
1452
|
+
value={undefined}
|
|
1453
|
+
changeAction={async value => {
|
|
1454
|
+
calls.push(value);
|
|
1455
|
+
// Never settles, so the value prop never catches up to what the
|
|
1456
|
+
// trigger already shows.
|
|
1457
|
+
await new Promise<void>(() => {});
|
|
1458
|
+
}}
|
|
1459
|
+
/>,
|
|
1460
|
+
);
|
|
1461
|
+
|
|
1462
|
+
const trigger = screen.getByRole('combobox');
|
|
1463
|
+
await user.tab();
|
|
1464
|
+
type('ccc', trigger);
|
|
1465
|
+
|
|
1466
|
+
// The anchor must come from the optimistic value, not the stale prop.
|
|
1467
|
+
// Three options make that observable: with a stale anchor every press
|
|
1468
|
+
// re-matches Chicago, which the duplicate guard then swallows.
|
|
1469
|
+
expect(calls).toEqual(['Chicago', 'Cleveland', 'Columbus']);
|
|
1470
|
+
});
|
|
1471
|
+
|
|
1472
|
+
it('starts a fresh buffer after selecting from the open menu', async () => {
|
|
1473
|
+
const user = userEvent.setup();
|
|
1474
|
+
const onChange = vi.fn();
|
|
1475
|
+
render(
|
|
1476
|
+
<Selector
|
|
1477
|
+
label="Animal"
|
|
1478
|
+
options={['Cat', 'Dog']}
|
|
1479
|
+
onChange={onChange}
|
|
1480
|
+
/>,
|
|
1481
|
+
);
|
|
1482
|
+
|
|
1483
|
+
await user.tab();
|
|
1484
|
+
await user.keyboard('{Enter}'); // open
|
|
1485
|
+
await user.keyboard('d'); // highlight Dog
|
|
1486
|
+
await user.keyboard('{Enter}'); // commit Dog, closes
|
|
1487
|
+
onChange.mockClear();
|
|
1488
|
+
|
|
1489
|
+
// The stale 'd' must not linger: 'c' is a fresh buffer, not "dc".
|
|
1490
|
+
await user.keyboard('c');
|
|
1491
|
+
expect(onChange).toHaveBeenCalledWith('Cat');
|
|
1492
|
+
});
|
|
1493
|
+
|
|
1494
|
+
it('starts a fresh buffer after the value is cleared', async () => {
|
|
1495
|
+
const user = userEvent.setup();
|
|
1496
|
+
const onChange = vi.fn();
|
|
1497
|
+
function Harness() {
|
|
1498
|
+
const [value, setValue] = useState<string | null>('Dog');
|
|
1499
|
+
return (
|
|
1500
|
+
<Selector
|
|
1501
|
+
label="Animal"
|
|
1502
|
+
options={['Cat', 'Dog']}
|
|
1503
|
+
hasClear
|
|
1504
|
+
value={value}
|
|
1505
|
+
onChange={next => {
|
|
1506
|
+
setValue(next);
|
|
1507
|
+
onChange(next);
|
|
1508
|
+
}}
|
|
1509
|
+
/>
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1512
|
+
render(<Harness />);
|
|
1513
|
+
|
|
1514
|
+
const trigger = screen.getByRole('combobox');
|
|
1515
|
+
await user.tab();
|
|
1516
|
+
// Fills the buffer with 'd' without committing — Dog is already current.
|
|
1517
|
+
type('d', trigger);
|
|
1518
|
+
fireEvent.keyDown(trigger, {key: 'Delete'});
|
|
1519
|
+
expect(onChange).toHaveBeenLastCalledWith(null);
|
|
1520
|
+
|
|
1521
|
+
// The stale 'd' must not survive the clear: 'c' is a fresh buffer, not
|
|
1522
|
+
// "dc", which would match nothing and leave the value cleared.
|
|
1523
|
+
type('c', trigger);
|
|
1524
|
+
expect(onChange).toHaveBeenLastCalledWith('Cat');
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
it('matches on the label and commits the value', async () => {
|
|
1528
|
+
const user = userEvent.setup();
|
|
1529
|
+
const onChange = vi.fn();
|
|
1530
|
+
// Values deliberately crossed against labels: a native select matches
|
|
1531
|
+
// the rendered text and reports the value.
|
|
1532
|
+
function Harness() {
|
|
1533
|
+
const [value, setValue] = useState<string | undefined>(undefined);
|
|
1534
|
+
return (
|
|
1535
|
+
<Selector
|
|
1536
|
+
label="Fruit"
|
|
1537
|
+
options={[
|
|
1538
|
+
{value: 'zzz', label: 'Apple'},
|
|
1539
|
+
{value: 'apple', label: 'Zebra'},
|
|
1540
|
+
]}
|
|
1541
|
+
value={value}
|
|
1542
|
+
onChange={next => {
|
|
1543
|
+
setValue(next);
|
|
1544
|
+
onChange(next);
|
|
1545
|
+
}}
|
|
1546
|
+
/>
|
|
1547
|
+
);
|
|
1548
|
+
}
|
|
1549
|
+
render(<Harness />);
|
|
1550
|
+
|
|
1551
|
+
const trigger = screen.getByRole('combobox');
|
|
1552
|
+
await user.tab();
|
|
1553
|
+
type('a', trigger);
|
|
1554
|
+
|
|
1555
|
+
expect(onChange).toHaveBeenCalledWith('zzz');
|
|
1556
|
+
expect(trigger).toHaveTextContent('Apple');
|
|
1557
|
+
|
|
1558
|
+
// No other label starts with "a" — the option whose *value* is 'apple'
|
|
1559
|
+
// is labelled Zebra — so a second press stays put and commits nothing.
|
|
1560
|
+
type('a', trigger);
|
|
1561
|
+
expect(onChange).toHaveBeenCalledTimes(1);
|
|
1562
|
+
});
|
|
1563
|
+
|
|
1564
|
+
it('matches across sections, ignoring dividers and group titles', async () => {
|
|
1565
|
+
const user = userEvent.setup();
|
|
1566
|
+
const onChange = vi.fn();
|
|
1567
|
+
render(
|
|
1568
|
+
<Selector
|
|
1569
|
+
label="Fruit"
|
|
1570
|
+
options={[
|
|
1571
|
+
'Almond',
|
|
1572
|
+
{type: 'divider'},
|
|
1573
|
+
{
|
|
1574
|
+
type: 'section',
|
|
1575
|
+
title: 'Tropical',
|
|
1576
|
+
options: [
|
|
1577
|
+
{value: 'mango', label: 'Mango'},
|
|
1578
|
+
{value: 'papaya', label: 'Papaya'},
|
|
1579
|
+
],
|
|
1580
|
+
},
|
|
1581
|
+
]}
|
|
1582
|
+
onChange={onChange}
|
|
1583
|
+
/>,
|
|
1584
|
+
);
|
|
1585
|
+
|
|
1586
|
+
const trigger = screen.getByRole('combobox');
|
|
1587
|
+
await user.tab();
|
|
1588
|
+
type('p', trigger);
|
|
1589
|
+
expect(onChange).toHaveBeenCalledWith('papaya');
|
|
1590
|
+
|
|
1591
|
+
// The section title "Tropical" is decoration, not an option.
|
|
1592
|
+
onChange.mockClear();
|
|
1593
|
+
type('t', trigger);
|
|
1594
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
it('keeps aria-activedescendant on the matched option across a section', async () => {
|
|
1598
|
+
const user = userEvent.setup();
|
|
1599
|
+
render(
|
|
1600
|
+
<Selector
|
|
1601
|
+
label="Fruit"
|
|
1602
|
+
options={[
|
|
1603
|
+
'Almond',
|
|
1604
|
+
{type: 'divider'},
|
|
1605
|
+
{
|
|
1606
|
+
type: 'section',
|
|
1607
|
+
title: 'Berries',
|
|
1608
|
+
options: [{value: 'blueberry', label: 'Blueberry'}],
|
|
1609
|
+
},
|
|
1610
|
+
]}
|
|
1611
|
+
value="Almond"
|
|
1612
|
+
onChange={() => {}}
|
|
1613
|
+
/>,
|
|
1614
|
+
);
|
|
1615
|
+
|
|
1616
|
+
const trigger = screen.getByRole('combobox');
|
|
1617
|
+
await user.tab();
|
|
1618
|
+
await user.keyboard('{Enter}'); // opens on Almond
|
|
1619
|
+
type('b', trigger);
|
|
1620
|
+
|
|
1621
|
+
const activeId = trigger.getAttribute('aria-activedescendant');
|
|
1622
|
+
expect(document.getElementById(activeId ?? '')).toHaveTextContent(
|
|
1623
|
+
'Blueberry',
|
|
1624
|
+
);
|
|
1625
|
+
});
|
|
1626
|
+
|
|
1627
|
+
it('anchors at the top when the value matches no option', async () => {
|
|
1628
|
+
const user = userEvent.setup();
|
|
1629
|
+
const onChange = vi.fn();
|
|
1630
|
+
render(
|
|
1631
|
+
<Selector
|
|
1632
|
+
label="Fruit"
|
|
1633
|
+
options={['Apple', 'Apricot']}
|
|
1634
|
+
value="Durian"
|
|
1635
|
+
onChange={onChange}
|
|
1636
|
+
/>,
|
|
1637
|
+
);
|
|
1638
|
+
|
|
1639
|
+
const trigger = screen.getByRole('combobox');
|
|
1640
|
+
await user.tab();
|
|
1641
|
+
type('a', trigger);
|
|
1642
|
+
|
|
1643
|
+
// Nothing is really selected, so the first match must stay reachable.
|
|
1644
|
+
expect(onChange).toHaveBeenCalledWith('Apple');
|
|
1645
|
+
});
|
|
1646
|
+
|
|
1647
|
+
it('lets Space open the menu after an abandoned typeahead', async () => {
|
|
1648
|
+
const user = userEvent.setup();
|
|
1649
|
+
render(<Selector label="Fruit" options={OPTIONS} />);
|
|
1650
|
+
|
|
1651
|
+
const trigger = screen.getByRole('combobox');
|
|
1652
|
+
await user.tab();
|
|
1653
|
+
await user.keyboard('{Enter}'); // open
|
|
1654
|
+
await user.keyboard('z'); // no match; buffer holds "z"
|
|
1655
|
+
await user.keyboard('{Escape}'); // close, abandoning the buffer
|
|
1656
|
+
|
|
1657
|
+
// A live "z" buffer would swallow Space as a match character.
|
|
1658
|
+
await user.keyboard(' ');
|
|
1659
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
1660
|
+
});
|
|
1661
|
+
|
|
1662
|
+
it('seeds every character typed before the search input takes focus', async () => {
|
|
1663
|
+
const user = userEvent.setup();
|
|
1664
|
+
render(<Selector label="Fruit" options={OPTIONS} hasSearch />);
|
|
1665
|
+
|
|
1666
|
+
await user.tab();
|
|
1667
|
+
// The popup opens on the first key, but focus only moves to the search
|
|
1668
|
+
// input on the next frame — the second key still lands on the trigger.
|
|
1669
|
+
await user.keyboard('ch');
|
|
1670
|
+
|
|
1671
|
+
const search = screen.getByPlaceholderText('Search…');
|
|
1672
|
+
await waitFor(() => expect(search).toHaveValue('ch'));
|
|
1673
|
+
});
|
|
1674
|
+
});
|
|
1675
|
+
|
|
1676
|
+
describe('InputGroup integration', () => {
|
|
1677
|
+
it('uses the group Field chrome and composes group and selector labels', () => {
|
|
1678
|
+
render(
|
|
1679
|
+
<InputGroup
|
|
1680
|
+
label="Destination"
|
|
1681
|
+
description="Where the alert should route"
|
|
1682
|
+
status={{type: 'error', message: 'Destination is required'}}>
|
|
1683
|
+
<InputGroupText>#</InputGroupText>
|
|
1684
|
+
<Selector
|
|
1685
|
+
label="Channel"
|
|
1686
|
+
isLabelHidden
|
|
1687
|
+
options={OPTIONS}
|
|
1688
|
+
placeholder="Choose a channel"
|
|
1689
|
+
/>
|
|
1690
|
+
</InputGroup>,
|
|
1691
|
+
);
|
|
1692
|
+
|
|
1693
|
+
const group = screen.getByRole('group', {name: 'Destination'});
|
|
1694
|
+
const groupLabelID = group.getAttribute('aria-labelledby');
|
|
1695
|
+
const trigger = screen.getByRole('combobox', {
|
|
1696
|
+
name: 'Destination Channel',
|
|
1697
|
+
});
|
|
1698
|
+
const labelledByIDs =
|
|
1699
|
+
trigger.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
1700
|
+
|
|
1701
|
+
expect(labelledByIDs).toHaveLength(2);
|
|
1702
|
+
expect(labelledByIDs[0]).toBe(groupLabelID);
|
|
1703
|
+
expect(document.getElementById(labelledByIDs[1])).toHaveTextContent(
|
|
1704
|
+
'Channel',
|
|
1705
|
+
);
|
|
1706
|
+
expect(trigger).toHaveAttribute(
|
|
1707
|
+
'aria-describedby',
|
|
1708
|
+
group.getAttribute('aria-describedby'),
|
|
1709
|
+
);
|
|
1710
|
+
expect(screen.getByText('#')).toBeInTheDocument();
|
|
1711
|
+
});
|
|
1712
|
+
|
|
1713
|
+
it('keeps disabled reasons described when grouped', () => {
|
|
1714
|
+
render(
|
|
1715
|
+
<InputGroup label="Destination">
|
|
1716
|
+
<InputGroupText>#</InputGroupText>
|
|
1717
|
+
<Selector
|
|
1718
|
+
label="Channel"
|
|
1719
|
+
isLabelHidden
|
|
1720
|
+
options={OPTIONS}
|
|
1721
|
+
isDisabled
|
|
1722
|
+
disabledMessage="Choose a project first"
|
|
1723
|
+
/>
|
|
1724
|
+
</InputGroup>,
|
|
1725
|
+
);
|
|
1726
|
+
|
|
1727
|
+
const trigger = screen.getByRole('combobox', {
|
|
1728
|
+
name: 'Destination Channel',
|
|
1729
|
+
});
|
|
1730
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
1731
|
+
|
|
1732
|
+
expect(trigger).not.toBeDisabled();
|
|
1733
|
+
expect(trigger).toHaveAttribute('aria-disabled', 'true');
|
|
1734
|
+
expect(trigger.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
1735
|
+
});
|
|
1736
|
+
});
|
|
1737
|
+
|
|
1738
|
+
describe('disabledMessage', () => {
|
|
1739
|
+
it('shows the reason tooltip on hover when disabled with a reason', async () => {
|
|
1740
|
+
render(
|
|
1741
|
+
<Selector
|
|
1742
|
+
label="Fruit"
|
|
1743
|
+
options={OPTIONS}
|
|
1744
|
+
isDisabled
|
|
1745
|
+
disabledMessage="You need the Editor role"
|
|
1746
|
+
data-testid="fruit-selector"
|
|
1747
|
+
/>,
|
|
1748
|
+
);
|
|
1749
|
+
|
|
1750
|
+
const container = screen.getByTestId('fruit-selector');
|
|
1751
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
1752
|
+
expect(tooltip).toHaveTextContent('You need the Editor role');
|
|
1753
|
+
|
|
1754
|
+
fireEvent.mouseEnter(container);
|
|
1755
|
+
await waitFor(() => {
|
|
1756
|
+
expect(tooltip).toHaveAttribute('popover-open');
|
|
1757
|
+
});
|
|
1758
|
+
|
|
1759
|
+
fireEvent.mouseLeave(container);
|
|
1760
|
+
await waitFor(() => {
|
|
1761
|
+
expect(tooltip).not.toHaveAttribute('popover-open');
|
|
1762
|
+
});
|
|
1763
|
+
});
|
|
1764
|
+
|
|
1765
|
+
it('shows the reason tooltip on keyboard focus', async () => {
|
|
1766
|
+
const user = userEvent.setup();
|
|
1767
|
+
render(
|
|
1768
|
+
<Selector
|
|
1769
|
+
label="Fruit"
|
|
1770
|
+
options={OPTIONS}
|
|
1771
|
+
isDisabled
|
|
1772
|
+
disabledMessage="You need the Editor role"
|
|
1773
|
+
/>,
|
|
1774
|
+
);
|
|
1775
|
+
|
|
1776
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
1777
|
+
await user.tab();
|
|
1778
|
+
expect(screen.getByRole('combobox')).toHaveFocus();
|
|
1779
|
+
await waitFor(() => {
|
|
1780
|
+
expect(tooltip).toHaveAttribute('popover-open');
|
|
1781
|
+
});
|
|
1782
|
+
});
|
|
1783
|
+
|
|
1784
|
+
it('does not render a tooltip when not disabled', () => {
|
|
1785
|
+
render(
|
|
1786
|
+
<Selector
|
|
1787
|
+
label="Fruit"
|
|
1788
|
+
options={OPTIONS}
|
|
1789
|
+
disabledMessage="You need the Editor role"
|
|
1790
|
+
/>,
|
|
1791
|
+
);
|
|
1792
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
1793
|
+
});
|
|
1794
|
+
|
|
1795
|
+
it('does not render a tooltip when disabled without a reason', () => {
|
|
1796
|
+
render(<Selector label="Fruit" options={OPTIONS} isDisabled />);
|
|
1797
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
1798
|
+
});
|
|
1799
|
+
|
|
1800
|
+
it('keeps the trigger focusable via aria-disabled when a reason is provided', () => {
|
|
1801
|
+
render(
|
|
1802
|
+
<Selector
|
|
1803
|
+
label="Fruit"
|
|
1804
|
+
options={OPTIONS}
|
|
1805
|
+
isDisabled
|
|
1806
|
+
disabledMessage="You need the Editor role"
|
|
1807
|
+
/>,
|
|
1808
|
+
);
|
|
1809
|
+
const trigger = screen.getByRole('combobox');
|
|
1810
|
+
expect(trigger).not.toBeDisabled();
|
|
1811
|
+
expect(trigger).toHaveAttribute('aria-disabled', 'true');
|
|
1812
|
+
expect(trigger).toHaveAttribute('tabIndex', '0');
|
|
1813
|
+
});
|
|
1814
|
+
|
|
1815
|
+
it('links the reason tooltip from the trigger via aria-describedby', () => {
|
|
1816
|
+
render(
|
|
1817
|
+
<Selector
|
|
1818
|
+
label="Fruit"
|
|
1819
|
+
options={OPTIONS}
|
|
1820
|
+
isDisabled
|
|
1821
|
+
disabledMessage="You need the Editor role"
|
|
1111
1822
|
/>,
|
|
1112
1823
|
);
|
|
1113
1824
|
const trigger = screen.getByRole('combobox');
|
|
@@ -1219,6 +1930,99 @@ describe('Selector statusVariant forwarding', () => {
|
|
|
1219
1930
|
'detached',
|
|
1220
1931
|
);
|
|
1221
1932
|
});
|
|
1933
|
+
|
|
1934
|
+
it('keeps the on-field status icon for the attached variant', () => {
|
|
1935
|
+
const {container} = render(
|
|
1936
|
+
<Selector
|
|
1937
|
+
label="Fruit"
|
|
1938
|
+
options={['Apple', 'Banana']}
|
|
1939
|
+
status={{type: 'error', message: 'Required'}}
|
|
1940
|
+
/>,
|
|
1941
|
+
);
|
|
1942
|
+
// Attached: the status glyph replaces the chevron indicator on the field.
|
|
1943
|
+
expect(
|
|
1944
|
+
container.querySelector('.astryx-selector-indicator-icon'),
|
|
1945
|
+
).toBeNull();
|
|
1946
|
+
});
|
|
1947
|
+
|
|
1948
|
+
it('suppresses the on-field status icon for the detached variant', () => {
|
|
1949
|
+
const {container} = render(
|
|
1950
|
+
<Selector
|
|
1951
|
+
label="Fruit"
|
|
1952
|
+
options={['Apple', 'Banana']}
|
|
1953
|
+
status={{type: 'error', message: 'Required'}}
|
|
1954
|
+
statusVariant="detached"
|
|
1955
|
+
/>,
|
|
1956
|
+
);
|
|
1957
|
+
// Detached: the message box below carries its own leading icon, so the
|
|
1958
|
+
// field keeps its chevron indicator rather than duplicating the glyph.
|
|
1959
|
+
expect(
|
|
1960
|
+
container.querySelector('.astryx-selector-indicator-icon'),
|
|
1961
|
+
).not.toBeNull();
|
|
1962
|
+
});
|
|
1963
|
+
|
|
1964
|
+
it('detaches attached status by default for the ghost variant', () => {
|
|
1965
|
+
const {container} = render(
|
|
1966
|
+
<Selector
|
|
1967
|
+
label="Fruit"
|
|
1968
|
+
options={['Apple', 'Banana']}
|
|
1969
|
+
variant="ghost"
|
|
1970
|
+
status={{type: 'error', message: 'Required'}}
|
|
1971
|
+
/>,
|
|
1972
|
+
);
|
|
1973
|
+
expect(container.querySelector('.astryx-selector')).toHaveAttribute(
|
|
1974
|
+
'data-variant',
|
|
1975
|
+
'ghost',
|
|
1976
|
+
);
|
|
1977
|
+
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
1978
|
+
'data-variant',
|
|
1979
|
+
'detached',
|
|
1980
|
+
);
|
|
1981
|
+
});
|
|
1982
|
+
|
|
1983
|
+
it('uses a status tooltip for ghost selectors when requested', () => {
|
|
1984
|
+
const {container} = render(
|
|
1985
|
+
<Selector
|
|
1986
|
+
label="Fruit"
|
|
1987
|
+
options={['Apple', 'Banana']}
|
|
1988
|
+
variant="ghost"
|
|
1989
|
+
status={{type: 'warning', message: 'Visible to all users'}}
|
|
1990
|
+
statusVariant="tooltip"
|
|
1991
|
+
/>,
|
|
1992
|
+
);
|
|
1993
|
+
expect(container.querySelector('.astryx-field-status')).toBeNull();
|
|
1994
|
+
const statusButton = screen.getByRole('button', {
|
|
1995
|
+
name: /warning details/i,
|
|
1996
|
+
});
|
|
1997
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
1998
|
+
expect(tooltip).toHaveTextContent('Visible to all users');
|
|
1999
|
+
expect(statusButton.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
2000
|
+
expect(
|
|
2001
|
+
screen.getByRole('combobox').getAttribute('aria-describedby'),
|
|
2002
|
+
).toContain(tooltip.id);
|
|
2003
|
+
});
|
|
2004
|
+
});
|
|
2005
|
+
|
|
2006
|
+
describe('Selector empty-state theme target', () => {
|
|
2007
|
+
const OPTIONS = ['Apple', 'Banana', 'Cherry'];
|
|
2008
|
+
|
|
2009
|
+
it('renders the astryx-selector-empty-state target on the "No results found" element', async () => {
|
|
2010
|
+
const user = userEvent.setup();
|
|
2011
|
+
const {container} = render(
|
|
2012
|
+
<Selector
|
|
2013
|
+
label="Fruit"
|
|
2014
|
+
options={OPTIONS}
|
|
2015
|
+
onChange={() => {}}
|
|
2016
|
+
hasSearch
|
|
2017
|
+
/>,
|
|
2018
|
+
);
|
|
2019
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
2020
|
+
await user.type(screen.getByRole('combobox', h), 'xyz');
|
|
2021
|
+
|
|
2022
|
+
const empty = container.querySelector('.astryx-selector-empty-state');
|
|
2023
|
+
expect(empty).not.toBeNull();
|
|
2024
|
+
expect(empty).toHaveTextContent('No results found');
|
|
2025
|
+
});
|
|
1222
2026
|
});
|
|
1223
2027
|
|
|
1224
2028
|
describe('Selector clear icon theme target', () => {
|
|
@@ -1319,7 +2123,7 @@ describe('Selector clear icon theme target', () => {
|
|
|
1319
2123
|
},
|
|
1320
2124
|
},
|
|
1321
2125
|
});
|
|
1322
|
-
const css =
|
|
2126
|
+
const css = generateThemeTestCSS(theme);
|
|
1323
2127
|
expect(css).toContain('.astryx-selector-clear-icon {');
|
|
1324
2128
|
expect(css).toContain('width: 12px');
|
|
1325
2129
|
expect(css).toContain('height: 12px');
|
|
@@ -1367,9 +2171,12 @@ describe('Selector indicator (chevron) icon theme target', () => {
|
|
|
1367
2171
|
});
|
|
1368
2172
|
});
|
|
1369
2173
|
|
|
1370
|
-
it('renders the default icon (
|
|
2174
|
+
it('renders the default icon (secondary color, sm size) byte-identically', () => {
|
|
1371
2175
|
// Pixel-identical default guard: the chevron glyph must carry the exact
|
|
1372
|
-
// same StyleX color/size classes as a standalone
|
|
2176
|
+
// same StyleX color/size classes as a standalone secondary/sm icon. The
|
|
2177
|
+
// glyph now sets --color-icon-secondary itself rather than inheriting it
|
|
2178
|
+
// from a wrapper span that set the same token, so the rendered color is
|
|
2179
|
+
// unchanged. The added
|
|
1373
2180
|
// target class + data-state are purely additive — they change nothing until
|
|
1374
2181
|
// a theme targets them.
|
|
1375
2182
|
const {container} = render(
|
|
@@ -1378,12 +2185,12 @@ describe('Selector indicator (chevron) icon theme target', () => {
|
|
|
1378
2185
|
const icon = getIndicatorIcon(container);
|
|
1379
2186
|
|
|
1380
2187
|
const {container: refContainer} = render(
|
|
1381
|
-
<Icon icon="chevronDown" size="sm" color="
|
|
2188
|
+
<Icon icon="chevronDown" size="sm" color="secondary" />,
|
|
1382
2189
|
);
|
|
1383
2190
|
const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
|
|
1384
2191
|
|
|
1385
2192
|
// Exclude the additive theme-target classes (the stable target + its
|
|
1386
|
-
// reflected state class) so only
|
|
2193
|
+
// reflected state class) so only StyleX classes remain.
|
|
1387
2194
|
const themeTargetClasses = new Set([
|
|
1388
2195
|
'astryx-selector-indicator-icon',
|
|
1389
2196
|
'collapsed',
|
|
@@ -1395,7 +2202,14 @@ describe('Selector indicator (chevron) icon theme target', () => {
|
|
|
1395
2202
|
.filter(c => !themeTargetClasses.has(c))
|
|
1396
2203
|
.sort();
|
|
1397
2204
|
|
|
1398
|
-
|
|
2205
|
+
// A superset, not an exact match: the chevron additionally carries the
|
|
2206
|
+
// rotation styles, which live on the glyph precisely so a theme can reach
|
|
2207
|
+
// the transform through the same selector as the color. The guard that
|
|
2208
|
+
// matters is that every color/size class of a standalone icon is still
|
|
2209
|
+
// present — i.e. the default look has not drifted.
|
|
2210
|
+
expect(styleClasses(icon)).toEqual(
|
|
2211
|
+
expect.arrayContaining(styleClasses(refIcon)),
|
|
2212
|
+
);
|
|
1399
2213
|
});
|
|
1400
2214
|
|
|
1401
2215
|
it('exposes selector-indicator-icon so a theme reaches the icon size and per-state color', () => {
|
|
@@ -1413,7 +2227,7 @@ describe('Selector indicator (chevron) icon theme target', () => {
|
|
|
1413
2227
|
},
|
|
1414
2228
|
},
|
|
1415
2229
|
});
|
|
1416
|
-
const css =
|
|
2230
|
+
const css = generateThemeTestCSS(theme);
|
|
1417
2231
|
expect(css).toContain('.astryx-selector-indicator-icon {');
|
|
1418
2232
|
expect(css).toContain('width: 14px');
|
|
1419
2233
|
expect(css).toContain('height: 14px');
|
|
@@ -1421,3 +2235,247 @@ describe('Selector indicator (chevron) icon theme target', () => {
|
|
|
1421
2235
|
expect(css).toContain('color: var(--color-icon-primary)');
|
|
1422
2236
|
});
|
|
1423
2237
|
});
|
|
2238
|
+
|
|
2239
|
+
describe('Selector search affordances', () => {
|
|
2240
|
+
it('renders a decorative (aria-hidden) magnifier icon whenever hasSearch is on', async () => {
|
|
2241
|
+
const user = userEvent.setup();
|
|
2242
|
+
render(
|
|
2243
|
+
<Selector
|
|
2244
|
+
label="Fruit"
|
|
2245
|
+
options={OPTIONS}
|
|
2246
|
+
value="Apple"
|
|
2247
|
+
onChange={() => {}}
|
|
2248
|
+
hasSearch
|
|
2249
|
+
/>,
|
|
2250
|
+
);
|
|
2251
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
2252
|
+
const search = screen.getByRole('combobox', {hidden: true});
|
|
2253
|
+
// The search field is a TextInput; the magnifier is its startIcon, so it
|
|
2254
|
+
// sits inside the input container as a sibling of the <input>.
|
|
2255
|
+
const container = search.parentElement;
|
|
2256
|
+
const magnifier = container?.querySelector('.astryx-icon');
|
|
2257
|
+
expect(magnifier).toBeTruthy();
|
|
2258
|
+
// Decorative: the icon is hidden from assistive tech and carries no name.
|
|
2259
|
+
expect(magnifier?.getAttribute('aria-hidden')).toBe('true');
|
|
2260
|
+
expect(magnifier?.getAttribute('aria-label')).toBeNull();
|
|
2261
|
+
});
|
|
2262
|
+
|
|
2263
|
+
it('renders the clear button once a query is typed and clears + refocuses on click', async () => {
|
|
2264
|
+
const user = userEvent.setup();
|
|
2265
|
+
render(
|
|
2266
|
+
<Selector
|
|
2267
|
+
label="Fruit"
|
|
2268
|
+
options={OPTIONS}
|
|
2269
|
+
value="Apple"
|
|
2270
|
+
onChange={() => {}}
|
|
2271
|
+
hasSearch
|
|
2272
|
+
/>,
|
|
2273
|
+
);
|
|
2274
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
2275
|
+
const search = screen.getByRole('combobox', {hidden: true});
|
|
2276
|
+
await user.type(search, 'ap');
|
|
2277
|
+
expect(search).toHaveValue('ap');
|
|
2278
|
+
|
|
2279
|
+
// The clear button is TextInput's built-in hasClear affordance; its name is
|
|
2280
|
+
// derived from the field label ("Search options").
|
|
2281
|
+
const clear = screen.getByRole('button', {
|
|
2282
|
+
name: 'Clear Search options',
|
|
2283
|
+
hidden: true,
|
|
2284
|
+
});
|
|
2285
|
+
|
|
2286
|
+
await user.click(clear);
|
|
2287
|
+
expect(search).toHaveValue('');
|
|
2288
|
+
expect(search).toHaveFocus();
|
|
2289
|
+
});
|
|
2290
|
+
|
|
2291
|
+
it('does not render the clear button when the query is empty', async () => {
|
|
2292
|
+
const user = userEvent.setup();
|
|
2293
|
+
render(
|
|
2294
|
+
<Selector
|
|
2295
|
+
label="Fruit"
|
|
2296
|
+
options={OPTIONS}
|
|
2297
|
+
value="Apple"
|
|
2298
|
+
onChange={() => {}}
|
|
2299
|
+
hasSearch
|
|
2300
|
+
/>,
|
|
2301
|
+
);
|
|
2302
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
2303
|
+
expect(
|
|
2304
|
+
screen.queryByRole('button', {
|
|
2305
|
+
name: 'Clear Search options',
|
|
2306
|
+
hidden: true,
|
|
2307
|
+
}),
|
|
2308
|
+
).not.toBeInTheDocument();
|
|
2309
|
+
});
|
|
2310
|
+
|
|
2311
|
+
it('keeps the combobox contract on the input, not the affordances', async () => {
|
|
2312
|
+
const user = userEvent.setup();
|
|
2313
|
+
render(
|
|
2314
|
+
<Selector
|
|
2315
|
+
label="Fruit"
|
|
2316
|
+
options={OPTIONS}
|
|
2317
|
+
value="Apple"
|
|
2318
|
+
onChange={() => {}}
|
|
2319
|
+
hasSearch
|
|
2320
|
+
/>,
|
|
2321
|
+
);
|
|
2322
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
2323
|
+
// Exactly one combobox — the input. The magnifier and clear button are not
|
|
2324
|
+
// part of the combobox contract.
|
|
2325
|
+
const comboboxes = screen.getAllByRole('combobox', {hidden: true});
|
|
2326
|
+
expect(comboboxes).toHaveLength(1);
|
|
2327
|
+
expect(comboboxes[0].tagName).toBe('INPUT');
|
|
2328
|
+
expect(comboboxes[0]).toHaveAttribute('aria-autocomplete', 'list');
|
|
2329
|
+
});
|
|
2330
|
+
|
|
2331
|
+
it('tabs from the search input to the clear button (keeping the popup open) when a query is showing it', async () => {
|
|
2332
|
+
const user = userEvent.setup();
|
|
2333
|
+
render(
|
|
2334
|
+
<Selector
|
|
2335
|
+
label="Fruit"
|
|
2336
|
+
options={OPTIONS}
|
|
2337
|
+
value="Apple"
|
|
2338
|
+
onChange={() => {}}
|
|
2339
|
+
hasSearch
|
|
2340
|
+
/>,
|
|
2341
|
+
);
|
|
2342
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
2343
|
+
const trigger = screen.getByRole('button', {name: 'Fruit'});
|
|
2344
|
+
const search = screen.getByRole('combobox', {hidden: true});
|
|
2345
|
+
await user.type(search, 'ap');
|
|
2346
|
+
expect(search).toHaveFocus();
|
|
2347
|
+
|
|
2348
|
+
// Forward-tab lands on the clear (✕) button and the popup stays open, so
|
|
2349
|
+
// the affordance is keyboard-reachable rather than being skipped when the
|
|
2350
|
+
// input's Tab dismisses the popup.
|
|
2351
|
+
await user.tab();
|
|
2352
|
+
const clear = screen.getByRole('button', {
|
|
2353
|
+
name: 'Clear Search options',
|
|
2354
|
+
hidden: true,
|
|
2355
|
+
});
|
|
2356
|
+
expect(clear).toHaveFocus();
|
|
2357
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
2358
|
+
});
|
|
2359
|
+
});
|
|
2360
|
+
|
|
2361
|
+
describe('Selector selected-marker theme target (selector-check)', () => {
|
|
2362
|
+
const openOptions = (): HTMLElement[] => screen.getAllByRole('option', h);
|
|
2363
|
+
|
|
2364
|
+
it('renders the astryx-selector-check target on the selected row only', () => {
|
|
2365
|
+
render(
|
|
2366
|
+
<Selector
|
|
2367
|
+
label="Fruit"
|
|
2368
|
+
options={OPTIONS}
|
|
2369
|
+
value="Banana"
|
|
2370
|
+
onChange={() => {}}
|
|
2371
|
+
isDefaultOpen
|
|
2372
|
+
/>,
|
|
2373
|
+
);
|
|
2374
|
+
const options = openOptions();
|
|
2375
|
+
const selected = options.find(
|
|
2376
|
+
o => o.getAttribute('aria-selected') === 'true',
|
|
2377
|
+
)!;
|
|
2378
|
+
const check = selected.querySelector('.astryx-selector-check');
|
|
2379
|
+
expect(check).toBeInTheDocument();
|
|
2380
|
+
// The target lands on the checkmark glyph itself, so a theme can restyle or
|
|
2381
|
+
// hide it (e.g. to compose its own selected indicator via renderOption).
|
|
2382
|
+
expect(check).toHaveClass('astryx-icon');
|
|
2383
|
+
|
|
2384
|
+
const unselected = options.filter(
|
|
2385
|
+
o => o.getAttribute('aria-selected') !== 'true',
|
|
2386
|
+
);
|
|
2387
|
+
for (const row of unselected) {
|
|
2388
|
+
expect(row.querySelector('.astryx-selector-check')).not.toBeInTheDocument();
|
|
2389
|
+
}
|
|
2390
|
+
});
|
|
2391
|
+
|
|
2392
|
+
it('renders the default checkmark byte-identically aside from the target class', () => {
|
|
2393
|
+
// The added target class is purely additive — it changes nothing about the
|
|
2394
|
+
// glyph's own color/size until a theme targets it.
|
|
2395
|
+
render(
|
|
2396
|
+
<Selector
|
|
2397
|
+
label="Fruit"
|
|
2398
|
+
options={OPTIONS}
|
|
2399
|
+
value="Banana"
|
|
2400
|
+
onChange={() => {}}
|
|
2401
|
+
isDefaultOpen
|
|
2402
|
+
/>,
|
|
2403
|
+
);
|
|
2404
|
+
const selected = screen
|
|
2405
|
+
.getAllByRole('option', h)
|
|
2406
|
+
.find(o => o.getAttribute('aria-selected') === 'true')!;
|
|
2407
|
+
const check = selected.querySelector(
|
|
2408
|
+
'.astryx-selector-check',
|
|
2409
|
+
) as HTMLElement;
|
|
2410
|
+
|
|
2411
|
+
const {container: refContainer} = render(
|
|
2412
|
+
<Icon icon="check" size="sm" color="accent" />,
|
|
2413
|
+
);
|
|
2414
|
+
const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
|
|
2415
|
+
const styleClasses = (el: HTMLElement) =>
|
|
2416
|
+
el.className
|
|
2417
|
+
.split(' ')
|
|
2418
|
+
.filter(c => c !== 'astryx-selector-check')
|
|
2419
|
+
.sort();
|
|
2420
|
+
expect(styleClasses(check)).toEqual(styleClasses(refIcon));
|
|
2421
|
+
});
|
|
2422
|
+
|
|
2423
|
+
it('exposes selector-check so a theme can hide or restyle the marker', () => {
|
|
2424
|
+
const theme = defineTheme({
|
|
2425
|
+
name: 'selector-check-test',
|
|
2426
|
+
components: {
|
|
2427
|
+
'selector-check': {
|
|
2428
|
+
base: {display: 'none'},
|
|
2429
|
+
},
|
|
2430
|
+
},
|
|
2431
|
+
});
|
|
2432
|
+
const css = generateThemeTestCSS(theme);
|
|
2433
|
+
expect(css).toContain('.astryx-selector-check {');
|
|
2434
|
+
expect(css).toContain('display: none');
|
|
2435
|
+
});
|
|
2436
|
+
});
|
|
2437
|
+
|
|
2438
|
+
describe('Selector disabled state theme target', () => {
|
|
2439
|
+
const getSelectorRoot = (container: HTMLElement): HTMLElement => {
|
|
2440
|
+
const root = container.querySelector('.astryx-selector');
|
|
2441
|
+
if (root == null) {
|
|
2442
|
+
throw new Error('selector root not found');
|
|
2443
|
+
}
|
|
2444
|
+
return root as HTMLElement;
|
|
2445
|
+
};
|
|
2446
|
+
|
|
2447
|
+
it('reflects data-disabled="disabled" on the root when disabled', () => {
|
|
2448
|
+
const {container} = render(
|
|
2449
|
+
<Selector label="Fruit" options={OPTIONS} onChange={() => {}} isDisabled />,
|
|
2450
|
+
);
|
|
2451
|
+
expect(getSelectorRoot(container)).toHaveAttribute(
|
|
2452
|
+
'data-disabled',
|
|
2453
|
+
'disabled',
|
|
2454
|
+
);
|
|
2455
|
+
});
|
|
2456
|
+
|
|
2457
|
+
it('omits the disabled class/attribute when enabled', () => {
|
|
2458
|
+
const {container} = render(
|
|
2459
|
+
<Selector label="Fruit" options={OPTIONS} onChange={() => {}} />,
|
|
2460
|
+
);
|
|
2461
|
+
const root = getSelectorRoot(container);
|
|
2462
|
+
expect(root).not.toHaveAttribute('data-disabled');
|
|
2463
|
+
expect(root).not.toHaveClass('disabled');
|
|
2464
|
+
});
|
|
2465
|
+
|
|
2466
|
+
it('exposes the disabled state so a theme can key on it', () => {
|
|
2467
|
+
const theme = defineTheme({
|
|
2468
|
+
name: 'selector-disabled-state-test',
|
|
2469
|
+
components: {
|
|
2470
|
+
selector: {
|
|
2471
|
+
'disabled:disabled': {opacity: '0.4'},
|
|
2472
|
+
},
|
|
2473
|
+
},
|
|
2474
|
+
});
|
|
2475
|
+
const css = generateThemeTestCSS(theme);
|
|
2476
|
+
expect(css).toContain('.astryx-selector.disabled');
|
|
2477
|
+
expect(css).toContain('opacity: 0.4');
|
|
2478
|
+
});
|
|
2479
|
+
});
|
|
2480
|
+
|
|
2481
|
+
|