@astryxdesign/core 0.4.7 → 0.5.0-canary.009bcb3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +161 -1
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +45 -20
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -2
- package/dist/AspectRatio/AspectRatio.d.ts +24 -0
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +23 -4
- package/dist/Avatar/Avatar.d.ts +25 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +58 -19
- package/dist/Avatar/index.d.ts +2 -2
- package/dist/Avatar/index.d.ts.map +1 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +8 -4
- package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
- package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
- package/dist/Banner/Banner.d.ts +49 -15
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +62 -20
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +17 -4
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +11 -6
- package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +26 -7
- package/dist/Calendar/Calendar.d.ts +7 -3
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +21 -23
- package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
- package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
- package/dist/Calendar/getInitialFocusDate.js +62 -0
- package/dist/Calendar/styles.d.ts +5 -14
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +15 -15
- package/dist/Card/Card.d.ts +12 -12
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +17 -9
- package/dist/Card/index.d.ts +35 -1
- package/dist/Card/index.d.ts.map +1 -1
- package/dist/Card/index.js +21 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +3 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +2 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +3 -3
- package/dist/Chat/ChatMessageList.d.ts +22 -3
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +6 -3
- package/dist/Chat/ChatTokenizedText.d.ts +2 -0
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +11 -6
- package/dist/Chat/useChatComposerTokens.js +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +10 -3
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +15 -4
- package/dist/CodeBlock/highlightRanges.js +1 -1
- package/dist/CodeBlock/highlightStyles.js +13 -13
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +3 -2
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +3 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +1 -3
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- package/dist/DateInput/DateInput.d.ts +43 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +22 -2
- package/dist/DateInput/NativeDateField.d.ts +10 -0
- package/dist/DateInput/NativeDateField.d.ts.map +1 -0
- package/dist/DateInput/NativeDateField.js +494 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +82 -23
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateInput/nativeDateSegments.d.ts +22 -0
- package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
- package/dist/DateInput/nativeDateSegments.js +111 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +406 -12
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.d.ts +21 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +110 -58
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -13
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -1
- package/dist/Field/InputClearButton.d.ts +9 -3
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +14 -3
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +3 -2
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +6 -3
- package/dist/HoverCard/HoverCard.d.ts +6 -0
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +104 -3
- package/dist/HoverCard/useHoverCard.d.ts +19 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +74 -26
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +6 -2
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +2 -19
- package/dist/Layer/LayerDepthContext.d.ts +52 -0
- package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
- package/dist/Layer/LayerDepthContext.js +66 -0
- package/dist/Layer/gestureCounter.d.ts +8 -0
- package/dist/Layer/gestureCounter.d.ts.map +1 -0
- package/dist/Layer/gestureCounter.js +53 -0
- package/dist/Layer/index.d.ts +3 -0
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +4 -0
- package/dist/Layer/layerStack.d.ts +98 -0
- package/dist/Layer/layerStack.d.ts.map +1 -0
- package/dist/Layer/layerStack.js +306 -0
- package/dist/Layer/useLayer.d.ts +23 -13
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +128 -8
- package/dist/Layer/useLayerDismissal.d.ts +93 -0
- package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
- package/dist/Layer/useLayerDismissal.js +91 -0
- package/dist/Lightbox/Lightbox.d.ts +1 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +103 -81
- package/dist/List/List.d.ts +1 -1
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +15 -4
- package/dist/Markdown/Markdown.d.ts +1 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +20 -7
- package/dist/Markdown/index.d.ts +1 -1
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/parser.d.ts +38 -1
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +182 -32
- package/dist/MetadataList/MetadataListItem.d.ts +1 -1
- package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
- package/dist/MetadataList/MetadataListItem.js +4 -1
- package/dist/MobileNav/MobileNav.d.ts +6 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +61 -36
- package/dist/MultiSelector/MultiSelector.d.ts +32 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +73 -15
- package/dist/MultiSelector/hooks.d.ts +7 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +3 -2
- package/dist/MultiSelector/index.d.ts +1 -1
- package/dist/MultiSelector/index.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.js +5 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +9 -5
- package/dist/NumberInput/NumberInput.d.ts +6 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +54 -104
- package/dist/NumberInput/numberInputCommit.d.ts +34 -0
- package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
- package/dist/NumberInput/numberInputCommit.js +71 -0
- package/dist/NumberInput/numberParser.d.ts +64 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -0
- package/dist/NumberInput/numberParser.js +350 -0
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +3 -2
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +3 -2
- package/dist/Overlay/Overlay.d.ts.map +1 -1
- package/dist/Overlay/Overlay.js +3 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +1 -9
- package/dist/Popover/usePopover.d.ts +7 -41
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +40 -21
- package/dist/PowerSearch/PowerSearch.d.ts +8 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +19 -6
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +110 -27
- package/dist/PowerSearch/types.d.ts +2 -0
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +14 -5
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +18 -5
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +3 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +12 -3
- package/dist/Selector/Selector.d.ts +18 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +91 -18
- package/dist/Selector/hooks.d.ts +7 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +3 -2
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -3
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +8 -7
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +4 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +37 -5
- package/dist/Spinner/Spinner.d.ts +3 -3
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +130 -78
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +6 -1
- package/dist/Stepper/Step.d.ts +140 -0
- package/dist/Stepper/Step.d.ts.map +1 -0
- package/dist/Stepper/Step.js +1045 -0
- package/dist/Stepper/StepStatus.d.ts +24 -0
- package/dist/Stepper/StepStatus.d.ts.map +1 -0
- package/dist/Stepper/StepStatus.js +1 -0
- package/dist/Stepper/Stepper.d.ts +93 -0
- package/dist/Stepper/Stepper.d.ts.map +1 -0
- package/dist/Stepper/Stepper.js +184 -0
- package/dist/Stepper/StepperContext.d.ts +41 -0
- package/dist/Stepper/StepperContext.d.ts.map +1 -0
- package/dist/Stepper/StepperContext.js +34 -0
- package/dist/Stepper/index.d.ts +8 -0
- package/dist/Stepper/index.d.ts.map +1 -0
- package/dist/Stepper/index.js +7 -0
- package/dist/Stepper/stepper.stylex.d.ts +15 -0
- package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
- package/dist/Stepper/stepper.stylex.js +20 -0
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +8 -3
- package/dist/TabList/Tab.d.ts +15 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +32 -7
- package/dist/TabList/TabList.d.ts +46 -7
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +353 -23
- package/dist/TabList/TabListContext.d.ts +11 -1
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +11 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +3 -2
- package/dist/TabList/index.d.ts +2 -2
- package/dist/TabList/index.d.ts.map +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +10 -2
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +3 -6
- package/dist/Table/TableRow.d.ts +16 -5
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +16 -5
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +54 -11
- package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +43 -5
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
- package/dist/Table/types.d.ts +22 -4
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -0
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +6 -3
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +16 -10
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +3 -2
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +15 -21
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +22 -7
- package/dist/Toast/ToastViewport.d.ts +1 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +71 -18
- package/dist/Token/Token.d.ts +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +20 -9
- package/dist/Token/TokenLink.d.ts +1 -1
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +7 -4
- package/dist/Tokenizer/Tokenizer.d.ts +14 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +33 -21
- package/dist/Tooltip/Tooltip.d.ts +5 -0
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +5 -0
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +39 -24
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +5 -4
- package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +31 -11
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +22 -7
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +7 -2
- package/dist/Typeahead/BaseTypeahead.d.ts +35 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +119 -37
- package/dist/Typeahead/Typeahead.d.ts +8 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +5 -2
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +7 -2
- package/dist/astryx.css +113 -11
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useFocusTrap.d.ts +7 -4
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +60 -95
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +3 -18
- package/dist/hooks/useMergedRefs.d.ts +18 -0
- package/dist/hooks/useMergedRefs.d.ts.map +1 -0
- package/dist/hooks/useMergedRefs.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +46 -10
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +24 -4
- package/dist/theme/generateThemeRules.d.ts +21 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +26 -0
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.js +5 -2
- package/dist/utils/groupItems.d.ts +5 -1
- package/dist/utils/groupItems.d.ts.map +1 -1
- package/dist/utils/groupItems.js +9 -9
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/isApplePlatform.d.ts +18 -0
- package/dist/utils/isApplePlatform.d.ts.map +1 -0
- package/dist/utils/isApplePlatform.js +37 -0
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +10 -1
- package/dist/utils/timeParser.d.ts +1 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +26 -12
- package/locales/af-ZA.json +6 -6
- package/locales/ar-SA.json +6 -6
- package/locales/ca-ES.json +5 -5
- package/locales/cs-CZ.json +6 -6
- package/locales/da-DK.json +6 -6
- package/locales/de-DE.json +6 -6
- package/locales/el-GR.json +6 -6
- package/locales/en.json +163 -11
- package/locales/es-ES.json +5 -5
- package/locales/fi-FI.json +6 -6
- package/locales/fr-FR.json +6 -6
- package/locales/he-IL.json +6 -6
- package/locales/hu-HU.json +6 -6
- package/locales/it-IT.json +6 -6
- package/locales/ja-JP.json +6 -6
- package/locales/ko-KR.json +6 -6
- package/locales/nl-NL.json +6 -6
- package/locales/no-NO.json +6 -6
- package/locales/pl-PL.json +6 -6
- package/locales/pseudo.json +114 -0
- package/locales/pt-BR.json +6 -6
- package/locales/pt-PT.json +6 -6
- package/locales/ro-RO.json +6 -6
- package/locales/ru-RU.json +6 -6
- package/locales/sr-SP.json +6 -6
- package/locales/sv-SE.json +6 -6
- package/locales/tr-TR.json +6 -6
- package/locales/uk-UA.json +6 -6
- package/locales/vi-VN.json +6 -6
- package/locales/zh-CN.json +6 -6
- package/locales/zh-TW.json +6 -6
- package/package.json +8 -3
- package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
- package/src/AlertDialog/AlertDialog.test.tsx +211 -2
- package/src/AlertDialog/AlertDialog.tsx +62 -20
- package/src/AppShell/AppShell.tsx +3 -2
- package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
- package/src/AspectRatio/AspectRatio.test.tsx +57 -10
- package/src/AspectRatio/AspectRatio.tsx +40 -1
- package/src/Avatar/Avatar.doc.mjs +14 -3
- package/src/Avatar/Avatar.test.tsx +97 -0
- package/src/Avatar/Avatar.tsx +125 -52
- package/src/Avatar/index.ts +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
- package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
- package/src/AvatarGroup/AvatarGroup.tsx +15 -6
- package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
- package/src/Banner/Banner.doc.mjs +22 -11
- package/src/Banner/Banner.test.tsx +177 -25
- package/src/Banner/Banner.tsx +93 -27
- package/src/BottomSheet/BottomSheet.test.tsx +123 -0
- package/src/BottomSheet/BottomSheet.tsx +17 -4
- package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
- package/src/Button/Button.doc.mjs +24 -1
- package/src/Button/Button.test.tsx +32 -4
- package/src/Button/Button.tsx +12 -5
- package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
- package/src/ButtonGroup/ButtonGroup.test.tsx +404 -1
- package/src/ButtonGroup/ButtonGroup.tsx +23 -5
- package/src/Calendar/Calendar.doc.mjs +7 -6
- package/src/Calendar/Calendar.test.tsx +143 -0
- package/src/Calendar/Calendar.tsx +30 -26
- package/src/Calendar/getInitialFocusDate.test.ts +94 -0
- package/src/Calendar/getInitialFocusDate.ts +93 -0
- package/src/Calendar/styles.ts +49 -31
- package/src/Card/Card.doc.mjs +10 -7
- package/src/Card/Card.test.tsx +113 -19
- package/src/Card/Card.tsx +67 -89
- package/src/Card/index.ts +36 -1
- package/src/Carousel/Carousel.tsx +3 -2
- package/src/Chat/ChatComposerInput.tsx +5 -1
- package/src/Chat/ChatLayout.tsx +3 -2
- package/src/Chat/ChatMessageList.doc.mjs +9 -1
- package/src/Chat/ChatMessageList.test.tsx +46 -0
- package/src/Chat/ChatMessageList.tsx +28 -4
- package/src/Chat/ChatTokenizedText.tsx +17 -10
- package/src/Chat/useChatComposerTokens.ts +1 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
- package/src/CheckboxInput/CheckboxInput.tsx +8 -2
- package/src/ClickableCard/ClickableCard.tsx +3 -2
- package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
- package/src/CodeBlock/CodeBlock.test.tsx +37 -0
- package/src/CodeBlock/CodeBlock.tsx +20 -4
- package/src/CodeBlock/highlightRanges.ts +1 -1
- package/src/CodeBlock/highlightStyles.ts +13 -13
- package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
- package/src/ComplexSelector/ComplexSelector.test.tsx +32 -0
- package/src/ComplexSelector/ComplexSelector.tsx +1 -3
- package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
- package/src/ContextMenu/ContextMenu.tsx +4 -3
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.tsx +55 -2
- package/src/DateInput/DateInputTouch.test.tsx +146 -32
- package/src/DateInput/NativeDateField.test.tsx +635 -0
- package/src/DateInput/NativeDateField.tsx +641 -0
- package/src/DateInput/TouchDateField.tsx +108 -24
- package/src/DateInput/index.ts +1 -0
- package/src/DateInput/nativeDateSegments.ts +127 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +2 -2
- package/src/DateRangeInput/DateRangeInput.test.tsx +22 -0
- package/src/DateRangeInput/DateRangeInput.tsx +4 -2
- package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
- package/src/DateTimeInput/DateTimeInput.tsx +556 -24
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/Dialog.doc.mjs +8 -3
- package/src/Dialog/Dialog.test.tsx +429 -2
- package/src/Dialog/Dialog.tsx +133 -58
- package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
- package/src/DropdownMenu/DropdownMenu.tsx +4 -13
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
- package/src/Field/Field.doc.mjs +13 -2
- package/src/Field/FieldLabel.test.tsx +29 -0
- package/src/Field/FieldLabel.tsx +7 -0
- package/src/Field/InputClearButton.test.tsx +15 -1
- package/src/Field/InputClearButton.tsx +28 -4
- package/src/FileInput/FileInput.tsx +3 -2
- package/src/Heading/Heading.test.tsx +23 -1
- package/src/Heading/Heading.tsx +6 -3
- package/src/HoverCard/HoverCard.doc.mjs +13 -2
- package/src/HoverCard/HoverCard.test.tsx +154 -4
- package/src/HoverCard/HoverCard.tsx +143 -3
- package/src/HoverCard/useHoverCard.tsx +104 -33
- package/src/Indicator/CheckboxIndicator.tsx +14 -8
- package/src/Indicator/Indicator.doc.mjs +2 -0
- package/src/Item/Item.tsx +5 -4
- package/src/Kbd/Kbd.tsx +2 -19
- package/src/Layer/LayerDepthContext.tsx +62 -0
- package/src/Layer/gestureCounter.ts +57 -0
- package/src/Layer/index.ts +9 -0
- package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
- package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
- package/src/Layer/layerStack.ts +362 -0
- package/src/Layer/useLayer.test.tsx +324 -15
- package/src/Layer/useLayer.tsx +164 -8
- package/src/Layer/useLayerDismissal.test.tsx +469 -0
- package/src/Layer/useLayerDismissal.ts +173 -0
- package/src/Layout/Layout.doc.mjs +2 -2
- package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
- package/src/Lightbox/Lightbox.doc.mjs +12 -0
- package/src/Lightbox/Lightbox.tsx +124 -102
- package/src/Link/Link.doc.mjs +39 -0
- package/src/List/List.test.tsx +38 -0
- package/src/List/List.tsx +8 -1
- package/src/Markdown/Markdown.doc.mjs +5 -0
- package/src/Markdown/Markdown.test.tsx +37 -0
- package/src/Markdown/Markdown.tsx +16 -5
- package/src/Markdown/incremental.test.ts +16 -2
- package/src/Markdown/index.ts +1 -0
- package/src/Markdown/parser.perf.test.ts +96 -1
- package/src/Markdown/parser.test.ts +178 -2
- package/src/Markdown/parser.ts +253 -32
- package/src/MetadataList/MetadataList.test.tsx +75 -2
- package/src/MetadataList/MetadataListItem.tsx +5 -2
- package/src/MobileNav/MobileNav.tsx +62 -36
- package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +49 -1
- package/src/MultiSelector/MultiSelector.test.tsx +311 -0
- package/src/MultiSelector/MultiSelector.tsx +151 -15
- package/src/MultiSelector/hooks.ts +9 -2
- package/src/MultiSelector/index.ts +1 -0
- package/src/NavIcon/NavIcon.doc.mjs +8 -2
- package/src/NavIcon/NavIcon.test.tsx +9 -0
- package/src/NavIcon/NavIcon.tsx +5 -1
- package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
- package/src/NavMenu/NavHeadingMenu.tsx +9 -5
- package/src/NumberInput/NumberInput.doc.mjs +31 -7
- package/src/NumberInput/NumberInput.test.tsx +436 -8
- package/src/NumberInput/NumberInput.tsx +62 -114
- package/src/NumberInput/numberInputCommit.test.ts +72 -0
- package/src/NumberInput/numberInputCommit.ts +103 -0
- package/src/NumberInput/numberParser.docblock.test.ts +234 -0
- package/src/NumberInput/numberParser.test.ts +222 -0
- package/src/NumberInput/numberParser.ts +403 -0
- package/src/Outline/Outline.tsx +3 -2
- package/src/OverflowList/OverflowList.tsx +3 -2
- package/src/Overlay/Overlay.tsx +3 -2
- package/src/Pagination/Pagination.test.tsx +3 -2
- package/src/Popover/Popover.test.tsx +14 -0
- package/src/Popover/Popover.tsx +1 -9
- package/src/Popover/usePopover.tsx +57 -32
- package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
- package/src/PowerSearch/PowerSearch.test.tsx +240 -1
- package/src/PowerSearch/PowerSearch.tsx +34 -5
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +288 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +111 -1
- package/src/PowerSearch/PowerSearchValueEditor.tsx +124 -10
- package/src/PowerSearch/types.ts +2 -0
- package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
- package/src/PowerSearch/usePowerSearchSource.ts +13 -3
- package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
- package/src/ProgressBar/ProgressBar.test.tsx +24 -0
- package/src/ProgressBar/ProgressBar.tsx +28 -8
- package/src/Resizable/ResizeHandle.tsx +3 -2
- package/src/SegmentedControl/SegmentedControl.tsx +3 -2
- package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
- package/src/SelectableCard/SelectableCard.tsx +19 -2
- package/src/Selector/Selector.doc.mjs +26 -1
- package/src/Selector/Selector.test.tsx +346 -1
- package/src/Selector/Selector.tsx +148 -21
- package/src/Selector/hooks.ts +17 -2
- package/src/SideNav/SideNav.doc.mjs +6 -6
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavHeading.tsx +12 -12
- package/src/SideNav/SideNavItem.tsx +4 -2
- package/src/Slider/Slider.test.tsx +106 -1
- package/src/Slider/Slider.tsx +55 -3
- package/src/Spinner/Spinner.test.tsx +147 -1
- package/src/Spinner/Spinner.tsx +120 -101
- package/src/StatusDot/StatusDot.doc.mjs +8 -2
- package/src/StatusDot/StatusDot.test.tsx +9 -0
- package/src/StatusDot/StatusDot.tsx +7 -1
- package/src/Stepper/Step.doc.mjs +98 -0
- package/src/Stepper/Step.tsx +1638 -0
- package/src/Stepper/StepStatus.ts +26 -0
- package/src/Stepper/Stepper.doc.mjs +370 -0
- package/src/Stepper/Stepper.test.tsx +1024 -0
- package/src/Stepper/Stepper.tsx +258 -0
- package/src/Stepper/StepperContext.ts +71 -0
- package/src/Stepper/index.ts +18 -0
- package/src/Stepper/stepper.stylex.ts +19 -0
- package/src/Switch/Switch.doc.mjs +2 -0
- package/src/Switch/Switch.test.tsx +10 -0
- package/src/Switch/Switch.tsx +6 -2
- package/src/TabList/Tab.doc.mjs +13 -1
- package/src/TabList/Tab.tsx +67 -7
- package/src/TabList/TabList.doc.mjs +22 -6
- package/src/TabList/TabList.test.tsx +559 -0
- package/src/TabList/TabList.tsx +490 -22
- package/src/TabList/TabListContext.ts +13 -2
- package/src/TabList/TabMenu.tsx +3 -2
- package/src/TabList/index.ts +6 -2
- package/src/Table/BaseTable.tsx +12 -4
- package/src/Table/Table.doc.mjs +9 -2
- package/src/Table/Table.test.tsx +132 -14
- package/src/Table/Table.tsx +3 -8
- package/src/Table/TableBody.doc.mjs +40 -0
- package/src/Table/TableFooter.doc.mjs +40 -0
- package/src/Table/TableHeader.doc.mjs +40 -0
- package/src/Table/TableRow.tsx +16 -5
- package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
- package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
- package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +67 -12
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
- package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
- package/src/Table/plugins/selection/useTableSelection.test.tsx +138 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +63 -7
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
- package/src/Table/types.ts +22 -4
- package/src/Table/useBaseTablePlugins.ts +5 -0
- package/src/Table/useTableGroupedRows.doc.mjs +5 -4
- package/src/Table/useTablePagination.doc.mjs +7 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +31 -0
- package/src/Text/Text.test.tsx +67 -1
- package/src/Text/Text.tsx +6 -3
- package/src/TextArea/TextArea.doc.mjs +12 -2
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +37 -24
- package/src/TextInput/TextInput.doc.mjs +10 -0
- package/src/TextInput/TextInput.tsx +3 -2
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.tsx +2 -2
- package/src/Timestamp/Timestamp.test.tsx +58 -0
- package/src/Timestamp/Timestamp.tsx +12 -10
- package/src/Toast/Toast.doc.mjs +26 -12
- package/src/Toast/Toast.tsx +28 -4
- package/src/Toast/ToastViewport.test.tsx +536 -8
- package/src/Toast/ToastViewport.tsx +81 -12
- package/src/Token/Token.test.tsx +95 -0
- package/src/Token/Token.tsx +15 -10
- package/src/Token/TokenLink.tsx +14 -5
- package/src/Tokenizer/Tokenizer.doc.mjs +43 -3
- package/src/Tokenizer/Tokenizer.test.tsx +161 -0
- package/src/Tokenizer/Tokenizer.tsx +53 -24
- package/src/Toolbar/Toolbar.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.test.tsx +32 -0
- package/src/Tooltip/Tooltip.tsx +5 -0
- package/src/Tooltip/useTooltip.tsx +47 -24
- package/src/TopNav/TopNavHeading.tsx +5 -4
- package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
- package/src/TopNav/TopNavMegaMenu.tsx +47 -5
- package/src/TopNav/TopNavMenu.test.tsx +133 -1
- package/src/TopNav/TopNavMenu.tsx +38 -7
- package/src/TreeList/TreeList.test.tsx +49 -0
- package/src/TreeList/TreeList.tsx +7 -2
- package/src/Typeahead/BaseTypeahead.doc.mjs +24 -0
- package/src/Typeahead/BaseTypeahead.tsx +181 -39
- package/src/Typeahead/Typeahead.doc.mjs +11 -0
- package/src/Typeahead/Typeahead.test.tsx +203 -0
- package/src/Typeahead/Typeahead.tsx +12 -2
- package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
- package/src/Typeahead/TypeaheadItem.tsx +8 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useAnnounce.doc.mjs +96 -0
- package/src/hooks/useContainerReveal.doc.mjs +2 -2
- package/src/hooks/useDevWarning.doc.mjs +96 -0
- package/src/hooks/useFocusTrap.test.tsx +14 -0
- package/src/hooks/useFocusTrap.ts +62 -111
- package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
- package/src/hooks/useHotkeys.ts +3 -18
- package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
- package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
- package/src/hooks/useInteractiveRole.doc.mjs +119 -0
- package/src/hooks/useLongPress.doc.mjs +123 -0
- package/src/hooks/useMergedRefs.doc.mjs +79 -0
- package/src/hooks/useMergedRefs.test.tsx +62 -0
- package/src/hooks/useMergedRefs.ts +36 -0
- package/src/hooks/useTypeahead.doc.mjs +153 -0
- package/src/index.ts +1 -0
- package/src/raw-import.d.ts +14 -0
- package/src/theme/MediaTheme.doc.mjs +5 -5
- package/src/theme/Theme.test.tsx +104 -2
- package/src/theme/Theme.tsx +49 -14
- package/src/theme/defineTheme.test.ts +23 -0
- package/src/theme/derivedVarRegistry.test.ts +26 -3
- package/src/theme/derivedVarRegistry.ts +23 -4
- package/src/theme/generateThemeRules.test.ts +99 -1
- package/src/theme/generateThemeRules.ts +28 -0
- package/src/theme/syntax/tokens.ts +5 -2
- package/src/utils/groupItems.ts +12 -6
- package/src/utils/index.ts +1 -1
- package/src/utils/isApplePlatform.test.ts +61 -0
- package/src/utils/isApplePlatform.ts +37 -0
- package/src/utils/sharedResizeObserver.ts +10 -2
- package/src/utils/timeParser.test.ts +6 -1
- package/src/utils/timeParser.ts +35 -13
- package/src/__tests__/inputWidthContract.test.tsx +0 -69
|
@@ -21,10 +21,12 @@ import {
|
|
|
21
21
|
useId,
|
|
22
22
|
useState,
|
|
23
23
|
useCallback,
|
|
24
|
+
useEffect,
|
|
24
25
|
useRef,
|
|
25
26
|
useMemo,
|
|
26
27
|
useOptimistic,
|
|
27
28
|
useTransition,
|
|
29
|
+
type FocusEvent,
|
|
28
30
|
type KeyboardEvent,
|
|
29
31
|
} from 'react';
|
|
30
32
|
import * as stylex from '@stylexjs/stylex';
|
|
@@ -35,6 +37,7 @@ import {
|
|
|
35
37
|
spacingVars,
|
|
36
38
|
typographyVars,
|
|
37
39
|
typeScaleVars,
|
|
40
|
+
fontWeightVars,
|
|
38
41
|
borderVars,
|
|
39
42
|
} from '../theme/tokens.stylex';
|
|
40
43
|
import {
|
|
@@ -64,6 +67,7 @@ import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
|
|
|
64
67
|
import {
|
|
65
68
|
type ISOTimeString,
|
|
66
69
|
parseDateInput,
|
|
70
|
+
parseISOTime,
|
|
67
71
|
parseTimeInput,
|
|
68
72
|
formatDisplayTime12h,
|
|
69
73
|
formatDisplayTime24h,
|
|
@@ -72,7 +76,6 @@ import {
|
|
|
72
76
|
adjustTime,
|
|
73
77
|
isImeKeyEvent,
|
|
74
78
|
mergeProps,
|
|
75
|
-
mergeRefs,
|
|
76
79
|
isFocusDetached,
|
|
77
80
|
} from '../utils';
|
|
78
81
|
import {
|
|
@@ -91,6 +94,7 @@ import {themeProps} from '../utils/themeProps';
|
|
|
91
94
|
import {focusOutlineStyles} from '../utils/focusOutline.stylex';
|
|
92
95
|
import {useTranslator, InternationalizationContext} from '../i18n';
|
|
93
96
|
|
|
97
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
94
98
|
export type ISODateTimeString = string & {
|
|
95
99
|
readonly __brand: 'ISODateTimeString';
|
|
96
100
|
};
|
|
@@ -102,6 +106,12 @@ export type DateTimeInputSize = 'sm' | 'md' | 'lg';
|
|
|
102
106
|
/** Supported minute increments for arrow-key stepping of the time field. */
|
|
103
107
|
export type DateTimeInputTimeIncrement = 1 | 5 | 10 | 15 | 30;
|
|
104
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Supported minute cadences for the preset-time dropdown. Every value divides
|
|
111
|
+
* an hour evenly, so each option lands on a round clock time.
|
|
112
|
+
*/
|
|
113
|
+
export type DateTimeInputTimeOptionInterval = 5 | 10 | 15 | 30 | 60;
|
|
114
|
+
|
|
105
115
|
export type {
|
|
106
116
|
InputStatus as DateTimeInputStatus,
|
|
107
117
|
InputStatusType as DateTimeInputStatusType,
|
|
@@ -170,6 +180,57 @@ const styles = stylex.create({
|
|
|
170
180
|
flex: 1,
|
|
171
181
|
flexBasis: 0,
|
|
172
182
|
},
|
|
183
|
+
// Preset-time list. Paddings and states mirror BaseTypeahead's dropdown and
|
|
184
|
+
// Selector's options so every list in the system reads the same.
|
|
185
|
+
timeListbox: {
|
|
186
|
+
boxSizing: 'border-box',
|
|
187
|
+
maxHeight: 300,
|
|
188
|
+
overflowY: 'auto',
|
|
189
|
+
padding: spacingVars['--spacing-1'],
|
|
190
|
+
minWidth: 'anchor-size(width)',
|
|
191
|
+
},
|
|
192
|
+
timeOption: {
|
|
193
|
+
boxSizing: 'border-box',
|
|
194
|
+
display: 'flex',
|
|
195
|
+
alignItems: 'center',
|
|
196
|
+
width: '100%',
|
|
197
|
+
paddingBlock: spacingVars['--spacing-1-5'],
|
|
198
|
+
paddingInline: spacingVars['--spacing-2'],
|
|
199
|
+
borderRadius: radiusVars['--radius-element'],
|
|
200
|
+
cursor: {
|
|
201
|
+
default: 'pointer',
|
|
202
|
+
':is(:disabled,[aria-disabled="true"])': 'default',
|
|
203
|
+
},
|
|
204
|
+
textAlign: 'start',
|
|
205
|
+
fontFamily: typographyVars['--font-family-body'],
|
|
206
|
+
fontSize: typeScaleVars['--text-body-size'],
|
|
207
|
+
lineHeight: typeScaleVars['--text-body-leading'],
|
|
208
|
+
color: colorVars['--color-text-primary'],
|
|
209
|
+
backgroundColor: 'transparent',
|
|
210
|
+
},
|
|
211
|
+
timeOptionHighlighted: {
|
|
212
|
+
backgroundColor: colorVars['--color-overlay-hover'],
|
|
213
|
+
},
|
|
214
|
+
timeOptionSelected: {
|
|
215
|
+
fontWeight: fontWeightVars['--font-weight-medium'],
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Size-specific padding for the preset-time options, so an `sm` field gets a
|
|
221
|
+
* compact list. Matches DropdownMenuItem / Selector / BaseTypeahead.
|
|
222
|
+
*/
|
|
223
|
+
const timeOptionSizeStyles = stylex.create({
|
|
224
|
+
sm: {
|
|
225
|
+
paddingBlock: spacingVars['--spacing-1'],
|
|
226
|
+
paddingInline: spacingVars['--spacing-2'],
|
|
227
|
+
},
|
|
228
|
+
md: {
|
|
229
|
+
paddingBlock: spacingVars['--spacing-1-5'],
|
|
230
|
+
},
|
|
231
|
+
lg: {
|
|
232
|
+
paddingBlock: spacingVars['--spacing-2'],
|
|
233
|
+
},
|
|
173
234
|
});
|
|
174
235
|
|
|
175
236
|
const sizeStyles = stylex.create({
|
|
@@ -307,6 +368,22 @@ export interface DateTimeInputProps extends Omit<
|
|
|
307
368
|
*/
|
|
308
369
|
timeIncrement?: DateTimeInputTimeIncrement;
|
|
309
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Minute cadence for a dropdown of preset times on the time field. Set it to
|
|
373
|
+
* turn the time field into a combobox listing every valid time at that
|
|
374
|
+
* cadence (`60` gives the 12 AM - 11 PM list, `15` a quarter-hour list).
|
|
375
|
+
*
|
|
376
|
+
* Omitted, the time field stays a plain text input: typed entry and
|
|
377
|
+
* arrow-key stepping only, with no combobox semantics added to the
|
|
378
|
+
* accessibility tree. Typed entry keeps working when the dropdown is on —
|
|
379
|
+
* the list is a shortcut, not a restriction, so a time between two options
|
|
380
|
+
* can still be typed.
|
|
381
|
+
*
|
|
382
|
+
* Independent of `timeIncrement`, which governs arrow-key stepping. Setting
|
|
383
|
+
* both to the same value is the usual choice for scheduling flows.
|
|
384
|
+
*/
|
|
385
|
+
timeOptionInterval?: DateTimeInputTimeOptionInterval;
|
|
386
|
+
|
|
310
387
|
/**
|
|
311
388
|
* Whether to show a clear button when a value is set.
|
|
312
389
|
* @default false
|
|
@@ -396,6 +473,8 @@ function combineDateTime(
|
|
|
396
473
|
return `${date}T${time}` as ISODateTimeString;
|
|
397
474
|
}
|
|
398
475
|
|
|
476
|
+
const MINUTES_PER_DAY = 24 * 60;
|
|
477
|
+
|
|
399
478
|
function getDefaultTime(hasSeconds: boolean): ISOTimeString {
|
|
400
479
|
const now = new Date();
|
|
401
480
|
return formatISOTime(
|
|
@@ -436,6 +515,7 @@ export function DateTimeInput({
|
|
|
436
515
|
hasSeconds = false,
|
|
437
516
|
hourFormat = '12h',
|
|
438
517
|
timeIncrement = 1,
|
|
518
|
+
timeOptionInterval,
|
|
439
519
|
hasClear = false,
|
|
440
520
|
placeholder: placeholderFromProps,
|
|
441
521
|
timePlaceholder: timePlaceholderFromProps,
|
|
@@ -613,6 +693,46 @@ export function DateTimeInput({
|
|
|
613
693
|
return timePlaceholder;
|
|
614
694
|
}, [isTimeFocused, timeDisplayValue, hourFormat, timePlaceholder, t]);
|
|
615
695
|
|
|
696
|
+
// The time field's own accessible name. The option list is named from this
|
|
697
|
+
// rather than from `label`, so a consumer-supplied timeLabel renames both
|
|
698
|
+
// together instead of leaving the list announcing the old name.
|
|
699
|
+
const resolvedTimeLabel =
|
|
700
|
+
timeLabel ?? t('@astryx.dateTimeInput.timeSuffix', {label});
|
|
701
|
+
|
|
702
|
+
// --- Preset time options (#2727) ---
|
|
703
|
+
// Opt-in: without timeOptionInterval the time field keeps exactly the
|
|
704
|
+
// semantics it shipped with — a plain text input, no combobox role, no
|
|
705
|
+
// second listbox in the accessibility tree.
|
|
706
|
+
const hasTimeOptions = timeOptionInterval !== undefined;
|
|
707
|
+
|
|
708
|
+
const timeOptions = useMemo(() => {
|
|
709
|
+
if (timeOptionInterval === undefined) {
|
|
710
|
+
return [];
|
|
711
|
+
}
|
|
712
|
+
const options: {time: ISOTimeString; label: string}[] = [];
|
|
713
|
+
for (
|
|
714
|
+
let minutes = 0;
|
|
715
|
+
minutes < MINUTES_PER_DAY;
|
|
716
|
+
minutes += timeOptionInterval
|
|
717
|
+
) {
|
|
718
|
+
const time = formatISOTime(
|
|
719
|
+
{
|
|
720
|
+
hour: Math.floor(minutes / 60),
|
|
721
|
+
minute: minutes % 60,
|
|
722
|
+
second: 0,
|
|
723
|
+
},
|
|
724
|
+
hasSeconds,
|
|
725
|
+
);
|
|
726
|
+
// The same bound the typed path enforces, so the list can never offer a
|
|
727
|
+
// time that typing the identical string would reject.
|
|
728
|
+
if (!isTimeInRange(time, timeMin, timeMax)) {
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
options.push({time, label: formatDisplayTime(time, hasSeconds)});
|
|
732
|
+
}
|
|
733
|
+
return options;
|
|
734
|
+
}, [timeOptionInterval, hasSeconds, timeMin, timeMax, formatDisplayTime]);
|
|
735
|
+
|
|
616
736
|
// --- Unified change handler ---
|
|
617
737
|
const fireChange = useCallback(
|
|
618
738
|
(newValue: ISODateTimeString | undefined) => {
|
|
@@ -789,6 +909,222 @@ export function DateTimeInput({
|
|
|
789
909
|
[popover, commitDatePendingInput, isEffectivelyDisabled],
|
|
790
910
|
);
|
|
791
911
|
|
|
912
|
+
// --- Time-option popover (#2727) ---
|
|
913
|
+
const timeListboxId = useId();
|
|
914
|
+
const [highlightedTimeIndex, setHighlightedTimeIndex] = useState(-1);
|
|
915
|
+
|
|
916
|
+
// With popover="auto", showing the popover between pointerdown and
|
|
917
|
+
// pointerup/click lets the browser's light-dismiss treat that same click as
|
|
918
|
+
// "outside" and close it again. Defer the show past the click, as
|
|
919
|
+
// BaseTypeahead does for the same reason.
|
|
920
|
+
const timePointerActiveRef = useRef(false);
|
|
921
|
+
|
|
922
|
+
// Whether the highlight is still the one typing derived, or the user has
|
|
923
|
+
// since moved it themselves. Enter honours typed text only in the former
|
|
924
|
+
// case — otherwise the field would commit something other than the option
|
|
925
|
+
// it is showing as active.
|
|
926
|
+
const timeHighlightFollowsTypingRef = useRef(true);
|
|
927
|
+
|
|
928
|
+
const markTimePointerActive = useCallback(() => {
|
|
929
|
+
timePointerActiveRef.current = true;
|
|
930
|
+
document.addEventListener(
|
|
931
|
+
'click',
|
|
932
|
+
() => {
|
|
933
|
+
timePointerActiveRef.current = false;
|
|
934
|
+
},
|
|
935
|
+
{once: true},
|
|
936
|
+
);
|
|
937
|
+
}, []);
|
|
938
|
+
|
|
939
|
+
const timePopover = usePopover({
|
|
940
|
+
hasLightDismiss: true,
|
|
941
|
+
hasCloseButton: false,
|
|
942
|
+
hasAutoFocus: false,
|
|
943
|
+
// The popup's own role="listbox" carries the semantics; the input keeps
|
|
944
|
+
// DOM focus, so announcing a dialog here would misrepresent it.
|
|
945
|
+
role: 'none',
|
|
946
|
+
onHide: () => setHighlightedTimeIndex(-1),
|
|
947
|
+
});
|
|
948
|
+
|
|
949
|
+
// Anchor the list to the time wrapper, not the date input the field's own
|
|
950
|
+
// trigger ref points at.
|
|
951
|
+
useEffect(() => {
|
|
952
|
+
if (!hasTimeOptions) {
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
const el = timeContainerRef.current;
|
|
956
|
+
if (el) {
|
|
957
|
+
timePopover.triggerRef(el);
|
|
958
|
+
}
|
|
959
|
+
return () => {
|
|
960
|
+
timePopover.triggerRef(null);
|
|
961
|
+
};
|
|
962
|
+
}, [timePopover, hasTimeOptions]);
|
|
963
|
+
|
|
964
|
+
const timeOptionId = useCallback(
|
|
965
|
+
(index: number) => `${timeListboxId}-option-${index}`,
|
|
966
|
+
[timeListboxId],
|
|
967
|
+
);
|
|
968
|
+
|
|
969
|
+
// A field can go disabled or busy while its list is open — a changeAction
|
|
970
|
+
// starting elsewhere in the form is enough. Leave it up and the dropdown
|
|
971
|
+
// hangs over a control that no longer accepts input.
|
|
972
|
+
// The same applies to a list that empties after it opened, which a narrowing
|
|
973
|
+
// min/max window does. An open-but-empty list gates the keyboard switch off,
|
|
974
|
+
// so the arrows quietly fall back to stepping the value instead.
|
|
975
|
+
useEffect(() => {
|
|
976
|
+
if (
|
|
977
|
+
timePopover.isOpen &&
|
|
978
|
+
(isEffectivelyDisabled || timeOptions.length === 0)
|
|
979
|
+
) {
|
|
980
|
+
timePopover.hide();
|
|
981
|
+
}
|
|
982
|
+
}, [isEffectivelyDisabled, timeOptions.length, timePopover]);
|
|
983
|
+
|
|
984
|
+
// The option list can shrink under an open popover — min/max tighten when
|
|
985
|
+
// the date moves onto a boundary day, or the cadence prop changes. A stale
|
|
986
|
+
// index past the new end shows no highlight at all and makes the arrow keys
|
|
987
|
+
// look dead until the user walks it back into range.
|
|
988
|
+
// Clamped as it is read rather than synced through an effect: no extra
|
|
989
|
+
// render, and the index can never point past the end even for the paint
|
|
990
|
+
// where the list shrank.
|
|
991
|
+
const activeTimeIndex =
|
|
992
|
+
highlightedTimeIndex > timeOptions.length - 1
|
|
993
|
+
? timeOptions.length - 1
|
|
994
|
+
: highlightedTimeIndex;
|
|
995
|
+
|
|
996
|
+
// Keep the active option visible. The listbox is a fixed-height scroll
|
|
997
|
+
// container, so without this a list opens at midnight with the highlight far
|
|
998
|
+
// below the fold, and keyboard navigation walks off-screen. Mirrors
|
|
999
|
+
// BaseTypeahead's scrollIntoView({block: 'nearest'}).
|
|
1000
|
+
useEffect(() => {
|
|
1001
|
+
if (
|
|
1002
|
+
!timePopover.isOpen ||
|
|
1003
|
+
activeTimeIndex < 0 ||
|
|
1004
|
+
activeTimeIndex >= timeOptions.length
|
|
1005
|
+
) {
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
document
|
|
1009
|
+
.getElementById(timeOptionId(activeTimeIndex))
|
|
1010
|
+
?.scrollIntoView?.({block: 'nearest'});
|
|
1011
|
+
}, [timePopover.isOpen, activeTimeIndex, timeOptionId, timeOptions.length]);
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* The selected time in the same shape the options carry. splitDateTime slices
|
|
1015
|
+
* whatever follows the `T`, so a caller passing `14:00:00` with hasSeconds
|
|
1016
|
+
* off leaves `"14:00:00"` against options of `"14:00"` — comparing raw would
|
|
1017
|
+
* mark nothing selected, silently.
|
|
1018
|
+
*/
|
|
1019
|
+
const selectedOptionTime = useMemo(() => {
|
|
1020
|
+
if (!valueParts.time) {
|
|
1021
|
+
return undefined;
|
|
1022
|
+
}
|
|
1023
|
+
const parsed = parseISOTime(valueParts.time);
|
|
1024
|
+
return parsed ? formatISOTime(parsed, hasSeconds) : undefined;
|
|
1025
|
+
}, [valueParts.time, hasSeconds]);
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Index of the option at or immediately before `time`, so opening on a value
|
|
1029
|
+
* that is not itself an option (13:07 in a 15-minute list) still lands the
|
|
1030
|
+
* highlight somewhere sensible instead of nowhere.
|
|
1031
|
+
*/
|
|
1032
|
+
const closestOptionIndex = useCallback(
|
|
1033
|
+
(time: ISOTimeString | undefined) => {
|
|
1034
|
+
if (timeOptions.length === 0) {
|
|
1035
|
+
return -1;
|
|
1036
|
+
}
|
|
1037
|
+
// No time yet — the state a field lands in once a date is picked. The
|
|
1038
|
+
// list still opens on the first option, per the APG listbox pattern;
|
|
1039
|
+
// leaving it inactive made ArrowUp and Enter do nothing at all.
|
|
1040
|
+
if (!time) {
|
|
1041
|
+
return 0;
|
|
1042
|
+
}
|
|
1043
|
+
let candidate = -1;
|
|
1044
|
+
for (let i = 0; i < timeOptions.length; i++) {
|
|
1045
|
+
if (timeOptions[i].time <= time) {
|
|
1046
|
+
candidate = i;
|
|
1047
|
+
} else {
|
|
1048
|
+
break;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
// A value below every option (min pushes the list past it) still gets the
|
|
1052
|
+
// first option rather than an empty highlight.
|
|
1053
|
+
return candidate === -1 ? 0 : candidate;
|
|
1054
|
+
},
|
|
1055
|
+
[timeOptions],
|
|
1056
|
+
);
|
|
1057
|
+
|
|
1058
|
+
const showTimeOptions = useCallback(() => {
|
|
1059
|
+
if (
|
|
1060
|
+
!hasTimeOptions ||
|
|
1061
|
+
isEffectivelyDisabled ||
|
|
1062
|
+
timePopover.isOpen ||
|
|
1063
|
+
// A min/max window narrower than the cadence survives no option at all.
|
|
1064
|
+
// Opening on that would show an empty panel with nothing to pick.
|
|
1065
|
+
timeOptions.length === 0
|
|
1066
|
+
) {
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
setHighlightedTimeIndex(closestOptionIndex(selectedOptionTime));
|
|
1070
|
+
// useInputContainer routes wrapper clicks through input.click() once the
|
|
1071
|
+
// input advertises a popup, and a programmatic click does not focus. The
|
|
1072
|
+
// input must hold DOM focus or aria-activedescendant announces nothing.
|
|
1073
|
+
timeInputRef.current?.focus();
|
|
1074
|
+
if (timePointerActiveRef.current) {
|
|
1075
|
+
document.addEventListener(
|
|
1076
|
+
'click',
|
|
1077
|
+
() =>
|
|
1078
|
+
requestAnimationFrame(() => timePopover.show({skipAutoFocus: true})),
|
|
1079
|
+
{once: true},
|
|
1080
|
+
);
|
|
1081
|
+
} else {
|
|
1082
|
+
timePopover.show({skipAutoFocus: true});
|
|
1083
|
+
}
|
|
1084
|
+
}, [
|
|
1085
|
+
hasTimeOptions,
|
|
1086
|
+
isEffectivelyDisabled,
|
|
1087
|
+
timePopover,
|
|
1088
|
+
timeOptions.length,
|
|
1089
|
+
closestOptionIndex,
|
|
1090
|
+
selectedOptionTime,
|
|
1091
|
+
]);
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
* The single commit path for a time chosen from the list. Deliberately the
|
|
1095
|
+
* same shape as the typed path: same range check, same date requirement, so
|
|
1096
|
+
* picking 9:00 AM and typing "9:00 AM" are indistinguishable downstream.
|
|
1097
|
+
*/
|
|
1098
|
+
const commitTimeOption = useCallback(
|
|
1099
|
+
(time: ISOTimeString) => {
|
|
1100
|
+
if (isEffectivelyDisabled || !isTimeInRange(time, timeMin, timeMax)) {
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
setTimePendingInput(null);
|
|
1104
|
+
// Compared against the normalised time, the same one the selected marker
|
|
1105
|
+
// uses. Comparing the raw value instead made clicking the option that
|
|
1106
|
+
// renders as selected emit a change, whenever the value carried seconds
|
|
1107
|
+
// the field does not display.
|
|
1108
|
+
if (time !== selectedOptionTime && valueParts.date) {
|
|
1109
|
+
const combined = combineDateTime(valueParts.date, time);
|
|
1110
|
+
if (combined) {
|
|
1111
|
+
fireChange(combined);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
timePopover.hide();
|
|
1115
|
+
timeInputRef.current?.focus();
|
|
1116
|
+
},
|
|
1117
|
+
[
|
|
1118
|
+
isEffectivelyDisabled,
|
|
1119
|
+
timeMin,
|
|
1120
|
+
timeMax,
|
|
1121
|
+
selectedOptionTime,
|
|
1122
|
+
valueParts.date,
|
|
1123
|
+
fireChange,
|
|
1124
|
+
timePopover,
|
|
1125
|
+
],
|
|
1126
|
+
);
|
|
1127
|
+
|
|
792
1128
|
// --- Time handlers ---
|
|
793
1129
|
const handleTimeInputChange = useCallback(
|
|
794
1130
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -801,6 +1137,15 @@ export function DateTimeInput({
|
|
|
801
1137
|
setTimePendingInput(text);
|
|
802
1138
|
|
|
803
1139
|
const parsed = parseTimeInput(text, hasSeconds);
|
|
1140
|
+
|
|
1141
|
+
// Typing narrows nothing — free-form entry is the contract, and a time
|
|
1142
|
+
// between two options must stay reachable. The list instead follows the
|
|
1143
|
+
// typed value so Enter lands somewhere the user expects.
|
|
1144
|
+
if (timePopover.isOpen && parsed) {
|
|
1145
|
+
timeHighlightFollowsTypingRef.current = true;
|
|
1146
|
+
setHighlightedTimeIndex(closestOptionIndex(parsed));
|
|
1147
|
+
}
|
|
1148
|
+
|
|
804
1149
|
if (
|
|
805
1150
|
parsed &&
|
|
806
1151
|
isTimeInRange(parsed, timeMin, timeMax) &&
|
|
@@ -822,6 +1167,8 @@ export function DateTimeInput({
|
|
|
822
1167
|
valueParts.date,
|
|
823
1168
|
fireChange,
|
|
824
1169
|
isEffectivelyDisabled,
|
|
1170
|
+
timePopover.isOpen,
|
|
1171
|
+
closestOptionIndex,
|
|
825
1172
|
],
|
|
826
1173
|
);
|
|
827
1174
|
|
|
@@ -835,29 +1182,59 @@ export function DateTimeInput({
|
|
|
835
1182
|
setIsTimeFocused(true);
|
|
836
1183
|
}, [isEffectivelyDisabled]);
|
|
837
1184
|
|
|
838
|
-
const handleTimeBlur = useCallback(
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1185
|
+
const handleTimeBlur = useCallback(
|
|
1186
|
+
(e: FocusEvent<HTMLInputElement>) => {
|
|
1187
|
+
setIsTimeFocused(false);
|
|
1188
|
+
|
|
1189
|
+
// Native light dismiss only fires on outside clicks and Escape, so a focus
|
|
1190
|
+
// move that is neither — Tab handled elsewhere, or a programmatic focus —
|
|
1191
|
+
// would strand the listbox open in the top layer. Focus landing inside the
|
|
1192
|
+
// field or the popup itself is not a leave. Mirrors BaseTypeahead.
|
|
1193
|
+
if (timePopover.isOpen) {
|
|
1194
|
+
const next = e.relatedTarget as Node | null;
|
|
1195
|
+
const popoverEl = next ? document.getElementById(timePopover.id) : null;
|
|
1196
|
+
if (
|
|
1197
|
+
!next ||
|
|
1198
|
+
!(
|
|
1199
|
+
timeContainerRef.current?.contains(next) ||
|
|
1200
|
+
popoverEl?.contains(next)
|
|
1201
|
+
)
|
|
1202
|
+
) {
|
|
1203
|
+
timePopover.hide();
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
843
1206
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
1207
|
+
if (timePendingInput === null) {
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
849
1210
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1211
|
+
if (!timePendingInput.trim()) {
|
|
1212
|
+
// Empty time: revert display to previous value (don't emit partial datetime)
|
|
1213
|
+
setTimePendingInput(null);
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
const parsed = parseTimeInput(timePendingInput, hasSeconds);
|
|
1218
|
+
if (parsed && isTimeInRange(parsed, timeMin, timeMax)) {
|
|
1219
|
+
if (parsed !== valueParts.time && valueParts.date) {
|
|
1220
|
+
const combined = combineDateTime(valueParts.date, parsed);
|
|
1221
|
+
if (combined) {
|
|
1222
|
+
fireChange(combined);
|
|
1223
|
+
}
|
|
856
1224
|
}
|
|
857
1225
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1226
|
+
setTimePendingInput(null);
|
|
1227
|
+
},
|
|
1228
|
+
[
|
|
1229
|
+
timePendingInput,
|
|
1230
|
+
hasSeconds,
|
|
1231
|
+
timeMin,
|
|
1232
|
+
timeMax,
|
|
1233
|
+
valueParts,
|
|
1234
|
+
fireChange,
|
|
1235
|
+
timePopover,
|
|
1236
|
+
],
|
|
1237
|
+
);
|
|
861
1238
|
|
|
862
1239
|
const handleTimeKeyDown = useCallback(
|
|
863
1240
|
(e: KeyboardEvent<HTMLInputElement>) => {
|
|
@@ -868,6 +1245,84 @@ export function DateTimeInput({
|
|
|
868
1245
|
if (isImeKeyEvent(e.nativeEvent)) {
|
|
869
1246
|
return;
|
|
870
1247
|
}
|
|
1248
|
+
|
|
1249
|
+
// The dropdown claims the arrow keys only while it is open. Closed, they
|
|
1250
|
+
// keep stepping the value by timeIncrement exactly as they always have —
|
|
1251
|
+
// that behaviour is documented and tested, so the list borrows Alt+Arrow
|
|
1252
|
+
// Down (the APG "open without moving" binding) to open instead.
|
|
1253
|
+
if (hasTimeOptions && !isEffectivelyDisabled) {
|
|
1254
|
+
if (e.key === 'Escape' && timePopover.isOpen) {
|
|
1255
|
+
e.preventDefault();
|
|
1256
|
+
timePopover.hide();
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
if (e.key === 'ArrowDown' && e.altKey) {
|
|
1261
|
+
e.preventDefault();
|
|
1262
|
+
// A keyboard open is never mid-click, so clear the deferral flag. A
|
|
1263
|
+
// press that ended without a click would otherwise leave it set and
|
|
1264
|
+
// hold every later open hostage to the next click anywhere.
|
|
1265
|
+
timePointerActiveRef.current = false;
|
|
1266
|
+
showTimeOptions();
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
if (timePopover.isOpen && timeOptions.length > 0) {
|
|
1271
|
+
switch (e.key) {
|
|
1272
|
+
case 'ArrowDown':
|
|
1273
|
+
e.preventDefault();
|
|
1274
|
+
timeHighlightFollowsTypingRef.current = false;
|
|
1275
|
+
setHighlightedTimeIndex(
|
|
1276
|
+
activeTimeIndex < timeOptions.length - 1
|
|
1277
|
+
? activeTimeIndex + 1
|
|
1278
|
+
: activeTimeIndex,
|
|
1279
|
+
);
|
|
1280
|
+
return;
|
|
1281
|
+
case 'ArrowUp':
|
|
1282
|
+
e.preventDefault();
|
|
1283
|
+
timeHighlightFollowsTypingRef.current = false;
|
|
1284
|
+
setHighlightedTimeIndex(
|
|
1285
|
+
activeTimeIndex > 0 ? activeTimeIndex - 1 : activeTimeIndex,
|
|
1286
|
+
);
|
|
1287
|
+
return;
|
|
1288
|
+
case 'Home':
|
|
1289
|
+
e.preventDefault();
|
|
1290
|
+
timeHighlightFollowsTypingRef.current = false;
|
|
1291
|
+
setHighlightedTimeIndex(0);
|
|
1292
|
+
return;
|
|
1293
|
+
case 'End':
|
|
1294
|
+
e.preventDefault();
|
|
1295
|
+
timeHighlightFollowsTypingRef.current = false;
|
|
1296
|
+
setHighlightedTimeIndex(timeOptions.length - 1);
|
|
1297
|
+
return;
|
|
1298
|
+
case 'Enter': {
|
|
1299
|
+
e.preventDefault();
|
|
1300
|
+
// Typed text wins over the highlight. The highlight only tracks
|
|
1301
|
+
// the option at or before what was typed, so committing it here
|
|
1302
|
+
// would round 1:07 PM down to 1:00 PM and discard the entry.
|
|
1303
|
+
const typed =
|
|
1304
|
+
timeHighlightFollowsTypingRef.current &&
|
|
1305
|
+
timePendingInput !== null
|
|
1306
|
+
? parseTimeInput(timePendingInput, hasSeconds)
|
|
1307
|
+
: null;
|
|
1308
|
+
const option = timeOptions[activeTimeIndex];
|
|
1309
|
+
if (typed) {
|
|
1310
|
+
commitTimeOption(typed);
|
|
1311
|
+
} else if (option) {
|
|
1312
|
+
commitTimeOption(option.time);
|
|
1313
|
+
}
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
case 'Tab':
|
|
1317
|
+
// Let focus leave; blur commits any typed text as usual.
|
|
1318
|
+
timePopover.hide();
|
|
1319
|
+
return;
|
|
1320
|
+
default:
|
|
1321
|
+
break;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
871
1326
|
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
872
1327
|
e.preventDefault();
|
|
873
1328
|
|
|
@@ -907,6 +1362,14 @@ export function DateTimeInput({
|
|
|
907
1362
|
fireChange,
|
|
908
1363
|
announce,
|
|
909
1364
|
formatDisplayTime,
|
|
1365
|
+
hasTimeOptions,
|
|
1366
|
+
isEffectivelyDisabled,
|
|
1367
|
+
timePopover,
|
|
1368
|
+
timeOptions,
|
|
1369
|
+
activeTimeIndex,
|
|
1370
|
+
timePendingInput,
|
|
1371
|
+
showTimeOptions,
|
|
1372
|
+
commitTimeOption,
|
|
910
1373
|
],
|
|
911
1374
|
);
|
|
912
1375
|
|
|
@@ -1009,7 +1472,7 @@ export function DateTimeInput({
|
|
|
1009
1472
|
/>
|
|
1010
1473
|
</button>
|
|
1011
1474
|
<input
|
|
1012
|
-
ref={
|
|
1475
|
+
ref={useMergedRefs(ref, dateInputRef)}
|
|
1013
1476
|
id={dateInputId}
|
|
1014
1477
|
type="text"
|
|
1015
1478
|
role="combobox"
|
|
@@ -1067,6 +1530,10 @@ export function DateTimeInput({
|
|
|
1067
1530
|
ref={timeContainerRef}
|
|
1068
1531
|
onClick={handleTimeWrapperClick}
|
|
1069
1532
|
onMouseUp={handleTimeWrapperMouseUp}
|
|
1533
|
+
// On the wrapper, not just the input: clicking the clock icon or the
|
|
1534
|
+
// padding is routed to the input as a synthetic click, which would
|
|
1535
|
+
// otherwise open the list mid-gesture and let light dismiss eat it.
|
|
1536
|
+
onPointerDown={hasTimeOptions ? markTimePointerActive : undefined}
|
|
1070
1537
|
{...mergeProps(
|
|
1071
1538
|
themeProps('date-time-input-time-segment', {
|
|
1072
1539
|
size,
|
|
@@ -1105,16 +1572,32 @@ export function DateTimeInput({
|
|
|
1105
1572
|
onFocus={handleTimeFocus}
|
|
1106
1573
|
onBlur={handleTimeBlur}
|
|
1107
1574
|
onKeyDown={handleTimeKeyDown}
|
|
1575
|
+
onClick={hasTimeOptions ? showTimeOptions : undefined}
|
|
1576
|
+
onPointerDown={hasTimeOptions ? markTimePointerActive : undefined}
|
|
1108
1577
|
placeholder={resolvedTimePlaceholder}
|
|
1578
|
+
// Combobox semantics appear only with the dropdown opted in, so a
|
|
1579
|
+
// field without it keeps a single combobox on the date half.
|
|
1580
|
+
role={hasTimeOptions ? 'combobox' : undefined}
|
|
1581
|
+
aria-expanded={hasTimeOptions ? timePopover.isOpen : undefined}
|
|
1582
|
+
aria-controls={
|
|
1583
|
+
hasTimeOptions && timePopover.isOpen ? timeListboxId : undefined
|
|
1584
|
+
}
|
|
1585
|
+
aria-autocomplete={hasTimeOptions ? 'list' : undefined}
|
|
1586
|
+
aria-activedescendant={
|
|
1587
|
+
hasTimeOptions &&
|
|
1588
|
+
timePopover.isOpen &&
|
|
1589
|
+
activeTimeIndex >= 0 &&
|
|
1590
|
+
activeTimeIndex < timeOptions.length
|
|
1591
|
+
? timeOptionId(activeTimeIndex)
|
|
1592
|
+
: undefined
|
|
1593
|
+
}
|
|
1109
1594
|
// With a disabledMessage the input keeps focusability via
|
|
1110
1595
|
// aria-disabled so the reason is focus-discoverable; typing is
|
|
1111
1596
|
// blocked with readOnly and the mutation guards.
|
|
1112
1597
|
disabled={isEffectivelyDisabled && !showsDisabledMessage}
|
|
1113
1598
|
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
1114
1599
|
readOnly={showsDisabledMessage || undefined}
|
|
1115
|
-
aria-label={
|
|
1116
|
-
timeLabel ?? t('@astryx.dateTimeInput.timeSuffix', {label})
|
|
1117
|
-
}
|
|
1600
|
+
aria-label={resolvedTimeLabel}
|
|
1118
1601
|
aria-describedby={ariaDescribedBy}
|
|
1119
1602
|
aria-required={isEffectivelyRequired ? 'true' : undefined}
|
|
1120
1603
|
aria-invalid={
|
|
@@ -1152,6 +1635,55 @@ export function DateTimeInput({
|
|
|
1152
1635
|
{placement: 'below', alignment: 'start'},
|
|
1153
1636
|
)}
|
|
1154
1637
|
|
|
1638
|
+
{hasTimeOptions &&
|
|
1639
|
+
timePopover.render(
|
|
1640
|
+
// The layer renders its children open or closed, so mount the list
|
|
1641
|
+
// only while it is open — a 5-minute cadence is 288 nodes that would
|
|
1642
|
+
// otherwise sit in the DOM of every opted-in field for its lifetime.
|
|
1643
|
+
!timePopover.isOpen ? null : (
|
|
1644
|
+
<div
|
|
1645
|
+
id={timeListboxId}
|
|
1646
|
+
role="listbox"
|
|
1647
|
+
aria-label={t('@astryx.dateTimeInput.timeOptionsLabel', {
|
|
1648
|
+
label: resolvedTimeLabel,
|
|
1649
|
+
})}
|
|
1650
|
+
{...mergeProps(
|
|
1651
|
+
themeProps('date-time-input-time-listbox'),
|
|
1652
|
+
stylex.props(styles.timeListbox),
|
|
1653
|
+
)}>
|
|
1654
|
+
{timeOptions.map((option, index) => {
|
|
1655
|
+
const isSelected = option.time === selectedOptionTime;
|
|
1656
|
+
return (
|
|
1657
|
+
<div
|
|
1658
|
+
key={option.time}
|
|
1659
|
+
id={timeOptionId(index)}
|
|
1660
|
+
role="option"
|
|
1661
|
+
aria-selected={isSelected}
|
|
1662
|
+
tabIndex={-1}
|
|
1663
|
+
// Pointer-down commit: the input must not lose focus to the
|
|
1664
|
+
// option, or blur would fire its own commit first.
|
|
1665
|
+
onPointerDown={e => e.preventDefault()}
|
|
1666
|
+
onClick={() => commitTimeOption(option.time)}
|
|
1667
|
+
onMouseEnter={() => setHighlightedTimeIndex(index)}
|
|
1668
|
+
{...mergeProps(
|
|
1669
|
+
themeProps('date-time-input-time-option'),
|
|
1670
|
+
stylex.props(
|
|
1671
|
+
styles.timeOption,
|
|
1672
|
+
timeOptionSizeStyles[size],
|
|
1673
|
+
index === activeTimeIndex &&
|
|
1674
|
+
styles.timeOptionHighlighted,
|
|
1675
|
+
isSelected && styles.timeOptionSelected,
|
|
1676
|
+
),
|
|
1677
|
+
)}>
|
|
1678
|
+
{option.label}
|
|
1679
|
+
</div>
|
|
1680
|
+
);
|
|
1681
|
+
})}
|
|
1682
|
+
</div>
|
|
1683
|
+
),
|
|
1684
|
+
{placement: 'below', alignment: 'start'},
|
|
1685
|
+
)}
|
|
1686
|
+
|
|
1155
1687
|
{showsDisabledMessage &&
|
|
1156
1688
|
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
1157
1689
|
</Field>
|