@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
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file isApplePlatform.ts
|
|
5
|
+
* @input Reads navigator.userAgentData.platform and navigator.platform
|
|
6
|
+
* @output Exports isApplePlatform
|
|
7
|
+
* @position Internal util; the single platform detection behind useHotkeys and Kbd
|
|
8
|
+
*
|
|
9
|
+
* Deliberately absent from utils/index.ts: packages/core/src/index.ts does
|
|
10
|
+
* `export * from './utils'`, so naming it there would publish it as API.
|
|
11
|
+
* Import it by path, as interactionModality is imported.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Detects whether the current platform is macOS/iOS.
|
|
16
|
+
* Prefers the User-Agent Client Hints API when it names a platform (modern
|
|
17
|
+
* Chrome/Edge), falls back to navigator.platform (deprecated but universally
|
|
18
|
+
* supported) when it names none.
|
|
19
|
+
*/
|
|
20
|
+
export function isApplePlatform() {
|
|
21
|
+
if (typeof navigator === 'undefined') {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const uaData = 'userAgentData' in navigator ? navigator.userAgentData : null;
|
|
25
|
+
if (uaData && typeof uaData === 'object' && 'platform' in uaData) {
|
|
26
|
+
const uaPlatform = uaData.platform;
|
|
27
|
+
const named = typeof uaPlatform === 'string' ? uaPlatform.trim() : '';
|
|
28
|
+
// A value that names nothing is no answer, not a negative one: builds that
|
|
29
|
+
// rewrite their client-hints identity ship '', and 'Unknown' is the spec's
|
|
30
|
+
// own sentinel for "cannot say". Both fall through rather than reading as
|
|
31
|
+
// "not Apple".
|
|
32
|
+
if (named !== '' && named.toLowerCase() !== 'unknown') {
|
|
33
|
+
return /mac/i.test(named);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return /Mac|iPhone|iPad|iPod/.test(navigator.platform ?? '');
|
|
37
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sharedResizeObserver.d.ts","sourceRoot":"","sources":["../../src/utils/sharedResizeObserver.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"sharedResizeObserver.d.ts","sourceRoot":"","sources":["../../src/utils/sharedResizeObserver.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AA2B3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,cAAc,GACvB,IAAI,CAQN;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAStD"}
|
|
@@ -20,7 +20,16 @@
|
|
|
20
20
|
*/
|
|
21
21
|
let observer = null;
|
|
22
22
|
const callbacks = new Map();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The shared observer, or null where the API does not exist (jsdom, an old
|
|
26
|
+
* browser). Callers still get the one-shot measurement `observeResize` fires
|
|
27
|
+
* on registration; live resize updates are the part that needs the API.
|
|
28
|
+
*/
|
|
23
29
|
function getObserver() {
|
|
30
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
24
33
|
if (!observer) {
|
|
25
34
|
observer = new ResizeObserver(entries => {
|
|
26
35
|
for (const entry of entries) {
|
|
@@ -57,7 +66,7 @@ function getObserver() {
|
|
|
57
66
|
*/
|
|
58
67
|
export function observeResize(element, callback) {
|
|
59
68
|
callbacks.set(element, callback);
|
|
60
|
-
getObserver()
|
|
69
|
+
getObserver()?.observe(element);
|
|
61
70
|
|
|
62
71
|
// Fire once immediately so callers get an initial measurement
|
|
63
72
|
// without duplicating their logic outside the observer path.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @file timeParser.ts
|
|
3
3
|
* @input Uses string parsing
|
|
4
4
|
* @output Exports time parsing and formatting utilities
|
|
5
|
-
* @position Shared utility; used by
|
|
5
|
+
* @position Shared utility; used by TimeInput and DateTimeInput
|
|
6
6
|
*
|
|
7
7
|
* SYNC: When modified, update this header
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeParser.d.ts","sourceRoot":"","sources":["../../src/utils/timeParser.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG;IAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAMvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA6B5D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,cAAc,GAAE,OAAe,GAC9B,aAAa,CAUf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,cAAc,GAAE,OAAe,GAC9B,MAAM,CAqBR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,cAAc,GAAE,OAAe,GAC9B,MAAM,CAmBR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,cAAc,GAAE,OAAe,GAC9B,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"timeParser.d.ts","sourceRoot":"","sources":["../../src/utils/timeParser.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG;IAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAMvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA6B5D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,cAAc,GAAE,OAAe,GAC9B,aAAa,CAUf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,cAAc,GAAE,OAAe,GAC9B,MAAM,CAqBR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,cAAc,GAAE,OAAe,GAC9B,MAAM,CAmBR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,cAAc,GAAE,OAAe,GAC9B,aAAa,GAAG,IAAI,CA6HtB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,CAAC,EAAE,aAAa,GAAG,SAAS,EAC5B,CAAC,EAAE,aAAa,GAAG,SAAS,GAC3B,MAAM,CA4BR;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,aAAa,EACnB,GAAG,CAAC,EAAE,aAAa,EACnB,GAAG,CAAC,EAAE,aAAa,GAClB,OAAO,CAQT;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,aAAa,EACnB,GAAG,CAAC,EAAE,aAAa,EACnB,GAAG,CAAC,EAAE,aAAa,EACnB,cAAc,GAAE,OAAe,GAC9B,aAAa,CAoBf;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,aAAa,EACnB,YAAY,EAAE,MAAM,EACpB,cAAc,GAAE,OAAe,GAC9B,aAAa,CAwBf"}
|
package/dist/utils/timeParser.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file timeParser.ts
|
|
5
5
|
* @input Uses string parsing
|
|
6
6
|
* @output Exports time parsing and formatting utilities
|
|
7
|
-
* @position Shared utility; used by
|
|
7
|
+
* @position Shared utility; used by TimeInput and DateTimeInput
|
|
8
8
|
*
|
|
9
9
|
* SYNC: When modified, update this header
|
|
10
10
|
*/
|
|
@@ -134,17 +134,29 @@ export function parseTimeInput(input, includeSeconds = false) {
|
|
|
134
134
|
|
|
135
135
|
// Remove AM/PM suffix
|
|
136
136
|
const timeStr = trimmed.replace(/\s*[ap]\.?m?\.?\s*$/i, '').trim();
|
|
137
|
+
const convertHourTo24Hour = hour => {
|
|
138
|
+
if (!hasMeridiem) {
|
|
139
|
+
return hour;
|
|
140
|
+
}
|
|
141
|
+
if (hour < 1 || hour > 12) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
if (isPM && hour !== 12) {
|
|
145
|
+
return hour + 12;
|
|
146
|
+
}
|
|
147
|
+
if (isAM && hour === 12) {
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
return hour;
|
|
151
|
+
};
|
|
137
152
|
|
|
138
153
|
// Handle formats like "2pm" -> "2"
|
|
139
154
|
if (/^\d{1,2}$/.test(timeStr)) {
|
|
140
155
|
const hour = parseInt(timeStr, 10);
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
if (isAM && hour === 12) {
|
|
147
|
-
hour24 = 0;
|
|
156
|
+
if (hasMeridiem) {
|
|
157
|
+
const hour24 = convertHourTo24Hour(hour);
|
|
158
|
+
if (hour24 === null) {
|
|
159
|
+
return null;
|
|
148
160
|
}
|
|
149
161
|
return formatISOTime({
|
|
150
162
|
hour: hour24,
|
|
@@ -166,9 +178,10 @@ export function parseTimeInput(input, includeSeconds = false) {
|
|
|
166
178
|
if (/^\d{4}$/.test(timeStr)) {
|
|
167
179
|
const hour = parseInt(timeStr.slice(0, 2), 10);
|
|
168
180
|
const minute = parseInt(timeStr.slice(2, 4), 10);
|
|
169
|
-
|
|
181
|
+
const hour24 = convertHourTo24Hour(hour);
|
|
182
|
+
if (hour24 !== null && hour24 >= 0 && hour24 <= 23 && minute >= 0 && minute <= 59) {
|
|
170
183
|
return formatISOTime({
|
|
171
|
-
hour,
|
|
184
|
+
hour: hour24,
|
|
172
185
|
minute,
|
|
173
186
|
second: 0
|
|
174
187
|
}, includeSeconds);
|
|
@@ -181,9 +194,10 @@ export function parseTimeInput(input, includeSeconds = false) {
|
|
|
181
194
|
const hour = parseInt(timeStr.slice(0, 2), 10);
|
|
182
195
|
const minute = parseInt(timeStr.slice(2, 4), 10);
|
|
183
196
|
const second = parseInt(timeStr.slice(4, 6), 10);
|
|
184
|
-
|
|
197
|
+
const hour24 = convertHourTo24Hour(hour);
|
|
198
|
+
if (hour24 !== null && hour24 >= 0 && hour24 <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59) {
|
|
185
199
|
return formatISOTime({
|
|
186
|
-
hour,
|
|
200
|
+
hour: hour24,
|
|
187
201
|
minute,
|
|
188
202
|
second
|
|
189
203
|
}, includeSeconds);
|
package/locales/en.json
CHANGED
|
@@ -563,6 +563,10 @@
|
|
|
563
563
|
"defaultMessage": "Apply",
|
|
564
564
|
"description": "Primary button label inside a table's filter panel/popover; commits pending filter values. Imperative verb; pairs with `Reset`."
|
|
565
565
|
},
|
|
566
|
+
"@astryx.table.rowStatus.columnHeader": {
|
|
567
|
+
"defaultMessage": "Row status",
|
|
568
|
+
"description": "Screen-reader-only column header for the narrow status-indicator gutter a Table gains from useTableRowStatus. Sighted users see a blank gutter; assistive tech announces this as the column name."
|
|
569
|
+
},
|
|
566
570
|
"@astryx.table.selection.selectAllRows": {
|
|
567
571
|
"defaultMessage": "Select all rows",
|
|
568
572
|
"description": "Aria label for the \"select all rows\" checkbox in a Table header."
|
|
@@ -747,6 +751,10 @@
|
|
|
747
751
|
"defaultMessage": "{label} time",
|
|
748
752
|
"description": "Screen-reader-only accessible name for the time-of-day slot in a DateTimeInput. Example: `Start date time`; reorder freely (e.g. \"time of {label}\")."
|
|
749
753
|
},
|
|
754
|
+
"@astryx.dateTimeInput.timeOptionsLabel": {
|
|
755
|
+
"defaultMessage": "{label} options",
|
|
756
|
+
"description": "Screen-reader-only accessible name for the list of preset times that drops down from a DateTimeInput's time slot. `{label}` is the accessible name of the time field itself, already ending in the word for time — example: `Meeting time options`. Plural: the list holds every selectable time."
|
|
757
|
+
},
|
|
750
758
|
"@astryx.dateRangeInput.placeholder": {
|
|
751
759
|
"defaultMessage": "Select date range",
|
|
752
760
|
"description": "Grey placeholder inside an empty DateRangeInput field. Represents picking a start–end date pair. Imperative verb."
|
|
@@ -809,7 +817,15 @@
|
|
|
809
817
|
},
|
|
810
818
|
"@astryx.table.pagination.label": {
|
|
811
819
|
"defaultMessage": "Table pagination",
|
|
812
|
-
"description": "Screen-reader-only accessible name for
|
|
820
|
+
"description": "Screen-reader-only accessible name for a table's pagination `<nav>` (rendered below and/or above the table per the plugin's position config). Kept separate from `@astryx.pagination.label` so translations may diverge. When position='both', this string is interpolated as the {label} value into `@astryx.table.pagination.labelAbove`/`labelBelow` — keep it compatible with those suffix templates."
|
|
821
|
+
},
|
|
822
|
+
"@astryx.table.pagination.labelAbove": {
|
|
823
|
+
"defaultMessage": "{label} (top)",
|
|
824
|
+
"description": "Accessible name for the pagination `<nav>` rendered above the table when position='both' renders two navs. `label` is the resolved base label (default \"Table pagination\" or consumer-supplied); the suffix keeps the two same-type landmarks distinguishable."
|
|
825
|
+
},
|
|
826
|
+
"@astryx.table.pagination.labelBelow": {
|
|
827
|
+
"defaultMessage": "{label} (bottom)",
|
|
828
|
+
"description": "Accessible name for the pagination `<nav>` rendered below the table when position='both' renders two navs. `label` is the resolved base label (default \"Table pagination\" or consumer-supplied); the suffix keeps the two same-type landmarks distinguishable."
|
|
813
829
|
},
|
|
814
830
|
"@astryx.timeInput.placeholder": {
|
|
815
831
|
"defaultMessage": "Select a time",
|
|
@@ -1059,6 +1075,10 @@
|
|
|
1059
1075
|
"defaultMessage": "Expand row",
|
|
1060
1076
|
"description": "Screen-reader-only label on the row-expand chevron when the row is currently collapsed. Part of a four-way set with `collapseRow`, `expandAllRows`, `collapseAllRows`."
|
|
1061
1077
|
},
|
|
1078
|
+
"@astryx.tableRowExpansion.columnHeader": {
|
|
1079
|
+
"defaultMessage": "Row expansion",
|
|
1080
|
+
"description": "Screen-reader-only header for the leading column that holds the per-row expand/collapse chevrons. The column shows no visible label."
|
|
1081
|
+
},
|
|
1062
1082
|
"@astryx.tableRowExpansion.collapseAllRows": {
|
|
1063
1083
|
"defaultMessage": "Collapse all rows",
|
|
1064
1084
|
"description": "Screen-reader-only label on the same header button when every row is expanded. Part of the four-way set."
|
|
@@ -1067,29 +1087,33 @@
|
|
|
1067
1087
|
"defaultMessage": "Expand all rows",
|
|
1068
1088
|
"description": "Screen-reader-only label on the header expand-all/collapse-all button when at least one row is collapsed (clicking expands every expandable row). Part of the four-way set."
|
|
1069
1089
|
},
|
|
1090
|
+
"@astryx.stepper.label": {
|
|
1091
|
+
"defaultMessage": "Progress",
|
|
1092
|
+
"description": "Screen-reader-only fallback name for the Stepper's ordered list of steps, describing the sequence as a whole (e.g. `Progress`). Used as the aria-label when the consumer does not pass a `label`. Singular per ARIA convention."
|
|
1093
|
+
},
|
|
1070
1094
|
"@astryx.step.goToStep": {
|
|
1071
1095
|
"defaultMessage": "Go to step {stepNumber, number}: {label}",
|
|
1072
|
-
"description": "Accessible name for a clickable step in the
|
|
1096
|
+
"description": "Accessible name for a clickable step in the Stepper. {stepNumber} is the 1-based position, {label} is the step's visible label."
|
|
1073
1097
|
},
|
|
1074
1098
|
"@astryx.step.goToStepWithStatus": {
|
|
1075
1099
|
"defaultMessage": "Go to step {stepNumber, number}: {label}, {status}",
|
|
1076
|
-
"description": "Accessible name for a clickable
|
|
1100
|
+
"description": "Accessible name for a clickable Stepper step that also carries a status. {status} is one of the translated `step.status.*` words (completed/warning/error). Keep the pattern parallel to `step.goToStep`."
|
|
1077
1101
|
},
|
|
1078
1102
|
"@astryx.step.optional": {
|
|
1079
1103
|
"defaultMessage": "Optional",
|
|
1080
|
-
"description": "Visible indicator appended after a
|
|
1104
|
+
"description": "Visible indicator appended after a Stepper step's label when the step is optional (isOptional). Very short; appears inline after the label text."
|
|
1081
1105
|
},
|
|
1082
1106
|
"@astryx.step.status.completed": {
|
|
1083
1107
|
"defaultMessage": "completed",
|
|
1084
|
-
"description": "Screen-reader-only status word rendered next to a
|
|
1108
|
+
"description": "Screen-reader-only status word rendered next to a Stepper step label when the step is done (either progress-completed or status=success). Lowercase adjective; it is read mid-sentence after the step label."
|
|
1085
1109
|
},
|
|
1086
1110
|
"@astryx.step.status.warning": {
|
|
1087
1111
|
"defaultMessage": "warning",
|
|
1088
|
-
"description": "Screen-reader-only status word rendered next to a
|
|
1112
|
+
"description": "Screen-reader-only status word rendered next to a Stepper step label when status=warning. Lowercase noun/adjective; read mid-sentence after the step label."
|
|
1089
1113
|
},
|
|
1090
1114
|
"@astryx.step.status.error": {
|
|
1091
1115
|
"defaultMessage": "error",
|
|
1092
|
-
"description": "Screen-reader-only status word rendered next to a
|
|
1116
|
+
"description": "Screen-reader-only status word rendered next to a Stepper step label when status=error. Lowercase noun; read mid-sentence after the step label."
|
|
1093
1117
|
},
|
|
1094
1118
|
"@astryx.tableTree.collapseRow": {
|
|
1095
1119
|
"defaultMessage": "Collapse row",
|
package/locales/pseudo.json
CHANGED
|
@@ -422,6 +422,9 @@
|
|
|
422
422
|
"@astryx.table.filter.apply": {
|
|
423
423
|
"defaultMessage": "⟦Àþþłý⟧"
|
|
424
424
|
},
|
|
425
|
+
"@astryx.table.rowStatus.columnHeader": {
|
|
426
|
+
"defaultMessage": "⟦Řóŵ šţàţúš⟧"
|
|
427
|
+
},
|
|
425
428
|
"@astryx.table.selection.selectAllRows": {
|
|
426
429
|
"defaultMessage": "⟦Šéłéçţ àłł řóŵš⟧"
|
|
427
430
|
},
|
|
@@ -560,6 +563,9 @@
|
|
|
560
563
|
"@astryx.dateTimeInput.timeSuffix": {
|
|
561
564
|
"defaultMessage": "⟦{label} ţíɱé⟧"
|
|
562
565
|
},
|
|
566
|
+
"@astryx.dateTimeInput.timeOptionsLabel": {
|
|
567
|
+
"defaultMessage": "⟦{label} óþţíóñš⟧"
|
|
568
|
+
},
|
|
563
569
|
"@astryx.dateRangeInput.placeholder": {
|
|
564
570
|
"defaultMessage": "⟦Šéłéçţ ðàţé řàñĝé⟧"
|
|
565
571
|
},
|
|
@@ -608,6 +614,12 @@
|
|
|
608
614
|
"@astryx.table.pagination.label": {
|
|
609
615
|
"defaultMessage": "⟦Ţàƀłé þàĝíñàţíóñ⟧"
|
|
610
616
|
},
|
|
617
|
+
"@astryx.table.pagination.labelAbove": {
|
|
618
|
+
"defaultMessage": "⟦{label} (ţóþ)⟧"
|
|
619
|
+
},
|
|
620
|
+
"@astryx.table.pagination.labelBelow": {
|
|
621
|
+
"defaultMessage": "⟦{label} (ƀóţţóɱ)⟧"
|
|
622
|
+
},
|
|
611
623
|
"@astryx.timeInput.placeholder": {
|
|
612
624
|
"defaultMessage": "⟦Šéłéçţ à ţíɱé⟧"
|
|
613
625
|
},
|
|
@@ -794,12 +806,18 @@
|
|
|
794
806
|
"@astryx.tableRowExpansion.expandRow": {
|
|
795
807
|
"defaultMessage": "⟦Éẋþàñð řóŵ⟧"
|
|
796
808
|
},
|
|
809
|
+
"@astryx.tableRowExpansion.columnHeader": {
|
|
810
|
+
"defaultMessage": "⟦Řóŵ éẋþàñšíóñ⟧"
|
|
811
|
+
},
|
|
797
812
|
"@astryx.tableRowExpansion.collapseAllRows": {
|
|
798
813
|
"defaultMessage": "⟦Çółłàþšé àłł řóŵš⟧"
|
|
799
814
|
},
|
|
800
815
|
"@astryx.tableRowExpansion.expandAllRows": {
|
|
801
816
|
"defaultMessage": "⟦Éẋþàñð àłł řóŵš⟧"
|
|
802
817
|
},
|
|
818
|
+
"@astryx.stepper.label": {
|
|
819
|
+
"defaultMessage": "⟦Þřóĝřéšš⟧"
|
|
820
|
+
},
|
|
803
821
|
"@astryx.step.goToStep": {
|
|
804
822
|
"defaultMessage": "⟦Ĝó ţó šţéþ {stepNumber, number}: {label}⟧"
|
|
805
823
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-canary.32a62fd",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -489,6 +489,11 @@
|
|
|
489
489
|
"types": "./dist/StatusDot/index.d.ts",
|
|
490
490
|
"default": "./dist/StatusDot/index.js"
|
|
491
491
|
},
|
|
492
|
+
"./Stepper": {
|
|
493
|
+
"source": "./src/Stepper/index.ts",
|
|
494
|
+
"types": "./dist/Stepper/index.d.ts",
|
|
495
|
+
"default": "./dist/Stepper/index.js"
|
|
496
|
+
},
|
|
492
497
|
"./Switch": {
|
|
493
498
|
"source": "./src/Switch/index.ts",
|
|
494
499
|
"types": "./dist/Switch/index.d.ts",
|
|
@@ -656,6 +661,7 @@
|
|
|
656
661
|
"react-dom": ">=19.0.0"
|
|
657
662
|
},
|
|
658
663
|
"devDependencies": {
|
|
664
|
+
"@astryxdesign/cli": "0.5.0-canary.32a62fd",
|
|
659
665
|
"@babel/cli": "^8.0.4",
|
|
660
666
|
"@babel/core": "^7.29.7",
|
|
661
667
|
"@babel/preset-react": "^8.0.1",
|
|
@@ -664,8 +670,7 @@
|
|
|
664
670
|
"@testing-library/dom": "^10.0.0",
|
|
665
671
|
"@testing-library/jest-dom": "^6.6.0",
|
|
666
672
|
"@testing-library/react": "^16.3.2",
|
|
667
|
-
"rimraf": "^6.0.1"
|
|
668
|
-
"@astryxdesign/cli": "0.4.7"
|
|
673
|
+
"rimraf": "^6.0.1"
|
|
669
674
|
},
|
|
670
675
|
"dependencies": {
|
|
671
676
|
"intl-messageformat": "^11.2.9"
|
|
@@ -50,7 +50,7 @@ import {AppShellMobileContext} from './AppShellMobileContext';
|
|
|
50
50
|
import type {AppShellMobileContextValue} from './AppShellMobileContext';
|
|
51
51
|
import type {SpacingStep} from '../utils/types';
|
|
52
52
|
import type {BaseProps} from '../BaseProps';
|
|
53
|
-
import {mergeProps,
|
|
53
|
+
import {mergeProps, isRenderable} from '../utils';
|
|
54
54
|
import {focusOutlineProps} from '../utils/focusOutline.stylex';
|
|
55
55
|
import {useMediaQuery} from '../hooks/useMediaQuery';
|
|
56
56
|
import {observeResize, unobserveResize} from '../utils/sharedResizeObserver';
|
|
@@ -58,6 +58,7 @@ import {themeProps} from '../utils/themeProps';
|
|
|
58
58
|
import {useTranslator} from '../i18n';
|
|
59
59
|
import type {AppShellVariantMap} from './index';
|
|
60
60
|
|
|
61
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
61
62
|
const HasActivity = typeof React.Activity !== 'undefined';
|
|
62
63
|
const ActivityWrapper = HasActivity
|
|
63
64
|
? ({
|
|
@@ -792,7 +793,7 @@ export function AppShell({
|
|
|
792
793
|
<AppShellMobileContext value={mobileContextValue}>
|
|
793
794
|
<div
|
|
794
795
|
{...rest}
|
|
795
|
-
ref={
|
|
796
|
+
ref={useMergedRefs(ref, shellRef)}
|
|
796
797
|
data-testid={dataTestId}
|
|
797
798
|
{...mergeProps(
|
|
798
799
|
themeProps('app-shell', {variant}),
|
|
@@ -16,6 +16,7 @@ export const docs = {
|
|
|
16
16
|
{guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
|
|
17
17
|
{guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
|
|
18
18
|
{guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
|
|
19
|
+
{guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule — component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`) — with only the conditional branch the ratio is unset outside the query and the box collapses.'},
|
|
19
20
|
{guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
|
|
20
21
|
{guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
|
|
21
22
|
{guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
|
|
@@ -30,7 +31,7 @@ export const docs = {
|
|
|
30
31
|
{
|
|
31
32
|
name: 'ratio',
|
|
32
33
|
type: 'number',
|
|
33
|
-
description: 'Aspect ratio as width/height (e.g. 16/9, 1).',
|
|
34
|
+
description: 'Aspect ratio as width/height (e.g. 16/9, 1). Emitted as a class-level declaration (never inline), so `xstyle` rules or unlayered consumer CSS can override it responsively.',
|
|
34
35
|
required: true,
|
|
35
36
|
},
|
|
36
37
|
{
|
|
@@ -83,6 +84,7 @@ export const docsZh = {
|
|
|
83
84
|
{guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
|
|
84
85
|
{guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
|
|
85
86
|
{guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
|
|
87
|
+
{guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule — component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`) — with only the conditional branch the ratio is unset outside the query and the box collapses.'},
|
|
86
88
|
{guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
|
|
87
89
|
{guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
|
|
88
90
|
{guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
|
|
@@ -94,7 +96,7 @@ export const docsZh = {
|
|
|
94
96
|
],
|
|
95
97
|
},
|
|
96
98
|
props: [
|
|
97
|
-
{name: 'ratio', type: 'number', description: '宽高比,以宽/高表示(例如 16/9、1
|
|
99
|
+
{name: 'ratio', type: 'number', description: '宽高比,以宽/高表示(例如 16/9、1)。以类级声明输出(非内联样式),可通过 `xstyle` 规则或未分层的(unlayered)消费者 CSS 做响应式覆盖。', required: true},
|
|
98
100
|
{
|
|
99
101
|
name: 'shape',
|
|
100
102
|
type: "'rectangle' | 'ellipse'",
|
|
@@ -133,6 +135,7 @@ export const docsDense = {
|
|
|
133
135
|
{guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
|
|
134
136
|
{guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
|
|
135
137
|
{guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
|
|
138
|
+
{guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule — component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`) — with only the conditional branch the ratio is unset outside the query and the box collapses.'},
|
|
136
139
|
{guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
|
|
137
140
|
{guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
|
|
138
141
|
{guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
|
|
@@ -144,7 +147,7 @@ export const docsDense = {
|
|
|
144
147
|
],
|
|
145
148
|
},
|
|
146
149
|
propDescriptions: {
|
|
147
|
-
ratio: 'width/height ratio (e.g. 16/9, 1)',
|
|
150
|
+
ratio: 'width/height ratio (e.g. 16/9, 1); class-level declaration (never inline) so xstyle/unlayered-CSS @container overrides win',
|
|
148
151
|
shape: "container shape: 'rectangle' (default) | 'ellipse' (circle at ratio 1)",
|
|
149
152
|
fit: "child layout: 'cover' fill+crop | 'contain' fill+letterbox | 'center' natural size; omitted = child styles itself",
|
|
150
153
|
children: 'content positioned absolutely to fill container',
|
|
@@ -13,6 +13,20 @@ import {describe, it, expect, vi, beforeAll} from 'vitest';
|
|
|
13
13
|
import {render, screen} from '@testing-library/react';
|
|
14
14
|
import {AspectRatio} from './AspectRatio';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* The ratio compiles to a class-level `aspect-ratio: var(--x-aspectRatio)`
|
|
18
|
+
* declaration with the value carried by a CSS variable (so xstyle/@media
|
|
19
|
+
* and unlayered consumer CSS overrides can win). `--x-aspectRatio` is the
|
|
20
|
+
* debug-mode variable name emitted for the `aspectRatio` property.
|
|
21
|
+
*/
|
|
22
|
+
function ratioVar(el: HTMLElement): string {
|
|
23
|
+
return el.style.getPropertyValue('--x-aspectRatio');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function ratioValue(ratio: number): string {
|
|
27
|
+
return String(ratio);
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
describe('AspectRatio', () => {
|
|
17
31
|
it('renders with correct aspect ratio', () => {
|
|
18
32
|
render(
|
|
@@ -22,7 +36,7 @@ describe('AspectRatio', () => {
|
|
|
22
36
|
);
|
|
23
37
|
const element = screen.getByTestId('aspect-ratio');
|
|
24
38
|
expect(element).toBeInTheDocument();
|
|
25
|
-
expect(element
|
|
39
|
+
expect(ratioVar(element)).toBe(ratioValue(16 / 9));
|
|
26
40
|
});
|
|
27
41
|
|
|
28
42
|
it('children fill the container', () => {
|
|
@@ -47,7 +61,7 @@ describe('AspectRatio', () => {
|
|
|
47
61
|
</AspectRatio>,
|
|
48
62
|
);
|
|
49
63
|
const element = screen.getByTestId('aspect-ratio');
|
|
50
|
-
expect(element
|
|
64
|
+
expect(ratioVar(element)).toBe(ratioValue(ratio));
|
|
51
65
|
});
|
|
52
66
|
|
|
53
67
|
it('renders with 4:3 ratio', () => {
|
|
@@ -58,7 +72,7 @@ describe('AspectRatio', () => {
|
|
|
58
72
|
</AspectRatio>,
|
|
59
73
|
);
|
|
60
74
|
const element = screen.getByTestId('aspect-ratio');
|
|
61
|
-
expect(element
|
|
75
|
+
expect(ratioVar(element)).toBe(ratioValue(ratio));
|
|
62
76
|
});
|
|
63
77
|
|
|
64
78
|
it('renders with 1:1 square ratio', () => {
|
|
@@ -68,7 +82,7 @@ describe('AspectRatio', () => {
|
|
|
68
82
|
</AspectRatio>,
|
|
69
83
|
);
|
|
70
84
|
const element = screen.getByTestId('aspect-ratio');
|
|
71
|
-
expect(element
|
|
85
|
+
expect(ratioVar(element)).toBe(ratioValue(1));
|
|
72
86
|
});
|
|
73
87
|
|
|
74
88
|
it('renders with 21:9 ultrawide ratio', () => {
|
|
@@ -79,7 +93,7 @@ describe('AspectRatio', () => {
|
|
|
79
93
|
</AspectRatio>,
|
|
80
94
|
);
|
|
81
95
|
const element = screen.getByTestId('aspect-ratio');
|
|
82
|
-
expect(element
|
|
96
|
+
expect(ratioVar(element)).toBe(ratioValue(ratio));
|
|
83
97
|
});
|
|
84
98
|
|
|
85
99
|
it('renders an ellipse that respects the ratio (circle at 1:1)', () => {
|
|
@@ -89,7 +103,7 @@ describe('AspectRatio', () => {
|
|
|
89
103
|
</AspectRatio>,
|
|
90
104
|
);
|
|
91
105
|
const element = screen.getByTestId('aspect-ratio');
|
|
92
|
-
expect(element
|
|
106
|
+
expect(ratioVar(element)).toBe(ratioValue(1));
|
|
93
107
|
expect(element.className).toContain('ellipse');
|
|
94
108
|
});
|
|
95
109
|
|
|
@@ -101,7 +115,7 @@ describe('AspectRatio', () => {
|
|
|
101
115
|
);
|
|
102
116
|
const element = screen.getByTestId('aspect-ratio');
|
|
103
117
|
// Ratio is preserved — the ellipse does not force 1:1.
|
|
104
|
-
expect(element
|
|
118
|
+
expect(ratioVar(element)).toBe(ratioValue(16 / 9));
|
|
105
119
|
expect(element.className).toContain('ellipse');
|
|
106
120
|
});
|
|
107
121
|
|
|
@@ -112,7 +126,7 @@ describe('AspectRatio', () => {
|
|
|
112
126
|
</AspectRatio>,
|
|
113
127
|
);
|
|
114
128
|
const element = screen.getByTestId('aspect-ratio');
|
|
115
|
-
expect(element
|
|
129
|
+
expect(ratioVar(element)).toBe(ratioValue(1));
|
|
116
130
|
expect(element.className).toContain('rectangle');
|
|
117
131
|
// No ellipse border-radius when shape is the default rectangle
|
|
118
132
|
expect(element.style.borderRadius).toBe('');
|
|
@@ -177,6 +191,38 @@ describe('AspectRatio', () => {
|
|
|
177
191
|
expect(video).toBeInTheDocument();
|
|
178
192
|
});
|
|
179
193
|
|
|
194
|
+
describe('responsive ratio', () => {
|
|
195
|
+
it('emits the ratio as a class-level declaration, not an inline style', () => {
|
|
196
|
+
render(
|
|
197
|
+
<AspectRatio ratio={3 / 1} data-testid="aspect-ratio">
|
|
198
|
+
<div>Hero</div>
|
|
199
|
+
</AspectRatio>,
|
|
200
|
+
);
|
|
201
|
+
const element = screen.getByTestId('aspect-ratio');
|
|
202
|
+
// No inline aspect-ratio — the declaration lives in a class reading a
|
|
203
|
+
// CSS variable, so @media/@container rules (via xstyle, or via
|
|
204
|
+
// unlayered consumer CSS beating the astryx-base layer) can override
|
|
205
|
+
// it.
|
|
206
|
+
expect(element.style.aspectRatio).toBe('');
|
|
207
|
+
expect(ratioVar(element)).toBe(ratioValue(3 / 1));
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('lets a consumer inline style win over the class-level ratio', () => {
|
|
211
|
+
render(
|
|
212
|
+
<AspectRatio
|
|
213
|
+
ratio={3 / 1}
|
|
214
|
+
style={{aspectRatio: '3 / 2'}}
|
|
215
|
+
data-testid="aspect-ratio">
|
|
216
|
+
<div>Hero</div>
|
|
217
|
+
</AspectRatio>,
|
|
218
|
+
);
|
|
219
|
+
const element = screen.getByTestId('aspect-ratio');
|
|
220
|
+
// The consumer's style prop passes through untouched (it is no longer
|
|
221
|
+
// merged with a component-owned inline aspect-ratio).
|
|
222
|
+
expect(element.style.aspectRatio).toBe('3 / 2');
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
180
226
|
describe('fit', () => {
|
|
181
227
|
it('marks the child\'s direct parent with data-astryx-aspect-ratio-override for fit="cover"', () => {
|
|
182
228
|
render(
|
|
@@ -277,7 +323,7 @@ describe('AspectRatio', () => {
|
|
|
277
323
|
});
|
|
278
324
|
|
|
279
325
|
describe('style merging', () => {
|
|
280
|
-
it('keeps the consumer style and
|
|
326
|
+
it('keeps the consumer style and lets an inline ratio win', () => {
|
|
281
327
|
render(
|
|
282
328
|
<AspectRatio
|
|
283
329
|
ratio={16 / 9}
|
|
@@ -288,7 +334,8 @@ describe('AspectRatio', () => {
|
|
|
288
334
|
);
|
|
289
335
|
const element = screen.getByTestId('aspect-ratio');
|
|
290
336
|
expect(element.style.opacity).toBe('0.5');
|
|
291
|
-
expect(element.style.aspectRatio).toBe(
|
|
337
|
+
expect(element.style.aspectRatio).toBe('3 / 1');
|
|
338
|
+
expect(ratioVar(element)).toBe(ratioValue(16 / 9));
|
|
292
339
|
});
|
|
293
340
|
|
|
294
341
|
it('keeps a consumer className beside the theme target', () => {
|
|
@@ -43,6 +43,25 @@ export interface AspectRatioProps extends BaseProps<HTMLDivElement> {
|
|
|
43
43
|
ref?: React.Ref<HTMLDivElement>;
|
|
44
44
|
/**
|
|
45
45
|
* The aspect ratio as width/height (e.g., 16/9 = 1.777..., 4/3 = 1.333..., 1 for square).
|
|
46
|
+
*
|
|
47
|
+
* The ratio is emitted as a class-level declaration — never an inline
|
|
48
|
+
* style — so it can be made responsive:
|
|
49
|
+
* - StyleX consumers pass an `aspect-ratio` rule via `xstyle`, including
|
|
50
|
+
* under `@media`/`@container` conditions.
|
|
51
|
+
* - Plain-CSS/Tailwind consumers override `aspect-ratio` from their own
|
|
52
|
+
* (unlayered) rules: the compiled component styles live in the
|
|
53
|
+
* `astryx-base` cascade layer, and unlayered CSS wins over layered
|
|
54
|
+
* rules regardless of specificity.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```
|
|
58
|
+
* // 3:1 hero that becomes 3:2 when its container stacks
|
|
59
|
+
* <AspectRatio ratio={3 / 1} className="gallery-hero">…</AspectRatio>
|
|
60
|
+
*
|
|
61
|
+
* // CSS: @container gallery (max-width: 720px) {
|
|
62
|
+
* // .gallery-hero { aspect-ratio: 3 / 2; }
|
|
63
|
+
* // }
|
|
64
|
+
* ```
|
|
46
65
|
*/
|
|
47
66
|
ratio: number;
|
|
48
67
|
|
|
@@ -132,6 +151,20 @@ const styles = stylex.create({
|
|
|
132
151
|
},
|
|
133
152
|
});
|
|
134
153
|
|
|
154
|
+
// The ratio compiles to a CSS variable + a class-level declaration
|
|
155
|
+
// (aspect-ratio: var(--x)) instead of a raw inline style, so consumer
|
|
156
|
+
// overrides — `xstyle` rules, including ones inside @media/@container
|
|
157
|
+
// queries — can still win. A raw inline `aspect-ratio` would beat any class
|
|
158
|
+
// (same rationale as Grid's dynamic track values). Non-StyleX consumers
|
|
159
|
+
// don't need a dedicated hook: the compiled declaration sits in the
|
|
160
|
+
// `astryx-base` cascade layer, so any unlayered consumer rule wins
|
|
161
|
+
// regardless of specificity.
|
|
162
|
+
const dynamicStyles = stylex.create({
|
|
163
|
+
ratio: (ratio: number) => ({
|
|
164
|
+
aspectRatio: ratio,
|
|
165
|
+
}),
|
|
166
|
+
});
|
|
167
|
+
|
|
135
168
|
/**
|
|
136
169
|
* AspectRatio component for maintaining a specific aspect ratio for its children.
|
|
137
170
|
*
|
|
@@ -147,6 +180,11 @@ const styles = stylex.create({
|
|
|
147
180
|
* `ratio={1}` or an oval at other ratios. Both shapes respect the provided
|
|
148
181
|
* `ratio`.
|
|
149
182
|
*
|
|
183
|
+
* The ratio is a class-level declaration (not an inline style), so it can be
|
|
184
|
+
* overridden responsively — via `xstyle` for StyleX consumers, or with a
|
|
185
|
+
* plain unlayered `aspect-ratio` rule for plain-CSS consumers (component
|
|
186
|
+
* styles live in the `astryx-base` cascade layer, which unlayered CSS beats).
|
|
187
|
+
*
|
|
150
188
|
* Sizing: the box takes its width from its container and derives its height
|
|
151
189
|
* from the ratio, so it needs an ancestor with a definite width. Two
|
|
152
190
|
* consequences are worth knowing. Constraining only the height (`height` or
|
|
@@ -188,11 +226,12 @@ export function AspectRatio({
|
|
|
188
226
|
themeProps('aspect-ratio', {shape}),
|
|
189
227
|
stylex.props(
|
|
190
228
|
styles.container,
|
|
229
|
+
dynamicStyles.ratio(ratio),
|
|
191
230
|
shape === 'ellipse' && styles.ellipse,
|
|
192
231
|
xstyle,
|
|
193
232
|
),
|
|
194
233
|
className,
|
|
195
|
-
|
|
234
|
+
style,
|
|
196
235
|
)}
|
|
197
236
|
{...props}>
|
|
198
237
|
{/* The marker attribute carries the fit value so the reset.css child
|