@astryxdesign/core 0.5.2-canary.2da7a39 → 0.5.2-canary.2e51213
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/dist/AppShell/AppShell.d.ts +2 -2
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +10 -7
- package/dist/Banner/Banner.d.ts +5 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +7 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +22 -15
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +2 -2
- package/dist/Chat/ChatComposer.d.ts +2 -2
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +21 -2
- package/dist/Chat/ChatToolCalls.d.ts +1 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +12 -34
- package/dist/Chat/useChatNewMessages.js +3 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts +5 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +47 -13
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +269 -162
- package/dist/DateTimeInput/NativeDateSegment.d.ts +24 -0
- package/dist/DateTimeInput/NativeDateSegment.d.ts.map +1 -0
- package/dist/DateTimeInput/NativeDateSegment.js +235 -0
- package/dist/DateTimeInput/NativeTimeSegment.d.ts +30 -0
- package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -0
- package/dist/DateTimeInput/NativeTimeSegment.js +248 -0
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +95 -0
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -0
- package/dist/DateTimeInput/nativePickerSegmentStyles.js +103 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +2 -4
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +10 -4
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +3 -5
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +4 -2
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
- package/dist/Layer/useTouchTrigger.js +2 -4
- package/dist/Layout/Layout.d.ts +7 -8
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +7 -8
- package/dist/MultiSelector/MultiSelector.d.ts +11 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +89 -45
- package/dist/RadioList/RadioListItem.d.ts +30 -5
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +17 -4
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +102 -44
- package/dist/Resizable/index.d.ts +2 -0
- package/dist/Resizable/index.d.ts.map +1 -1
- package/dist/Resizable/index.js +1 -0
- package/dist/Resizable/useResizable.d.ts +89 -8
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +521 -38
- package/dist/Resizable/utils.d.ts +35 -0
- package/dist/Resizable/utils.d.ts.map +1 -0
- package/dist/Resizable/utils.js +27 -0
- package/dist/Selector/Selector.d.ts +10 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +105 -57
- package/dist/Selector/useSelectorPresentation.d.ts +1 -0
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
- package/dist/Selector/useSelectorPresentation.js +17 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -5
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +9 -10
- package/dist/Stepper/Step.d.ts +2 -1
- package/dist/Stepper/Step.d.ts.map +1 -1
- package/dist/Stepper/Step.js +75 -11
- package/dist/Stepper/Stepper.d.ts.map +1 -1
- package/dist/Stepper/Stepper.js +1 -0
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +2 -3
- package/dist/Table/index.d.ts +16 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +4 -0
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +8 -9
- package/dist/Table/plugins/rowStatus/index.d.ts +1 -1
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +11 -30
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +108 -62
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +9 -1
- package/dist/Text/useTruncation.d.ts +1 -1
- package/dist/Text/useTruncation.d.ts.map +1 -1
- package/dist/Text/useTruncation.js +8 -7
- package/dist/TimeInput/TimeInput.d.ts +16 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +98 -60
- package/dist/TimeInput/index.d.ts +1 -1
- package/dist/TimeInput/index.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.d.ts +2 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +4 -145
- package/dist/Timestamp/formatRelativeTime.d.ts +20 -0
- package/dist/Timestamp/formatRelativeTime.d.ts.map +1 -0
- package/dist/Timestamp/formatRelativeTime.js +81 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +125 -77
- package/dist/Tokenizer/Tokenizer.d.ts +0 -38
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +94 -26
- package/dist/Tokenizer/useEndLaneReserve.d.ts +31 -0
- package/dist/Tokenizer/useEndLaneReserve.d.ts.map +1 -0
- package/dist/Tokenizer/useEndLaneReserve.js +136 -0
- package/dist/Tooltip/useTooltip.d.ts +1 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +53 -42
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +85 -30
- package/dist/Typeahead/Typeahead.d.ts +0 -21
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +108 -67
- package/dist/Typeahead/busyIndicatorLane.d.ts +62 -0
- package/dist/Typeahead/busyIndicatorLane.d.ts.map +1 -0
- package/dist/Typeahead/busyIndicatorLane.js +98 -0
- package/dist/astryx.css +25 -7
- package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -1
- package/dist/hooks/useFocusReturnVisibility.js +3 -5
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +11 -11
- package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
- package/dist/hooks/useScrollOverflow.js +7 -4
- package/dist/theme/defineTheme.d.ts +13 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +1 -1
- package/dist/theme/localTokens.d.ts +18 -0
- package/dist/theme/localTokens.d.ts.map +1 -0
- package/dist/theme/localTokens.js +162 -0
- package/dist/utils/interactionModality.d.ts +6 -28
- package/dist/utils/interactionModality.d.ts.map +1 -1
- package/dist/utils/interactionModality.js +72 -37
- package/dist/utils/sharedResizeObserver.d.ts +17 -9
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +54 -12
- package/locales/en.json +8 -0
- package/locales/pseudo.json +6 -0
- package/package.json +7 -2
- package/src/AlertDialog/useImperativeAlertDialog.test.tsx +163 -0
- package/src/AppShell/AppShell.doc.mjs +4 -3
- package/src/AppShell/AppShell.test.tsx +21 -0
- package/src/AppShell/AppShell.tsx +12 -7
- package/src/Banner/Banner.doc.mjs +5 -1
- package/src/Banner/Banner.tsx +12 -1
- package/src/BottomSheet/BottomSheet.doc.mjs +31 -0
- package/src/BottomSheet/BottomSheet.spec.md +178 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +18 -9
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +4 -1
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +12 -0
- package/src/Button/Button.doc.mjs +56 -0
- package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
- package/src/Calendar/hooks/useCalendarConstraints.test.ts +153 -0
- package/src/Calendar/hooks/useCalendarDays.test.ts +265 -0
- package/src/Calendar/hooks/useCalendarNavigation.test.ts +252 -0
- package/src/Carousel/Carousel.test.tsx +83 -0
- package/src/Carousel/Carousel.tsx +8 -2
- package/src/Chat/ChatComposer.doc.mjs +7 -4
- package/src/Chat/ChatComposer.test.tsx +84 -2
- package/src/Chat/ChatComposer.tsx +45 -3
- package/src/Chat/ChatSendButton.test.tsx +189 -0
- package/src/Chat/ChatToolCalls.doc.mjs +1 -1
- package/src/Chat/ChatToolCalls.test.tsx +33 -1
- package/src/Chat/ChatToolCalls.tsx +13 -34
- package/src/Chat/useChatNewMessages.ts +3 -3
- package/src/Chat/useChatPasteAsToken.test.ts +191 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +172 -31
- package/src/CheckboxList/CheckboxList.spec.md +215 -0
- package/src/CheckboxList/CheckboxList.test.tsx +45 -0
- package/src/CheckboxList/CheckboxListItem.doc.mjs +11 -9
- package/src/CheckboxList/CheckboxListItem.tsx +5 -3
- package/src/Collapsible/useCollapsible.test.tsx +236 -0
- package/src/CommandPalette/CommandPalette.doc.mjs +72 -0
- package/src/CommandPalette/CommandPalette.spec.md +224 -0
- package/src/CommandPalette/CommandPaletteEmpty.test.tsx +101 -0
- package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
- package/src/ComplexSelector/ComplexSelector.spec.md +190 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +48 -0
- package/src/ContextMenu/ContextMenu.spec.md +207 -0
- package/src/DateTimeInput/DateTimeInput.doc.mjs +43 -23
- package/src/DateTimeInput/DateTimeInput.tsx +388 -181
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +10 -2
- package/src/DateTimeInput/NativeDateSegment.tsx +308 -0
- package/src/DateTimeInput/NativePickerSegments.test.tsx +626 -0
- package/src/DateTimeInput/NativeTimeSegment.tsx +331 -0
- package/src/DateTimeInput/index.ts +1 -0
- package/src/DateTimeInput/nativePickerSegmentStyles.ts +120 -0
- package/src/Divider/Divider.doc.mjs +24 -0
- package/src/Divider/Divider.spec.md +157 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +104 -0
- package/src/DropdownMenu/DropdownMenu.spec.md +246 -0
- package/src/DropdownMenu/DropdownMenu.tsx +2 -4
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/Field.test.tsx +39 -0
- package/src/Field/Field.tsx +18 -1
- package/src/Field/InputClearButton.test.tsx +68 -6
- package/src/Field/PanelSearchInput.tsx +3 -5
- package/src/FieldStatus/FieldStatus.doc.mjs +21 -0
- package/src/FieldStatus/FieldStatus.spec.md +213 -0
- package/src/FieldStatus/FieldStatus.test.tsx +17 -0
- package/src/FieldStatus/FieldStatus.tsx +7 -2
- package/src/Grid/Grid.doc.mjs +19 -0
- package/src/Grid/Grid.spec.md +162 -0
- package/src/Icon/Icon.doc.mjs +196 -48
- package/src/Icon/Icon.spec.md +192 -0
- package/src/IconButton/IconButton.doc.mjs +38 -0
- package/src/Kbd/Kbd.doc.mjs +18 -0
- package/src/Kbd/Kbd.spec.md +142 -0
- package/src/Layer/useTouchTrigger.ts +2 -4
- package/src/Layout/Layout.doc.mjs +57 -17
- package/src/Layout/Layout.spec.md +235 -0
- package/src/Layout/Layout.test.tsx +1 -1
- package/src/Layout/Layout.tsx +7 -8
- package/src/Layout/LayoutHeader.doc.mjs +9 -0
- package/src/Layout/LayoutPanel.doc.mjs +4 -3
- package/src/Lightbox/Lightbox.doc.mjs +149 -33
- package/src/Lightbox/Lightbox.spec.md +198 -0
- package/src/Lightbox/useLightbox.test.tsx +263 -0
- package/src/Markdown/Markdown.doc.mjs +60 -0
- package/src/Markdown/Markdown.spec.md +207 -0
- package/src/MobileNav/MobileNav.doc.mjs +140 -32
- package/src/MobileNav/MobileNav.spec.md +209 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +42 -0
- package/src/MoreMenu/MoreMenu.spec.md +222 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +124 -1
- package/src/MultiSelector/MultiSelector.spec.md +293 -0
- package/src/MultiSelector/MultiSelector.test.tsx +305 -2
- package/src/MultiSelector/MultiSelector.tsx +124 -55
- package/src/NavIcon/NavIcon.doc.mjs +17 -0
- package/src/NavIcon/NavIcon.spec.md +134 -0
- package/src/NavMenu/NavHeadingMenu.spec.md +210 -0
- package/src/NavMenu/NavMenu.doc.mjs +37 -0
- package/src/Outline/Outline.doc.mjs +35 -0
- package/src/Outline/Outline.spec.md +162 -0
- package/src/OverflowList/OverflowList.doc.mjs +24 -0
- package/src/OverflowList/OverflowList.spec.md +157 -0
- package/src/Pagination/Pagination.doc.mjs +74 -0
- package/src/Pagination/Pagination.spec.md +226 -0
- package/src/Popover/Popover.doc.mjs +264 -65
- package/src/Popover/Popover.spec.md +421 -0
- package/src/Popover/usePopover.doc.mjs +208 -33
- package/src/PowerSearch/PowerSearch.spec.md +291 -0
- package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +253 -0
- package/src/PowerSearch/PowerSearchToken.test.tsx +228 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +198 -38
- package/src/ProgressBar/ProgressBar.spec.md +261 -0
- package/src/RadioList/RadioList.test.tsx +136 -2
- package/src/RadioList/RadioListItem.doc.mjs +30 -11
- package/src/RadioList/RadioListItem.tsx +44 -8
- package/src/Resizable/Resizable.doc.mjs +130 -24
- package/src/Resizable/Resizable.spec.md +246 -0
- package/src/Resizable/ResizeHandle.test.tsx +177 -56
- package/src/Resizable/ResizeHandle.tsx +128 -45
- package/src/Resizable/index.ts +2 -0
- package/src/Resizable/shippedDirections.test.ts +462 -0
- package/src/Resizable/useResizable.doc.mjs +124 -29
- package/src/Resizable/useResizable.test.ts +1277 -3
- package/src/Resizable/useResizable.ts +760 -48
- package/src/Resizable/utils.test.ts +74 -0
- package/src/Resizable/utils.ts +35 -0
- package/src/Section/Section.doc.mjs +17 -0
- package/src/Section/Section.spec.md +139 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +83 -0
- package/src/SegmentedControl/SegmentedControl.spec.md +152 -0
- package/src/Selector/Selector.doc.mjs +133 -97
- package/src/Selector/Selector.spec.md +300 -0
- package/src/Selector/Selector.test.tsx +318 -1
- package/src/Selector/Selector.tsx +127 -60
- package/src/Selector/useSelectorPresentation.ts +24 -4
- package/src/SideNav/SideNav.test.tsx +3 -3
- package/src/SideNav/SideNavCollapseButton.doc.mjs +8 -0
- package/src/SideNav/SideNavItem.doc.mjs +1 -1
- package/src/Skeleton/Skeleton.doc.mjs +12 -0
- package/src/Skeleton/Skeleton.spec.md +127 -0
- package/src/Slider/Slider.doc.mjs +184 -30
- package/src/Slider/Slider.spec.md +224 -0
- package/src/Slider/Slider.tsx +2 -5
- package/src/Spinner/Spinner.doc.mjs +5 -5
- package/src/Spinner/Spinner.test.tsx +32 -7
- package/src/Spinner/Spinner.tsx +46 -14
- package/src/Stack/Stack.doc.mjs +22 -0
- package/src/Stack/Stack.spec.md +155 -0
- package/src/StatusDot/StatusDot.doc.mjs +17 -0
- package/src/StatusDot/StatusDot.spec.md +138 -0
- package/src/Stepper/Step.doc.mjs +1 -1
- package/src/Stepper/Step.tsx +118 -5
- package/src/Stepper/Stepper.doc.mjs +51 -1
- package/src/Stepper/Stepper.spec.md +245 -0
- package/src/Stepper/Stepper.test.tsx +315 -0
- package/src/Stepper/Stepper.tsx +8 -0
- package/src/Switch/Switch.doc.mjs +40 -0
- package/src/Switch/Switch.spec.md +175 -0
- package/src/TabList/TabList.tsx +2 -3
- package/src/Table/Table.doc.mjs +102 -24
- package/src/Table/Table.perf.test.tsx +51 -1
- package/src/Table/Table.spec.md +325 -0
- package/src/Table/TableHeaderCell.test.tsx +291 -0
- package/src/Table/index.ts +19 -4
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -12
- package/src/Table/plugins/filtering/useTableFilterState.test.tsx +143 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +2 -1
- package/src/Table/plugins/rowStatus/index.ts +1 -4
- package/src/Table/plugins/rowStatus/useTableRowStatus.public.test.ts +92 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +354 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +431 -56
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +155 -84
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +72 -0
- package/src/Table/plugins/sortable/useTableSortable.tsx +18 -1
- package/src/Table/useTableGroupedRows.doc.mjs +2 -2
- package/src/Table/useTableRowStatus.doc.mjs +5 -5
- package/src/Text/Text.doc.mjs +190 -43
- package/src/Text/Text.spec.md +206 -0
- package/src/Text/useTruncation.ts +8 -7
- package/src/TextArea/TextArea.doc.mjs +255 -45
- package/src/TextArea/TextArea.spec.md +205 -0
- package/src/TimeInput/NativeTimeInput.test.tsx +269 -0
- package/src/TimeInput/TimeInput.doc.mjs +47 -23
- package/src/TimeInput/TimeInput.tsx +109 -50
- package/src/TimeInput/index.ts +1 -0
- package/src/Timestamp/Timestamp.doc.mjs +2 -2
- package/src/Timestamp/Timestamp.test.tsx +75 -3
- package/src/Timestamp/Timestamp.tsx +7 -153
- package/src/Timestamp/formatRelativeTime.ts +96 -0
- package/src/Toast/ToastViewport.test.tsx +194 -0
- package/src/Toast/ToastViewport.tsx +136 -58
- package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -0
- package/src/Tokenizer/Tokenizer.spec.md +293 -0
- package/src/Tokenizer/Tokenizer.test.tsx +335 -1
- package/src/Tokenizer/Tokenizer.tsx +129 -46
- package/src/Tokenizer/useEndLaneReserve.ts +146 -0
- package/src/Toolbar/Toolbar.doc.mjs +19 -0
- package/src/Toolbar/Toolbar.spec.md +174 -0
- package/src/Tooltip/Tooltip.doc.mjs +17 -0
- package/src/Tooltip/Tooltip.spec.md +142 -0
- package/src/Tooltip/Tooltip.test.tsx +21 -1
- package/src/Tooltip/useTooltip.test.tsx +318 -0
- package/src/Tooltip/useTooltip.tsx +60 -39
- package/src/TreeList/TreeList.doc.mjs +58 -0
- package/src/TreeList/TreeList.spec.md +224 -0
- package/src/Typeahead/BaseTypeahead.tsx +96 -25
- package/src/Typeahead/Typeahead.doc.mjs +89 -1
- package/src/Typeahead/Typeahead.spec.md +257 -0
- package/src/Typeahead/Typeahead.test.tsx +502 -1
- package/src/Typeahead/Typeahead.tsx +187 -69
- package/src/Typeahead/TypeaheadItem.test.tsx +93 -2
- package/src/Typeahead/busyIndicatorLane.tsx +109 -0
- package/src/__tests__/stylexDeclarations.ts +51 -0
- package/src/hooks/useFocusReturnVisibility.ts +3 -5
- package/src/hooks/useOverflow.ts +11 -11
- package/src/hooks/useScrollLock.test.ts +103 -0
- package/src/hooks/useScrollOverflow.ts +7 -4
- package/src/i18n/useTranslator.test.tsx +197 -0
- package/src/theme/defineTheme.test.ts +227 -0
- package/src/theme/defineTheme.ts +30 -0
- package/src/theme/derivedVarRegistry.test.ts +6 -0
- package/src/theme/generateThemeRules.ts +4 -1
- package/src/theme/localTokens.ts +272 -0
- package/src/theme/themingTargets.test.ts +126 -28
- package/src/utils/interactionModality.test.ts +83 -0
- package/src/utils/interactionModality.ts +88 -36
- package/src/utils/sharedResizeObserver.test.ts +124 -5
- package/src/utils/sharedResizeObserver.ts +60 -14
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file NativeDateSegment.tsx
|
|
7
|
+
* @input Uses React, Icon, nativeDateSegments, and DateTimeInput's date state
|
|
8
|
+
* @output Exports NativeDateSegment — the OS-picker date half of DateTimeInput
|
|
9
|
+
* @position Internal DateTimeInput surface selected by `nativePicker`
|
|
10
|
+
*
|
|
11
|
+
* Hands date picking to the platform through `<input type="date">`. Its
|
|
12
|
+
* sibling NativeTimeSegment hands time picking to `<input type="time">`, so
|
|
13
|
+
* both halves of DateTimeInput follow the same `nativePicker` choice.
|
|
14
|
+
*
|
|
15
|
+
* The input is deliberately uncontrolled and observed through native event
|
|
16
|
+
* listeners. On iOS, writing its value while the picker sheet is open can
|
|
17
|
+
* detach the sheet, and React's synthetic change event does not reliably see
|
|
18
|
+
* picker edits. External values therefore reconcile only while unfocused.
|
|
19
|
+
*
|
|
20
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
21
|
+
* - /packages/core/src/DateTimeInput/DateTimeInput.tsx (surface selection)
|
|
22
|
+
* - /packages/core/src/DateTimeInput/NativePickerSegments.test.tsx (tests)
|
|
23
|
+
* - /packages/core/src/DateTimeInput/DateTimeInput.doc.mjs (prop docs)
|
|
24
|
+
*/
|
|
25
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
26
|
+
import * as stylex from '@stylexjs/stylex';
|
|
27
|
+
import { hasEditableDateSegments } from "../DateInput/nativeDateSegments.js";
|
|
28
|
+
import { useMediaQuery } from "../hooks/useMediaQuery.js";
|
|
29
|
+
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
30
|
+
import { Icon } from "../Icon/index.js";
|
|
31
|
+
import { useLocale, useTranslator } from "../i18n/index.js";
|
|
32
|
+
import { VisuallyHidden } from "../VisuallyHidden/index.js";
|
|
33
|
+
import { focusOutlineStyles, formatSharedDate, parseDateInput, plainDateFromISO, plainDateToISO, themeProps } from "../utils/index.js";
|
|
34
|
+
import { nativePickerSegmentStyles as styles } from "./nativePickerSegmentStyles.js";
|
|
35
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
36
|
+
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
37
|
+
/** The native date half rendered inside DateTimeInput's date wrapper. */
|
|
38
|
+
export function NativeDateSegment({
|
|
39
|
+
id,
|
|
40
|
+
inputRef,
|
|
41
|
+
value,
|
|
42
|
+
onChange,
|
|
43
|
+
placeholder,
|
|
44
|
+
min,
|
|
45
|
+
max,
|
|
46
|
+
isDateDisabled,
|
|
47
|
+
isEffectivelyDisabled,
|
|
48
|
+
hasDisabledMessage,
|
|
49
|
+
isEffectivelyRequired,
|
|
50
|
+
isBusy,
|
|
51
|
+
statusType,
|
|
52
|
+
ariaDescribedBy
|
|
53
|
+
}) {
|
|
54
|
+
const t = useTranslator();
|
|
55
|
+
const locale = useLocale();
|
|
56
|
+
const isTouchPointer = useMediaQuery('(pointer: coarse)');
|
|
57
|
+
const internalInputRef = useRef(null);
|
|
58
|
+
const mergedInputRef = useMergedRefs(inputRef, internalInputRef);
|
|
59
|
+
const [rejectedValue, setRejectedValue] = useState(null);
|
|
60
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
61
|
+
const [isSegmentEditable, setIsSegmentEditable] = useState(false);
|
|
62
|
+
const valueAtFocusRef = useRef(null);
|
|
63
|
+
const lastCommitRef = useRef(null);
|
|
64
|
+
const prevValueRef = useRef(value);
|
|
65
|
+
if (value !== prevValueRef.current) {
|
|
66
|
+
prevValueRef.current = value;
|
|
67
|
+
// Keep the accepted DOM value cached while a native picker is open. An
|
|
68
|
+
// optimistic rollback changes the prop but leaves the focused control alone;
|
|
69
|
+
// clearing this cache would replay that rejected edit on blur.
|
|
70
|
+
if (!isFocused) {
|
|
71
|
+
lastCommitRef.current = null;
|
|
72
|
+
}
|
|
73
|
+
if (rejectedValue !== null) {
|
|
74
|
+
setRejectedValue(null);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const nativeValue = value && ISO_DATE.test(value) ? value : '';
|
|
78
|
+
const isInputValid = rejectedValue === null;
|
|
79
|
+
const overlayText = nativeValue ? formatSharedDate(plainDateFromISO(nativeValue), 'date_long', locale) : placeholder;
|
|
80
|
+
const showsOverlay = !!overlayText && !(isFocused && isSegmentEditable);
|
|
81
|
+
const commitValue = useCallback(newValue => {
|
|
82
|
+
if (isEffectivelyDisabled) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (lastCommitRef.current === newValue) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (!newValue) {
|
|
89
|
+
lastCommitRef.current = newValue;
|
|
90
|
+
setRejectedValue(null);
|
|
91
|
+
if (value !== undefined) {
|
|
92
|
+
onChange(undefined);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const parsed = parseDateInput(newValue, locale);
|
|
97
|
+
if (!parsed) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (isDateDisabled(parsed)) {
|
|
101
|
+
setRejectedValue(newValue);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
setRejectedValue(null);
|
|
105
|
+
lastCommitRef.current = newValue;
|
|
106
|
+
const parsedISO = plainDateToISO(parsed);
|
|
107
|
+
if (parsedISO !== value) {
|
|
108
|
+
onChange(parsedISO);
|
|
109
|
+
}
|
|
110
|
+
}, [isDateDisabled, isEffectivelyDisabled, locale, onChange, value]);
|
|
111
|
+
const handleChange = useCallback(event => {
|
|
112
|
+
commitValue(event.target.value);
|
|
113
|
+
}, [commitValue]);
|
|
114
|
+
|
|
115
|
+
// React's synthetic change system does not reliably observe iOS picker edits.
|
|
116
|
+
const commitRef = useRef(commitValue);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
commitRef.current = commitValue;
|
|
119
|
+
});
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
const input = internalInputRef.current;
|
|
122
|
+
if (!input) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const handleNative = () => commitRef.current(input.value);
|
|
126
|
+
input.addEventListener('input', handleNative);
|
|
127
|
+
input.addEventListener('change', handleNative);
|
|
128
|
+
return () => {
|
|
129
|
+
input.removeEventListener('input', handleNative);
|
|
130
|
+
input.removeEventListener('change', handleNative);
|
|
131
|
+
};
|
|
132
|
+
}, []);
|
|
133
|
+
|
|
134
|
+
// React touches defaultValue after mount when the prop changes, so capture it
|
|
135
|
+
// once. The effect below owns every later write and skips focused controls.
|
|
136
|
+
const initialValueRef = useRef(null);
|
|
137
|
+
if (initialValueRef.current === null) {
|
|
138
|
+
initialValueRef.current = nativeValue;
|
|
139
|
+
}
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
if (isFocused) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const input = internalInputRef.current;
|
|
145
|
+
if (input && input.value !== nativeValue) {
|
|
146
|
+
input.value = nativeValue;
|
|
147
|
+
}
|
|
148
|
+
}, [isFocused, nativeValue]);
|
|
149
|
+
const handleFocus = useCallback(() => {
|
|
150
|
+
valueAtFocusRef.current = nativeValue;
|
|
151
|
+
setIsSegmentEditable(hasEditableDateSegments(isTouchPointer));
|
|
152
|
+
setIsFocused(true);
|
|
153
|
+
}, [isTouchPointer, nativeValue]);
|
|
154
|
+
const handleBlur = useCallback(() => {
|
|
155
|
+
const domValue = internalInputRef.current?.value;
|
|
156
|
+
const valueChangedWhileFocused = valueAtFocusRef.current !== null && valueAtFocusRef.current !== nativeValue;
|
|
157
|
+
const wasRejected = rejectedValue !== null;
|
|
158
|
+
valueAtFocusRef.current = null;
|
|
159
|
+
setIsFocused(false);
|
|
160
|
+
setRejectedValue(null);
|
|
161
|
+
if (!valueChangedWhileFocused && !wasRejected && domValue !== undefined && domValue !== nativeValue) {
|
|
162
|
+
commitValue(domValue);
|
|
163
|
+
}
|
|
164
|
+
lastCommitRef.current = null;
|
|
165
|
+
}, [commitValue, nativeValue, rejectedValue]);
|
|
166
|
+
const openPicker = useCallback(() => {
|
|
167
|
+
if (isEffectivelyDisabled) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const input = internalInputRef.current;
|
|
171
|
+
if (!input) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
input.focus();
|
|
175
|
+
if (typeof input.showPicker === 'function') {
|
|
176
|
+
try {
|
|
177
|
+
input.showPicker();
|
|
178
|
+
} catch {
|
|
179
|
+
// Focus is the fallback when showPicker needs user activation or the
|
|
180
|
+
// browser does not expose it for date controls.
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}, [isEffectivelyDisabled]);
|
|
184
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
185
|
+
children: [/*#__PURE__*/_jsx("button", {
|
|
186
|
+
type: "button",
|
|
187
|
+
onClick: openPicker,
|
|
188
|
+
disabled: isEffectivelyDisabled,
|
|
189
|
+
"aria-label": t('@astryx.dateInput.openCalendar'),
|
|
190
|
+
tabIndex: -1,
|
|
191
|
+
...stylex.props(focusOutlineStyles.focusVisible, styles.iconButton, isEffectivelyDisabled && styles.iconButtonDisabled),
|
|
192
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
193
|
+
icon: "calendar",
|
|
194
|
+
size: "sm",
|
|
195
|
+
color: "secondary",
|
|
196
|
+
...themeProps('date-time-input-toggle-icon', {
|
|
197
|
+
state: 'collapsed'
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
}), /*#__PURE__*/_jsxs("span", {
|
|
201
|
+
...stylex.props(styles.slot),
|
|
202
|
+
children: [/*#__PURE__*/_jsx("input", {
|
|
203
|
+
ref: mergedInputRef,
|
|
204
|
+
id: id,
|
|
205
|
+
type: "date"
|
|
206
|
+
// UNCONTROLLED on purpose; see initialValueRef and the sync effect.
|
|
207
|
+
,
|
|
208
|
+
defaultValue: initialValueRef.current ?? '',
|
|
209
|
+
onChange: handleChange,
|
|
210
|
+
onFocus: handleFocus,
|
|
211
|
+
onBlur: handleBlur,
|
|
212
|
+
min: min,
|
|
213
|
+
max: max,
|
|
214
|
+
disabled: isEffectivelyDisabled && !hasDisabledMessage,
|
|
215
|
+
"aria-disabled": hasDisabledMessage ? 'true' : undefined,
|
|
216
|
+
readOnly: hasDisabledMessage || undefined,
|
|
217
|
+
"aria-describedby": ariaDescribedBy,
|
|
218
|
+
"aria-required": isEffectivelyRequired ? 'true' : undefined,
|
|
219
|
+
"aria-invalid": statusType === 'error' || !isInputValid ? 'true' : undefined,
|
|
220
|
+
"aria-busy": isBusy || undefined,
|
|
221
|
+
...stylex.props(styles.input, showsOverlay && styles.inputTextHidden, isEffectivelyDisabled && styles.inputDisabled, !isInputValid && styles.inputInvalid)
|
|
222
|
+
}), showsOverlay && /*#__PURE__*/_jsx("span", {
|
|
223
|
+
"aria-hidden": "true",
|
|
224
|
+
...stylex.props(styles.overlay, nativeValue ? styles.overlayValue : styles.overlayPlaceholder, isEffectivelyDisabled && styles.inputDisabled, !isInputValid && !!nativeValue && styles.inputInvalid),
|
|
225
|
+
children: overlayText
|
|
226
|
+
})]
|
|
227
|
+
}), /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
228
|
+
as: "div",
|
|
229
|
+
role: "alert",
|
|
230
|
+
"aria-live": "assertive",
|
|
231
|
+
children: !isInputValid ? t('@astryx.dateInput.invalidDate') : ''
|
|
232
|
+
})]
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
NativeDateSegment.displayName = 'NativeDateSegment';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { InputStatusType } from '../Field';
|
|
2
|
+
import type { ThemeProps } from '../utils/themeProps';
|
|
3
|
+
import { type ISOTimeString } from '../utils';
|
|
4
|
+
export type NativeTimeSegmentProps = {
|
|
5
|
+
id: string;
|
|
6
|
+
inputRef: React.Ref<HTMLInputElement>;
|
|
7
|
+
value?: ISOTimeString;
|
|
8
|
+
onChange: (value: ISOTimeString | undefined) => void;
|
|
9
|
+
placeholder: string;
|
|
10
|
+
inputLabel?: string;
|
|
11
|
+
openPickerLabel: string;
|
|
12
|
+
ariaLabelledBy?: string;
|
|
13
|
+
iconThemeProps?: ThemeProps;
|
|
14
|
+
hasAutoFocus?: boolean;
|
|
15
|
+
min?: ISOTimeString;
|
|
16
|
+
max?: ISOTimeString;
|
|
17
|
+
hourFormat: '12h' | '24h';
|
|
18
|
+
isEffectivelyDisabled: boolean;
|
|
19
|
+
hasDisabledMessage: boolean;
|
|
20
|
+
isEffectivelyRequired: boolean;
|
|
21
|
+
isBusy: boolean;
|
|
22
|
+
statusType?: InputStatusType;
|
|
23
|
+
ariaDescribedBy?: string;
|
|
24
|
+
};
|
|
25
|
+
/** The shared native time control rendered inside Astryx field chrome. */
|
|
26
|
+
export declare function NativeTimeSegment({ id, inputRef, value, onChange, placeholder, inputLabel, openPickerLabel, ariaLabelledBy, iconThemeProps, hasAutoFocus, min, max, hourFormat, isEffectivelyDisabled, hasDisabledMessage, isEffectivelyRequired, isBusy, statusType, ariaDescribedBy, }: NativeTimeSegmentProps): import("react").JSX.Element;
|
|
27
|
+
export declare namespace NativeTimeSegment {
|
|
28
|
+
var displayName: string;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=NativeTimeSegment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTimeSegment.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/NativeTimeSegment.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,UAAU,CAAC;AAK9C,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAOL,KAAK,aAAa,EACnB,MAAM,UAAU,CAAC;AAmBlB,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,EAChC,EAAE,EACF,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAoB,EACpB,GAAG,EACH,GAAG,EACH,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,EACrB,MAAM,EACN,UAAU,EACV,eAAe,GAChB,EAAE,sBAAsB,+BA+NxB;yBAnPe,iBAAiB"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file NativeTimeSegment.tsx
|
|
7
|
+
* @input Uses React, native picker segment styles, and shared time utilities
|
|
8
|
+
* @output Exports NativeTimeSegment — the shared OS-picker time control
|
|
9
|
+
* @position Internal native control used by DateTimeInput and TimeInput
|
|
10
|
+
*
|
|
11
|
+
* Hands time picking to the platform through `<input type="time">`. The input
|
|
12
|
+
* is deliberately uncontrolled and observed through native event listeners,
|
|
13
|
+
* matching NativeDateSegment's iOS-safe value ownership: external values only
|
|
14
|
+
* reconcile while the picker is unfocused, and native edits do not depend on
|
|
15
|
+
* React's synthetic change event.
|
|
16
|
+
*
|
|
17
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
18
|
+
* - /packages/core/src/DateTimeInput/DateTimeInput.tsx (DateTimeInput integration)
|
|
19
|
+
* - /packages/core/src/TimeInput/TimeInput.tsx (TimeInput integration)
|
|
20
|
+
* - /packages/core/src/DateTimeInput/NativePickerSegments.test.tsx (DateTimeInput tests)
|
|
21
|
+
* - /packages/core/src/TimeInput/NativeTimeInput.test.tsx (TimeInput tests)
|
|
22
|
+
* - /packages/core/src/DateTimeInput/DateTimeInput.doc.mjs (DateTimeInput prop docs)
|
|
23
|
+
* - /packages/core/src/TimeInput/TimeInput.doc.mjs (TimeInput prop docs)
|
|
24
|
+
*/
|
|
25
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
26
|
+
import * as stylex from '@stylexjs/stylex';
|
|
27
|
+
import { hasEditableDateSegments } from "../DateInput/nativeDateSegments.js";
|
|
28
|
+
import { useMediaQuery } from "../hooks/useMediaQuery.js";
|
|
29
|
+
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
30
|
+
import { Icon } from "../Icon/index.js";
|
|
31
|
+
import { useTranslator } from "../i18n/index.js";
|
|
32
|
+
import { VisuallyHidden } from "../VisuallyHidden/index.js";
|
|
33
|
+
import { focusOutlineStyles, formatDisplayTime12h, formatDisplayTime24h, formatISOTime, isTimeInRange, parseISOTime } from "../utils/index.js";
|
|
34
|
+
import { nativePickerSegmentStyles as styles } from "./nativePickerSegmentStyles.js";
|
|
35
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
36
|
+
const FRACTIONAL_SECONDS = /\.\d+$/;
|
|
37
|
+
function normalizeNativeTime(value) {
|
|
38
|
+
if (!value) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const withoutFraction = value.replace(FRACTIONAL_SECONDS, '');
|
|
42
|
+
const parsed = parseISOTime(withoutFraction);
|
|
43
|
+
return parsed ? formatISOTime(parsed, false) : undefined;
|
|
44
|
+
}
|
|
45
|
+
/** The shared native time control rendered inside Astryx field chrome. */
|
|
46
|
+
export function NativeTimeSegment({
|
|
47
|
+
id,
|
|
48
|
+
inputRef,
|
|
49
|
+
value,
|
|
50
|
+
onChange,
|
|
51
|
+
placeholder,
|
|
52
|
+
inputLabel,
|
|
53
|
+
openPickerLabel,
|
|
54
|
+
ariaLabelledBy,
|
|
55
|
+
iconThemeProps,
|
|
56
|
+
hasAutoFocus = false,
|
|
57
|
+
min,
|
|
58
|
+
max,
|
|
59
|
+
hourFormat,
|
|
60
|
+
isEffectivelyDisabled,
|
|
61
|
+
hasDisabledMessage,
|
|
62
|
+
isEffectivelyRequired,
|
|
63
|
+
isBusy,
|
|
64
|
+
statusType,
|
|
65
|
+
ariaDescribedBy
|
|
66
|
+
}) {
|
|
67
|
+
const t = useTranslator();
|
|
68
|
+
const isTouchPointer = useMediaQuery('(pointer: coarse)');
|
|
69
|
+
const internalInputRef = useRef(null);
|
|
70
|
+
const mergedInputRef = useMergedRefs(inputRef, internalInputRef);
|
|
71
|
+
const [rejectedValue, setRejectedValue] = useState(null);
|
|
72
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
73
|
+
const [isSegmentEditable, setIsSegmentEditable] = useState(false);
|
|
74
|
+
const valueAtFocusRef = useRef(null);
|
|
75
|
+
const lastCommitRef = useRef(null);
|
|
76
|
+
const prevValueRef = useRef(value);
|
|
77
|
+
if (value !== prevValueRef.current) {
|
|
78
|
+
prevValueRef.current = value;
|
|
79
|
+
// Preserve the accepted DOM value while the OS wheel is open so an
|
|
80
|
+
// optimistic rollback cannot replay that edit when the field blurs.
|
|
81
|
+
if (!isFocused) {
|
|
82
|
+
lastCommitRef.current = null;
|
|
83
|
+
}
|
|
84
|
+
if (rejectedValue !== null) {
|
|
85
|
+
setRejectedValue(null);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const nativeValue = normalizeNativeTime(value) ?? '';
|
|
89
|
+
const isInputValid = rejectedValue === null;
|
|
90
|
+
const formatDisplayTime = hourFormat === '12h' ? formatDisplayTime12h : formatDisplayTime24h;
|
|
91
|
+
const overlayText = nativeValue ? formatDisplayTime(nativeValue, false) : placeholder;
|
|
92
|
+
const showsOverlay = !!overlayText && !(isFocused && isSegmentEditable);
|
|
93
|
+
const commitValue = useCallback(newValue => {
|
|
94
|
+
if (isEffectivelyDisabled || lastCommitRef.current === newValue) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!newValue) {
|
|
98
|
+
lastCommitRef.current = newValue;
|
|
99
|
+
setRejectedValue(null);
|
|
100
|
+
if (value !== undefined) {
|
|
101
|
+
onChange(undefined);
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const normalized = normalizeNativeTime(newValue);
|
|
106
|
+
if (!normalized) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!isTimeInRange(normalized, min, max)) {
|
|
110
|
+
setRejectedValue(newValue);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
setRejectedValue(null);
|
|
114
|
+
lastCommitRef.current = newValue;
|
|
115
|
+
if (normalized !== value) {
|
|
116
|
+
onChange(normalized);
|
|
117
|
+
}
|
|
118
|
+
}, [isEffectivelyDisabled, max, min, onChange, value]);
|
|
119
|
+
const handleChange = useCallback(event => {
|
|
120
|
+
commitValue(event.target.value);
|
|
121
|
+
}, [commitValue]);
|
|
122
|
+
|
|
123
|
+
// React's synthetic change system does not reliably observe iOS picker edits.
|
|
124
|
+
const commitRef = useRef(commitValue);
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
commitRef.current = commitValue;
|
|
127
|
+
});
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
const input = internalInputRef.current;
|
|
130
|
+
if (!input) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const handleNative = () => commitRef.current(input.value);
|
|
134
|
+
input.addEventListener('input', handleNative);
|
|
135
|
+
input.addEventListener('change', handleNative);
|
|
136
|
+
return () => {
|
|
137
|
+
input.removeEventListener('input', handleNative);
|
|
138
|
+
input.removeEventListener('change', handleNative);
|
|
139
|
+
};
|
|
140
|
+
}, []);
|
|
141
|
+
|
|
142
|
+
// React touches defaultValue after mount when the prop changes. Capture it
|
|
143
|
+
// once, then reconcile through the unfocused-only effect below.
|
|
144
|
+
const initialValueRef = useRef(null);
|
|
145
|
+
if (initialValueRef.current === null) {
|
|
146
|
+
initialValueRef.current = nativeValue;
|
|
147
|
+
}
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
if (isFocused) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const input = internalInputRef.current;
|
|
153
|
+
if (input && input.value !== nativeValue) {
|
|
154
|
+
input.value = nativeValue;
|
|
155
|
+
}
|
|
156
|
+
}, [isFocused, nativeValue]);
|
|
157
|
+
const handleFocus = useCallback(() => {
|
|
158
|
+
valueAtFocusRef.current = nativeValue;
|
|
159
|
+
// The engine probe classifies whether WebKit/Blink exposes editable native
|
|
160
|
+
// segments. Date and time controls share that engine-level behavior.
|
|
161
|
+
setIsSegmentEditable(hasEditableDateSegments(isTouchPointer));
|
|
162
|
+
setIsFocused(true);
|
|
163
|
+
}, [isTouchPointer, nativeValue]);
|
|
164
|
+
const handleBlur = useCallback(() => {
|
|
165
|
+
const domValue = internalInputRef.current?.value;
|
|
166
|
+
const valueChangedWhileFocused = valueAtFocusRef.current !== null && valueAtFocusRef.current !== nativeValue;
|
|
167
|
+
const wasRejected = rejectedValue !== null;
|
|
168
|
+
valueAtFocusRef.current = null;
|
|
169
|
+
setIsFocused(false);
|
|
170
|
+
setRejectedValue(null);
|
|
171
|
+
if (!valueChangedWhileFocused && !wasRejected && domValue !== undefined && domValue !== nativeValue) {
|
|
172
|
+
commitValue(domValue);
|
|
173
|
+
}
|
|
174
|
+
lastCommitRef.current = null;
|
|
175
|
+
}, [commitValue, nativeValue, rejectedValue]);
|
|
176
|
+
const openPicker = useCallback(() => {
|
|
177
|
+
if (isEffectivelyDisabled) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const input = internalInputRef.current;
|
|
181
|
+
if (!input) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
input.focus();
|
|
185
|
+
if (typeof input.showPicker === 'function') {
|
|
186
|
+
try {
|
|
187
|
+
input.showPicker();
|
|
188
|
+
} catch {
|
|
189
|
+
// Focus raises the iOS picker and is the fallback when showPicker needs
|
|
190
|
+
// user activation or is unavailable.
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}, [isEffectivelyDisabled]);
|
|
194
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
195
|
+
children: [/*#__PURE__*/_jsx("button", {
|
|
196
|
+
type: "button",
|
|
197
|
+
onClick: openPicker,
|
|
198
|
+
disabled: isEffectivelyDisabled,
|
|
199
|
+
"aria-label": openPickerLabel,
|
|
200
|
+
tabIndex: -1,
|
|
201
|
+
...stylex.props(focusOutlineStyles.focusVisible, styles.iconButton, isEffectivelyDisabled && styles.iconButtonDisabled),
|
|
202
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
203
|
+
icon: "clock",
|
|
204
|
+
size: "sm",
|
|
205
|
+
color: "secondary",
|
|
206
|
+
...iconThemeProps
|
|
207
|
+
})
|
|
208
|
+
}), /*#__PURE__*/_jsxs("span", {
|
|
209
|
+
...stylex.props(styles.slot),
|
|
210
|
+
children: [/*#__PURE__*/_jsx("input", {
|
|
211
|
+
ref: mergedInputRef,
|
|
212
|
+
id: id,
|
|
213
|
+
type: "time"
|
|
214
|
+
// UNCONTROLLED on purpose; see initialValueRef and the sync effect.
|
|
215
|
+
,
|
|
216
|
+
defaultValue: initialValueRef.current ?? '',
|
|
217
|
+
onChange: handleChange,
|
|
218
|
+
onFocus: handleFocus,
|
|
219
|
+
onBlur: handleBlur,
|
|
220
|
+
min: min,
|
|
221
|
+
max: max,
|
|
222
|
+
step: 60,
|
|
223
|
+
disabled: isEffectivelyDisabled && !hasDisabledMessage,
|
|
224
|
+
"aria-disabled": hasDisabledMessage ? 'true' : undefined,
|
|
225
|
+
readOnly: hasDisabledMessage || undefined,
|
|
226
|
+
"aria-label": ariaLabelledBy ? undefined : inputLabel,
|
|
227
|
+
"aria-labelledby": ariaLabelledBy,
|
|
228
|
+
"aria-describedby": ariaDescribedBy,
|
|
229
|
+
autoFocus: hasAutoFocus,
|
|
230
|
+
"data-autofocus": hasAutoFocus || undefined,
|
|
231
|
+
"aria-required": isEffectivelyRequired ? 'true' : undefined,
|
|
232
|
+
"aria-invalid": statusType === 'error' || !isInputValid ? 'true' : undefined,
|
|
233
|
+
"aria-busy": isBusy || undefined,
|
|
234
|
+
...stylex.props(styles.input, showsOverlay && styles.inputTextHidden, isEffectivelyDisabled && styles.inputDisabled, !isInputValid && styles.inputInvalid)
|
|
235
|
+
}), showsOverlay && /*#__PURE__*/_jsx("span", {
|
|
236
|
+
"aria-hidden": "true",
|
|
237
|
+
...stylex.props(styles.overlay, nativeValue ? styles.overlayValue : styles.overlayPlaceholder, isEffectivelyDisabled && styles.inputDisabled, !isInputValid && !!nativeValue && styles.inputInvalid),
|
|
238
|
+
children: overlayText
|
|
239
|
+
})]
|
|
240
|
+
}), /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
241
|
+
as: "div",
|
|
242
|
+
role: "alert",
|
|
243
|
+
"aria-live": "assertive",
|
|
244
|
+
children: !isInputValid ? t('@astryx.timeInput.invalidTime') : ''
|
|
245
|
+
})]
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
NativeTimeSegment.displayName = 'NativeTimeSegment';
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* @position Package entry point for DateTimeInput
|
|
6
6
|
*/
|
|
7
7
|
export { DateTimeInput } from './DateTimeInput';
|
|
8
|
-
export type { DateTimeInputProps, DateTimeInputSize, DateTimeInputHourFormat, DateTimeInputTimeIncrement, DateTimeInputTimeOptionInterval, DateTimeInputStatus, DateTimeInputStatusType, ISODateTimeString, } from './DateTimeInput';
|
|
8
|
+
export type { DateTimeInputProps, DateTimeInputSize, DateTimeInputHourFormat, DateTimeInputNativePicker, DateTimeInputTimeIncrement, DateTimeInputTimeOptionInterval, DateTimeInputStatus, DateTimeInputStatusType, ISODateTimeString, } from './DateTimeInput';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/index.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,0BAA0B,EAC1B,+BAA+B,EAC/B,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/index.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,0BAA0B,EAC1B,+BAA+B,EAC/B,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file nativePickerSegmentStyles.ts
|
|
3
|
+
* @input Uses StyleX and Astryx typography, color, and radius tokens
|
|
4
|
+
* @output Exports styles shared by DateTimeInput's native date and time controls
|
|
5
|
+
* @position Internal styling shared by NativeDateSegment and NativeTimeSegment
|
|
6
|
+
*/
|
|
7
|
+
import * as stylex from '@stylexjs/stylex';
|
|
8
|
+
export declare const nativePickerSegmentStyles: Readonly<{
|
|
9
|
+
readonly iconButton: Readonly<{
|
|
10
|
+
readonly display: stylex.StyleXClassNameFor<"display", "flex">;
|
|
11
|
+
readonly alignItems: stylex.StyleXClassNameFor<"alignItems", "center">;
|
|
12
|
+
readonly justifyContent: stylex.StyleXClassNameFor<"justifyContent", "center">;
|
|
13
|
+
readonly padding: stylex.StyleXClassNameFor<"padding", 0>;
|
|
14
|
+
readonly margin: stylex.StyleXClassNameFor<"margin", 0>;
|
|
15
|
+
readonly borderWidth: stylex.StyleXClassNameFor<"borderWidth", 0>;
|
|
16
|
+
readonly borderStyle: stylex.StyleXClassNameFor<"borderStyle", "none">;
|
|
17
|
+
readonly backgroundColor: stylex.StyleXClassNameFor<"backgroundColor", "transparent">;
|
|
18
|
+
readonly cursor: stylex.StyleXClassNameFor<"cursor", "default" | "pointer">;
|
|
19
|
+
readonly borderRadius: stylex.StyleXClassNameFor<"borderRadius", "8px">;
|
|
20
|
+
}>;
|
|
21
|
+
readonly iconButtonDisabled: Readonly<{
|
|
22
|
+
readonly cursor: stylex.StyleXClassNameFor<"cursor", "default">;
|
|
23
|
+
}>;
|
|
24
|
+
readonly input: Readonly<{
|
|
25
|
+
readonly display: stylex.StyleXClassNameFor<"display", "block">;
|
|
26
|
+
readonly flex: stylex.StyleXClassNameFor<"flex", 1>;
|
|
27
|
+
readonly minWidth: stylex.StyleXClassNameFor<"minWidth", 0>;
|
|
28
|
+
readonly borderWidth: stylex.StyleXClassNameFor<"borderWidth", 0>;
|
|
29
|
+
readonly borderStyle: stylex.StyleXClassNameFor<"borderStyle", "none">;
|
|
30
|
+
readonly padding: stylex.StyleXClassNameFor<"padding", 0>;
|
|
31
|
+
readonly fontFamily: stylex.StyleXClassNameFor<"fontFamily", "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif">;
|
|
32
|
+
readonly fontSize: stylex.StyleXClassNameFor<"fontSize", "var(--font-size-base)" | `max(1rem, ${stylex.StyleXVar<"var(--font-size-base)">})`>;
|
|
33
|
+
readonly lineHeight: stylex.StyleXClassNameFor<"lineHeight", "1.4286">;
|
|
34
|
+
readonly color: stylex.StyleXClassNameFor<"color", "light-dark(#0A1317, #DFE2E5)">;
|
|
35
|
+
readonly backgroundColor: stylex.StyleXClassNameFor<"backgroundColor", "transparent">;
|
|
36
|
+
readonly outline: stylex.StyleXClassNameFor<"outline", "none">;
|
|
37
|
+
readonly height: stylex.StyleXClassNameFor<"height", "1lh" | `calc(max(1rem, ${stylex.StyleXVar<"var(--font-size-base)">}) * ${stylex.StyleXVar<"1.4286">})`>;
|
|
38
|
+
readonly WebkitAppearance: stylex.StyleXClassNameFor<"WebkitAppearance", "none">;
|
|
39
|
+
readonly appearance: stylex.StyleXClassNameFor<"appearance", "none">;
|
|
40
|
+
readonly '::-webkit-calendar-picker-indicator': stylex.StyleXClassNameFor<"::-webkit-calendar-picker-indicator", {
|
|
41
|
+
readonly display: "none";
|
|
42
|
+
}>;
|
|
43
|
+
readonly '::-webkit-date-and-time-value': stylex.StyleXClassNameFor<"::-webkit-date-and-time-value", {
|
|
44
|
+
readonly textAlign: "start";
|
|
45
|
+
readonly marginBlock: 0;
|
|
46
|
+
readonly marginInline: 0;
|
|
47
|
+
readonly paddingBlock: 0;
|
|
48
|
+
readonly paddingInline: 0;
|
|
49
|
+
readonly lineHeight: "inherit";
|
|
50
|
+
readonly minHeight: 0;
|
|
51
|
+
}>;
|
|
52
|
+
readonly '::-webkit-datetime-edit': stylex.StyleXClassNameFor<"::-webkit-datetime-edit", {
|
|
53
|
+
readonly paddingBlock: 0;
|
|
54
|
+
readonly paddingInline: 0;
|
|
55
|
+
readonly lineHeight: "inherit";
|
|
56
|
+
}>;
|
|
57
|
+
}>;
|
|
58
|
+
readonly inputDisabled: Readonly<{
|
|
59
|
+
readonly cursor: stylex.StyleXClassNameFor<"cursor", "default">;
|
|
60
|
+
}>;
|
|
61
|
+
readonly inputInvalid: Readonly<{
|
|
62
|
+
readonly color: stylex.StyleXClassNameFor<"color", "light-dark(#4E606F, #AAAFB5)">;
|
|
63
|
+
}>;
|
|
64
|
+
readonly inputTextHidden: Readonly<{
|
|
65
|
+
readonly color: stylex.StyleXClassNameFor<"color", "transparent">;
|
|
66
|
+
readonly WebkitTextFillColor: stylex.StyleXClassNameFor<"WebkitTextFillColor", "transparent">;
|
|
67
|
+
}>;
|
|
68
|
+
readonly slot: Readonly<{
|
|
69
|
+
readonly position: stylex.StyleXClassNameFor<"position", "relative">;
|
|
70
|
+
readonly display: stylex.StyleXClassNameFor<"display", "flex">;
|
|
71
|
+
readonly alignItems: stylex.StyleXClassNameFor<"alignItems", "center">;
|
|
72
|
+
readonly flex: stylex.StyleXClassNameFor<"flex", 1>;
|
|
73
|
+
readonly minInlineSize: stylex.StyleXClassNameFor<"minInlineSize", 0>;
|
|
74
|
+
}>;
|
|
75
|
+
readonly overlay: Readonly<{
|
|
76
|
+
readonly position: stylex.StyleXClassNameFor<"position", "absolute">;
|
|
77
|
+
readonly insetInlineStart: stylex.StyleXClassNameFor<"insetInlineStart", 0>;
|
|
78
|
+
readonly insetInlineEnd: stylex.StyleXClassNameFor<"insetInlineEnd", 0>;
|
|
79
|
+
readonly insetBlock: stylex.StyleXClassNameFor<"insetBlock", 0>;
|
|
80
|
+
readonly display: stylex.StyleXClassNameFor<"display", "block">;
|
|
81
|
+
readonly fontSize: stylex.StyleXClassNameFor<"fontSize", "var(--font-size-base)" | `max(1rem, ${stylex.StyleXVar<"var(--font-size-base)">})`>;
|
|
82
|
+
readonly lineHeight: stylex.StyleXClassNameFor<"lineHeight", "1.4286">;
|
|
83
|
+
readonly pointerEvents: stylex.StyleXClassNameFor<"pointerEvents", "none">;
|
|
84
|
+
readonly overflow: stylex.StyleXClassNameFor<"overflow", "hidden">;
|
|
85
|
+
readonly whiteSpace: stylex.StyleXClassNameFor<"whiteSpace", "nowrap">;
|
|
86
|
+
readonly textOverflow: stylex.StyleXClassNameFor<"textOverflow", "ellipsis">;
|
|
87
|
+
}>;
|
|
88
|
+
readonly overlayValue: Readonly<{
|
|
89
|
+
readonly color: stylex.StyleXClassNameFor<"color", "light-dark(#0A1317, #DFE2E5)">;
|
|
90
|
+
}>;
|
|
91
|
+
readonly overlayPlaceholder: Readonly<{
|
|
92
|
+
readonly color: stylex.StyleXClassNameFor<"color", "light-dark(#4E606F, #AAAFB5)">;
|
|
93
|
+
}>;
|
|
94
|
+
}>;
|
|
95
|
+
//# sourceMappingURL=nativePickerSegmentStyles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nativePickerSegmentStyles.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/nativePickerSegmentStyles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAQ3C,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsGpC,CAAC"}
|