@astryxdesign/core 0.3.0 → 0.4.0-canary.058f476
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +156 -0
- package/dist/AlertDialog/AlertDialog.d.ts +10 -2
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +22 -3
- package/dist/AppShell/AppShell.d.ts +2 -2
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +40 -9
- package/dist/AspectRatio/AspectRatio.d.ts +13 -0
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +10 -2
- package/dist/AspectRatio/index.d.ts.map +1 -1
- package/dist/AspectRatio/index.js +1 -2
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +33 -20
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +2 -3
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +1 -2
- package/dist/Badge/index.d.ts.map +1 -1
- package/dist/Badge/index.js +1 -2
- package/dist/Banner/Banner.d.ts +3 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +32 -17
- package/dist/Blockquote/Blockquote.d.ts.map +1 -1
- package/dist/Blockquote/Blockquote.js +1 -2
- package/dist/Blockquote/index.d.ts.map +1 -1
- package/dist/Blockquote/index.js +1 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +21 -8
- package/dist/Breadcrumbs/index.d.ts +2 -1
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +1 -0
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +12 -16
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +2 -1
- package/dist/Calendar/styles.d.ts +0 -2
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +0 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +1 -2
- package/dist/Card/index.d.ts.map +1 -1
- package/dist/Card/index.js +1 -2
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +8 -12
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +1 -2
- package/dist/Center/index.d.ts.map +1 -1
- package/dist/Center/index.js +1 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +2 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +3 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +4 -3
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +17 -17
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +2 -6
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +36 -125
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -11
- package/dist/Code/Code.d.ts.map +1 -1
- package/dist/Code/Code.js +1 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +84 -67
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +35 -15
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -0
- package/dist/CommandPalette/CommandPaletteItem.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +6 -3
- package/dist/CommandPalette/CommandPaletteList.js +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +32 -31
- package/dist/ContextMenu/ContextMenu.d.ts +2 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +1 -1
- package/dist/ContextMenu/index.d.ts +2 -1
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +1 -0
- package/dist/DateInput/DateInput.d.ts +9 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +47 -33
- package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +55 -32
- package/dist/DateTimeInput/DateTimeInput.d.ts +9 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +54 -30
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +4 -4
- package/dist/DropdownMenu/DropdownMenu.d.ts +33 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +62 -20
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +8 -11
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +32 -31
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts +25 -0
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuDivider.js +66 -0
- package/dist/DropdownMenu/DropdownMenuItem.d.ts +15 -2
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +20 -8
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +10 -3
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +5 -5
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +24 -67
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -8
- package/dist/DropdownMenu/index.d.ts +2 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +4 -0
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +35 -27
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +9 -5
- package/dist/Field/InputClearButton.d.ts +16 -3
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +15 -4
- package/dist/Field/PanelSearchInput.d.ts +81 -0
- package/dist/Field/PanelSearchInput.d.ts.map +1 -0
- package/dist/Field/PanelSearchInput.js +151 -0
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +21 -10
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +1 -2
- package/dist/Grid/index.d.ts.map +1 -1
- package/dist/Grid/index.js +1 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +3 -19
- package/dist/Icon/globalIconRegistry.d.ts +5 -4
- package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
- package/dist/Icon/globalIconRegistry.js +5 -4
- package/dist/Indicator/CheckIndicator.d.ts +25 -0
- package/dist/Indicator/CheckIndicator.d.ts.map +1 -0
- package/dist/Indicator/CheckIndicator.js +155 -0
- package/dist/Indicator/CheckboxIndicator.d.ts +22 -0
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -0
- package/dist/Indicator/CheckboxIndicator.js +173 -0
- package/dist/Indicator/RadioIndicator.d.ts +23 -0
- package/dist/Indicator/RadioIndicator.d.ts.map +1 -0
- package/dist/Indicator/RadioIndicator.js +137 -0
- package/dist/Indicator/index.d.ts +24 -0
- package/dist/Indicator/index.d.ts.map +1 -0
- package/dist/Indicator/index.js +26 -0
- package/dist/Indicator/indicator.markers.stylex.d.ts +16 -0
- package/dist/Indicator/indicator.markers.stylex.d.ts.map +1 -0
- package/dist/Indicator/indicator.markers.stylex.js +21 -0
- package/dist/Indicator/indicatorRegistry.d.ts +71 -0
- package/dist/Indicator/indicatorRegistry.d.ts.map +1 -0
- package/dist/Indicator/indicatorRegistry.js +93 -0
- package/dist/Indicator/types.d.ts +177 -0
- package/dist/Indicator/types.d.ts.map +1 -0
- package/dist/Indicator/types.js +1 -0
- package/dist/Indicator/useIndicator.d.ts +18 -0
- package/dist/Indicator/useIndicator.d.ts.map +1 -0
- package/dist/Indicator/useIndicator.js +30 -0
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -8
- package/dist/Layer/useLayer.d.ts +14 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +25 -2
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +80 -103
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +4 -5
- package/dist/MobileNav/MobileNav.js +8 -8
- package/dist/MoreMenu/MoreMenu.d.ts +14 -1
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts +8 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +205 -170
- package/dist/NumberInput/NumberInput.d.ts +27 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +230 -42
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +2 -3
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +61 -63
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +6 -8
- package/dist/Popover/usePopover.d.ts +15 -0
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +14 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +7 -0
- package/dist/ProgressBar/ProgressBar.d.ts +11 -4
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +95 -6
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +29 -84
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +2 -3
- package/dist/Section/Section.d.ts.map +1 -1
- package/dist/Section/Section.js +1 -2
- package/dist/Section/index.d.ts.map +1 -1
- package/dist/Section/index.js +1 -2
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -3
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +3 -11
- package/dist/Selector/Selector.d.ts +12 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +293 -183
- package/dist/Selector/hooks.d.ts +18 -6
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +57 -40
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +29 -14
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +56 -20
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +28 -22
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +1 -2
- package/dist/Skeleton/index.d.ts.map +1 -1
- package/dist/Skeleton/index.js +1 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +2 -6
- package/dist/Stack/stack.stylex.d.ts +3 -3
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +14 -13
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -3
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +41 -19
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +8 -0
- package/dist/Table/TableRow.d.ts +1 -1
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +4 -2
- package/dist/Table/index.d.ts +1 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +22 -18
- package/dist/Table/plugins/rowExpansion/index.d.ts +1 -1
- package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/index.js +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +41 -76
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +94 -345
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +23 -4
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +29 -33
- package/dist/Table/tableContextMenu.d.ts.map +1 -1
- package/dist/Table/tableContextMenu.js +2 -1
- package/dist/Table/types.d.ts +11 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +16 -6
- package/dist/TextInput/TextInput.d.ts +10 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +13 -19
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +32 -26
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +14 -17
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +14 -3
- package/dist/Timestamp/TimestampHoverCard.d.ts.map +1 -1
- package/dist/Timestamp/TimestampHoverCard.js +16 -34
- package/dist/Timestamp/formatInstant.d.ts +11 -1
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +3 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +20 -11
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +4 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +3 -19
- package/dist/TopNav/TopNav.d.ts.map +1 -1
- package/dist/TopNav/TopNav.js +6 -5
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +54 -16
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +3 -9
- package/dist/TopNav/TopNavMegaMenu.d.ts +7 -0
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +146 -60
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +22 -3
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +83 -38
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +13 -0
- package/dist/TreeList/TreeListBranches.d.ts +1 -1
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +14 -4
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +57 -30
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +16 -8
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +1 -2
- package/dist/VisuallyHidden/index.d.ts.map +1 -1
- package/dist/VisuallyHidden/index.js +1 -2
- package/dist/astryx.css +86 -96
- package/dist/astryx.umd.js +56 -56
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/containerReveal.stylex.d.ts +61 -0
- package/dist/hooks/containerReveal.stylex.d.ts.map +1 -0
- package/dist/hooks/containerReveal.stylex.js +63 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/useClipboard.d.ts +59 -0
- package/dist/hooks/useClipboard.d.ts.map +1 -0
- package/dist/hooks/useClipboard.js +106 -0
- package/dist/hooks/useContainerReveal.d.ts +14 -8
- package/dist/hooks/useContainerReveal.d.ts.map +1 -1
- package/dist/hooks/useContainerReveal.js +28 -69
- package/dist/hooks/useIndicatorFocusRing.d.ts +28 -0
- package/dist/hooks/useIndicatorFocusRing.d.ts.map +1 -0
- package/dist/hooks/useIndicatorFocusRing.js +96 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +17 -4
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +12 -2
- package/dist/hooks/useScrollLock.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.js +33 -18
- package/dist/hooks/useStreamingText.d.ts +18 -3
- package/dist/hooks/useStreamingText.d.ts.map +1 -1
- package/dist/hooks/useStreamingText.js +47 -7
- package/dist/hooks/useTreeFocus.d.ts.map +1 -1
- package/dist/hooks/useTreeFocus.js +9 -3
- package/dist/hooks/useTypeahead.d.ts +3 -2
- package/dist/hooks/useTypeahead.d.ts.map +1 -1
- package/dist/hooks/useTypeahead.js +19 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/defineTheme.d.ts +18 -2
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +10 -1
- package/dist/theme/derivedVarRegistry.d.ts +8 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +14 -13
- package/dist/theme/expandColorScale.d.ts +3 -1
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +17 -7
- package/dist/theme/expandTypeScale.d.ts.map +1 -1
- package/dist/theme/expandTypeScale.js +17 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +11 -0
- package/dist/theme/index.d.ts +2 -1
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +1 -1
- package/dist/theme/tokens.stylex.d.ts +12 -0
- package/dist/theme/tokens.stylex.d.ts.map +1 -1
- package/dist/theme/tokens.stylex.js +23 -0
- package/dist/utils/focusOutline.stylex.d.ts +122 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -0
- package/dist/utils/focusOutline.stylex.js +143 -0
- package/dist/utils/focusReturn.d.ts +24 -0
- package/dist/utils/focusReturn.d.ts.map +1 -0
- package/dist/utils/focusReturn.js +29 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +6 -1
- package/dist/utils/interactionModality.d.ts +34 -0
- package/dist/utils/interactionModality.d.ts.map +1 -0
- package/dist/utils/interactionModality.js +70 -0
- package/dist/utils/mergeRefs.d.ts.map +1 -1
- package/dist/utils/mergeRefs.js +7 -5
- package/dist/utils/rtlStyles.d.ts +2 -2
- package/dist/utils/rtlStyles.js +2 -2
- package/dist/utils/themeProps.d.ts +20 -1
- package/dist/utils/themeProps.d.ts.map +1 -1
- package/dist/utils/themeProps.js +8 -2
- package/locales/en.json +52 -0
- package/locales/pseudo.json +39 -0
- package/package.json +8 -3
- package/src/AlertDialog/AlertDialog.doc.mjs +16 -3
- package/src/AlertDialog/AlertDialog.test.tsx +208 -1
- package/src/AlertDialog/AlertDialog.tsx +21 -3
- package/src/AppShell/AppShell.doc.mjs +14 -0
- package/src/AppShell/AppShell.test.tsx +139 -0
- package/src/AppShell/AppShell.tsx +32 -22
- package/src/AspectRatio/AspectRatio.doc.mjs +27 -3
- package/src/AspectRatio/AspectRatio.test.tsx +30 -0
- package/src/AspectRatio/AspectRatio.tsx +13 -2
- package/src/AspectRatio/index.ts +0 -2
- package/src/Avatar/Avatar.doc.mjs +2 -13
- package/src/Avatar/Avatar.test.tsx +33 -8
- package/src/Avatar/Avatar.tsx +52 -50
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -9
- package/src/Badge/Badge.tsx +0 -2
- package/src/Badge/index.ts +0 -2
- package/src/Banner/Banner.test.tsx +58 -1
- package/src/Banner/Banner.tsx +33 -11
- package/src/Blockquote/Blockquote.tsx +0 -2
- package/src/Blockquote/index.ts +0 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +16 -6
- package/src/Breadcrumbs/index.ts +5 -1
- package/src/Button/Button.doc.mjs +2 -2
- package/src/Button/Button.tsx +22 -41
- package/src/Calendar/Calendar.tsx +2 -1
- package/src/Calendar/styles.ts +0 -8
- package/src/Card/Card.tsx +0 -2
- package/src/Card/index.ts +0 -2
- package/src/Carousel/Carousel.doc.mjs +3 -0
- package/src/Carousel/Carousel.tsx +10 -6
- package/src/Center/Center.tsx +0 -2
- package/src/Center/index.ts +0 -2
- package/src/Chat/Chat.doc.mjs +2 -0
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatLayoutScrollButton.test.tsx +22 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +8 -1
- package/src/Chat/ChatSendButton.tsx +2 -3
- package/src/Chat/ChatToolCalls.test.tsx +35 -0
- package/src/Chat/ChatToolCalls.tsx +36 -16
- package/src/Chat/useTriggerMenu.tsx +2 -5
- package/src/CheckboxInput/CheckboxInput.doc.mjs +4 -2
- package/src/CheckboxInput/CheckboxInput.test.tsx +120 -0
- package/src/CheckboxInput/CheckboxInput.tsx +45 -202
- package/src/ClickableCard/ClickableCard.tsx +6 -11
- package/src/Code/Code.tsx +0 -2
- package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
- package/src/CodeBlock/CodeBlock.test.tsx +91 -0
- package/src/CodeBlock/CodeBlock.tsx +57 -80
- package/src/Collapsible/Collapsible.tsx +22 -18
- package/src/CommandPalette/CommandPalette.test.tsx +83 -0
- package/src/CommandPalette/CommandPalette.tsx +5 -0
- package/src/CommandPalette/CommandPaletteItem.tsx +7 -4
- package/src/CommandPalette/CommandPaletteList.tsx +2 -2
- package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
- package/src/ComplexSelector/ComplexSelector.test.tsx +73 -0
- package/src/ComplexSelector/ComplexSelector.tsx +41 -28
- package/src/ContextMenu/ContextMenu.doc.mjs +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +41 -0
- package/src/ContextMenu/ContextMenu.tsx +3 -3
- package/src/ContextMenu/index.ts +5 -1
- package/src/DateInput/DateInput.doc.mjs +18 -3
- package/src/DateInput/DateInput.test.tsx +112 -11
- package/src/DateInput/DateInput.tsx +44 -25
- package/src/DateRangeInput/DateRangeInput.doc.mjs +10 -2
- package/src/DateRangeInput/DateRangeInput.test.tsx +110 -14
- package/src/DateRangeInput/DateRangeInput.tsx +27 -21
- package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -2
- package/src/DateTimeInput/DateTimeInput.test.tsx +154 -1
- package/src/DateTimeInput/DateTimeInput.tsx +58 -17
- package/src/Dialog/Dialog.tsx +2 -9
- package/src/DropdownMenu/DropdownMenu.doc.mjs +5 -9
- package/src/DropdownMenu/DropdownMenu.test.tsx +534 -4
- package/src/DropdownMenu/DropdownMenu.tsx +113 -52
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +27 -30
- package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +34 -0
- package/src/DropdownMenu/DropdownMenuDivider.tsx +81 -0
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +39 -4
- package/src/DropdownMenu/DropdownMenuItem.tsx +48 -10
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +2 -1
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +30 -76
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +25 -19
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +44 -14
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +1 -5
- package/src/DropdownMenu/index.ts +8 -1
- package/src/DropdownMenu/renderDropdownItems.tsx +33 -34
- package/src/EmptyState/EmptyState.doc.mjs +4 -0
- package/src/EmptyState/EmptyState.test.tsx +62 -0
- package/src/EmptyState/EmptyState.tsx +16 -6
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/InputClearButton.test.tsx +117 -0
- package/src/Field/InputClearButton.tsx +30 -3
- package/src/Field/PanelSearchInput.tsx +271 -0
- package/src/FileInput/FileInput.tsx +21 -8
- package/src/Grid/Grid.tsx +0 -2
- package/src/Grid/index.ts +0 -2
- package/src/HoverCard/useHoverCard.tsx +2 -23
- package/src/Icon/Icon.doc.mjs +2 -1
- package/src/Icon/globalIconRegistry.tsx +5 -4
- package/src/Indicator/CheckIndicator.tsx +174 -0
- package/src/Indicator/CheckboxIndicator.tsx +257 -0
- package/src/Indicator/Indicator.doc.mjs +344 -0
- package/src/Indicator/Indicator.test.tsx +393 -0
- package/src/Indicator/RadioIndicator.tsx +206 -0
- package/src/Indicator/index.ts +46 -0
- package/src/Indicator/indicator.markers.stylex.ts +19 -0
- package/src/Indicator/indicatorRegistry.test.tsx +106 -0
- package/src/Indicator/indicatorRegistry.ts +120 -0
- package/src/Indicator/types.ts +197 -0
- package/src/Indicator/useIndicator.ts +39 -0
- package/src/Item/Item.doc.mjs +1 -1
- package/src/Item/Item.tsx +7 -14
- package/src/Layer/useLayer.doc.mjs +2 -2
- package/src/Layer/useLayer.test.tsx +85 -0
- package/src/Layer/useLayer.tsx +39 -1
- package/src/Lightbox/Lightbox.doc.mjs +1 -1
- package/src/Lightbox/Lightbox.tsx +45 -49
- package/src/Link/Link.tsx +4 -11
- package/src/MobileNav/MobileNav.tsx +3 -3
- package/src/MoreMenu/MoreMenu.doc.mjs +31 -0
- package/src/MoreMenu/MoreMenu.test.tsx +68 -1
- package/src/MoreMenu/MoreMenu.tsx +19 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +18 -1
- package/src/MultiSelector/MultiSelector.test.tsx +387 -18
- package/src/MultiSelector/MultiSelector.tsx +267 -220
- package/src/NumberInput/NumberInput.doc.mjs +265 -50
- package/src/NumberInput/NumberInput.test.tsx +726 -21
- package/src/NumberInput/NumberInput.tsx +353 -59
- package/src/Outline/Outline.tsx +2 -5
- package/src/Pagination/Pagination.doc.mjs +1 -1
- package/src/Pagination/Pagination.test.tsx +22 -7
- package/src/Pagination/Pagination.tsx +38 -35
- package/src/Popover/Popover.doc.mjs +2 -0
- package/src/Popover/Popover.tsx +6 -7
- package/src/Popover/usePopover.tsx +37 -4
- package/src/PowerSearch/PowerSearch.tsx +1 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +42 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +7 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +27 -5
- package/src/ProgressBar/ProgressBar.test.tsx +224 -1
- package/src/ProgressBar/ProgressBar.tsx +126 -30
- package/src/RadioList/RadioList.doc.mjs +4 -2
- package/src/RadioList/RadioListItem.tsx +31 -130
- package/src/Resizable/ResizeHandle.tsx +2 -9
- package/src/Section/Section.tsx +0 -2
- package/src/Section/index.ts +0 -2
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -9
- package/src/SelectableCard/SelectableCard.tsx +4 -9
- package/src/Selector/Selector.doc.mjs +17 -4
- package/src/Selector/Selector.test.tsx +1394 -100
- package/src/Selector/Selector.tsx +355 -212
- package/src/Selector/hooks.ts +77 -50
- package/src/SideNav/SideNav.test.tsx +46 -0
- package/src/SideNav/SideNav.tsx +1 -0
- package/src/SideNav/SideNavCollapseButton.tsx +15 -10
- package/src/SideNav/SideNavHeading.tsx +48 -10
- package/src/SideNav/SideNavItem.tsx +20 -12
- package/src/Skeleton/Skeleton.tsx +0 -2
- package/src/Skeleton/index.ts +0 -2
- package/src/Slider/Slider.tsx +2 -11
- package/src/Stack/Stack.doc.mjs +110 -0
- package/src/StatusDot/StatusDot.doc.mjs +12 -3
- package/src/Switch/Switch.test.tsx +32 -0
- package/src/Switch/Switch.tsx +18 -10
- package/src/TabList/Tab.tsx +2 -9
- package/src/TabList/TabMenu.tsx +14 -21
- package/src/Table/BaseTable.tsx +11 -0
- package/src/Table/Table.test.tsx +31 -0
- package/src/Table/TableRow.tsx +6 -0
- package/src/Table/index.ts +1 -4
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +30 -14
- package/src/Table/plugins/rowExpansion/index.ts +1 -4
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +125 -175
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +115 -458
- package/src/Table/plugins/sortable/useTableSortable.tsx +2 -6
- package/src/Table/plugins/tree/useTableTreeData.tsx +43 -24
- package/src/Table/tableContextMenu.test.tsx +27 -0
- package/src/Table/tableContextMenu.tsx +1 -0
- package/src/Table/types.ts +11 -0
- package/src/Table/useTableGroupedRows.doc.mjs +1 -1
- package/src/Table/useTableRowExpansion.doc.mjs +43 -66
- package/src/TextArea/TextArea.doc.mjs +42 -2
- package/src/TextArea/TextArea.test.tsx +219 -0
- package/src/TextArea/TextArea.tsx +34 -7
- package/src/TextInput/TextInput.doc.mjs +18 -2
- package/src/TextInput/TextInput.test.tsx +189 -0
- package/src/TextInput/TextInput.tsx +25 -31
- package/src/Thumbnail/Thumbnail.tsx +2 -9
- package/src/TimeInput/TimeInput.doc.mjs +2 -2
- package/src/TimeInput/TimeInput.test.tsx +84 -3
- package/src/TimeInput/TimeInput.tsx +26 -28
- package/src/Timestamp/Timestamp.doc.mjs +4 -3
- package/src/Timestamp/Timestamp.test.tsx +91 -14
- package/src/Timestamp/Timestamp.tsx +14 -2
- package/src/Timestamp/TimestampHoverCard.tsx +13 -35
- package/src/Timestamp/formatInstant.ts +16 -1
- package/src/Token/Token.tsx +5 -28
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.test.tsx +45 -3
- package/src/Tokenizer/Tokenizer.tsx +10 -2
- package/src/Tooltip/useTooltip.tsx +2 -23
- package/src/TopNav/TopNav.tsx +1 -3
- package/src/TopNav/TopNavHeading.tsx +42 -13
- package/src/TopNav/TopNavItem.tsx +3 -21
- package/src/TopNav/TopNavMegaMenu.doc.mjs +5 -0
- package/src/TopNav/TopNavMegaMenu.test.tsx +433 -33
- package/src/TopNav/TopNavMegaMenu.tsx +118 -53
- package/src/TopNav/TopNavMegaMenuItem.tsx +2 -9
- package/src/TopNav/TopNavMenu.tsx +34 -37
- package/src/TreeList/TreeList.doc.mjs +5 -0
- package/src/TreeList/TreeList.test.tsx +208 -8
- package/src/TreeList/TreeList.tsx +22 -0
- package/src/TreeList/TreeListBranches.tsx +25 -2
- package/src/TreeList/TreeListItem.tsx +89 -52
- package/src/Typeahead/BaseTypeahead.tsx +19 -6
- package/src/Typeahead/Typeahead.doc.mjs +1 -0
- package/src/Typeahead/Typeahead.test.tsx +76 -3
- package/src/VisuallyHidden/VisuallyHidden.tsx +0 -2
- package/src/VisuallyHidden/index.ts +0 -2
- package/src/hooks/containerReveal.stylex.ts +102 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useClipboard.doc.mjs +87 -0
- package/src/hooks/useClipboard.test.tsx +151 -0
- package/src/hooks/useClipboard.ts +135 -0
- package/src/hooks/useContainerReveal.doc.mjs +7 -7
- package/src/hooks/useContainerReveal.test.tsx +42 -62
- package/src/hooks/useContainerReveal.ts +36 -91
- package/src/hooks/useImageMode.test.ts +1 -1
- package/src/hooks/useIndicatorFocusRing.tsx +120 -0
- package/src/hooks/useInputStatusIcon.tsx +8 -8
- package/src/hooks/useLongPress.test.tsx +18 -0
- package/src/hooks/useLongPress.ts +12 -2
- package/src/hooks/useScrollLock.test.ts +72 -0
- package/src/hooks/useScrollLock.ts +51 -19
- package/src/hooks/useStreamingText.test.ts +46 -1
- package/src/hooks/useStreamingText.ts +49 -7
- package/src/hooks/useTreeFocus.test.tsx +50 -0
- package/src/hooks/useTreeFocus.ts +14 -3
- package/src/hooks/useTypeahead.test.tsx +150 -0
- package/src/hooks/useTypeahead.ts +24 -9
- package/src/i18n/InternationalizationProvider.doc.mjs +7 -2
- package/src/index.ts +1 -0
- package/src/serverSafeComponents.test.ts +665 -0
- package/src/theme/defineTheme.ts +27 -0
- package/src/theme/derivedVarRegistry.test.ts +21 -1
- package/src/theme/derivedVarRegistry.ts +19 -6
- package/src/theme/expandColorScale.test.ts +14 -0
- package/src/theme/expandColorScale.ts +24 -9
- package/src/theme/expandTypeScale.test.ts +43 -0
- package/src/theme/expandTypeScale.ts +17 -0
- package/src/theme/generateThemeRules.test.ts +78 -20
- package/src/theme/generateThemeRules.ts +11 -0
- package/src/theme/index.ts +15 -0
- package/src/theme/tokens.stylex.ts +18 -0
- package/src/theme/tokens.test.ts +37 -0
- package/src/utils/focusOutline.stylex.ts +177 -0
- package/src/utils/focusReturn.test.ts +42 -0
- package/src/utils/focusReturn.ts +31 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/interactionModality.ts +74 -0
- package/src/utils/mergeRefs.test.ts +48 -0
- package/src/utils/mergeRefs.ts +12 -6
- package/src/utils/rtlStyles.ts +2 -2
- package/src/utils/themeProps.ts +26 -4
- package/dist/CheckboxInput/checkbox.markers.stylex.d.ts +0 -9
- package/dist/CheckboxInput/checkbox.markers.stylex.d.ts.map +0 -1
- package/dist/CheckboxInput/checkbox.markers.stylex.js +0 -14
- package/dist/RadioList/radio.markers.stylex.d.ts +0 -7
- package/dist/RadioList/radio.markers.stylex.d.ts.map +0 -1
- package/dist/RadioList/radio.markers.stylex.js +0 -12
- package/dist/hooks/containerReveal.pool.stylex.d.ts +0 -303
- package/dist/hooks/containerReveal.pool.stylex.d.ts.map +0 -1
- package/dist/hooks/containerReveal.pool.stylex.js +0 -292
- package/src/CheckboxInput/checkbox.markers.stylex.ts +0 -12
- package/src/RadioList/radio.markers.stylex.ts +0 -10
- package/src/hooks/containerReveal.pool.stylex.ts +0 -571
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file Selector.tsx
|
|
7
|
-
* @input Uses React, StyleX, usePopover, useTooltip, Icon, InputGroupContext
|
|
7
|
+
* @input Uses React, StyleX, usePopover, useTooltip, Icon, InputGroupContext,
|
|
8
|
+
* and Selector positioning hooks
|
|
8
9
|
* @output Exports Selector component
|
|
9
10
|
* @position Core implementation; consumed by index.ts
|
|
10
11
|
*
|
|
@@ -31,9 +32,12 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
31
32
|
import {usePopover} from '../Popover/usePopover';
|
|
32
33
|
import {useTooltip} from '../Tooltip';
|
|
33
34
|
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
35
|
+
import {useIndicator} from '../Indicator';
|
|
36
|
+
import type {IndicatorPosition} from '../Indicator';
|
|
34
37
|
import type {IconName} from '../Icon';
|
|
35
38
|
import {
|
|
36
39
|
Field,
|
|
40
|
+
InputClearButton,
|
|
37
41
|
inputStatusBorderStyles,
|
|
38
42
|
inputStatusHoverShadowStyles,
|
|
39
43
|
inputWrapperStyles,
|
|
@@ -43,7 +47,7 @@ import {Divider} from '../Divider';
|
|
|
43
47
|
import {layerAnimations} from '../Layer/layerAnimations.stylex';
|
|
44
48
|
import type {LayerPlacement} from '../Layer/useLayer';
|
|
45
49
|
import {Spinner} from '../Spinner';
|
|
46
|
-
import {
|
|
50
|
+
import {PanelSearchInput} from '../Field/PanelSearchInput';
|
|
47
51
|
import {useAnnounce} from '../hooks/useAnnounce';
|
|
48
52
|
import {
|
|
49
53
|
colorVars,
|
|
@@ -66,12 +70,15 @@ import {
|
|
|
66
70
|
getSelectableOptions,
|
|
67
71
|
} from './utils';
|
|
68
72
|
import {useCombobox, useSelectedItemOffset} from './hooks';
|
|
73
|
+
import {useTypeahead} from '../hooks/useTypeahead';
|
|
69
74
|
import {SelectorOption} from './SelectorOption';
|
|
70
75
|
import {getInputARIA, mergeProps} from '../utils';
|
|
71
76
|
import {useSize} from '../SizeContext/SizeContext';
|
|
72
77
|
import type {BaseProps} from '../BaseProps';
|
|
73
78
|
import type {SizeValue} from '../utils/types';
|
|
74
79
|
import {themeProps} from '../utils/themeProps';
|
|
80
|
+
import {focusOutlineStyles} from '../utils/focusOutline.stylex';
|
|
81
|
+
import {stableClassName} from '../naming';
|
|
75
82
|
import {groupStyles} from '../InputGroup/groupStyles';
|
|
76
83
|
import {useInputGroup} from '../InputGroup/InputGroupContext';
|
|
77
84
|
import {VisuallyHidden} from '../VisuallyHidden';
|
|
@@ -134,26 +141,27 @@ const styles = stylex.create({
|
|
|
134
141
|
whiteSpace: 'nowrap',
|
|
135
142
|
textAlign: 'start',
|
|
136
143
|
},
|
|
144
|
+
// Only what Icon does not already provide: `size="sm"` gives the 16px box
|
|
145
|
+
// and `color` the token, but the glyph still must not shrink inside the flex
|
|
146
|
+
// trigger.
|
|
137
147
|
triggerIcon: {
|
|
138
148
|
flexShrink: 0,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
},
|
|
150
|
+
// Rotation lives on the chevron glyph itself (passed through `xstyle`), not
|
|
151
|
+
// on the layout wrapper above, so the icon's `selector-indicator-icon` theme
|
|
152
|
+
// target and the open/closed transform sit on one element — a theme can
|
|
153
|
+
// restyle the mark and its rotation through a single selector. The wrapper
|
|
154
|
+
// keeps only layout. The status branch renders a different icon, so it never
|
|
155
|
+
// picks these up and needs no transition opt-out.
|
|
156
|
+
triggerIconRotation: {
|
|
144
157
|
transitionProperty: 'transform',
|
|
145
158
|
transitionDuration: durationVars['--duration-fast'],
|
|
146
159
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
147
160
|
transformOrigin: 'center',
|
|
148
|
-
color: colorVars['--color-icon-secondary'],
|
|
149
161
|
},
|
|
150
162
|
triggerIconOpen: {
|
|
151
163
|
transform: 'rotate(180deg)',
|
|
152
164
|
},
|
|
153
|
-
triggerIconStatus: {
|
|
154
|
-
// Disable rotation transition for status icons
|
|
155
|
-
transition: 'none',
|
|
156
|
-
},
|
|
157
165
|
triggerGhost: {
|
|
158
166
|
width: 'auto',
|
|
159
167
|
borderWidth: 0,
|
|
@@ -173,14 +181,6 @@ const styles = stylex.create({
|
|
|
173
181
|
':focus-within': 'none',
|
|
174
182
|
},
|
|
175
183
|
fontWeight: fontWeightVars['--font-weight-medium'],
|
|
176
|
-
outline: {
|
|
177
|
-
default: 'none',
|
|
178
|
-
':has(:focus-visible)': `2px solid ${colorVars['--color-accent']}`,
|
|
179
|
-
},
|
|
180
|
-
outlineOffset: {
|
|
181
|
-
default: '0',
|
|
182
|
-
':has(:focus-visible)': '3px',
|
|
183
|
-
},
|
|
184
184
|
transitionProperty:
|
|
185
185
|
'background-image, background-color, color, opacity, transform',
|
|
186
186
|
transform: {
|
|
@@ -197,23 +197,6 @@ const styles = stylex.create({
|
|
|
197
197
|
},
|
|
198
198
|
|
|
199
199
|
// Clear button
|
|
200
|
-
clearButton: {
|
|
201
|
-
display: 'flex',
|
|
202
|
-
alignItems: 'center',
|
|
203
|
-
justifyContent: 'center',
|
|
204
|
-
padding: 0,
|
|
205
|
-
margin: 0,
|
|
206
|
-
borderWidth: 0,
|
|
207
|
-
borderStyle: 'none',
|
|
208
|
-
backgroundColor: 'transparent',
|
|
209
|
-
cursor: 'pointer',
|
|
210
|
-
borderRadius: radiusVars['--radius-element'],
|
|
211
|
-
outline: {
|
|
212
|
-
default: 'none',
|
|
213
|
-
':focus-visible': `${borderVars['--border-width']} solid ${colorVars['--color-accent']}`,
|
|
214
|
-
},
|
|
215
|
-
outlineOffset: 1,
|
|
216
|
-
},
|
|
217
200
|
statusButton: {
|
|
218
201
|
display: 'flex',
|
|
219
202
|
alignItems: 'center',
|
|
@@ -226,11 +209,6 @@ const styles = stylex.create({
|
|
|
226
209
|
color: 'inherit',
|
|
227
210
|
cursor: 'pointer',
|
|
228
211
|
borderRadius: radiusVars['--radius-element'],
|
|
229
|
-
outline: {
|
|
230
|
-
default: 'none',
|
|
231
|
-
':focus-visible': `${borderVars['--border-width']} solid ${colorVars['--color-accent']}`,
|
|
232
|
-
},
|
|
233
|
-
outlineOffset: 1,
|
|
234
212
|
},
|
|
235
213
|
|
|
236
214
|
// Dropdown container
|
|
@@ -238,10 +216,21 @@ const styles = stylex.create({
|
|
|
238
216
|
boxSizing: 'border-box',
|
|
239
217
|
maxHeight: '300px',
|
|
240
218
|
overflowY: 'auto',
|
|
241
|
-
|
|
219
|
+
paddingBlock: spacingVars['--spacing-1'],
|
|
220
|
+
paddingInline: spacingVars['--spacing-1'],
|
|
242
221
|
opacity: 1,
|
|
243
222
|
transition: `opacity ${durationVars['--duration-fast']}`,
|
|
244
223
|
},
|
|
224
|
+
dropdownInput: {
|
|
225
|
+
// The input trigger's text inset includes its border. Mirror that extra
|
|
226
|
+
// pixel in the menu; the borderless ghost variant needs no correction.
|
|
227
|
+
paddingInline: `calc(${spacingVars['--spacing-1']} + ${borderVars['--border-width']})`,
|
|
228
|
+
},
|
|
229
|
+
// Same correction for the search row's gutter, so the search field and the
|
|
230
|
+
// option rows share one left edge.
|
|
231
|
+
searchRowInput: {
|
|
232
|
+
paddingInline: `calc(${spacingVars['--spacing-1']} + ${borderVars['--border-width']})`,
|
|
233
|
+
},
|
|
245
234
|
dropdownHidden: {
|
|
246
235
|
opacity: 0,
|
|
247
236
|
transition: 'none',
|
|
@@ -251,15 +240,6 @@ const styles = stylex.create({
|
|
|
251
240
|
popover: {
|
|
252
241
|
minWidth: 'anchor-size(width)',
|
|
253
242
|
},
|
|
254
|
-
// Search field. The inner TextInput owns the border, focus ring, magnifier
|
|
255
|
-
// (startIcon), and clear button (hasClear); this wrapper only supplies the
|
|
256
|
-
// dropdown's inline/block padding around it.
|
|
257
|
-
searchWrapper: {
|
|
258
|
-
display: 'flex',
|
|
259
|
-
alignItems: 'center',
|
|
260
|
-
paddingInline: spacingVars['--spacing-2'],
|
|
261
|
-
paddingBlock: spacingVars['--spacing-1'],
|
|
262
|
-
},
|
|
263
243
|
|
|
264
244
|
// Empty state
|
|
265
245
|
emptyState: {
|
|
@@ -270,9 +250,19 @@ const styles = stylex.create({
|
|
|
270
250
|
fontSize: typeScaleVars['--text-label-size'],
|
|
271
251
|
},
|
|
272
252
|
|
|
273
|
-
// Section
|
|
274
|
-
|
|
275
|
-
|
|
253
|
+
// Section heading. Plain secondary text, no rules — the same treatment
|
|
254
|
+
// DropdownMenu and CommandPaletteGroup already use for a group heading in a
|
|
255
|
+
// panel list. A labeled Divider (line–text–line) reads as a separator, and
|
|
256
|
+
// next to the search row's own divider it stacked two rules a few pixels
|
|
257
|
+
// apart.
|
|
258
|
+
sectionHeading: {
|
|
259
|
+
paddingBlock: spacingVars['--spacing-1'],
|
|
260
|
+
paddingInline: spacingVars['--spacing-2'],
|
|
261
|
+
fontFamily: typographyVars['--font-family-body'],
|
|
262
|
+
fontSize: typeScaleVars['--text-supporting-size'],
|
|
263
|
+
lineHeight: typeScaleVars['--text-supporting-leading'],
|
|
264
|
+
color: colorVars['--color-text-secondary'],
|
|
265
|
+
userSelect: 'none',
|
|
276
266
|
},
|
|
277
267
|
|
|
278
268
|
// Divider
|
|
@@ -306,6 +296,19 @@ const styles = stylex.create({
|
|
|
306
296
|
flex: 1,
|
|
307
297
|
minWidth: 0,
|
|
308
298
|
},
|
|
299
|
+
// The mark's column, reserved on every row and at either position, so a row
|
|
300
|
+
// occupies the same geometry whether or not it is the chosen one — the
|
|
301
|
+
// default check draws nothing when unchecked, and without the column a list
|
|
302
|
+
// would indent (or truncate) its chosen row differently from the rest.
|
|
303
|
+
// `minWidth` rather than `width`: a theme can replace `check` with a larger
|
|
304
|
+
// indicator (a radio is 20px at `sm`), and the column has to grow with it.
|
|
305
|
+
itemMarkColumn: {
|
|
306
|
+
display: 'inline-flex',
|
|
307
|
+
alignItems: 'center',
|
|
308
|
+
justifyContent: 'center',
|
|
309
|
+
flexShrink: 0,
|
|
310
|
+
minWidth: '1rem',
|
|
311
|
+
},
|
|
309
312
|
itemCheckmark: {
|
|
310
313
|
flexShrink: 0,
|
|
311
314
|
width: 16,
|
|
@@ -523,6 +526,16 @@ interface SelectorPropsBase<
|
|
|
523
526
|
*/
|
|
524
527
|
renderOption?: (option: SelectorOptionData) => ReactNode;
|
|
525
528
|
|
|
529
|
+
/**
|
|
530
|
+
* Which edge of the option row carries the selected mark. `start` reserves a
|
|
531
|
+
* mark column ahead of every label so they stay aligned, the way a native
|
|
532
|
+
* menu does; `end` is the house convention shared with Typeahead and
|
|
533
|
+
* CommandPalette.
|
|
534
|
+
*
|
|
535
|
+
* @default 'end'
|
|
536
|
+
*/
|
|
537
|
+
indicatorPosition?: IndicatorPosition;
|
|
538
|
+
|
|
526
539
|
/**
|
|
527
540
|
* Whether to show a search input for filtering options.
|
|
528
541
|
* @default false
|
|
@@ -673,6 +686,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
673
686
|
startIcon,
|
|
674
687
|
htmlName,
|
|
675
688
|
renderOption,
|
|
689
|
+
indicatorPosition = 'end',
|
|
676
690
|
hasSearch = false,
|
|
677
691
|
searchPlaceholder: searchPlaceholderFromProps,
|
|
678
692
|
placement,
|
|
@@ -703,18 +717,22 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
703
717
|
const statusMessageId = useId();
|
|
704
718
|
const inputLabelId = useId();
|
|
705
719
|
const searchId = useId();
|
|
720
|
+
// Measure from the same outer control that usePopover anchors to; using the
|
|
721
|
+
// shorter inner button makes every size's selected row land too low.
|
|
722
|
+
const anchorRef = useRef<HTMLDivElement>(null);
|
|
706
723
|
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
707
724
|
const searchRef = useRef<HTMLInputElement>(null);
|
|
708
725
|
const inputGroup = useInputGroup();
|
|
709
726
|
|
|
710
727
|
const [searchQuery, setSearchQuery] = useState('');
|
|
711
|
-
// A typed query shows
|
|
728
|
+
// A typed query shows the search row's clear (✕) button, which becomes
|
|
712
729
|
// the next tab stop after the search input.
|
|
713
730
|
const hasQuery = searchQuery.length > 0;
|
|
714
731
|
|
|
715
732
|
const [, startTransition] = useTransition();
|
|
716
733
|
const [optimisticValue, setOptimisticValue] = useOptimistic(normalizedValue);
|
|
717
734
|
const isBusy = isLoading || optimisticValue !== normalizedValue;
|
|
735
|
+
const announce = useAnnounce();
|
|
718
736
|
|
|
719
737
|
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
720
738
|
// tooltip listeners attach to the trigger container (which already exists)
|
|
@@ -775,15 +793,15 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
775
793
|
// Ref for listbox to measure selected item position
|
|
776
794
|
const listboxRef = useRef<HTMLDivElement>(null);
|
|
777
795
|
|
|
778
|
-
//
|
|
779
|
-
//
|
|
780
|
-
//
|
|
781
|
-
|
|
782
|
-
const announce = useAnnounce();
|
|
796
|
+
// Typeahead is defined below (it needs the popover), but closing and clearing
|
|
797
|
+
// must drop its pending buffer — otherwise a stale prefix survives the reset
|
|
798
|
+
// window and poisons the next keystroke ("Dog" then "c" would search "dc").
|
|
799
|
+
const resetTypeaheadRef = useRef<() => void>(() => {});
|
|
783
800
|
|
|
784
801
|
// Layer for dropdown positioning
|
|
785
802
|
const handleLayerHide = useCallback(() => {
|
|
786
803
|
setSearchQuery('');
|
|
804
|
+
resetTypeaheadRef.current();
|
|
787
805
|
// Clear any lingering result count when the popover closes so stale status
|
|
788
806
|
// text does not linger in the a11y tree.
|
|
789
807
|
announce('');
|
|
@@ -798,6 +816,9 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
798
816
|
// The popup's own role="listbox" is the exposed semantics; the trigger
|
|
799
817
|
// keeps DOM focus, so wrapping it in a modal dialog would misrepresent it.
|
|
800
818
|
role: 'none',
|
|
819
|
+
// The theme target belongs on the SURFACE that paints the popup, which
|
|
820
|
+
// `usePopover` owns — not on the scrolling list inside it.
|
|
821
|
+
surfaceTarget: 'selector-popup',
|
|
801
822
|
});
|
|
802
823
|
|
|
803
824
|
// Open dropdown on mount when isDefaultOpen is true
|
|
@@ -840,7 +861,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
840
861
|
selectedItemIndex,
|
|
841
862
|
listboxId,
|
|
842
863
|
listboxRef,
|
|
843
|
-
|
|
864
|
+
anchorRef,
|
|
844
865
|
});
|
|
845
866
|
|
|
846
867
|
const selectedItemOffset = shouldOverlaySelectedItem ? rawOffset : 0;
|
|
@@ -854,6 +875,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
854
875
|
// Clear the current value. Shared by the clear button and the keyboard
|
|
855
876
|
// Delete/Backspace path so clearing is reachable without a mouse.
|
|
856
877
|
const clearValue = useCallback(() => {
|
|
878
|
+
resetTypeaheadRef.current();
|
|
857
879
|
onChange?.(null);
|
|
858
880
|
if (changeAction) {
|
|
859
881
|
startTransition(async () => {
|
|
@@ -863,10 +885,29 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
863
885
|
}
|
|
864
886
|
}, [onChange, changeAction, startTransition, setOptimisticValue]);
|
|
865
887
|
|
|
866
|
-
//
|
|
888
|
+
// Type-to-find appends to the query rather than replacing it: characters
|
|
889
|
+
// typed before focus reaches the search input must not be dropped.
|
|
890
|
+
const appendSearchQuery = useCallback((char: string) => {
|
|
891
|
+
setSearchQuery(query => query + char);
|
|
892
|
+
}, []);
|
|
893
|
+
|
|
894
|
+
const commitValue = useCallback(
|
|
895
|
+
(newValue: string) => {
|
|
896
|
+
onChange?.(newValue);
|
|
897
|
+
if (changeAction) {
|
|
898
|
+
startTransition(async () => {
|
|
899
|
+
setOptimisticValue(newValue);
|
|
900
|
+
await changeAction(newValue);
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
},
|
|
904
|
+
[onChange, changeAction, startTransition, setOptimisticValue],
|
|
905
|
+
);
|
|
906
|
+
|
|
907
|
+
// Selector behavior (keyboard nav, selection)
|
|
867
908
|
const {
|
|
868
909
|
highlightedIndex,
|
|
869
|
-
setHighlightedIndex
|
|
910
|
+
setHighlightedIndex,
|
|
870
911
|
getItemId,
|
|
871
912
|
onTriggerClick,
|
|
872
913
|
onKeyDown,
|
|
@@ -874,7 +915,11 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
874
915
|
onItemMouseEnter,
|
|
875
916
|
} = useCombobox({
|
|
876
917
|
selectableItems: filteredItems,
|
|
877
|
-
value:
|
|
918
|
+
// The optimistic value, not the raw prop: with a pending changeAction the
|
|
919
|
+
// prop still holds the old selection, so the popup would open with the
|
|
920
|
+
// highlight on it and Delete/Backspace could clear a value the action has
|
|
921
|
+
// already replaced.
|
|
922
|
+
value: optimisticValue,
|
|
878
923
|
isDisabled,
|
|
879
924
|
isOpen: popover.isOpen,
|
|
880
925
|
hasSearch,
|
|
@@ -882,27 +927,61 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
882
927
|
popover.show();
|
|
883
928
|
if (hasSearch) {
|
|
884
929
|
requestAnimationFrame(() => {
|
|
885
|
-
searchRef.current
|
|
930
|
+
const input = searchRef.current;
|
|
931
|
+
if (input) {
|
|
932
|
+
input.focus();
|
|
933
|
+
// When typing seeded the query, place the caret after it so the
|
|
934
|
+
// user keeps typing where they left off.
|
|
935
|
+
input.setSelectionRange(input.value.length, input.value.length);
|
|
936
|
+
}
|
|
886
937
|
});
|
|
887
938
|
}
|
|
888
939
|
}, [popover, hasSearch]),
|
|
889
940
|
onClose: popover.hide,
|
|
890
|
-
onSelect:
|
|
891
|
-
(newValue: string) => {
|
|
892
|
-
onChange?.(newValue);
|
|
893
|
-
if (changeAction) {
|
|
894
|
-
startTransition(async () => {
|
|
895
|
-
setOptimisticValue(newValue);
|
|
896
|
-
await changeAction(newValue);
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
},
|
|
900
|
-
[onChange, changeAction, startTransition, setOptimisticValue],
|
|
901
|
-
),
|
|
941
|
+
onSelect: commitValue,
|
|
902
942
|
onClear: hasClear ? clearValue : undefined,
|
|
943
|
+
onSearchSeed: appendSearchQuery,
|
|
903
944
|
listboxId,
|
|
904
945
|
});
|
|
905
946
|
|
|
947
|
+
// Type-to-select, shared with the other collections (menus, listboxes).
|
|
948
|
+
// Open, it walks the highlight — aria-activedescendant announces each match.
|
|
949
|
+
// Closed, it commits the match like a native select, which changes the value
|
|
950
|
+
// without opening the popup or moving focus, so nothing else would prompt
|
|
951
|
+
// assistive tech to re-read the trigger: announce it explicitly.
|
|
952
|
+
const typeahead = useTypeahead({
|
|
953
|
+
getItemLabels: () => selectableItems.map(item => item.label ?? item.value),
|
|
954
|
+
isDisabled: index => selectableItems[index]?.disabled === true,
|
|
955
|
+
// Cycle onward from the highlight when open, from the committed selection
|
|
956
|
+
// when closed — the optimistic one, so a pending changeAction cannot strand
|
|
957
|
+
// cycling on the first match. -1 means nothing is selected or highlighted,
|
|
958
|
+
// which the hook reads as "search from the top".
|
|
959
|
+
getCurrentIndex: () =>
|
|
960
|
+
popover.isOpen ? highlightedIndex : selectedItemIndex,
|
|
961
|
+
onMatch: index => {
|
|
962
|
+
const item = selectableItems[index];
|
|
963
|
+
if (popover.isOpen) {
|
|
964
|
+
setHighlightedIndex(index);
|
|
965
|
+
} else if (item.value !== optimisticValue) {
|
|
966
|
+
commitValue(item.value);
|
|
967
|
+
announce(item.label ?? item.value);
|
|
968
|
+
}
|
|
969
|
+
},
|
|
970
|
+
});
|
|
971
|
+
resetTypeaheadRef.current = typeahead.reset;
|
|
972
|
+
|
|
973
|
+
const handleTriggerKeyDown = useCallback(
|
|
974
|
+
(e: React.KeyboardEvent) => {
|
|
975
|
+
// With hasSearch the query input owns typing, so type-to-select is off.
|
|
976
|
+
if (!isDisabled && !hasSearch && typeahead.onKeyDown(e)) {
|
|
977
|
+
e.preventDefault();
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
onKeyDown(e);
|
|
981
|
+
},
|
|
982
|
+
[isDisabled, hasSearch, typeahead, onKeyDown],
|
|
983
|
+
);
|
|
984
|
+
|
|
906
985
|
// Keep the highlighted option visible during keyboard navigation. The
|
|
907
986
|
// listbox is a fixed-height scroll container, so without this the virtual
|
|
908
987
|
// cursor walks off-screen once navigation passes the visible window. Mirrors
|
|
@@ -931,11 +1010,40 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
931
1010
|
return null;
|
|
932
1011
|
}
|
|
933
1012
|
return (
|
|
934
|
-
<
|
|
935
|
-
{
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1013
|
+
<PanelSearchInput
|
|
1014
|
+
ref={searchRef}
|
|
1015
|
+
id={searchId}
|
|
1016
|
+
// The search row is the panel's header: a magnifier, a borderless
|
|
1017
|
+
// input, and the shared clear (✕) button. It deliberately does NOT
|
|
1018
|
+
// render a bordered TextInput — the popup is already a bordered
|
|
1019
|
+
// surface, and a field inside it drew a second box within that box.
|
|
1020
|
+
label={t('@astryx.selector.searchOptions')}
|
|
1021
|
+
// Same accessible name the TextInput's built-in clear produced
|
|
1022
|
+
// ("Clear Search options"), so the affordance keeps its name while its
|
|
1023
|
+
// chrome changes.
|
|
1024
|
+
clearLabel={t('@astryx.textInput.clearLabel', {
|
|
1025
|
+
label: t('@astryx.selector.searchOptions'),
|
|
1026
|
+
})}
|
|
1027
|
+
{...themeProps('selector-search')}
|
|
1028
|
+
xstyle={variant !== 'ghost' && styles.searchRowInput}
|
|
1029
|
+
// When hasSearch is set, focus moves into this input on open, so it —
|
|
1030
|
+
// not the trigger — must be the combobox that reports the highlighted
|
|
1031
|
+
// option via aria-activedescendant (comboboxes-4). A bare searchbox
|
|
1032
|
+
// left the highlight silent to screen readers.
|
|
1033
|
+
role="combobox"
|
|
1034
|
+
aria-expanded={popover.isOpen}
|
|
1035
|
+
aria-controls={listboxId}
|
|
1036
|
+
aria-autocomplete="list"
|
|
1037
|
+
aria-activedescendant={
|
|
1038
|
+
popover.isOpen && highlightedIndex >= 0
|
|
1039
|
+
? getItemId(highlightedIndex)
|
|
1040
|
+
: undefined
|
|
1041
|
+
}
|
|
1042
|
+
value={searchQuery}
|
|
1043
|
+
onValueChange={handleSearchChange}
|
|
1044
|
+
onContainerKeyDown={e => {
|
|
1045
|
+
// The clear (✕) button lives inside the row, after the input in DOM
|
|
1046
|
+
// order. When it is focused and the user tabs forward there is
|
|
939
1047
|
// nothing else in the popup, so dismiss it (Shift+Tab returns to the
|
|
940
1048
|
// input natively). Key events originating on the input are handled on
|
|
941
1049
|
// the input below; ignore them here so we don't double-dismiss.
|
|
@@ -945,65 +1053,32 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
945
1053
|
if (e.key === 'Tab' && !e.shiftKey) {
|
|
946
1054
|
onKeyDown(e);
|
|
947
1055
|
}
|
|
948
|
-
}}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
//
|
|
953
|
-
//
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
width="100%"
|
|
965
|
-
// When hasSearch is set, focus moves into this input on open, so it —
|
|
966
|
-
// not the trigger — must be the combobox that reports the highlighted
|
|
967
|
-
// option via aria-activedescendant (comboboxes-4). A bare searchbox
|
|
968
|
-
// left the highlight silent to screen readers. role + aria-* pass
|
|
969
|
-
// through to the underlying <input> via BaseProps.
|
|
970
|
-
role="combobox"
|
|
971
|
-
aria-expanded={popover.isOpen}
|
|
972
|
-
aria-controls={listboxId}
|
|
973
|
-
aria-autocomplete="list"
|
|
974
|
-
aria-activedescendant={
|
|
975
|
-
popover.isOpen && highlightedIndex >= 0
|
|
976
|
-
? getItemId(highlightedIndex)
|
|
977
|
-
: undefined
|
|
1056
|
+
}}
|
|
1057
|
+
onKeyDown={e => {
|
|
1058
|
+
// Arrow keys navigate options; Enter selects; Escape closes.
|
|
1059
|
+
// Home/End are left to the input for caret movement (APG editable
|
|
1060
|
+
// combobox); PageUp/PageDown are the sanctioned substitute for
|
|
1061
|
+
// jumping to the first/last option.
|
|
1062
|
+
if (
|
|
1063
|
+
e.key === 'ArrowDown' ||
|
|
1064
|
+
e.key === 'ArrowUp' ||
|
|
1065
|
+
e.key === 'PageUp' ||
|
|
1066
|
+
e.key === 'PageDown' ||
|
|
1067
|
+
e.key === 'Enter' ||
|
|
1068
|
+
e.key === 'Escape'
|
|
1069
|
+
) {
|
|
1070
|
+
onKeyDown(e);
|
|
1071
|
+
return;
|
|
978
1072
|
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
e.key === 'ArrowUp' ||
|
|
989
|
-
e.key === 'PageUp' ||
|
|
990
|
-
e.key === 'PageDown' ||
|
|
991
|
-
e.key === 'Enter' ||
|
|
992
|
-
e.key === 'Escape'
|
|
993
|
-
) {
|
|
994
|
-
onKeyDown(e);
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
// Tab: when a query is showing the clear (✕) button, forward-tab
|
|
998
|
-
// moves focus to it (keeping the popup open) so the affordance is
|
|
999
|
-
// keyboard-reachable. Every other Tab dismisses the popup as usual.
|
|
1000
|
-
if (e.key === 'Tab' && (e.shiftKey || !hasQuery)) {
|
|
1001
|
-
onKeyDown(e);
|
|
1002
|
-
}
|
|
1003
|
-
}}
|
|
1004
|
-
placeholder={searchPlaceholder}
|
|
1005
|
-
/>
|
|
1006
|
-
</div>
|
|
1073
|
+
// Tab: when a query is showing the clear (✕) button, forward-tab
|
|
1074
|
+
// moves focus to it (keeping the popup open) so the affordance is
|
|
1075
|
+
// keyboard-reachable. Every other Tab dismisses the popup as usual.
|
|
1076
|
+
if (e.key === 'Tab' && (e.shiftKey || !hasQuery)) {
|
|
1077
|
+
onKeyDown(e);
|
|
1078
|
+
}
|
|
1079
|
+
}}
|
|
1080
|
+
placeholder={searchPlaceholder}
|
|
1081
|
+
/>
|
|
1007
1082
|
);
|
|
1008
1083
|
}, [
|
|
1009
1084
|
hasSearch,
|
|
@@ -1017,15 +1092,60 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1017
1092
|
popover.isOpen,
|
|
1018
1093
|
highlightedIndex,
|
|
1019
1094
|
getItemId,
|
|
1095
|
+
variant,
|
|
1020
1096
|
t,
|
|
1021
1097
|
]);
|
|
1022
1098
|
|
|
1099
|
+
// The single-selection mark, resolved from the theme once per render. A
|
|
1100
|
+
// theme that maps `check` to another indicator (a radio, say) changes every
|
|
1101
|
+
// selected-option mark in the app through this one lookup.
|
|
1102
|
+
const SelectionMark = useIndicator('check');
|
|
1103
|
+
|
|
1023
1104
|
// Render an individual item
|
|
1024
1105
|
const renderItem = useCallback(
|
|
1025
1106
|
(item: SelectorOptionData, flatIndex: number) => {
|
|
1026
1107
|
const isHighlighted = flatIndex === highlightedIndex;
|
|
1027
1108
|
const isSelected = item.value === normalizedValue;
|
|
1028
1109
|
|
|
1110
|
+
/*
|
|
1111
|
+
* Rendered UNCONDITIONALLY, with the state passed down: the default
|
|
1112
|
+
* check draws nothing when unchecked, but a theme that replaces the
|
|
1113
|
+
* `check` indicator with a radio needs the unselected state to draw
|
|
1114
|
+
* its empty circle. `{isSelected && …}` would make that impossible.
|
|
1115
|
+
*
|
|
1116
|
+
* `selector-check` stays the stable target for the mark's position
|
|
1117
|
+
* in the row; the indicator owns what the mark looks like.
|
|
1118
|
+
*/
|
|
1119
|
+
const mark = (
|
|
1120
|
+
<span {...stylex.props(styles.itemMarkColumn)}>
|
|
1121
|
+
<SelectionMark
|
|
1122
|
+
state={isSelected ? 'checked' : 'unchecked'}
|
|
1123
|
+
size="sm"
|
|
1124
|
+
isDisabled={item.disabled ?? false}
|
|
1125
|
+
{...themeProps('selector-check')}
|
|
1126
|
+
/>
|
|
1127
|
+
</span>
|
|
1128
|
+
);
|
|
1129
|
+
|
|
1130
|
+
const optionContent = (
|
|
1131
|
+
<span {...stylex.props(styles.itemContent)}>
|
|
1132
|
+
{renderOption ? renderOption(item) : <DefaultOption option={item} />}
|
|
1133
|
+
</span>
|
|
1134
|
+
);
|
|
1135
|
+
|
|
1136
|
+
const content =
|
|
1137
|
+
indicatorPosition === 'start' ? (
|
|
1138
|
+
<>
|
|
1139
|
+
{mark}
|
|
1140
|
+
{optionContent}
|
|
1141
|
+
</>
|
|
1142
|
+
) : (
|
|
1143
|
+
<>
|
|
1144
|
+
{optionContent}
|
|
1145
|
+
{mark}
|
|
1146
|
+
</>
|
|
1147
|
+
);
|
|
1148
|
+
|
|
1029
1149
|
return (
|
|
1030
1150
|
<div
|
|
1031
1151
|
key={item.value}
|
|
@@ -1042,25 +1162,20 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1042
1162
|
isSelected && styles.itemSelected,
|
|
1043
1163
|
item.disabled && styles.itemDisabled,
|
|
1044
1164
|
)}>
|
|
1045
|
-
|
|
1046
|
-
{renderOption ? (
|
|
1047
|
-
renderOption(item)
|
|
1048
|
-
) : (
|
|
1049
|
-
<DefaultOption option={item} />
|
|
1050
|
-
)}
|
|
1051
|
-
</span>
|
|
1052
|
-
{isSelected && <Icon icon="check" size="sm" color="accent" />}
|
|
1165
|
+
{content}
|
|
1053
1166
|
</div>
|
|
1054
1167
|
);
|
|
1055
1168
|
},
|
|
1056
1169
|
[
|
|
1057
1170
|
renderOption,
|
|
1171
|
+
indicatorPosition,
|
|
1058
1172
|
highlightedIndex,
|
|
1059
1173
|
size,
|
|
1060
1174
|
normalizedValue,
|
|
1061
1175
|
getItemId,
|
|
1062
1176
|
onItemSelect,
|
|
1063
1177
|
onItemMouseEnter,
|
|
1178
|
+
SelectionMark,
|
|
1064
1179
|
],
|
|
1065
1180
|
);
|
|
1066
1181
|
|
|
@@ -1078,7 +1193,10 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1078
1193
|
<div
|
|
1079
1194
|
key="empty"
|
|
1080
1195
|
role="presentation"
|
|
1081
|
-
{...
|
|
1196
|
+
{...mergeProps(
|
|
1197
|
+
themeProps('selector-empty-state'),
|
|
1198
|
+
stylex.props(styles.emptyState),
|
|
1199
|
+
)}>
|
|
1082
1200
|
No results found
|
|
1083
1201
|
</div>,
|
|
1084
1202
|
];
|
|
@@ -1112,17 +1230,23 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1112
1230
|
if (sectionItems.length === 0) {
|
|
1113
1231
|
continue;
|
|
1114
1232
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
xstyle={styles.sectionDivider}
|
|
1121
|
-
/>,
|
|
1122
|
-
);
|
|
1123
|
-
}
|
|
1233
|
+
// The heading lives INSIDE the group and is aria-hidden: the group
|
|
1234
|
+
// already carries the title as its accessible name, so exposing the
|
|
1235
|
+
// text again would announce it twice. This also keeps role="listbox"'s
|
|
1236
|
+
// children to option/group only — the old labeled Divider sat in the
|
|
1237
|
+
// listbox as a stray role="separator".
|
|
1124
1238
|
elements.push(
|
|
1125
1239
|
<div key={`section-${i}`} role="group" aria-label={option.title}>
|
|
1240
|
+
{option.title && (
|
|
1241
|
+
<div
|
|
1242
|
+
aria-hidden="true"
|
|
1243
|
+
{...mergeProps(
|
|
1244
|
+
themeProps('selector-section-heading'),
|
|
1245
|
+
stylex.props(styles.sectionHeading),
|
|
1246
|
+
)}>
|
|
1247
|
+
{option.title}
|
|
1248
|
+
</div>
|
|
1249
|
+
)}
|
|
1126
1250
|
{sectionItems}
|
|
1127
1251
|
</div>,
|
|
1128
1252
|
);
|
|
@@ -1150,6 +1274,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1150
1274
|
<>
|
|
1151
1275
|
<div
|
|
1152
1276
|
ref={el => {
|
|
1277
|
+
anchorRef.current = el;
|
|
1153
1278
|
popover.triggerRef(el);
|
|
1154
1279
|
// Anchor + hover/focus listeners for the disabled-message tooltip.
|
|
1155
1280
|
// Handlers are gated internally by isEnabled, and anchor names
|
|
@@ -1163,12 +1288,14 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1163
1288
|
variant,
|
|
1164
1289
|
size,
|
|
1165
1290
|
status: status?.type ?? null,
|
|
1291
|
+
disabled: isDisabled ? 'disabled' : null,
|
|
1166
1292
|
}),
|
|
1167
1293
|
stylex.props(
|
|
1168
1294
|
inputWrapperStyles.base,
|
|
1169
1295
|
styles.triggerContainer,
|
|
1170
1296
|
sizeStyles[size],
|
|
1171
1297
|
variant === 'ghost' && styles.triggerGhost,
|
|
1298
|
+
variant === 'ghost' && focusOutlineStyles.focusWithin,
|
|
1172
1299
|
isDisabled && inputWrapperStyles.disabled,
|
|
1173
1300
|
variant === 'ghost' && isDisabled && styles.triggerGhostDisabled,
|
|
1174
1301
|
!selectedItem && styles.triggerPlaceholder,
|
|
@@ -1217,7 +1344,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1217
1344
|
// still blocked by the isDisabled guards in useCombobox.
|
|
1218
1345
|
disabled={isDisabled && !showsDisabledMessage}
|
|
1219
1346
|
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
1220
|
-
onKeyDown={
|
|
1347
|
+
onKeyDown={handleTriggerKeyDown}
|
|
1221
1348
|
tabIndex={isDisabled && !showsDisabledMessage ? -1 : 0}
|
|
1222
1349
|
{...stylex.props(styles.trigger)}>
|
|
1223
1350
|
<span {...stylex.props(styles.triggerLabel)}>
|
|
@@ -1236,80 +1363,89 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1236
1363
|
)}
|
|
1237
1364
|
{isBusy && <Spinner size="sm" />}
|
|
1238
1365
|
{hasClear && value != null && !isDisabled && (
|
|
1239
|
-
<
|
|
1240
|
-
|
|
1366
|
+
<InputClearButton
|
|
1367
|
+
label={t('@astryx.selector.clearLabel', {label})}
|
|
1241
1368
|
onClick={handleClear}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
<Icon
|
|
1245
|
-
icon="close"
|
|
1246
|
-
size="sm"
|
|
1247
|
-
color="secondary"
|
|
1248
|
-
// Stable theme target on the clear glyph itself, so a theme can
|
|
1249
|
-
// restyle just this icon (color, size, hover) via `defineTheme`.
|
|
1250
|
-
// Same-element rules in @layer astryx-theme win over the icon's
|
|
1251
|
-
// own base color/size, which a button-level target could not
|
|
1252
|
-
// reach.
|
|
1253
|
-
{...themeProps('selector-clear-icon')}
|
|
1254
|
-
/>
|
|
1255
|
-
</button>
|
|
1369
|
+
iconClassName={stableClassName('selector-clear-icon')}
|
|
1370
|
+
/>
|
|
1256
1371
|
)}
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
color={STATUS_ICON_COLOR_MAP[status.type]}
|
|
1276
|
-
/>
|
|
1277
|
-
</button>
|
|
1278
|
-
) : (
|
|
1372
|
+
{/*
|
|
1373
|
+
No wrapper span: Icon's own span already provides the 16px box (`sm`)
|
|
1374
|
+
and the icon color, so the status glyph and the chevron are each
|
|
1375
|
+
directly targetable instead of sharing one untargetable parent — and
|
|
1376
|
+
the two affordances stop sharing a node.
|
|
1377
|
+
*/}
|
|
1378
|
+
{showStatusIcon ? (
|
|
1379
|
+
showStatusTooltip ? (
|
|
1380
|
+
<button
|
|
1381
|
+
ref={statusTooltip.ref}
|
|
1382
|
+
type="button"
|
|
1383
|
+
aria-label={t(STATUS_BUTTON_LABEL_KEY[status.type])}
|
|
1384
|
+
aria-describedby={statusTooltip.describedBy}
|
|
1385
|
+
onClick={e => e.stopPropagation()}
|
|
1386
|
+
{...stylex.props(
|
|
1387
|
+
focusOutlineStyles.focusVisible,
|
|
1388
|
+
styles.statusButton,
|
|
1389
|
+
)}>
|
|
1279
1390
|
<Icon
|
|
1280
1391
|
icon={STATUS_ICON_MAP[status.type]}
|
|
1281
1392
|
size="sm"
|
|
1282
1393
|
color={STATUS_ICON_COLOR_MAP[status.type]}
|
|
1394
|
+
xstyle={styles.triggerIcon}
|
|
1283
1395
|
/>
|
|
1284
|
-
|
|
1396
|
+
</button>
|
|
1285
1397
|
) : (
|
|
1286
1398
|
<Icon
|
|
1287
|
-
icon=
|
|
1399
|
+
icon={STATUS_ICON_MAP[status.type]}
|
|
1288
1400
|
size="sm"
|
|
1289
|
-
color=
|
|
1290
|
-
|
|
1291
|
-
// restyle just this icon (color, size, hover) — and its
|
|
1292
|
-
// open/closed state — via `defineTheme`. Same-element rules in
|
|
1293
|
-
// @layer astryx-theme win over the icon's own base color/size,
|
|
1294
|
-
// which a button-level target could not reach.
|
|
1295
|
-
{...themeProps('selector-indicator-icon', {
|
|
1296
|
-
state: popover.isOpen ? 'expanded' : 'collapsed',
|
|
1297
|
-
})}
|
|
1401
|
+
color={STATUS_ICON_COLOR_MAP[status.type]}
|
|
1402
|
+
xstyle={styles.triggerIcon}
|
|
1298
1403
|
/>
|
|
1299
|
-
)
|
|
1300
|
-
|
|
1404
|
+
)
|
|
1405
|
+
) : (
|
|
1406
|
+
<Icon
|
|
1407
|
+
icon="chevronDown"
|
|
1408
|
+
size="sm"
|
|
1409
|
+
color="secondary"
|
|
1410
|
+
// The rotation rides on the glyph, alongside the box and color
|
|
1411
|
+
// the wrapper used to provide, so one element carries the mark,
|
|
1412
|
+
// its open/closed transform, and the theme target.
|
|
1413
|
+
xstyle={[
|
|
1414
|
+
styles.triggerIcon,
|
|
1415
|
+
styles.triggerIconRotation,
|
|
1416
|
+
popover.isOpen && styles.triggerIconOpen,
|
|
1417
|
+
]}
|
|
1418
|
+
// Stable theme target on the chevron glyph itself, so a theme can
|
|
1419
|
+
// restyle just this icon (color, size, hover) — and its
|
|
1420
|
+
// open/closed state — via `defineTheme`. Same-element rules in
|
|
1421
|
+
// @layer astryx-theme win over the icon's own base color/size,
|
|
1422
|
+
// which a button-level target could not reach.
|
|
1423
|
+
{...themeProps('selector-indicator-icon', {
|
|
1424
|
+
state: popover.isOpen ? 'expanded' : 'collapsed',
|
|
1425
|
+
})}
|
|
1426
|
+
/>
|
|
1427
|
+
)}
|
|
1301
1428
|
</div>
|
|
1302
1429
|
|
|
1303
1430
|
{popover.render(
|
|
1304
1431
|
hasSearch ? (
|
|
1305
1432
|
<div>
|
|
1306
1433
|
{renderSearch()}
|
|
1434
|
+
{/*
|
|
1435
|
+
Separates the header from the options and spans the panel: the
|
|
1436
|
+
search row and the listbox each hold their own inline padding,
|
|
1437
|
+
the line does not, so it reads as the panel's own edge.
|
|
1438
|
+
*/}
|
|
1439
|
+
<Divider />
|
|
1307
1440
|
<div
|
|
1308
1441
|
ref={listboxRef}
|
|
1309
1442
|
id={listboxId}
|
|
1310
1443
|
role="listbox"
|
|
1311
1444
|
aria-labelledby={triggerId}
|
|
1312
|
-
{...stylex.props(
|
|
1445
|
+
{...stylex.props(
|
|
1446
|
+
styles.dropdown,
|
|
1447
|
+
variant !== 'ghost' && styles.dropdownInput,
|
|
1448
|
+
)}>
|
|
1313
1449
|
{renderOptions()}
|
|
1314
1450
|
</div>
|
|
1315
1451
|
</div>
|
|
@@ -1321,6 +1457,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1321
1457
|
aria-labelledby={triggerId}
|
|
1322
1458
|
{...stylex.props(
|
|
1323
1459
|
styles.dropdown,
|
|
1460
|
+
variant !== 'ghost' && styles.dropdownInput,
|
|
1324
1461
|
!isPositioned && styles.dropdownHidden,
|
|
1325
1462
|
)}>
|
|
1326
1463
|
{renderOptions()}
|
|
@@ -1329,6 +1466,12 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1329
1466
|
{
|
|
1330
1467
|
placement: popoverPlacement,
|
|
1331
1468
|
alignment: 'start',
|
|
1469
|
+
// The system's standard menu clearance, except in overlay mode:
|
|
1470
|
+
// there the measured negative margin owns the block geometry and
|
|
1471
|
+
// the menu is meant to sit on the trigger, not clear it.
|
|
1472
|
+
offset: shouldOverlaySelectedItem
|
|
1473
|
+
? undefined
|
|
1474
|
+
: spacingVars['--spacing-1'],
|
|
1332
1475
|
xstyle: [styles.popover, layerAnimations[popoverPlacement]],
|
|
1333
1476
|
style: popoverOffsetStyle,
|
|
1334
1477
|
},
|