@astryxdesign/core 0.4.7 → 0.5.0-canary.32a62fd
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/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 +5 -4
- 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 +13 -14
- 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/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 +477 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +38 -4
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.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 +7 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +89 -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 +52 -3
- package/dist/HoverCard/useHoverCard.d.ts +16 -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/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 +177 -29
- 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 +15 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +17 -6
- 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 +1 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +27 -37
- package/dist/NumberInput/numberParser.d.ts +43 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -0
- package/dist/NumberInput/numberParser.js +293 -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 +19 -9
- 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.map +1 -1
- package/dist/Selector/Selector.js +5 -0
- 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 +3 -3
- 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/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/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 +94 -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 +31 -7
- package/locales/pseudo.json +18 -0
- package/package.json +8 -3
- 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 +22 -0
- package/src/Button/Button.test.tsx +13 -0
- package/src/Button/Button.tsx +5 -4
- package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
- package/src/ButtonGroup/ButtonGroup.test.tsx +391 -1
- package/src/ButtonGroup/ButtonGroup.tsx +23 -5
- package/src/Calendar/Calendar.doc.mjs +4 -3
- package/src/Calendar/Calendar.test.tsx +52 -0
- package/src/Calendar/Calendar.tsx +18 -15
- package/src/Calendar/getInitialFocusDate.test.ts +94 -0
- package/src/Calendar/getInitialFocusDate.ts +93 -0
- 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 +68 -9
- package/src/DateInput/NativeDateField.test.tsx +565 -0
- package/src/DateInput/NativeDateField.tsx +623 -0
- package/src/DateInput/TouchDateField.tsx +38 -4
- package/src/DateInput/index.ts +1 -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 +261 -1
- package/src/Dialog/Dialog.tsx +109 -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 +101 -4
- package/src/HoverCard/HoverCard.tsx +71 -3
- package/src/HoverCard/useHoverCard.tsx +101 -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/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/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 +145 -2
- package/src/Markdown/parser.ts +244 -29
- package/src/MobileNav/MobileNav.tsx +62 -36
- package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
- package/src/MultiSelector/MultiSelector.test.tsx +106 -0
- package/src/MultiSelector/MultiSelector.tsx +50 -6
- 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 +20 -0
- package/src/NumberInput/NumberInput.tsx +28 -29
- package/src/NumberInput/numberParser.test.ts +137 -0
- package/src/NumberInput/numberParser.ts +346 -0
- package/src/Outline/Outline.tsx +3 -2
- package/src/OverflowList/OverflowList.tsx +3 -2
- package/src/Overlay/Overlay.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 +201 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +47 -1
- package/src/PowerSearch/PowerSearchValueEditor.tsx +15 -0
- 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 +12 -1
- package/src/Selector/Selector.test.tsx +45 -1
- package/src/Selector/Selector.tsx +11 -1
- 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.tsx +3 -2
- 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/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.tsx +4 -2
- package/src/Toast/Toast.doc.mjs +6 -0
- 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/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
|
@@ -62,14 +62,14 @@ export const docs = {
|
|
|
62
62
|
{
|
|
63
63
|
name: 'width',
|
|
64
64
|
type: 'number | string',
|
|
65
|
-
description: '
|
|
65
|
+
description: 'Preferred width of the dialog in pixels or any CSS value. Standard dialogs clamp to their container and the dynamic viewport with spacing-token gutters so narrow viewports keep content on screen.',
|
|
66
66
|
default: '400',
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
name: 'maxHeight',
|
|
70
70
|
type: 'number | string',
|
|
71
|
-
description: 'Maximum height of the dialog.',
|
|
72
|
-
default: "'
|
|
71
|
+
description: 'Maximum height of the dialog. Defaults to a dynamic viewport value so browser UI changes are reflected where supported.',
|
|
72
|
+
default: "'75dvh'",
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
name: 'position',
|
|
@@ -90,6 +90,11 @@ export const docs = {
|
|
|
90
90
|
description: 'Controls dismissal behavior: required disables Escape and backdrop click; form disables backdrop click after interaction; info allows both.',
|
|
91
91
|
default: "'info'",
|
|
92
92
|
},
|
|
93
|
+
{
|
|
94
|
+
name: 'padding',
|
|
95
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
96
|
+
description: 'Internal padding of the dialog using the spacing scale step.',
|
|
97
|
+
},
|
|
93
98
|
{
|
|
94
99
|
name: 'isInline',
|
|
95
100
|
type: 'boolean',
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
* SYNC: When Dialog.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import {readFileSync} from 'node:fs';
|
|
12
13
|
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
14
|
+
import {render, screen, fireEvent} from '@testing-library/react';
|
|
14
15
|
import {Dialog, resolveDialogPositionOffsets} from './Dialog';
|
|
15
16
|
import {DialogHeader} from './DialogHeader';
|
|
16
17
|
|
|
@@ -144,6 +145,195 @@ describe('Dialog', () => {
|
|
|
144
145
|
});
|
|
145
146
|
});
|
|
146
147
|
|
|
148
|
+
describe('IME composition', () => {
|
|
149
|
+
// A CJK user presses Escape to cancel a half-formed character several times
|
|
150
|
+
// a sentence. jsdom models neither composition nor the close watcher, so
|
|
151
|
+
// these pin the wiring; the behaviour itself is measured in Chromium
|
|
152
|
+
// against the Layer Dismissal stories.
|
|
153
|
+
function DialogWithField({onOpenChange}: {onOpenChange: () => void}) {
|
|
154
|
+
return (
|
|
155
|
+
<Dialog isOpen onOpenChange={onOpenChange} aria-label="Filters">
|
|
156
|
+
<input aria-label="Search" />
|
|
157
|
+
</Dialog>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
it('claims the composing Escape instead of letting the browser act', () => {
|
|
162
|
+
const onOpenChange = vi.fn();
|
|
163
|
+
render(<DialogWithField onOpenChange={onOpenChange} />);
|
|
164
|
+
|
|
165
|
+
const event = new KeyboardEvent('keydown', {
|
|
166
|
+
key: 'Escape',
|
|
167
|
+
bubbles: true,
|
|
168
|
+
cancelable: true,
|
|
169
|
+
});
|
|
170
|
+
Object.defineProperty(event, 'isComposing', {value: true});
|
|
171
|
+
screen.getByRole('textbox', {name: 'Search'}).dispatchEvent(event);
|
|
172
|
+
|
|
173
|
+
// Unclaimed, this press becomes a close request that arrives at
|
|
174
|
+
// handleCancel and closes the dialog on the same keystroke.
|
|
175
|
+
expect(event.defaultPrevented).toBe(true);
|
|
176
|
+
expect(onOpenChange).not.toHaveBeenCalled();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('ignores a close request that arrives mid-composition', () => {
|
|
180
|
+
// The back gesture and the platform close watcher carry no composition
|
|
181
|
+
// state, so the dialog asks the stack rather than the event.
|
|
182
|
+
const onOpenChange = vi.fn();
|
|
183
|
+
render(<DialogWithField onOpenChange={onOpenChange} />);
|
|
184
|
+
const field = screen.getByRole('textbox', {name: 'Search'});
|
|
185
|
+
|
|
186
|
+
fireEvent.compositionStart(field);
|
|
187
|
+
const duringComposition = new Event('cancel', {cancelable: true});
|
|
188
|
+
screen.getByRole('dialog').dispatchEvent(duringComposition);
|
|
189
|
+
|
|
190
|
+
expect(duringComposition.defaultPrevented).toBe(true);
|
|
191
|
+
expect(onOpenChange).not.toHaveBeenCalled();
|
|
192
|
+
|
|
193
|
+
fireEvent.compositionEnd(field);
|
|
194
|
+
screen
|
|
195
|
+
.getByRole('dialog')
|
|
196
|
+
.dispatchEvent(new Event('cancel', {cancelable: true}));
|
|
197
|
+
|
|
198
|
+
expect(onOpenChange).toHaveBeenCalledTimes(1);
|
|
199
|
+
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('nested-modal dismissal', () => {
|
|
204
|
+
function NestedModals({
|
|
205
|
+
isInnerOpen,
|
|
206
|
+
onOuterChange,
|
|
207
|
+
onInnerChange,
|
|
208
|
+
}: {
|
|
209
|
+
isInnerOpen: boolean;
|
|
210
|
+
onOuterChange: (isOpen: boolean) => void;
|
|
211
|
+
onInnerChange: (isOpen: boolean) => void;
|
|
212
|
+
}) {
|
|
213
|
+
return (
|
|
214
|
+
<Dialog
|
|
215
|
+
isOpen={true}
|
|
216
|
+
onOpenChange={onOuterChange}
|
|
217
|
+
purpose="info"
|
|
218
|
+
aria-label="Outer">
|
|
219
|
+
Outer content
|
|
220
|
+
<Dialog
|
|
221
|
+
isOpen={isInnerOpen}
|
|
222
|
+
onOpenChange={onInnerChange}
|
|
223
|
+
purpose="info"
|
|
224
|
+
aria-label="Inner">
|
|
225
|
+
Inner content
|
|
226
|
+
</Dialog>
|
|
227
|
+
</Dialog>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const getDialog = (label: string) =>
|
|
232
|
+
screen
|
|
233
|
+
.getAllByRole('dialog', {hidden: true})
|
|
234
|
+
.find(d => d.getAttribute('aria-label') === label)!;
|
|
235
|
+
|
|
236
|
+
const pressEscape = (target: Element) => {
|
|
237
|
+
target.dispatchEvent(
|
|
238
|
+
new KeyboardEvent('keydown', {
|
|
239
|
+
key: 'Escape',
|
|
240
|
+
bubbles: true,
|
|
241
|
+
cancelable: true,
|
|
242
|
+
}),
|
|
243
|
+
);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
it('closes only the inner modal, not the outer, on Escape', () => {
|
|
247
|
+
const onOuterChange = vi.fn();
|
|
248
|
+
const onInnerChange = vi.fn();
|
|
249
|
+
|
|
250
|
+
render(
|
|
251
|
+
<NestedModals
|
|
252
|
+
isInnerOpen={true}
|
|
253
|
+
onOuterChange={onOuterChange}
|
|
254
|
+
onInnerChange={onInnerChange}
|
|
255
|
+
/>,
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const outer = getDialog('Outer');
|
|
259
|
+
const inner = getDialog('Inner');
|
|
260
|
+
expect(outer.contains(inner)).toBe(true);
|
|
261
|
+
|
|
262
|
+
pressEscape(inner);
|
|
263
|
+
|
|
264
|
+
expect(onInnerChange).toHaveBeenCalledTimes(1);
|
|
265
|
+
expect(onInnerChange).toHaveBeenCalledWith(false);
|
|
266
|
+
expect(onOuterChange).not.toHaveBeenCalled();
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('closes the outer modal on the next Escape once the inner one is gone', () => {
|
|
270
|
+
const onOuterChange = vi.fn();
|
|
271
|
+
const onInnerChange = vi.fn();
|
|
272
|
+
|
|
273
|
+
const {rerender} = render(
|
|
274
|
+
<NestedModals
|
|
275
|
+
isInnerOpen={true}
|
|
276
|
+
onOuterChange={onOuterChange}
|
|
277
|
+
onInnerChange={onInnerChange}
|
|
278
|
+
/>,
|
|
279
|
+
);
|
|
280
|
+
rerender(
|
|
281
|
+
<NestedModals
|
|
282
|
+
isInnerOpen={false}
|
|
283
|
+
onOuterChange={onOuterChange}
|
|
284
|
+
onInnerChange={onInnerChange}
|
|
285
|
+
/>,
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
pressEscape(getDialog('Outer'));
|
|
289
|
+
|
|
290
|
+
expect(onOuterChange).toHaveBeenCalledTimes(1);
|
|
291
|
+
expect(onOuterChange).toHaveBeenCalledWith(false);
|
|
292
|
+
expect(onInnerChange).not.toHaveBeenCalled();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('closes the top-most modal on a browser-initiated cancel', () => {
|
|
296
|
+
const onOuterChange = vi.fn();
|
|
297
|
+
const onInnerChange = vi.fn();
|
|
298
|
+
|
|
299
|
+
render(
|
|
300
|
+
<NestedModals
|
|
301
|
+
isInnerOpen={true}
|
|
302
|
+
onOuterChange={onOuterChange}
|
|
303
|
+
onInnerChange={onInnerChange}
|
|
304
|
+
/>,
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
const cancelEvent = new Event('cancel', {cancelable: true});
|
|
308
|
+
getDialog('Inner').dispatchEvent(cancelEvent);
|
|
309
|
+
|
|
310
|
+
expect(cancelEvent.defaultPrevented).toBe(true);
|
|
311
|
+
expect(onInnerChange).toHaveBeenCalledTimes(1);
|
|
312
|
+
expect(onInnerChange).toHaveBeenCalledWith(false);
|
|
313
|
+
expect(onOuterChange).not.toHaveBeenCalled();
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('leaves a modal that is not top-most open on a browser-initiated cancel', () => {
|
|
317
|
+
const onOuterChange = vi.fn();
|
|
318
|
+
const onInnerChange = vi.fn();
|
|
319
|
+
|
|
320
|
+
render(
|
|
321
|
+
<NestedModals
|
|
322
|
+
isInnerOpen={true}
|
|
323
|
+
onOuterChange={onOuterChange}
|
|
324
|
+
onInnerChange={onInnerChange}
|
|
325
|
+
/>,
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
const cancelEvent = new Event('cancel', {cancelable: true});
|
|
329
|
+
getDialog('Outer').dispatchEvent(cancelEvent);
|
|
330
|
+
|
|
331
|
+
expect(cancelEvent.defaultPrevented).toBe(true);
|
|
332
|
+
expect(onOuterChange).not.toHaveBeenCalled();
|
|
333
|
+
expect(onInnerChange).not.toHaveBeenCalled();
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
|
|
147
337
|
describe('variant: standard', () => {
|
|
148
338
|
it('renders with default variant', () => {
|
|
149
339
|
render(
|
|
@@ -184,6 +374,76 @@ describe('Dialog', () => {
|
|
|
184
374
|
});
|
|
185
375
|
});
|
|
186
376
|
|
|
377
|
+
describe('responsive sizing', () => {
|
|
378
|
+
it('keeps the requested width but clamps standard dialogs to container and dynamic viewport gutters', () => {
|
|
379
|
+
render(
|
|
380
|
+
<Dialog
|
|
381
|
+
isOpen={true}
|
|
382
|
+
onOpenChange={() => {}}
|
|
383
|
+
width={600}
|
|
384
|
+
maxHeight="70dvh"
|
|
385
|
+
aria-label="Sized dialog">
|
|
386
|
+
Content
|
|
387
|
+
</Dialog>,
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
const dialog = screen.getByRole('dialog');
|
|
391
|
+
const inlineStyle = dialog.getAttribute('style') ?? '';
|
|
392
|
+
expect(inlineStyle).toContain('--x-width: 600px');
|
|
393
|
+
expect(inlineStyle).toContain(
|
|
394
|
+
'--x-maxWidth: min(100%, calc(100dvw - var(--spacing-4) - var(--spacing-4)))',
|
|
395
|
+
);
|
|
396
|
+
expect(inlineStyle).toContain('--x-maxHeight: 70dvh');
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('uses a fullscreen-specific fade animation instead of centered dialog movement', () => {
|
|
400
|
+
const source = readFileSync(
|
|
401
|
+
'packages/core/src/Dialog/Dialog.tsx',
|
|
402
|
+
'utf8',
|
|
403
|
+
);
|
|
404
|
+
const standardOpen = source.slice(
|
|
405
|
+
source.indexOf(' open: {'),
|
|
406
|
+
source.indexOf(' // Backdrop using ::backdrop'),
|
|
407
|
+
);
|
|
408
|
+
const fullscreenOpen = source.slice(
|
|
409
|
+
source.indexOf(' fullscreenOpen: {'),
|
|
410
|
+
source.indexOf(' fullscreenSafeArea: {'),
|
|
411
|
+
);
|
|
412
|
+
const modalStyleOrder = source.slice(
|
|
413
|
+
source.indexOf('focusOutlineProps.focusVisible('),
|
|
414
|
+
source.indexOf(
|
|
415
|
+
' xstyle,',
|
|
416
|
+
source.indexOf('focusOutlineProps.focusVisible('),
|
|
417
|
+
),
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
expect(standardOpen).toContain('enterDirectional');
|
|
421
|
+
expect(fullscreenOpen).toContain('enterFullscreen');
|
|
422
|
+
expect(fullscreenOpen).not.toContain('enterDirectional');
|
|
423
|
+
expect(modalStyleOrder.indexOf('styles.open')).toBeLessThan(
|
|
424
|
+
modalStyleOrder.indexOf('styles.fullscreenOpen'),
|
|
425
|
+
);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('protects fullscreen content with safe-area padding', () => {
|
|
429
|
+
render(
|
|
430
|
+
<Dialog
|
|
431
|
+
isOpen={true}
|
|
432
|
+
onOpenChange={() => {}}
|
|
433
|
+
variant="fullscreen"
|
|
434
|
+
aria-label="Fullscreen dialog">
|
|
435
|
+
<div data-testid="child">Content</div>
|
|
436
|
+
</Dialog>,
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
const wrapper = screen.getByTestId('child').parentElement!;
|
|
440
|
+
const computed = window.getComputedStyle(wrapper);
|
|
441
|
+
expect(computed.paddingInlineStart).toContain('safe-area-inset-left');
|
|
442
|
+
expect(computed.paddingInlineEnd).toContain('safe-area-inset-right');
|
|
443
|
+
expect(wrapper.parentElement!.tagName).toBe('DIALOG');
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
187
447
|
describe('position prop', () => {
|
|
188
448
|
it('accepts position configuration', () => {
|
|
189
449
|
render(
|
package/src/Dialog/Dialog.tsx
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
* @output Exports Dialog component, DialogProps, DialogVariant, DialogPurpose types
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by Dialog.test.tsx
|
|
10
10
|
*
|
|
11
|
+
* The standard variant treats `width` as the preferred surface width, then
|
|
12
|
+
* clamps it to the dynamic viewport with spacing-token gutters so narrow
|
|
13
|
+
* viewports keep content and controls on screen without changing the public API.
|
|
14
|
+
* Fullscreen dialogs preserve the same padding floor while honoring safe-area
|
|
15
|
+
* insets, and fade in without the centered-dialog translate/scale motion.
|
|
16
|
+
*
|
|
11
17
|
* SYNC: When modified, update these files to stay in sync:
|
|
12
18
|
* - /packages/core/src/Dialog/Dialog.doc.mjs (props table, features, implementation notes)
|
|
13
19
|
* - /packages/core/src/Dialog/Dialog.test.tsx (tests for new/changed behavior)
|
|
@@ -27,14 +33,15 @@ import {
|
|
|
27
33
|
import type {BaseProps} from '../BaseProps';
|
|
28
34
|
import * as stylex from '@stylexjs/stylex';
|
|
29
35
|
import {useScrollLock} from '../hooks/useScrollLock';
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
36
|
+
import {LayerDepthProvider} from '../Layer/LayerDepthContext';
|
|
37
|
+
import {useLayerDismissal} from '../Layer/useLayerDismissal';
|
|
32
38
|
import {
|
|
33
39
|
colorVars,
|
|
34
40
|
radiusVars,
|
|
35
41
|
durationVars,
|
|
36
42
|
easeVars,
|
|
37
43
|
shadowVars,
|
|
44
|
+
spacingVars,
|
|
38
45
|
} from '../theme/tokens.stylex';
|
|
39
46
|
import {container} from '../Layout/container.stylex';
|
|
40
47
|
import type {SpacingToken} from '../Layout/container.stylex';
|
|
@@ -47,13 +54,14 @@ import {
|
|
|
47
54
|
overlayPaddingReset,
|
|
48
55
|
} from '../Layout/padding.stylex';
|
|
49
56
|
import type {SpacingStep} from '../utils/types';
|
|
50
|
-
import {mergeProps
|
|
57
|
+
import {mergeProps} from '../utils';
|
|
51
58
|
import {devWarn} from '../utils/devWarning';
|
|
52
59
|
import {DialogContext} from './DialogContext';
|
|
53
60
|
import {themeProps} from '../utils/themeProps';
|
|
54
61
|
import type {DialogVariantMap} from './index';
|
|
55
62
|
import {focusOutlineProps} from '../utils/focusOutline.stylex';
|
|
56
63
|
|
|
64
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
57
65
|
/**
|
|
58
66
|
* Calculate a directional translate offset for dialog entry animation.
|
|
59
67
|
* Returns a normalized vector from the trigger element toward the viewport
|
|
@@ -118,6 +126,11 @@ const enterDirectional = stylex.keyframes({
|
|
|
118
126
|
to: {opacity: 1, transform: 'translate(0, 0) scale(1)'},
|
|
119
127
|
});
|
|
120
128
|
|
|
129
|
+
const enterFullscreen = stylex.keyframes({
|
|
130
|
+
from: {opacity: 0},
|
|
131
|
+
to: {opacity: 1},
|
|
132
|
+
});
|
|
133
|
+
|
|
121
134
|
/**
|
|
122
135
|
* Dialog styles using native <dialog> element
|
|
123
136
|
* Uses ::backdrop pseudo-element for overlay
|
|
@@ -171,6 +184,22 @@ const styles = stylex.create({
|
|
|
171
184
|
margin: 0,
|
|
172
185
|
inset: 0,
|
|
173
186
|
},
|
|
187
|
+
fullscreenOpen: {
|
|
188
|
+
animationName: {
|
|
189
|
+
default: enterFullscreen,
|
|
190
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
fullscreenSafeArea: {
|
|
194
|
+
paddingBlockStart:
|
|
195
|
+
'max(var(--container-padding-block-start), env(safe-area-inset-top, 0px))',
|
|
196
|
+
paddingBlockEnd:
|
|
197
|
+
'max(var(--container-padding-block-end), env(safe-area-inset-bottom, 0px))',
|
|
198
|
+
paddingInlineStart:
|
|
199
|
+
'max(var(--container-padding-inline-start), env(safe-area-inset-left, 0px))',
|
|
200
|
+
paddingInlineEnd:
|
|
201
|
+
'max(var(--container-padding-inline-end), env(safe-area-inset-right, 0px))',
|
|
202
|
+
},
|
|
174
203
|
inner: {
|
|
175
204
|
display: 'flex',
|
|
176
205
|
flexDirection: 'column',
|
|
@@ -194,12 +223,30 @@ const styles = stylex.create({
|
|
|
194
223
|
},
|
|
195
224
|
});
|
|
196
225
|
|
|
197
|
-
|
|
226
|
+
const STANDARD_DIALOG_VIEWPORT_GUTTER = spacingVars['--spacing-4'];
|
|
227
|
+
const STANDARD_DIALOG_VIEWPORT_MAX_WIDTH = `calc(100dvw - ${STANDARD_DIALOG_VIEWPORT_GUTTER} - ${STANDARD_DIALOG_VIEWPORT_GUTTER})`;
|
|
228
|
+
const STANDARD_DIALOG_MAX_WIDTH = `min(100%, ${STANDARD_DIALOG_VIEWPORT_MAX_WIDTH})`;
|
|
229
|
+
|
|
230
|
+
function formatSizeValue(value: number | string): string {
|
|
231
|
+
return typeof value === 'number' ? `${value}px` : value;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function resolveDialogSizing(
|
|
235
|
+
width: number | string,
|
|
236
|
+
maxHeight: number | string,
|
|
237
|
+
) {
|
|
238
|
+
return {
|
|
239
|
+
width: formatSizeValue(width),
|
|
240
|
+
maxWidth: STANDARD_DIALOG_MAX_WIDTH,
|
|
241
|
+
maxHeight: formatSizeValue(maxHeight),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
198
245
|
const dynamicStyles = stylex.create({
|
|
199
|
-
sizing: (width:
|
|
200
|
-
width
|
|
201
|
-
maxWidth
|
|
202
|
-
maxHeight
|
|
246
|
+
sizing: (width: string, maxWidth: string, maxHeight: string) => ({
|
|
247
|
+
width,
|
|
248
|
+
maxWidth,
|
|
249
|
+
maxHeight,
|
|
203
250
|
}),
|
|
204
251
|
position: (
|
|
205
252
|
top: string,
|
|
@@ -288,7 +335,7 @@ export interface DialogProps extends BaseProps<HTMLDialogElement> {
|
|
|
288
335
|
* The actual height will be the height of its content.
|
|
289
336
|
* Numbers are treated as pixels, strings are used as-is.
|
|
290
337
|
* Ignored when variant is 'fullscreen'.
|
|
291
|
-
* @default '
|
|
338
|
+
* @default '75dvh'
|
|
292
339
|
*/
|
|
293
340
|
maxHeight?: number | string;
|
|
294
341
|
|
|
@@ -356,7 +403,7 @@ export function Dialog({
|
|
|
356
403
|
isInline = false,
|
|
357
404
|
onOpenChange,
|
|
358
405
|
width = 400,
|
|
359
|
-
maxHeight = '
|
|
406
|
+
maxHeight = '75dvh',
|
|
360
407
|
position,
|
|
361
408
|
variant = 'standard',
|
|
362
409
|
purpose = 'info',
|
|
@@ -374,6 +421,9 @@ export function Dialog({
|
|
|
374
421
|
const paddingToken = spacingStepToToken[effectivePadding] as SpacingToken;
|
|
375
422
|
|
|
376
423
|
const isFullscreen = variant === 'fullscreen';
|
|
424
|
+
const standardSizing = isFullscreen
|
|
425
|
+
? null
|
|
426
|
+
: resolveDialogSizing(width, maxHeight);
|
|
377
427
|
|
|
378
428
|
// Default accessible name: publish a title id through DialogContext so a
|
|
379
429
|
// DialogHeader applies it to its heading (mirrors AlertDialog's explicit
|
|
@@ -415,6 +465,8 @@ export function Dialog({
|
|
|
415
465
|
[titleId, hasConsumerName],
|
|
416
466
|
);
|
|
417
467
|
|
|
468
|
+
const mergedDialogRef = useMergedRefs(ref, attachDialog);
|
|
469
|
+
|
|
418
470
|
// Capture the element that was focused when the dialog opened,
|
|
419
471
|
// for directional animation origin and focus restoration on close.
|
|
420
472
|
const triggerElementRef = useRef<HTMLElement | null>(null);
|
|
@@ -474,34 +526,24 @@ export function Dialog({
|
|
|
474
526
|
// Skip for inline rendering — no modal overlay to compensate for.
|
|
475
527
|
useScrollLock(isOpen && !isInline);
|
|
476
528
|
|
|
477
|
-
//
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
event.preventDefault();
|
|
496
|
-
if (allowEscape) {
|
|
497
|
-
onOpenChange(false);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
};
|
|
501
|
-
|
|
502
|
-
dialog.addEventListener('keydown', handleKeyDown);
|
|
503
|
-
return () => dialog.removeEventListener('keydown', handleKeyDown);
|
|
504
|
-
}, [isOpen, isInline, allowEscape, onOpenChange]);
|
|
529
|
+
// Join the shared layer dismissal stack. The stack owns the Escape listener
|
|
530
|
+
// and routes each press to the top-most layer, so this dialog does not listen
|
|
531
|
+
// itself — that is what stops a modal opened from inside another modal (or a
|
|
532
|
+
// popover opened inside this one) from closing two layers on one press.
|
|
533
|
+
//
|
|
534
|
+
// A `required` dialog registers as `block`: it must not be dismissed, and the
|
|
535
|
+
// press must not fall through and dismiss a layer behind it either.
|
|
536
|
+
//
|
|
537
|
+
// Inline mode opts out — it renders dialog content in normal flow, with
|
|
538
|
+
// nothing layered over anything.
|
|
539
|
+
const {shouldDismissOnCloseRequest} = useLayerDismissal({
|
|
540
|
+
isActive: isOpen,
|
|
541
|
+
isEnabled: !isInline,
|
|
542
|
+
escapeBehavior: allowEscape ? 'close' : 'block',
|
|
543
|
+
onDismiss: () => {
|
|
544
|
+
onOpenChange(false);
|
|
545
|
+
},
|
|
546
|
+
});
|
|
505
547
|
|
|
506
548
|
// Dev-time guardrail: an open modal should always have an accessible name.
|
|
507
549
|
// The header-title check reads the DOM, so this stays in an effect; the ref
|
|
@@ -537,12 +579,18 @@ export function Dialog({
|
|
|
537
579
|
}
|
|
538
580
|
};
|
|
539
581
|
|
|
540
|
-
//
|
|
582
|
+
// The native `cancel` event is the browser's own close-watcher firing: an
|
|
583
|
+
// Android back gesture, or a close request the stack never saw a press for.
|
|
584
|
+
// Escape presses the stack owns never arrive here — it preventDefault()s
|
|
585
|
+
// those, which suppresses the close watcher.
|
|
586
|
+
//
|
|
587
|
+
// Always preventDefault so the browser cannot close a controlled <dialog>
|
|
588
|
+
// behind React's back, then answer the request with the stack's own rules:
|
|
589
|
+
// only the top-most layer dismisses, a `required` dialog swallows it, and
|
|
590
|
+
// nothing dismisses while an IME composition is in progress.
|
|
541
591
|
const handleCancel = (event: React.SyntheticEvent<HTMLDialogElement>) => {
|
|
542
592
|
event.preventDefault();
|
|
543
|
-
|
|
544
|
-
// itself on the same Escape press.
|
|
545
|
-
if (hasActiveFocusTrapEscape()) {
|
|
593
|
+
if (!shouldDismissOnCloseRequest()) {
|
|
546
594
|
return;
|
|
547
595
|
}
|
|
548
596
|
if (allowEscape) {
|
|
@@ -550,7 +598,6 @@ export function Dialog({
|
|
|
550
598
|
}
|
|
551
599
|
};
|
|
552
600
|
|
|
553
|
-
// Shared inner content wrapper
|
|
554
601
|
const innerContent = (
|
|
555
602
|
<div
|
|
556
603
|
{...stylex.props(
|
|
@@ -559,22 +606,14 @@ export function Dialog({
|
|
|
559
606
|
useThemeDefault
|
|
560
607
|
? {
|
|
561
608
|
useThemeDefault: 'dialog',
|
|
562
|
-
maxHeight:
|
|
563
|
-
? undefined
|
|
564
|
-
: typeof maxHeight === 'number'
|
|
565
|
-
? `${maxHeight}px`
|
|
566
|
-
: maxHeight,
|
|
609
|
+
maxHeight: standardSizing?.maxHeight,
|
|
567
610
|
}
|
|
568
611
|
: {
|
|
569
612
|
paddingInnerX: paddingToken,
|
|
570
613
|
paddingInnerY: paddingToken,
|
|
571
614
|
paddingOuterX: paddingToken,
|
|
572
615
|
paddingOuterY: paddingToken,
|
|
573
|
-
maxHeight:
|
|
574
|
-
? undefined
|
|
575
|
-
: typeof maxHeight === 'number'
|
|
576
|
-
? `${maxHeight}px`
|
|
577
|
-
: maxHeight,
|
|
616
|
+
maxHeight: standardSizing?.maxHeight,
|
|
578
617
|
},
|
|
579
618
|
),
|
|
580
619
|
!useThemeDefault &&
|
|
@@ -589,6 +628,7 @@ export function Dialog({
|
|
|
589
628
|
!useThemeDefault &&
|
|
590
629
|
effectivePadding !== 4 &&
|
|
591
630
|
containerPaddingBlockEndVarStyles[effectivePadding],
|
|
631
|
+
isFullscreen && styles.fullscreenSafeArea,
|
|
592
632
|
)}>
|
|
593
633
|
<DialogContext value={dialogContextValue}>{children}</DialogContext>
|
|
594
634
|
</div>
|
|
@@ -612,7 +652,12 @@ export function Dialog({
|
|
|
612
652
|
stylex.props(
|
|
613
653
|
styles.inlineWrapper,
|
|
614
654
|
overlayPaddingReset.reset,
|
|
615
|
-
|
|
655
|
+
standardSizing &&
|
|
656
|
+
dynamicStyles.sizing(
|
|
657
|
+
standardSizing.width,
|
|
658
|
+
standardSizing.maxWidth,
|
|
659
|
+
standardSizing.maxHeight,
|
|
660
|
+
),
|
|
616
661
|
isFullscreen && styles.fullscreen,
|
|
617
662
|
xstyle,
|
|
618
663
|
),
|
|
@@ -623,7 +668,7 @@ export function Dialog({
|
|
|
623
668
|
(props as Record<string, unknown>)['data-testid'] as
|
|
624
669
|
string | undefined
|
|
625
670
|
}>
|
|
626
|
-
{innerContent}
|
|
671
|
+
<LayerDepthProvider>{innerContent}</LayerDepthProvider>
|
|
627
672
|
</div>
|
|
628
673
|
);
|
|
629
674
|
}
|
|
@@ -632,7 +677,7 @@ export function Dialog({
|
|
|
632
677
|
|
|
633
678
|
return (
|
|
634
679
|
<dialog
|
|
635
|
-
ref={
|
|
680
|
+
ref={mergedDialogRef}
|
|
636
681
|
{...safeProps}
|
|
637
682
|
{...mergeProps(
|
|
638
683
|
themeProps('dialog', {variant}),
|
|
@@ -641,7 +686,12 @@ export function Dialog({
|
|
|
641
686
|
overlayPaddingReset.reset,
|
|
642
687
|
isOpen && styles.open,
|
|
643
688
|
styles.backdrop,
|
|
644
|
-
|
|
689
|
+
standardSizing &&
|
|
690
|
+
dynamicStyles.sizing(
|
|
691
|
+
standardSizing.width,
|
|
692
|
+
standardSizing.maxWidth,
|
|
693
|
+
standardSizing.maxHeight,
|
|
694
|
+
),
|
|
645
695
|
hasPosition &&
|
|
646
696
|
(() => {
|
|
647
697
|
const o = resolveDialogPositionOffsets(position);
|
|
@@ -653,6 +703,7 @@ export function Dialog({
|
|
|
653
703
|
);
|
|
654
704
|
})(),
|
|
655
705
|
isFullscreen && styles.fullscreen,
|
|
706
|
+
isFullscreen && isOpen && styles.fullscreenOpen,
|
|
656
707
|
xstyle,
|
|
657
708
|
),
|
|
658
709
|
className,
|
|
@@ -665,7 +716,7 @@ export function Dialog({
|
|
|
665
716
|
// imperatively in `attachDialog`; a consumer-provided aria-labelledby
|
|
666
717
|
// flows through {...safeProps} above and wins.
|
|
667
718
|
{...(purpose === 'required' ? {role: 'alertdialog'} : undefined)}>
|
|
668
|
-
{innerContent}
|
|
719
|
+
<LayerDepthProvider>{innerContent}</LayerDepthProvider>
|
|
669
720
|
</dialog>
|
|
670
721
|
);
|
|
671
722
|
}
|
|
@@ -89,6 +89,12 @@ export const docs = {
|
|
|
89
89
|
type: '() => void',
|
|
90
90
|
description: 'Callback fired when the trigger button is clicked.',
|
|
91
91
|
},
|
|
92
|
+
{
|
|
93
|
+
name: 'placement',
|
|
94
|
+
type: "'above' | 'below' | 'start' | 'end'",
|
|
95
|
+
description: 'Position placement for the menu popover relative to the trigger button.',
|
|
96
|
+
default: "'below'",
|
|
97
|
+
},
|
|
92
98
|
{
|
|
93
99
|
name: 'hasChevron',
|
|
94
100
|
type: 'boolean',
|
|
@@ -701,11 +701,14 @@ describe('DropdownMenuSubMenu theming slots', () => {
|
|
|
701
701
|
name: /Move to/,
|
|
702
702
|
hidden: true,
|
|
703
703
|
});
|
|
704
|
-
// The indicator-icon slot
|
|
705
|
-
//
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
704
|
+
// The indicator-icon slot sits on the chevron glyph itself (the element
|
|
705
|
+
// that carries the icon size), so a theme can restyle its size/color
|
|
706
|
+
// directly.
|
|
707
|
+
const indicator = trigger.querySelector(
|
|
708
|
+
'.astryx-dropdown-menu-indicator-icon',
|
|
709
|
+
);
|
|
710
|
+
expect(indicator).toBeInTheDocument();
|
|
711
|
+
expect(indicator).toHaveClass('astryx-icon');
|
|
709
712
|
});
|
|
710
713
|
});
|
|
711
714
|
|