@astryxdesign/core 0.4.7 → 0.5.0-canary.009bcb3
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 +161 -1
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +45 -20
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -2
- package/dist/AspectRatio/AspectRatio.d.ts +24 -0
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +23 -4
- package/dist/Avatar/Avatar.d.ts +25 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +58 -19
- package/dist/Avatar/index.d.ts +2 -2
- package/dist/Avatar/index.d.ts.map +1 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +8 -4
- package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
- package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
- package/dist/Banner/Banner.d.ts +49 -15
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +62 -20
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +17 -4
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +11 -6
- package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +26 -7
- package/dist/Calendar/Calendar.d.ts +7 -3
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +21 -23
- package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
- package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
- package/dist/Calendar/getInitialFocusDate.js +62 -0
- package/dist/Calendar/styles.d.ts +5 -14
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +15 -15
- package/dist/Card/Card.d.ts +12 -12
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +17 -9
- package/dist/Card/index.d.ts +35 -1
- package/dist/Card/index.d.ts.map +1 -1
- package/dist/Card/index.js +21 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +3 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +2 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +3 -3
- package/dist/Chat/ChatMessageList.d.ts +22 -3
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +6 -3
- package/dist/Chat/ChatTokenizedText.d.ts +2 -0
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +11 -6
- package/dist/Chat/useChatComposerTokens.js +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +10 -3
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +15 -4
- package/dist/CodeBlock/highlightRanges.js +1 -1
- package/dist/CodeBlock/highlightStyles.js +13 -13
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +3 -2
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +3 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +1 -3
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- package/dist/DateInput/DateInput.d.ts +43 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +22 -2
- package/dist/DateInput/NativeDateField.d.ts +10 -0
- package/dist/DateInput/NativeDateField.d.ts.map +1 -0
- package/dist/DateInput/NativeDateField.js +494 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +82 -23
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateInput/nativeDateSegments.d.ts +22 -0
- package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
- package/dist/DateInput/nativeDateSegments.js +111 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +406 -12
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.d.ts +21 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +110 -58
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -13
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -1
- package/dist/Field/InputClearButton.d.ts +9 -3
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +14 -3
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +3 -2
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +6 -3
- package/dist/HoverCard/HoverCard.d.ts +6 -0
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +104 -3
- package/dist/HoverCard/useHoverCard.d.ts +19 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +74 -26
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +6 -2
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +2 -19
- package/dist/Layer/LayerDepthContext.d.ts +52 -0
- package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
- package/dist/Layer/LayerDepthContext.js +66 -0
- package/dist/Layer/gestureCounter.d.ts +8 -0
- package/dist/Layer/gestureCounter.d.ts.map +1 -0
- package/dist/Layer/gestureCounter.js +53 -0
- package/dist/Layer/index.d.ts +3 -0
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +4 -0
- package/dist/Layer/layerStack.d.ts +98 -0
- package/dist/Layer/layerStack.d.ts.map +1 -0
- package/dist/Layer/layerStack.js +306 -0
- package/dist/Layer/useLayer.d.ts +23 -13
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +128 -8
- package/dist/Layer/useLayerDismissal.d.ts +93 -0
- package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
- package/dist/Layer/useLayerDismissal.js +91 -0
- package/dist/Lightbox/Lightbox.d.ts +1 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +103 -81
- package/dist/List/List.d.ts +1 -1
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +15 -4
- package/dist/Markdown/Markdown.d.ts +1 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +20 -7
- package/dist/Markdown/index.d.ts +1 -1
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/parser.d.ts +38 -1
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +182 -32
- package/dist/MetadataList/MetadataListItem.d.ts +1 -1
- package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
- package/dist/MetadataList/MetadataListItem.js +4 -1
- package/dist/MobileNav/MobileNav.d.ts +6 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +61 -36
- package/dist/MultiSelector/MultiSelector.d.ts +32 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +73 -15
- package/dist/MultiSelector/hooks.d.ts +7 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +3 -2
- package/dist/MultiSelector/index.d.ts +1 -1
- package/dist/MultiSelector/index.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.js +5 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +9 -5
- package/dist/NumberInput/NumberInput.d.ts +6 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +54 -104
- package/dist/NumberInput/numberInputCommit.d.ts +34 -0
- package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
- package/dist/NumberInput/numberInputCommit.js +71 -0
- package/dist/NumberInput/numberParser.d.ts +64 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -0
- package/dist/NumberInput/numberParser.js +350 -0
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +3 -2
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +3 -2
- package/dist/Overlay/Overlay.d.ts.map +1 -1
- package/dist/Overlay/Overlay.js +3 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +1 -9
- package/dist/Popover/usePopover.d.ts +7 -41
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +40 -21
- package/dist/PowerSearch/PowerSearch.d.ts +8 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +19 -6
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +110 -27
- package/dist/PowerSearch/types.d.ts +2 -0
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +14 -5
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +18 -5
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +3 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +12 -3
- package/dist/Selector/Selector.d.ts +18 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +91 -18
- package/dist/Selector/hooks.d.ts +7 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +3 -2
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -3
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +8 -7
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +4 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +37 -5
- package/dist/Spinner/Spinner.d.ts +3 -3
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +130 -78
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +6 -1
- package/dist/Stepper/Step.d.ts +140 -0
- package/dist/Stepper/Step.d.ts.map +1 -0
- package/dist/Stepper/Step.js +1045 -0
- package/dist/Stepper/StepStatus.d.ts +24 -0
- package/dist/Stepper/StepStatus.d.ts.map +1 -0
- package/dist/Stepper/StepStatus.js +1 -0
- package/dist/Stepper/Stepper.d.ts +93 -0
- package/dist/Stepper/Stepper.d.ts.map +1 -0
- package/dist/Stepper/Stepper.js +184 -0
- package/dist/Stepper/StepperContext.d.ts +41 -0
- package/dist/Stepper/StepperContext.d.ts.map +1 -0
- package/dist/Stepper/StepperContext.js +34 -0
- package/dist/Stepper/index.d.ts +8 -0
- package/dist/Stepper/index.d.ts.map +1 -0
- package/dist/Stepper/index.js +7 -0
- package/dist/Stepper/stepper.stylex.d.ts +15 -0
- package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
- package/dist/Stepper/stepper.stylex.js +20 -0
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +8 -3
- package/dist/TabList/Tab.d.ts +15 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +32 -7
- package/dist/TabList/TabList.d.ts +46 -7
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +353 -23
- package/dist/TabList/TabListContext.d.ts +11 -1
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +11 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +3 -2
- package/dist/TabList/index.d.ts +2 -2
- package/dist/TabList/index.d.ts.map +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +10 -2
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +3 -6
- package/dist/Table/TableRow.d.ts +16 -5
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +16 -5
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +54 -11
- package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +43 -5
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
- package/dist/Table/types.d.ts +22 -4
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -0
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +6 -3
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +16 -10
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +3 -2
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +15 -21
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +22 -7
- package/dist/Toast/ToastViewport.d.ts +1 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +71 -18
- package/dist/Token/Token.d.ts +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +20 -9
- package/dist/Token/TokenLink.d.ts +1 -1
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +7 -4
- package/dist/Tokenizer/Tokenizer.d.ts +14 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +33 -21
- package/dist/Tooltip/Tooltip.d.ts +5 -0
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +5 -0
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +39 -24
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +5 -4
- package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +31 -11
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +22 -7
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +7 -2
- package/dist/Typeahead/BaseTypeahead.d.ts +35 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +119 -37
- package/dist/Typeahead/Typeahead.d.ts +8 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +5 -2
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +7 -2
- package/dist/astryx.css +113 -11
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useFocusTrap.d.ts +7 -4
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +60 -95
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +3 -18
- package/dist/hooks/useMergedRefs.d.ts +18 -0
- package/dist/hooks/useMergedRefs.d.ts.map +1 -0
- package/dist/hooks/useMergedRefs.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +46 -10
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +24 -4
- package/dist/theme/generateThemeRules.d.ts +21 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +26 -0
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.js +5 -2
- package/dist/utils/groupItems.d.ts +5 -1
- package/dist/utils/groupItems.d.ts.map +1 -1
- package/dist/utils/groupItems.js +9 -9
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/isApplePlatform.d.ts +18 -0
- package/dist/utils/isApplePlatform.d.ts.map +1 -0
- package/dist/utils/isApplePlatform.js +37 -0
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +10 -1
- package/dist/utils/timeParser.d.ts +1 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +26 -12
- package/locales/af-ZA.json +6 -6
- package/locales/ar-SA.json +6 -6
- package/locales/ca-ES.json +5 -5
- package/locales/cs-CZ.json +6 -6
- package/locales/da-DK.json +6 -6
- package/locales/de-DE.json +6 -6
- package/locales/el-GR.json +6 -6
- package/locales/en.json +163 -11
- package/locales/es-ES.json +5 -5
- package/locales/fi-FI.json +6 -6
- package/locales/fr-FR.json +6 -6
- package/locales/he-IL.json +6 -6
- package/locales/hu-HU.json +6 -6
- package/locales/it-IT.json +6 -6
- package/locales/ja-JP.json +6 -6
- package/locales/ko-KR.json +6 -6
- package/locales/nl-NL.json +6 -6
- package/locales/no-NO.json +6 -6
- package/locales/pl-PL.json +6 -6
- package/locales/pseudo.json +114 -0
- package/locales/pt-BR.json +6 -6
- package/locales/pt-PT.json +6 -6
- package/locales/ro-RO.json +6 -6
- package/locales/ru-RU.json +6 -6
- package/locales/sr-SP.json +6 -6
- package/locales/sv-SE.json +6 -6
- package/locales/tr-TR.json +6 -6
- package/locales/uk-UA.json +6 -6
- package/locales/vi-VN.json +6 -6
- package/locales/zh-CN.json +6 -6
- package/locales/zh-TW.json +6 -6
- package/package.json +8 -3
- package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
- package/src/AlertDialog/AlertDialog.test.tsx +211 -2
- package/src/AlertDialog/AlertDialog.tsx +62 -20
- package/src/AppShell/AppShell.tsx +3 -2
- package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
- package/src/AspectRatio/AspectRatio.test.tsx +57 -10
- package/src/AspectRatio/AspectRatio.tsx +40 -1
- package/src/Avatar/Avatar.doc.mjs +14 -3
- package/src/Avatar/Avatar.test.tsx +97 -0
- package/src/Avatar/Avatar.tsx +125 -52
- package/src/Avatar/index.ts +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
- package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
- package/src/AvatarGroup/AvatarGroup.tsx +15 -6
- package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
- package/src/Banner/Banner.doc.mjs +22 -11
- package/src/Banner/Banner.test.tsx +177 -25
- package/src/Banner/Banner.tsx +93 -27
- package/src/BottomSheet/BottomSheet.test.tsx +123 -0
- package/src/BottomSheet/BottomSheet.tsx +17 -4
- package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
- package/src/Button/Button.doc.mjs +24 -1
- package/src/Button/Button.test.tsx +32 -4
- package/src/Button/Button.tsx +12 -5
- package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
- package/src/ButtonGroup/ButtonGroup.test.tsx +404 -1
- package/src/ButtonGroup/ButtonGroup.tsx +23 -5
- package/src/Calendar/Calendar.doc.mjs +7 -6
- package/src/Calendar/Calendar.test.tsx +143 -0
- package/src/Calendar/Calendar.tsx +30 -26
- package/src/Calendar/getInitialFocusDate.test.ts +94 -0
- package/src/Calendar/getInitialFocusDate.ts +93 -0
- package/src/Calendar/styles.ts +49 -31
- package/src/Card/Card.doc.mjs +10 -7
- package/src/Card/Card.test.tsx +113 -19
- package/src/Card/Card.tsx +67 -89
- package/src/Card/index.ts +36 -1
- package/src/Carousel/Carousel.tsx +3 -2
- package/src/Chat/ChatComposerInput.tsx +5 -1
- package/src/Chat/ChatLayout.tsx +3 -2
- package/src/Chat/ChatMessageList.doc.mjs +9 -1
- package/src/Chat/ChatMessageList.test.tsx +46 -0
- package/src/Chat/ChatMessageList.tsx +28 -4
- package/src/Chat/ChatTokenizedText.tsx +17 -10
- package/src/Chat/useChatComposerTokens.ts +1 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
- package/src/CheckboxInput/CheckboxInput.tsx +8 -2
- package/src/ClickableCard/ClickableCard.tsx +3 -2
- package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
- package/src/CodeBlock/CodeBlock.test.tsx +37 -0
- package/src/CodeBlock/CodeBlock.tsx +20 -4
- package/src/CodeBlock/highlightRanges.ts +1 -1
- package/src/CodeBlock/highlightStyles.ts +13 -13
- package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
- package/src/ComplexSelector/ComplexSelector.test.tsx +32 -0
- package/src/ComplexSelector/ComplexSelector.tsx +1 -3
- package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
- package/src/ContextMenu/ContextMenu.tsx +4 -3
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.tsx +55 -2
- package/src/DateInput/DateInputTouch.test.tsx +146 -32
- package/src/DateInput/NativeDateField.test.tsx +635 -0
- package/src/DateInput/NativeDateField.tsx +641 -0
- package/src/DateInput/TouchDateField.tsx +108 -24
- package/src/DateInput/index.ts +1 -0
- package/src/DateInput/nativeDateSegments.ts +127 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +2 -2
- package/src/DateRangeInput/DateRangeInput.test.tsx +22 -0
- package/src/DateRangeInput/DateRangeInput.tsx +4 -2
- package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
- package/src/DateTimeInput/DateTimeInput.tsx +556 -24
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/Dialog.doc.mjs +8 -3
- package/src/Dialog/Dialog.test.tsx +429 -2
- package/src/Dialog/Dialog.tsx +133 -58
- package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
- package/src/DropdownMenu/DropdownMenu.tsx +4 -13
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
- package/src/Field/Field.doc.mjs +13 -2
- package/src/Field/FieldLabel.test.tsx +29 -0
- package/src/Field/FieldLabel.tsx +7 -0
- package/src/Field/InputClearButton.test.tsx +15 -1
- package/src/Field/InputClearButton.tsx +28 -4
- package/src/FileInput/FileInput.tsx +3 -2
- package/src/Heading/Heading.test.tsx +23 -1
- package/src/Heading/Heading.tsx +6 -3
- package/src/HoverCard/HoverCard.doc.mjs +13 -2
- package/src/HoverCard/HoverCard.test.tsx +154 -4
- package/src/HoverCard/HoverCard.tsx +143 -3
- package/src/HoverCard/useHoverCard.tsx +104 -33
- package/src/Indicator/CheckboxIndicator.tsx +14 -8
- package/src/Indicator/Indicator.doc.mjs +2 -0
- package/src/Item/Item.tsx +5 -4
- package/src/Kbd/Kbd.tsx +2 -19
- package/src/Layer/LayerDepthContext.tsx +62 -0
- package/src/Layer/gestureCounter.ts +57 -0
- package/src/Layer/index.ts +9 -0
- package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
- package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
- package/src/Layer/layerStack.ts +362 -0
- package/src/Layer/useLayer.test.tsx +324 -15
- package/src/Layer/useLayer.tsx +164 -8
- package/src/Layer/useLayerDismissal.test.tsx +469 -0
- package/src/Layer/useLayerDismissal.ts +173 -0
- package/src/Layout/Layout.doc.mjs +2 -2
- package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
- package/src/Lightbox/Lightbox.doc.mjs +12 -0
- package/src/Lightbox/Lightbox.tsx +124 -102
- package/src/Link/Link.doc.mjs +39 -0
- package/src/List/List.test.tsx +38 -0
- package/src/List/List.tsx +8 -1
- package/src/Markdown/Markdown.doc.mjs +5 -0
- package/src/Markdown/Markdown.test.tsx +37 -0
- package/src/Markdown/Markdown.tsx +16 -5
- package/src/Markdown/incremental.test.ts +16 -2
- package/src/Markdown/index.ts +1 -0
- package/src/Markdown/parser.perf.test.ts +96 -1
- package/src/Markdown/parser.test.ts +178 -2
- package/src/Markdown/parser.ts +253 -32
- package/src/MetadataList/MetadataList.test.tsx +75 -2
- package/src/MetadataList/MetadataListItem.tsx +5 -2
- package/src/MobileNav/MobileNav.tsx +62 -36
- package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +49 -1
- package/src/MultiSelector/MultiSelector.test.tsx +311 -0
- package/src/MultiSelector/MultiSelector.tsx +151 -15
- package/src/MultiSelector/hooks.ts +9 -2
- package/src/MultiSelector/index.ts +1 -0
- package/src/NavIcon/NavIcon.doc.mjs +8 -2
- package/src/NavIcon/NavIcon.test.tsx +9 -0
- package/src/NavIcon/NavIcon.tsx +5 -1
- package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
- package/src/NavMenu/NavHeadingMenu.tsx +9 -5
- package/src/NumberInput/NumberInput.doc.mjs +31 -7
- package/src/NumberInput/NumberInput.test.tsx +436 -8
- package/src/NumberInput/NumberInput.tsx +62 -114
- package/src/NumberInput/numberInputCommit.test.ts +72 -0
- package/src/NumberInput/numberInputCommit.ts +103 -0
- package/src/NumberInput/numberParser.docblock.test.ts +234 -0
- package/src/NumberInput/numberParser.test.ts +222 -0
- package/src/NumberInput/numberParser.ts +403 -0
- package/src/Outline/Outline.tsx +3 -2
- package/src/OverflowList/OverflowList.tsx +3 -2
- package/src/Overlay/Overlay.tsx +3 -2
- package/src/Pagination/Pagination.test.tsx +3 -2
- package/src/Popover/Popover.test.tsx +14 -0
- package/src/Popover/Popover.tsx +1 -9
- package/src/Popover/usePopover.tsx +57 -32
- package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
- package/src/PowerSearch/PowerSearch.test.tsx +240 -1
- package/src/PowerSearch/PowerSearch.tsx +34 -5
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +288 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +111 -1
- package/src/PowerSearch/PowerSearchValueEditor.tsx +124 -10
- package/src/PowerSearch/types.ts +2 -0
- package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
- package/src/PowerSearch/usePowerSearchSource.ts +13 -3
- package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
- package/src/ProgressBar/ProgressBar.test.tsx +24 -0
- package/src/ProgressBar/ProgressBar.tsx +28 -8
- package/src/Resizable/ResizeHandle.tsx +3 -2
- package/src/SegmentedControl/SegmentedControl.tsx +3 -2
- package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
- package/src/SelectableCard/SelectableCard.tsx +19 -2
- package/src/Selector/Selector.doc.mjs +26 -1
- package/src/Selector/Selector.test.tsx +346 -1
- package/src/Selector/Selector.tsx +148 -21
- package/src/Selector/hooks.ts +17 -2
- package/src/SideNav/SideNav.doc.mjs +6 -6
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavHeading.tsx +12 -12
- package/src/SideNav/SideNavItem.tsx +4 -2
- package/src/Slider/Slider.test.tsx +106 -1
- package/src/Slider/Slider.tsx +55 -3
- package/src/Spinner/Spinner.test.tsx +147 -1
- package/src/Spinner/Spinner.tsx +120 -101
- package/src/StatusDot/StatusDot.doc.mjs +8 -2
- package/src/StatusDot/StatusDot.test.tsx +9 -0
- package/src/StatusDot/StatusDot.tsx +7 -1
- package/src/Stepper/Step.doc.mjs +98 -0
- package/src/Stepper/Step.tsx +1638 -0
- package/src/Stepper/StepStatus.ts +26 -0
- package/src/Stepper/Stepper.doc.mjs +370 -0
- package/src/Stepper/Stepper.test.tsx +1024 -0
- package/src/Stepper/Stepper.tsx +258 -0
- package/src/Stepper/StepperContext.ts +71 -0
- package/src/Stepper/index.ts +18 -0
- package/src/Stepper/stepper.stylex.ts +19 -0
- package/src/Switch/Switch.doc.mjs +2 -0
- package/src/Switch/Switch.test.tsx +10 -0
- package/src/Switch/Switch.tsx +6 -2
- package/src/TabList/Tab.doc.mjs +13 -1
- package/src/TabList/Tab.tsx +67 -7
- package/src/TabList/TabList.doc.mjs +22 -6
- package/src/TabList/TabList.test.tsx +559 -0
- package/src/TabList/TabList.tsx +490 -22
- package/src/TabList/TabListContext.ts +13 -2
- package/src/TabList/TabMenu.tsx +3 -2
- package/src/TabList/index.ts +6 -2
- package/src/Table/BaseTable.tsx +12 -4
- package/src/Table/Table.doc.mjs +9 -2
- package/src/Table/Table.test.tsx +132 -14
- package/src/Table/Table.tsx +3 -8
- package/src/Table/TableBody.doc.mjs +40 -0
- package/src/Table/TableFooter.doc.mjs +40 -0
- package/src/Table/TableHeader.doc.mjs +40 -0
- package/src/Table/TableRow.tsx +16 -5
- package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
- package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
- package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +67 -12
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
- package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
- package/src/Table/plugins/selection/useTableSelection.test.tsx +138 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +63 -7
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
- package/src/Table/types.ts +22 -4
- package/src/Table/useBaseTablePlugins.ts +5 -0
- package/src/Table/useTableGroupedRows.doc.mjs +5 -4
- package/src/Table/useTablePagination.doc.mjs +7 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +31 -0
- package/src/Text/Text.test.tsx +67 -1
- package/src/Text/Text.tsx +6 -3
- package/src/TextArea/TextArea.doc.mjs +12 -2
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +37 -24
- package/src/TextInput/TextInput.doc.mjs +10 -0
- package/src/TextInput/TextInput.tsx +3 -2
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.tsx +2 -2
- package/src/Timestamp/Timestamp.test.tsx +58 -0
- package/src/Timestamp/Timestamp.tsx +12 -10
- package/src/Toast/Toast.doc.mjs +26 -12
- package/src/Toast/Toast.tsx +28 -4
- package/src/Toast/ToastViewport.test.tsx +536 -8
- package/src/Toast/ToastViewport.tsx +81 -12
- package/src/Token/Token.test.tsx +95 -0
- package/src/Token/Token.tsx +15 -10
- package/src/Token/TokenLink.tsx +14 -5
- package/src/Tokenizer/Tokenizer.doc.mjs +43 -3
- package/src/Tokenizer/Tokenizer.test.tsx +161 -0
- package/src/Tokenizer/Tokenizer.tsx +53 -24
- package/src/Toolbar/Toolbar.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.test.tsx +32 -0
- package/src/Tooltip/Tooltip.tsx +5 -0
- package/src/Tooltip/useTooltip.tsx +47 -24
- package/src/TopNav/TopNavHeading.tsx +5 -4
- package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
- package/src/TopNav/TopNavMegaMenu.tsx +47 -5
- package/src/TopNav/TopNavMenu.test.tsx +133 -1
- package/src/TopNav/TopNavMenu.tsx +38 -7
- package/src/TreeList/TreeList.test.tsx +49 -0
- package/src/TreeList/TreeList.tsx +7 -2
- package/src/Typeahead/BaseTypeahead.doc.mjs +24 -0
- package/src/Typeahead/BaseTypeahead.tsx +181 -39
- package/src/Typeahead/Typeahead.doc.mjs +11 -0
- package/src/Typeahead/Typeahead.test.tsx +203 -0
- package/src/Typeahead/Typeahead.tsx +12 -2
- package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
- package/src/Typeahead/TypeaheadItem.tsx +8 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useAnnounce.doc.mjs +96 -0
- package/src/hooks/useContainerReveal.doc.mjs +2 -2
- package/src/hooks/useDevWarning.doc.mjs +96 -0
- package/src/hooks/useFocusTrap.test.tsx +14 -0
- package/src/hooks/useFocusTrap.ts +62 -111
- package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
- package/src/hooks/useHotkeys.ts +3 -18
- package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
- package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
- package/src/hooks/useInteractiveRole.doc.mjs +119 -0
- package/src/hooks/useLongPress.doc.mjs +123 -0
- package/src/hooks/useMergedRefs.doc.mjs +79 -0
- package/src/hooks/useMergedRefs.test.tsx +62 -0
- package/src/hooks/useMergedRefs.ts +36 -0
- package/src/hooks/useTypeahead.doc.mjs +153 -0
- package/src/index.ts +1 -0
- package/src/raw-import.d.ts +14 -0
- package/src/theme/MediaTheme.doc.mjs +5 -5
- package/src/theme/Theme.test.tsx +104 -2
- package/src/theme/Theme.tsx +49 -14
- package/src/theme/defineTheme.test.ts +23 -0
- package/src/theme/derivedVarRegistry.test.ts +26 -3
- package/src/theme/derivedVarRegistry.ts +23 -4
- package/src/theme/generateThemeRules.test.ts +99 -1
- package/src/theme/generateThemeRules.ts +28 -0
- package/src/theme/syntax/tokens.ts +5 -2
- package/src/utils/groupItems.ts +12 -6
- package/src/utils/index.ts +1 -1
- package/src/utils/isApplePlatform.test.ts +61 -0
- package/src/utils/isApplePlatform.ts +37 -0
- package/src/utils/sharedResizeObserver.ts +10 -2
- package/src/utils/timeParser.test.ts +6 -1
- package/src/utils/timeParser.ts +35 -13
- package/src/__tests__/inputWidthContract.test.tsx +0 -69
|
@@ -41,12 +41,13 @@ import {
|
|
|
41
41
|
fontWeightVars,
|
|
42
42
|
typeScaleVars,
|
|
43
43
|
} from '../theme/tokens.stylex';
|
|
44
|
-
import {getKey,
|
|
44
|
+
import {getKey, groupItems, mergeProps} from '../utils';
|
|
45
45
|
import type {BaseProps} from '../BaseProps';
|
|
46
46
|
import type {SearchableItem, SearchSource} from './types';
|
|
47
47
|
import {themeProps} from '../utils/themeProps';
|
|
48
48
|
import {useTranslator} from '../i18n';
|
|
49
49
|
|
|
50
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
50
51
|
// =============================================================================
|
|
51
52
|
// Types
|
|
52
53
|
// =============================================================================
|
|
@@ -93,6 +94,22 @@ export interface BaseTypeaheadProps<T extends SearchableItem> extends Omit<
|
|
|
93
94
|
*/
|
|
94
95
|
maxMenuItems?: number;
|
|
95
96
|
|
|
97
|
+
/** Fixed dropdown width in pixels. Never shrinks below the anchor width. */
|
|
98
|
+
menuWidth?: number;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Minimum query length before the search source is queried. Below it no
|
|
102
|
+
* search runs and the menu stays closed, so a remote source is not asked
|
|
103
|
+
* for a result set that cannot be meaningful yet — and the user does not
|
|
104
|
+
* see "no results" for a query that was never searched.
|
|
105
|
+
*
|
|
106
|
+
* Measured with `String.length` (UTF-16 code units), like every other
|
|
107
|
+
* length check in the library.
|
|
108
|
+
*
|
|
109
|
+
* @default 1 — every non-empty query is searched.
|
|
110
|
+
*/
|
|
111
|
+
minQueryLength?: number;
|
|
112
|
+
|
|
96
113
|
/**
|
|
97
114
|
* Text shown when no results found.
|
|
98
115
|
* @default 'No results found'
|
|
@@ -131,6 +148,28 @@ export interface BaseTypeaheadProps<T extends SearchableItem> extends Omit<
|
|
|
131
148
|
*/
|
|
132
149
|
onOpenChange?: (isOpen: boolean) => void;
|
|
133
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Entries derived from the query text rather than fetched for it — today,
|
|
153
|
+
* Tokenizer's "Create ...".
|
|
154
|
+
*
|
|
155
|
+
* They are appended to whatever the search returned, and they are offered
|
|
156
|
+
* whatever `minQueryLength` says: that threshold exists to avoid a fetch
|
|
157
|
+
* that is too broad to be worth making, and these cost no fetch. A field
|
|
158
|
+
* that can create `QA` should not stop being able to just because a search
|
|
159
|
+
* for `QA` would match too much.
|
|
160
|
+
*
|
|
161
|
+
* Receives the results they will be appended to, so a caller can decline to
|
|
162
|
+
* offer an entry that duplicates one.
|
|
163
|
+
*
|
|
164
|
+
* Underscored and `@internal`: `BaseTypeaheadProps` is re-exported from the
|
|
165
|
+
* package entry point, so anything named on it ships as public API at the
|
|
166
|
+
* next cut. This is a wiring detail between Tokenizer and the base — the
|
|
167
|
+
* same reason `DefinedTheme.__inputTokens` carries its prefix.
|
|
168
|
+
*
|
|
169
|
+
* @internal
|
|
170
|
+
*/
|
|
171
|
+
__queryEntries?: (query: string, results: T[]) => T[];
|
|
172
|
+
|
|
134
173
|
/**
|
|
135
174
|
* Debounce delay in ms before triggering search after typing.
|
|
136
175
|
* Set to 0 for synchronous/local search sources that don't need debouncing.
|
|
@@ -226,6 +265,18 @@ const styles = stylex.create({
|
|
|
226
265
|
popover: {
|
|
227
266
|
minWidth: 'anchor-size(width)',
|
|
228
267
|
},
|
|
268
|
+
popoverCustomWidth: (width: number) => ({
|
|
269
|
+
width: `${width}px`,
|
|
270
|
+
}),
|
|
271
|
+
groupHeading: {
|
|
272
|
+
paddingInline: spacingVars['--spacing-2'],
|
|
273
|
+
paddingBlockStart: spacingVars['--spacing-2'],
|
|
274
|
+
paddingBlockEnd: spacingVars['--spacing-1'],
|
|
275
|
+
fontSize: typeScaleVars['--text-supporting-size'],
|
|
276
|
+
lineHeight: typeScaleVars['--text-supporting-leading'],
|
|
277
|
+
color: colorVars['--color-text-secondary'],
|
|
278
|
+
userSelect: 'none',
|
|
279
|
+
},
|
|
229
280
|
item: {
|
|
230
281
|
boxSizing: 'border-box',
|
|
231
282
|
display: 'flex',
|
|
@@ -285,6 +336,19 @@ const itemSizeStyles = stylex.create({
|
|
|
285
336
|
},
|
|
286
337
|
});
|
|
287
338
|
|
|
339
|
+
// =============================================================================
|
|
340
|
+
// Helpers
|
|
341
|
+
// =============================================================================
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* A query that has been typed but is still shorter than the caller's
|
|
345
|
+
* threshold. An empty query is not "below the minimum" — it is the
|
|
346
|
+
* untouched state, and `hasEntriesOnFocus` owns what happens there.
|
|
347
|
+
*/
|
|
348
|
+
function isBelowMinQueryLength(query: string, minQueryLength: number): boolean {
|
|
349
|
+
return query.length > 0 && query.length < minQueryLength;
|
|
350
|
+
}
|
|
351
|
+
|
|
288
352
|
// =============================================================================
|
|
289
353
|
// Component
|
|
290
354
|
// =============================================================================
|
|
@@ -316,12 +380,15 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
316
380
|
placeholder: placeholderFromProps,
|
|
317
381
|
hasEntriesOnFocus = false,
|
|
318
382
|
maxMenuItems = 10,
|
|
383
|
+
menuWidth,
|
|
384
|
+
minQueryLength = 1,
|
|
319
385
|
emptySearchResultsText: emptySearchResultsTextFromProps,
|
|
320
386
|
isDisabled = false,
|
|
321
387
|
isFocusableDisabled = false,
|
|
322
388
|
hasAutoFocus = false,
|
|
323
389
|
onChangeQuery,
|
|
324
390
|
onOpenChange,
|
|
391
|
+
__queryEntries,
|
|
325
392
|
inputId: externalInputId,
|
|
326
393
|
ariaDescribedBy,
|
|
327
394
|
ariaLabelledBy,
|
|
@@ -440,7 +507,11 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
440
507
|
return;
|
|
441
508
|
}
|
|
442
509
|
resultsGenRef.current = gen;
|
|
443
|
-
const
|
|
510
|
+
const fetched = searchResults.slice(0, maxMenuItems);
|
|
511
|
+
const shown = [
|
|
512
|
+
...fetched,
|
|
513
|
+
...(__queryEntries?.(searchQuery, fetched) ?? []),
|
|
514
|
+
];
|
|
444
515
|
setResults(shown);
|
|
445
516
|
setHighlightedIndex(shown.length > 0 ? 0 : -1);
|
|
446
517
|
if (searchResults.length > 0 || searchQuery.length > 0) {
|
|
@@ -473,6 +544,7 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
473
544
|
showLayer,
|
|
474
545
|
announce,
|
|
475
546
|
emptySearchResultsText,
|
|
547
|
+
__queryEntries,
|
|
476
548
|
t,
|
|
477
549
|
],
|
|
478
550
|
);
|
|
@@ -515,14 +587,35 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
515
587
|
clearTimeout(searchTimeoutRef.current);
|
|
516
588
|
}
|
|
517
589
|
|
|
518
|
-
|
|
590
|
+
// Nothing to search: either the field was emptied, or the query is
|
|
591
|
+
// still shorter than `minQueryLength`. Both drop stale results and
|
|
592
|
+
// close the menu — showing the empty state for a query that was never
|
|
593
|
+
// searched would report "no results" that nobody looked for.
|
|
594
|
+
if (
|
|
595
|
+
(newQuery.length === 0 && !hasEntriesOnFocus) ||
|
|
596
|
+
isBelowMinQueryLength(newQuery, minQueryLength)
|
|
597
|
+
) {
|
|
519
598
|
searchGenRef.current++;
|
|
520
599
|
searchSource.cancel?.();
|
|
521
|
-
|
|
600
|
+
// A query too short to search can still carry entries derived from
|
|
601
|
+
// the text itself. `hasSearched` stays false either way, so the menu
|
|
602
|
+
// never reports "no results" for a query nobody looked for.
|
|
603
|
+
const derived = __queryEntries?.(newQuery, []) ?? [];
|
|
604
|
+
setResults(derived);
|
|
605
|
+
setHighlightedIndex(derived.length > 0 ? 0 : -1);
|
|
522
606
|
setHasSearched(false);
|
|
607
|
+
// Bumping the generation abandons any in-flight search, which means
|
|
608
|
+
// its own `finally` will decline to clear this — so clear it here or
|
|
609
|
+
// the field spins forever. Backspacing below the threshold on a remote
|
|
610
|
+
// source is the everyday way to hit that.
|
|
611
|
+
setIsLoading(false);
|
|
523
612
|
// Clear any lingering result-count / no-results announcement.
|
|
524
613
|
announce('');
|
|
525
|
-
|
|
614
|
+
if (derived.length > 0) {
|
|
615
|
+
showLayer();
|
|
616
|
+
} else {
|
|
617
|
+
popover.hide();
|
|
618
|
+
}
|
|
526
619
|
return;
|
|
527
620
|
}
|
|
528
621
|
|
|
@@ -543,6 +636,9 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
543
636
|
[
|
|
544
637
|
onChangeQuery,
|
|
545
638
|
hasEntriesOnFocus,
|
|
639
|
+
minQueryLength,
|
|
640
|
+
__queryEntries,
|
|
641
|
+
showLayer,
|
|
546
642
|
performSearch,
|
|
547
643
|
performBootstrap,
|
|
548
644
|
popover,
|
|
@@ -574,6 +670,10 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
574
670
|
setQuery('');
|
|
575
671
|
setResults([]);
|
|
576
672
|
setHasSearched(false);
|
|
673
|
+
// Same reason as in handleQueryChange: the invalidated search will not
|
|
674
|
+
// clear this itself. Selecting a stale result while the next search is
|
|
675
|
+
// still in flight would otherwise leave the field spinning.
|
|
676
|
+
setIsLoading(false);
|
|
577
677
|
popover.hide();
|
|
578
678
|
inputRef.current?.focus();
|
|
579
679
|
},
|
|
@@ -657,7 +757,13 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
657
757
|
if (results.length > 0) {
|
|
658
758
|
popover.show();
|
|
659
759
|
setHighlightedIndex(0);
|
|
660
|
-
} else if (
|
|
760
|
+
} else if (
|
|
761
|
+
hasEntriesOnFocus &&
|
|
762
|
+
// A below-threshold query was never searched; falling back to the
|
|
763
|
+
// bootstrap entries here would open a menu of suggestions that
|
|
764
|
+
// ignore what the user has already typed.
|
|
765
|
+
!isBelowMinQueryLength(query, minQueryLength)
|
|
766
|
+
) {
|
|
661
767
|
void performBootstrap();
|
|
662
768
|
}
|
|
663
769
|
}
|
|
@@ -691,6 +797,14 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
691
797
|
e.preventDefault();
|
|
692
798
|
popover.hide();
|
|
693
799
|
break;
|
|
800
|
+
case 'Tab':
|
|
801
|
+
// Dismiss here rather than from the blur this press produces:
|
|
802
|
+
// hiding a top-layer popover during the focusout makes Chrome
|
|
803
|
+
// abandon the in-flight focus move and drop focus to <body>, so the
|
|
804
|
+
// user's Tab appears to do nothing. Selector and MultiSelector
|
|
805
|
+
// already dismiss on this keydown.
|
|
806
|
+
popover.hide();
|
|
807
|
+
break;
|
|
694
808
|
case 'Home':
|
|
695
809
|
if (popover.isOpen) {
|
|
696
810
|
e.preventDefault();
|
|
@@ -715,7 +829,8 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
715
829
|
highlightedIndex,
|
|
716
830
|
handleSelect,
|
|
717
831
|
hasEntriesOnFocus,
|
|
718
|
-
query
|
|
832
|
+
query,
|
|
833
|
+
minQueryLength,
|
|
719
834
|
performBootstrap,
|
|
720
835
|
externalOnKeyDown,
|
|
721
836
|
],
|
|
@@ -760,7 +875,7 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
760
875
|
return (
|
|
761
876
|
<>
|
|
762
877
|
<input
|
|
763
|
-
ref={
|
|
878
|
+
ref={useMergedRefs(ref, inputRef, fallbackAnchorRef)}
|
|
764
879
|
id={inputId}
|
|
765
880
|
type="text"
|
|
766
881
|
role="combobox"
|
|
@@ -835,44 +950,71 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
835
950
|
{emptySearchResultsText}
|
|
836
951
|
</div>
|
|
837
952
|
) : (
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
const
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
953
|
+
(() => {
|
|
954
|
+
let flatIndex = 0;
|
|
955
|
+
const renderOption = (item: T) => {
|
|
956
|
+
const index = flatIndex++;
|
|
957
|
+
const itemKey = getKey(item.id, index);
|
|
958
|
+
const isSelected = itemKey === selectedKey;
|
|
959
|
+
return (
|
|
960
|
+
<div
|
|
961
|
+
key={itemKey}
|
|
962
|
+
id={getItemId(index)}
|
|
963
|
+
role="option"
|
|
964
|
+
aria-selected={isSelected}
|
|
965
|
+
tabIndex={-1}
|
|
966
|
+
onClick={() => handleSelect(item)}
|
|
967
|
+
onMouseEnter={() => setHighlightedIndex(index)}
|
|
968
|
+
{...stylex.props(
|
|
969
|
+
styles.item,
|
|
970
|
+
itemSizeStyles[size],
|
|
971
|
+
index === highlightedIndex && styles.itemHighlighted,
|
|
972
|
+
isSelected && styles.itemSelected,
|
|
973
|
+
)}>
|
|
974
|
+
<span {...stylex.props(styles.itemContent)}>
|
|
975
|
+
{renderItem ? (
|
|
976
|
+
renderItem(item)
|
|
977
|
+
) : (
|
|
978
|
+
<TypeaheadItem item={item} />
|
|
979
|
+
)}
|
|
980
|
+
</span>
|
|
981
|
+
{isSelected && (
|
|
982
|
+
<Icon icon="check" size="sm" color="primary" />
|
|
861
983
|
)}
|
|
862
|
-
</
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
984
|
+
</div>
|
|
985
|
+
);
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
return groupItems(results, {ungroupedFirst: true}).map(group => {
|
|
989
|
+
const options = group.items.map(renderOption);
|
|
990
|
+
if (group.heading == null) {
|
|
991
|
+
return options;
|
|
992
|
+
}
|
|
993
|
+
return (
|
|
994
|
+
<div
|
|
995
|
+
key={`group-${group.heading}`}
|
|
996
|
+
role="group"
|
|
997
|
+
aria-label={group.heading}>
|
|
998
|
+
<div
|
|
999
|
+
aria-hidden="true"
|
|
1000
|
+
{...stylex.props(styles.groupHeading)}>
|
|
1001
|
+
{group.heading}
|
|
1002
|
+
</div>
|
|
1003
|
+
{options}
|
|
1004
|
+
</div>
|
|
1005
|
+
);
|
|
1006
|
+
});
|
|
1007
|
+
})()
|
|
869
1008
|
)}
|
|
870
1009
|
</div>,
|
|
871
1010
|
{
|
|
872
1011
|
placement: 'below',
|
|
873
1012
|
alignment: 'start',
|
|
874
1013
|
offset: spacingVars['--spacing-1'],
|
|
875
|
-
xstyle:
|
|
1014
|
+
xstyle: [
|
|
1015
|
+
styles.popover,
|
|
1016
|
+
menuWidth != null && styles.popoverCustomWidth(menuWidth),
|
|
1017
|
+
],
|
|
876
1018
|
},
|
|
877
1019
|
)}
|
|
878
1020
|
</>
|
|
@@ -83,6 +83,12 @@ export const docs = {
|
|
|
83
83
|
description: 'Maximum number of dropdown items to display.',
|
|
84
84
|
default: '10',
|
|
85
85
|
},
|
|
86
|
+
{
|
|
87
|
+
name: 'minQueryLength',
|
|
88
|
+
type: 'number',
|
|
89
|
+
description: 'Minimum query length before the search source is queried. Below it no search runs and the menu stays closed.',
|
|
90
|
+
default: '1',
|
|
91
|
+
},
|
|
86
92
|
{
|
|
87
93
|
name: 'status',
|
|
88
94
|
type: "{type: 'warning' | 'error' | 'success', message?: string}",
|
|
@@ -171,6 +177,11 @@ export const docs = {
|
|
|
171
177
|
description:
|
|
172
178
|
'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
|
|
173
179
|
},
|
|
180
|
+
{
|
|
181
|
+
name: 'startIcon',
|
|
182
|
+
type: 'IconType | ReactNode',
|
|
183
|
+
description: 'SVG icon component displayed at the start of the input.',
|
|
184
|
+
},
|
|
174
185
|
{
|
|
175
186
|
name: 'xstyle',
|
|
176
187
|
type: 'StyleXStyles',
|
|
@@ -420,6 +420,55 @@ describe('BaseTypeahead focus-out', () => {
|
|
|
420
420
|
});
|
|
421
421
|
});
|
|
422
422
|
|
|
423
|
+
it('closes the list on the Tab keydown, before the blur it produces', async () => {
|
|
424
|
+
render(
|
|
425
|
+
<BaseTypeahead
|
|
426
|
+
searchSource={fruitSource}
|
|
427
|
+
value={null}
|
|
428
|
+
onChange={() => {}}
|
|
429
|
+
debounceMs={0}
|
|
430
|
+
/>,
|
|
431
|
+
);
|
|
432
|
+
const input = screen.getByRole('combobox');
|
|
433
|
+
input.focus();
|
|
434
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
435
|
+
await waitFor(() => {
|
|
436
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// No blur is fired here on purpose: dismissing from the blur instead lets
|
|
440
|
+
// the popover close mid-focus-move, which Chrome answers by dropping
|
|
441
|
+
// focus to <body>.
|
|
442
|
+
fireEvent.keyDown(input, {key: 'Tab'});
|
|
443
|
+
await waitFor(() => {
|
|
444
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('Tab from the input with the list open moves focus to the next control', async () => {
|
|
449
|
+
const user = userEvent.setup();
|
|
450
|
+
render(
|
|
451
|
+
<>
|
|
452
|
+
<BaseTypeahead
|
|
453
|
+
searchSource={fruitSource}
|
|
454
|
+
value={null}
|
|
455
|
+
onChange={() => {}}
|
|
456
|
+
debounceMs={0}
|
|
457
|
+
/>
|
|
458
|
+
<button type="button">Next</button>
|
|
459
|
+
</>,
|
|
460
|
+
);
|
|
461
|
+
const input = screen.getByRole('combobox');
|
|
462
|
+
input.focus();
|
|
463
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
464
|
+
await waitFor(() => {
|
|
465
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
await user.keyboard('{Tab}');
|
|
469
|
+
expect(screen.getByRole('button', {name: 'Next'})).toHaveFocus();
|
|
470
|
+
});
|
|
471
|
+
|
|
423
472
|
it('keeps the dropdown open when focus moves into the anchor wrapper', async () => {
|
|
424
473
|
const anchor = document.createElement('div');
|
|
425
474
|
document.body.appendChild(anchor);
|
|
@@ -729,6 +778,160 @@ describe('BaseTypeahead hasEntriesOnFocus', () => {
|
|
|
729
778
|
});
|
|
730
779
|
});
|
|
731
780
|
|
|
781
|
+
describe('BaseTypeahead minQueryLength', () => {
|
|
782
|
+
it('does not search or open the menu below the threshold', async () => {
|
|
783
|
+
const search = vi.fn((query: string) =>
|
|
784
|
+
fruits.filter(f => f.label.toLowerCase().includes(query.toLowerCase())),
|
|
785
|
+
);
|
|
786
|
+
render(
|
|
787
|
+
<BaseTypeahead
|
|
788
|
+
searchSource={{search, bootstrap: () => []}}
|
|
789
|
+
value={null}
|
|
790
|
+
onChange={() => {}}
|
|
791
|
+
minQueryLength={3}
|
|
792
|
+
debounceMs={0}
|
|
793
|
+
/>,
|
|
794
|
+
);
|
|
795
|
+
const input = screen.getByRole('combobox');
|
|
796
|
+
|
|
797
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
798
|
+
await act(async () => {
|
|
799
|
+
await Promise.resolve();
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
expect(search).not.toHaveBeenCalled();
|
|
803
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
804
|
+
|
|
805
|
+
// Positive control: the third character crosses the threshold, so the
|
|
806
|
+
// same harness does see the search and the open menu.
|
|
807
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
808
|
+
await waitFor(() => {
|
|
809
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
810
|
+
});
|
|
811
|
+
expect(search).toHaveBeenCalledExactlyOnceWith('App');
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
it('closes the menu again when the query falls back below the threshold', async () => {
|
|
815
|
+
render(
|
|
816
|
+
<BaseTypeahead
|
|
817
|
+
searchSource={fruitSource}
|
|
818
|
+
value={null}
|
|
819
|
+
onChange={() => {}}
|
|
820
|
+
minQueryLength={3}
|
|
821
|
+
debounceMs={0}
|
|
822
|
+
/>,
|
|
823
|
+
);
|
|
824
|
+
const input = screen.getByRole('combobox');
|
|
825
|
+
|
|
826
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
827
|
+
await waitFor(() => {
|
|
828
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
832
|
+
await waitFor(() => {
|
|
833
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
834
|
+
});
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it('does not fall back to bootstrap entries on ArrowDown below the threshold', async () => {
|
|
838
|
+
const bootstrap = vi.fn(() => fruits.slice(0, 3));
|
|
839
|
+
render(
|
|
840
|
+
<BaseTypeahead
|
|
841
|
+
searchSource={{search: () => [], bootstrap}}
|
|
842
|
+
value={null}
|
|
843
|
+
onChange={() => {}}
|
|
844
|
+
hasEntriesOnFocus
|
|
845
|
+
minQueryLength={3}
|
|
846
|
+
debounceMs={0}
|
|
847
|
+
/>,
|
|
848
|
+
);
|
|
849
|
+
const input = screen.getByRole('combobox');
|
|
850
|
+
|
|
851
|
+
fireEvent.focus(input);
|
|
852
|
+
await waitFor(() => {
|
|
853
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
854
|
+
});
|
|
855
|
+
bootstrap.mockClear();
|
|
856
|
+
|
|
857
|
+
// Typing below the threshold closes the bootstrap menu...
|
|
858
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
859
|
+
await waitFor(() => {
|
|
860
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
// ...and ArrowDown must not re-open it with entries that ignore the
|
|
864
|
+
// two characters already typed.
|
|
865
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
866
|
+
await act(async () => {
|
|
867
|
+
await Promise.resolve();
|
|
868
|
+
});
|
|
869
|
+
expect(bootstrap).not.toHaveBeenCalled();
|
|
870
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
it('searches on the first character when minQueryLength is not set', async () => {
|
|
874
|
+
const search = vi.fn(() => fruits.slice(0, 1));
|
|
875
|
+
render(
|
|
876
|
+
<BaseTypeahead
|
|
877
|
+
searchSource={{search, bootstrap: () => []}}
|
|
878
|
+
value={null}
|
|
879
|
+
onChange={() => {}}
|
|
880
|
+
debounceMs={0}
|
|
881
|
+
/>,
|
|
882
|
+
);
|
|
883
|
+
const input = screen.getByRole('combobox');
|
|
884
|
+
|
|
885
|
+
fireEvent.change(input, {target: {value: 'A'}});
|
|
886
|
+
await waitFor(() => {
|
|
887
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
888
|
+
});
|
|
889
|
+
expect(search).toHaveBeenCalledExactlyOnceWith('A');
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
it('stops reporting "Loading" when the query falls below the threshold mid-search', async () => {
|
|
893
|
+
// Falling below the threshold abandons the in-flight search by bumping the
|
|
894
|
+
// search generation, which also makes that search decline to clear the
|
|
895
|
+
// loading flag on its way out. Backspacing from three characters to two on
|
|
896
|
+
// a remote source is the everyday way to hit it, and the field would
|
|
897
|
+
// otherwise report "Loading" to a screen reader until the third character
|
|
898
|
+
// went back in.
|
|
899
|
+
let settle: (items: SearchableItem[]) => void = () => {};
|
|
900
|
+
const search = vi.fn(
|
|
901
|
+
async () =>
|
|
902
|
+
new Promise<SearchableItem[]>(resolve => {
|
|
903
|
+
settle = resolve;
|
|
904
|
+
}),
|
|
905
|
+
);
|
|
906
|
+
render(
|
|
907
|
+
<BaseTypeahead
|
|
908
|
+
searchSource={{search, bootstrap: () => []}}
|
|
909
|
+
value={null}
|
|
910
|
+
onChange={() => {}}
|
|
911
|
+
minQueryLength={3}
|
|
912
|
+
debounceMs={0}
|
|
913
|
+
/>,
|
|
914
|
+
);
|
|
915
|
+
const input = screen.getByRole('combobox');
|
|
916
|
+
|
|
917
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
918
|
+
await waitFor(() => {
|
|
919
|
+
expect(screen.getByRole('status', {name: 'Loading'})).toBeInTheDocument();
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
923
|
+
await act(async () => {
|
|
924
|
+
settle(fruits.slice(0, 1));
|
|
925
|
+
await Promise.resolve();
|
|
926
|
+
});
|
|
927
|
+
|
|
928
|
+
expect(
|
|
929
|
+
screen.queryByRole('status', {name: 'Loading'}),
|
|
930
|
+
).not.toBeInTheDocument();
|
|
931
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
|
|
732
935
|
describe('BaseTypeahead hasSearched reset', () => {
|
|
733
936
|
it('does not show "No results found" after selecting an item and re-entering', async () => {
|
|
734
937
|
const onChange = vi.fn();
|
|
@@ -45,13 +45,14 @@ import {VisuallyHidden} from '../VisuallyHidden';
|
|
|
45
45
|
import {spacingVars, sizeVars} from '../theme/tokens.stylex';
|
|
46
46
|
import {groupStyles} from '../InputGroup/groupStyles';
|
|
47
47
|
import {useInputGroup} from '../InputGroup/InputGroupContext';
|
|
48
|
-
import {getInputARIA, isImeKeyEvent, mergeProps
|
|
48
|
+
import {getInputARIA, isImeKeyEvent, mergeProps} from '../utils';
|
|
49
49
|
import type {BaseProps} from '../BaseProps';
|
|
50
50
|
import type {SizeValue} from '../utils/types';
|
|
51
51
|
import type {SearchableItem, SearchSource} from './types';
|
|
52
52
|
import {themeProps} from '../utils/themeProps';
|
|
53
53
|
import {useTranslator} from '../i18n';
|
|
54
54
|
|
|
55
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
55
56
|
export type {
|
|
56
57
|
InputStatus as TypeaheadStatus,
|
|
57
58
|
InputStatusType as TypeaheadStatusType,
|
|
@@ -110,6 +111,13 @@ export interface TypeaheadProps<T extends SearchableItem> extends Omit<
|
|
|
110
111
|
hasEntriesOnFocus?: boolean;
|
|
111
112
|
/** Max dropdown items. @default 10 */
|
|
112
113
|
maxMenuItems?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Minimum query length before the search source is queried. Below it no
|
|
116
|
+
* search runs and the menu stays closed — useful for remote sources where
|
|
117
|
+
* one or two characters match too much to be worth fetching.
|
|
118
|
+
* @default 1
|
|
119
|
+
*/
|
|
120
|
+
minQueryLength?: number;
|
|
113
121
|
/** Text shown when no results found. @default 'No results found' */
|
|
114
122
|
emptySearchResultsText?: string;
|
|
115
123
|
/** Whether the input is disabled. @default false */
|
|
@@ -247,6 +255,7 @@ export function Typeahead<T extends SearchableItem>({
|
|
|
247
255
|
placeholder,
|
|
248
256
|
hasEntriesOnFocus,
|
|
249
257
|
maxMenuItems,
|
|
258
|
+
minQueryLength,
|
|
250
259
|
emptySearchResultsText,
|
|
251
260
|
isDisabled = false,
|
|
252
261
|
disabledMessage,
|
|
@@ -418,7 +427,7 @@ export function Typeahead<T extends SearchableItem>({
|
|
|
418
427
|
const typeaheadContent = (
|
|
419
428
|
<>
|
|
420
429
|
<div
|
|
421
|
-
ref={
|
|
430
|
+
ref={useMergedRefs(
|
|
422
431
|
wrapperRef,
|
|
423
432
|
disabledMessageTooltip.ref,
|
|
424
433
|
inputGroup ? ref : undefined,
|
|
@@ -466,6 +475,7 @@ export function Typeahead<T extends SearchableItem>({
|
|
|
466
475
|
placeholder={showToken ? undefined : placeholder}
|
|
467
476
|
hasEntriesOnFocus={hasEntriesOnFocus}
|
|
468
477
|
maxMenuItems={maxMenuItems}
|
|
478
|
+
minQueryLength={minQueryLength}
|
|
469
479
|
emptySearchResultsText={emptySearchResultsText}
|
|
470
480
|
isDisabled={isDisabled}
|
|
471
481
|
hasAutoFocus={hasAutoFocus}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file TypeaheadItem.test.tsx
|
|
5
|
+
* @input Uses vitest, @testing-library/react, TypeaheadItem
|
|
6
|
+
* @output Unit tests for TypeaheadItem
|
|
7
|
+
* @position Testing; validates TypeaheadItem.tsx implementation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {describe, it, expect} from 'vitest';
|
|
11
|
+
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {TypeaheadItem} from './TypeaheadItem';
|
|
13
|
+
|
|
14
|
+
describe('TypeaheadItem', () => {
|
|
15
|
+
it('forwards pass-through props to the item element', () => {
|
|
16
|
+
render(
|
|
17
|
+
<TypeaheadItem
|
|
18
|
+
item={{id: '1', label: 'Alice'}}
|
|
19
|
+
aria-label="Alice, engineer"
|
|
20
|
+
id="result-1"
|
|
21
|
+
data-source="directory"
|
|
22
|
+
data-testid="item"
|
|
23
|
+
/>,
|
|
24
|
+
);
|
|
25
|
+
const item = screen.getByTestId('item');
|
|
26
|
+
expect(item).toHaveAttribute('aria-label', 'Alice, engineer');
|
|
27
|
+
expect(item).toHaveAttribute('id', 'result-1');
|
|
28
|
+
expect(item).toHaveAttribute('data-source', 'directory');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('merges a caller className with its own classes', () => {
|
|
32
|
+
render(
|
|
33
|
+
<TypeaheadItem
|
|
34
|
+
item={{id: '1', label: 'Alice'}}
|
|
35
|
+
className="caller-class"
|
|
36
|
+
data-testid="item"
|
|
37
|
+
/>,
|
|
38
|
+
);
|
|
39
|
+
const item = screen.getByTestId('item');
|
|
40
|
+
expect(item.className).toContain('caller-class');
|
|
41
|
+
expect(item.className).toContain('astryx-typeahead-item');
|
|
42
|
+
});
|
|
43
|
+
});
|