@astryxdesign/core 0.4.7 → 0.5.0-canary.055e75f
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 +40 -15
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +51 -18
- 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 +3 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +14 -15
- 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 +6 -9
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +6 -6
- 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/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/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/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/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 -2
- 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/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/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/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +9 -4
- 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/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 +63 -11
- 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.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +3 -2
- 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/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +20 -17
- 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 +3 -3
- package/dist/Selector/Selector.d.ts +17 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +81 -14
- 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.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
- 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 +19 -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 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +9 -3
- 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.map +1 -1
- package/dist/Timestamp/Timestamp.js +5 -3
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +27 -8
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +2 -2
- package/dist/Tokenizer/Tokenizer.d.ts +3 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +2 -0
- 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.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +3 -3
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +4 -3
- package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +68 -29
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -2
- package/dist/astryx.css +98 -7
- 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/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +24 -4
- 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/en.json +154 -10
- package/locales/pseudo.json +108 -0
- 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 +13 -11
- package/src/Banner/Banner.test.tsx +102 -15
- package/src/Banner/Banner.tsx +72 -25
- 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 +4 -3
- package/src/Calendar/Calendar.test.tsx +103 -0
- package/src/Calendar/Calendar.tsx +19 -16
- 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 +44 -19
- package/src/Card/Card.tsx +12 -32
- 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/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/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/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/FileInput/FileInput.tsx +3 -2
- package/src/Heading/Heading.test.tsx +23 -1
- package/src/Heading/Heading.tsx +6 -2
- 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/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 +62 -14
- 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/Lightbox/Lightbox.doc.mjs +12 -0
- package/src/Lightbox/Lightbox.tsx +124 -102
- package/src/Link/Link.doc.mjs +39 -0
- package/src/Markdown/Markdown.doc.mjs +5 -0
- package/src/Markdown/Markdown.tsx +9 -4
- 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/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 +277 -0
- package/src/MultiSelector/MultiSelector.tsx +142 -11
- 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.tsx +3 -2
- 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/usePopover.tsx +31 -28
- 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.tsx +3 -2
- package/src/Selector/Selector.doc.mjs +26 -1
- package/src/Selector/Selector.test.tsx +311 -1
- package/src/Selector/Selector.tsx +139 -16
- 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 +17 -8
- 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 +76 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +40 -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 +23 -1
- package/src/Text/Text.tsx +6 -2
- package/src/TextArea/TextArea.doc.mjs +8 -2
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +15 -8
- 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 +18 -0
- package/src/Timestamp/Timestamp.tsx +4 -2
- package/src/Toast/Toast.doc.mjs +6 -0
- package/src/Toast/ToastViewport.tsx +17 -1
- package/src/Token/TokenLink.tsx +2 -2
- package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
- package/src/Tokenizer/Tokenizer.tsx +4 -0
- 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.tsx +3 -2
- package/src/TopNav/TopNavMenu.tsx +4 -3
- package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
- package/src/Typeahead/BaseTypeahead.tsx +85 -33
- package/src/Typeahead/Typeahead.doc.mjs +5 -0
- package/src/Typeahead/Typeahead.test.tsx +49 -0
- package/src/Typeahead/Typeahead.tsx +3 -2
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useContainerReveal.doc.mjs +2 -2
- 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/useMergedRefs.doc.mjs +79 -0
- package/src/hooks/useMergedRefs.test.tsx +62 -0
- package/src/hooks/useMergedRefs.ts +36 -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/derivedVarRegistry.test.ts +19 -3
- package/src/theme/derivedVarRegistry.ts +23 -4
- package/src/theme/generateThemeRules.test.ts +37 -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,9 @@ 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
|
+
|
|
96
100
|
/**
|
|
97
101
|
* Text shown when no results found.
|
|
98
102
|
* @default 'No results found'
|
|
@@ -226,6 +230,18 @@ const styles = stylex.create({
|
|
|
226
230
|
popover: {
|
|
227
231
|
minWidth: 'anchor-size(width)',
|
|
228
232
|
},
|
|
233
|
+
popoverCustomWidth: (width: number) => ({
|
|
234
|
+
width: `${width}px`,
|
|
235
|
+
}),
|
|
236
|
+
groupHeading: {
|
|
237
|
+
paddingInline: spacingVars['--spacing-2'],
|
|
238
|
+
paddingBlockStart: spacingVars['--spacing-2'],
|
|
239
|
+
paddingBlockEnd: spacingVars['--spacing-1'],
|
|
240
|
+
fontSize: typeScaleVars['--text-supporting-size'],
|
|
241
|
+
lineHeight: typeScaleVars['--text-supporting-leading'],
|
|
242
|
+
color: colorVars['--color-text-secondary'],
|
|
243
|
+
userSelect: 'none',
|
|
244
|
+
},
|
|
229
245
|
item: {
|
|
230
246
|
boxSizing: 'border-box',
|
|
231
247
|
display: 'flex',
|
|
@@ -316,6 +332,7 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
316
332
|
placeholder: placeholderFromProps,
|
|
317
333
|
hasEntriesOnFocus = false,
|
|
318
334
|
maxMenuItems = 10,
|
|
335
|
+
menuWidth,
|
|
319
336
|
emptySearchResultsText: emptySearchResultsTextFromProps,
|
|
320
337
|
isDisabled = false,
|
|
321
338
|
isFocusableDisabled = false,
|
|
@@ -691,6 +708,14 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
691
708
|
e.preventDefault();
|
|
692
709
|
popover.hide();
|
|
693
710
|
break;
|
|
711
|
+
case 'Tab':
|
|
712
|
+
// Dismiss here rather than from the blur this press produces:
|
|
713
|
+
// hiding a top-layer popover during the focusout makes Chrome
|
|
714
|
+
// abandon the in-flight focus move and drop focus to <body>, so the
|
|
715
|
+
// user's Tab appears to do nothing. Selector and MultiSelector
|
|
716
|
+
// already dismiss on this keydown.
|
|
717
|
+
popover.hide();
|
|
718
|
+
break;
|
|
694
719
|
case 'Home':
|
|
695
720
|
if (popover.isOpen) {
|
|
696
721
|
e.preventDefault();
|
|
@@ -760,7 +785,7 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
760
785
|
return (
|
|
761
786
|
<>
|
|
762
787
|
<input
|
|
763
|
-
ref={
|
|
788
|
+
ref={useMergedRefs(ref, inputRef, fallbackAnchorRef)}
|
|
764
789
|
id={inputId}
|
|
765
790
|
type="text"
|
|
766
791
|
role="combobox"
|
|
@@ -835,44 +860,71 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
835
860
|
{emptySearchResultsText}
|
|
836
861
|
</div>
|
|
837
862
|
) : (
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
const
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
863
|
+
(() => {
|
|
864
|
+
let flatIndex = 0;
|
|
865
|
+
const renderOption = (item: T) => {
|
|
866
|
+
const index = flatIndex++;
|
|
867
|
+
const itemKey = getKey(item.id, index);
|
|
868
|
+
const isSelected = itemKey === selectedKey;
|
|
869
|
+
return (
|
|
870
|
+
<div
|
|
871
|
+
key={itemKey}
|
|
872
|
+
id={getItemId(index)}
|
|
873
|
+
role="option"
|
|
874
|
+
aria-selected={isSelected}
|
|
875
|
+
tabIndex={-1}
|
|
876
|
+
onClick={() => handleSelect(item)}
|
|
877
|
+
onMouseEnter={() => setHighlightedIndex(index)}
|
|
878
|
+
{...stylex.props(
|
|
879
|
+
styles.item,
|
|
880
|
+
itemSizeStyles[size],
|
|
881
|
+
index === highlightedIndex && styles.itemHighlighted,
|
|
882
|
+
isSelected && styles.itemSelected,
|
|
883
|
+
)}>
|
|
884
|
+
<span {...stylex.props(styles.itemContent)}>
|
|
885
|
+
{renderItem ? (
|
|
886
|
+
renderItem(item)
|
|
887
|
+
) : (
|
|
888
|
+
<TypeaheadItem item={item} />
|
|
889
|
+
)}
|
|
890
|
+
</span>
|
|
891
|
+
{isSelected && (
|
|
892
|
+
<Icon icon="check" size="sm" color="primary" />
|
|
861
893
|
)}
|
|
862
|
-
</
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
894
|
+
</div>
|
|
895
|
+
);
|
|
896
|
+
};
|
|
897
|
+
|
|
898
|
+
return groupItems(results, {ungroupedFirst: true}).map(group => {
|
|
899
|
+
const options = group.items.map(renderOption);
|
|
900
|
+
if (group.heading == null) {
|
|
901
|
+
return options;
|
|
902
|
+
}
|
|
903
|
+
return (
|
|
904
|
+
<div
|
|
905
|
+
key={`group-${group.heading}`}
|
|
906
|
+
role="group"
|
|
907
|
+
aria-label={group.heading}>
|
|
908
|
+
<div
|
|
909
|
+
aria-hidden="true"
|
|
910
|
+
{...stylex.props(styles.groupHeading)}>
|
|
911
|
+
{group.heading}
|
|
912
|
+
</div>
|
|
913
|
+
{options}
|
|
914
|
+
</div>
|
|
915
|
+
);
|
|
916
|
+
});
|
|
917
|
+
})()
|
|
869
918
|
)}
|
|
870
919
|
</div>,
|
|
871
920
|
{
|
|
872
921
|
placement: 'below',
|
|
873
922
|
alignment: 'start',
|
|
874
923
|
offset: spacingVars['--spacing-1'],
|
|
875
|
-
xstyle:
|
|
924
|
+
xstyle: [
|
|
925
|
+
styles.popover,
|
|
926
|
+
menuWidth != null && styles.popoverCustomWidth(menuWidth),
|
|
927
|
+
],
|
|
876
928
|
},
|
|
877
929
|
)}
|
|
878
930
|
</>
|
|
@@ -171,6 +171,11 @@ export const docs = {
|
|
|
171
171
|
description:
|
|
172
172
|
'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
173
|
},
|
|
174
|
+
{
|
|
175
|
+
name: 'startIcon',
|
|
176
|
+
type: 'IconType | ReactNode',
|
|
177
|
+
description: 'SVG icon component displayed at the start of the input.',
|
|
178
|
+
},
|
|
174
179
|
{
|
|
175
180
|
name: 'xstyle',
|
|
176
181
|
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);
|
|
@@ -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,
|
|
@@ -418,7 +419,7 @@ export function Typeahead<T extends SearchableItem>({
|
|
|
418
419
|
const typeaheadContent = (
|
|
419
420
|
<>
|
|
420
421
|
<div
|
|
421
|
-
ref={
|
|
422
|
+
ref={useMergedRefs(
|
|
422
423
|
wrapperRef,
|
|
423
424
|
disabledMessageTooltip.ref,
|
|
424
425
|
inputGroup ? ref : undefined,
|
package/src/hooks/index.ts
CHANGED
|
@@ -56,6 +56,8 @@ export type {UseTypeaheadOptions, UseTypeaheadReturn} from './useTypeahead';
|
|
|
56
56
|
|
|
57
57
|
export {useMediaQuery} from './useMediaQuery';
|
|
58
58
|
|
|
59
|
+
export {useMergedRefs} from './useMergedRefs';
|
|
60
|
+
|
|
59
61
|
export {useOverflow} from './useOverflow';
|
|
60
62
|
export type {UseOverflowOptions, UseOverflowReturn} from './useOverflow';
|
|
61
63
|
|
|
@@ -24,7 +24,7 @@ export const docs = {
|
|
|
24
24
|
{
|
|
25
25
|
name: 'getContainerProps',
|
|
26
26
|
type: '(options?: ContainerRevealOptions) => {className?: string; style?: CSSProperties}',
|
|
27
|
-
description: 'Spread onto the container whose hover/focus-within drives the reveal. Accepts hoverDelay (ms the pointer must dwell before the reveal starts
|
|
27
|
+
description: 'Spread onto the container whose hover/focus-within drives the reveal. Accepts hoverDelay (ms the pointer must dwell before the reveal starts: a hover-intent gate like Tooltip\'s and HoverCard\'s delay, so a cursor sweeping across a list leaves nothing painted behind it) and forceState ("active" | "inactive") to pin the trigger state when a caller owns it: a motion gate, a scroll, or a row whose menu is open. "inactive" still yields to keyboard focus and coarse pointers.',
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
name: 'getContentRevealProps',
|
|
@@ -61,7 +61,7 @@ export const docsDense = {
|
|
|
61
61
|
'options.isEnabled': 'when false hook is inert: no container styles, content getters return no styles, content always shown. Read every render, so it can flip after mount.',
|
|
62
62
|
},
|
|
63
63
|
returnDescriptions: {
|
|
64
|
-
getContainerProps: 'spread onto container whose hover/focus-within drives reveal. Accepts hoverDelay (ms dwell before reveal starts
|
|
64
|
+
getContainerProps: 'spread onto container whose hover/focus-within drives reveal. Accepts hoverDelay (ms dwell before reveal starts: hover-intent gate like Tooltip / HoverCard delay) + forceState ("active" | "inactive") to pin trigger state when a caller owns it. "inactive" yields to keyboard focus + coarse pointers.',
|
|
65
65
|
getContentRevealProps: 'spread onto each revealed / concealed child. Accepts isRevealInverted (conceal-on-hover), isLayoutPreserved (reserve layout box while hidden) + forceVisibility ("shown" | "hidden") to pin this element regardless of container. "hidden" yields to focus.',
|
|
66
66
|
},
|
|
67
67
|
usage: {
|
|
@@ -208,6 +208,20 @@ describe('useFocusTrap tabbable model (infra-8)', () => {
|
|
|
208
208
|
expect(target).toHaveFocus();
|
|
209
209
|
expect(screen.getByTestId('outside')).not.toHaveFocus();
|
|
210
210
|
});
|
|
211
|
+
|
|
212
|
+
it('leaves Tab alone when focus is outside a trap with no tabbable controls', () => {
|
|
213
|
+
render(
|
|
214
|
+
<Trap>
|
|
215
|
+
<div role="option" tabIndex={-1} data-testid="option">
|
|
216
|
+
Option
|
|
217
|
+
</div>
|
|
218
|
+
</Trap>,
|
|
219
|
+
);
|
|
220
|
+
const outside = screen.getByTestId('outside');
|
|
221
|
+
outside.focus();
|
|
222
|
+
|
|
223
|
+
expect(fireEvent.keyDown(outside, {key: 'Tab'})).toBe(true);
|
|
224
|
+
});
|
|
211
225
|
});
|
|
212
226
|
|
|
213
227
|
describe('FOCUSABLE_SELECTOR href matching', () => {
|
|
@@ -19,80 +19,26 @@
|
|
|
19
19
|
import {useCallback, useEffect, useRef} from 'react';
|
|
20
20
|
|
|
21
21
|
import {FOCUSABLE_SELECTOR} from './focusableSelector';
|
|
22
|
-
import {
|
|
22
|
+
import {useLayerDismissal} from '../Layer/useLayerDismissal';
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* traps in a shared stack lets only the top-most trap respond to Escape.
|
|
31
|
-
*
|
|
32
|
-
* "Top-most" is resolved by DOM containment first, push order second. Push
|
|
33
|
-
* order alone is not reliable: React runs child effects before parent
|
|
34
|
-
* effects, so when an outer and an inner (DOM-nested) trap mount in the SAME
|
|
35
|
-
* commit, the inner trap pushes first and the outer trap would wrongly win a
|
|
36
|
-
* pure last-pushed comparison.
|
|
37
|
-
*/
|
|
38
|
-
interface EscapeStackEntry {
|
|
39
|
-
handler: () => void;
|
|
40
|
-
getContainer: () => HTMLElement | null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const escapeStack: EscapeStackEntry[] = [];
|
|
44
|
-
|
|
45
|
-
function pushEscapeHandler(entry: EscapeStackEntry): void {
|
|
46
|
-
escapeStack.push(entry);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function removeEscapeHandler(handler: () => void): void {
|
|
50
|
-
for (let i = escapeStack.length - 1; i >= 0; i--) {
|
|
51
|
-
if (escapeStack[i].handler === handler) {
|
|
52
|
-
escapeStack.splice(i, 1);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
24
|
+
// Escape-dismissible focus traps currently mounted. This is the whole state
|
|
25
|
+
// behind `hasActiveFocusTrapEscape`, which predates the shared stack and must
|
|
26
|
+
// keep answering about focus traps alone — the stack now carries families that
|
|
27
|
+
// never trapped focus (tooltips, hover cards), and counting those would tell
|
|
28
|
+
// callers a trap is above them when none is.
|
|
29
|
+
let activeEscapeTrapCount = 0;
|
|
57
30
|
|
|
58
31
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (escapeStack.length === 0) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
let top = escapeStack[0];
|
|
70
|
-
for (let i = 1; i < escapeStack.length; i++) {
|
|
71
|
-
const entry = escapeStack[i];
|
|
72
|
-
const topContainer = top.getContainer();
|
|
73
|
-
const entryContainer = entry.getContainer();
|
|
74
|
-
if (
|
|
75
|
-
topContainer != null &&
|
|
76
|
-
entryContainer != null &&
|
|
77
|
-
entryContainer !== topContainer &&
|
|
78
|
-
entryContainer.contains(topContainer)
|
|
79
|
-
) {
|
|
80
|
-
// The current top is nested inside this entry — it stays on top.
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
top = entry;
|
|
84
|
-
}
|
|
85
|
-
return top.handler === handler;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Whether any focus-trap Escape handler is currently active (i.e. a popover
|
|
90
|
-
* layer is open). Other overlay primitives that manage their own Escape (e.g.
|
|
91
|
-
* Dialog) can consult this to defer to a popover layered on top of them,
|
|
92
|
-
* giving topmost-only dismissal until a full layer stack exists.
|
|
32
|
+
* Whether an Escape-dismissible focus trap is currently active — a Popover,
|
|
33
|
+
* menu or other trapped layer that would take an Escape press.
|
|
34
|
+
*
|
|
35
|
+
* @deprecated The focus trap no longer owns Escape coordination — every overlay
|
|
36
|
+
* family shares one stack (`useLayerDismissal`), which routes each press to
|
|
37
|
+
* the top-most layer. A layer that wants the same ordering should join the
|
|
38
|
+
* stack rather than ask whether a trap exists.
|
|
93
39
|
*/
|
|
94
40
|
export function hasActiveFocusTrapEscape(): boolean {
|
|
95
|
-
return
|
|
41
|
+
return activeEscapeTrapCount > 0;
|
|
96
42
|
}
|
|
97
43
|
|
|
98
44
|
/**
|
|
@@ -243,6 +189,38 @@ export function useFocusTrap<T extends HTMLElement = HTMLElement>(
|
|
|
243
189
|
// Track if focus change was triggered by keyboard (Tab key)
|
|
244
190
|
const isKeyboardNavigationRef = useRef(false);
|
|
245
191
|
|
|
192
|
+
// Join the shared layer dismissal stack. The trap no longer listens for
|
|
193
|
+
// Escape itself: the stack owns one listener and routes each press to the
|
|
194
|
+
// top-most layer, so a popover inside a Dialog, a submenu inside a menu, and
|
|
195
|
+
// a modal inside a modal all peel off one at a time. A trap with no
|
|
196
|
+
// `onEscape` is not dismissible and stays off the stack, so a press flows
|
|
197
|
+
// past it to whatever is underneath.
|
|
198
|
+
// One expression drives both the stack registration and the deprecated
|
|
199
|
+
// `hasActiveFocusTrapEscape` count, so the two can never disagree about
|
|
200
|
+
// whether this trap is active.
|
|
201
|
+
const isEscapeTrap = isActive && onEscape != null;
|
|
202
|
+
|
|
203
|
+
useLayerDismissal({
|
|
204
|
+
isActive: isEscapeTrap,
|
|
205
|
+
onDismiss: () => {
|
|
206
|
+
onEscape?.();
|
|
207
|
+
},
|
|
208
|
+
// The trap renders nothing, so it cannot push a depth provider around its
|
|
209
|
+
// content; hand the stack the container instead so two DOM-nested traps
|
|
210
|
+
// still resolve in the right order.
|
|
211
|
+
getContainer: () => containerRef.current,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
if (!isEscapeTrap) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
activeEscapeTrapCount += 1;
|
|
219
|
+
return () => {
|
|
220
|
+
activeEscapeTrapCount -= 1;
|
|
221
|
+
};
|
|
222
|
+
}, [isEscapeTrap]);
|
|
223
|
+
|
|
246
224
|
/**
|
|
247
225
|
* Focus the first focusable element.
|
|
248
226
|
*/
|
|
@@ -353,67 +331,43 @@ export function useFocusTrap<T extends HTMLElement = HTMLElement>(
|
|
|
353
331
|
}, [isActive]);
|
|
354
332
|
|
|
355
333
|
/**
|
|
356
|
-
* Handle Tab key to wrap focus at boundaries
|
|
357
|
-
*
|
|
334
|
+
* Handle Tab key to wrap focus at boundaries. Also tracks that keyboard
|
|
335
|
+
* navigation is occurring.
|
|
336
|
+
*
|
|
337
|
+
* No Escape here, and no IME guard: the shared stack owns the press, claims
|
|
338
|
+
* a composing Escape so no close request follows, and dismisses the trap
|
|
339
|
+
* through `onEscape` above. The trap renders no element of its own, so it
|
|
340
|
+
* has no `cancel` to answer either.
|
|
358
341
|
*/
|
|
359
342
|
useEffect(() => {
|
|
360
343
|
if (!isActive) {
|
|
361
344
|
return;
|
|
362
345
|
}
|
|
363
346
|
|
|
364
|
-
// Register this trap on the shared Escape stack so only the top-most
|
|
365
|
-
// active trap responds to Escape. A stable identity per active period is
|
|
366
|
-
// enough — we push on activate and remove on cleanup. The container is
|
|
367
|
-
// read lazily: the ref may not be attached yet at effect time, and the
|
|
368
|
-
// stack resolves top-most by DOM containment at keydown time.
|
|
369
|
-
const escapeHandler = () => {
|
|
370
|
-
onEscape?.();
|
|
371
|
-
};
|
|
372
|
-
if (onEscape) {
|
|
373
|
-
pushEscapeHandler({
|
|
374
|
-
handler: escapeHandler,
|
|
375
|
-
getContainer: () => containerRef.current,
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
|
|
379
347
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
380
348
|
const container = containerRef.current;
|
|
381
349
|
if (!container) {
|
|
382
350
|
return;
|
|
383
351
|
}
|
|
384
352
|
|
|
385
|
-
if (event.key === 'Escape' && onEscape) {
|
|
386
|
-
// Ignore Escape that is cancelling an IME composition, already handled
|
|
387
|
-
// by a nested handler, or not targeting the top-most trap.
|
|
388
|
-
if (
|
|
389
|
-
event.defaultPrevented ||
|
|
390
|
-
isImeKeyEvent(event) ||
|
|
391
|
-
!isTopEscapeHandler(escapeHandler)
|
|
392
|
-
) {
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
// Mark handled and stop propagation so an outer layer (e.g. a Dialog
|
|
396
|
-
// hosting this popover) does not also dismiss on the same press.
|
|
397
|
-
event.preventDefault();
|
|
398
|
-
event.stopPropagation();
|
|
399
|
-
onEscape();
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
353
|
if (event.key === 'Tab') {
|
|
404
354
|
// Mark that keyboard navigation is happening
|
|
405
355
|
isKeyboardNavigationRef.current = true;
|
|
406
356
|
|
|
407
357
|
const focusable = getFocusableElements(container);
|
|
408
358
|
if (focusable.length === 0) {
|
|
359
|
+
const active = document.activeElement;
|
|
360
|
+
if (!(active instanceof HTMLElement) || !container.contains(active)) {
|
|
361
|
+
// A layer can be open while focus legitimately sits outside it —
|
|
362
|
+
// a listbox popup anchored to its own input. Cancelling there
|
|
363
|
+
// would take Tab away from the whole page.
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
409
366
|
// There is nowhere to advance to. Keep focus on the current
|
|
410
367
|
// programmatic target (for example a dialog panel with tabIndex=-1)
|
|
411
368
|
// rather than allowing the browser to move into background content.
|
|
412
369
|
event.preventDefault();
|
|
413
|
-
|
|
414
|
-
if (active instanceof HTMLElement && container.contains(active)) {
|
|
415
|
-
lastFocusRef.current = active;
|
|
416
|
-
}
|
|
370
|
+
lastFocusRef.current = active;
|
|
417
371
|
isKeyboardNavigationRef.current = false;
|
|
418
372
|
return;
|
|
419
373
|
}
|
|
@@ -441,9 +395,6 @@ export function useFocusTrap<T extends HTMLElement = HTMLElement>(
|
|
|
441
395
|
|
|
442
396
|
return () => {
|
|
443
397
|
document.removeEventListener('keydown', handleKeyDown);
|
|
444
|
-
if (onEscape) {
|
|
445
|
-
removeEscapeHandler(escapeHandler);
|
|
446
|
-
}
|
|
447
398
|
};
|
|
448
399
|
}, [isActive, onEscape]);
|
|
449
400
|
|