@astryxdesign/core 0.4.7 → 0.5.0-canary.32a62fd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +161 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -2
- package/dist/AspectRatio/AspectRatio.d.ts +24 -0
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +23 -4
- package/dist/Avatar/Avatar.d.ts +25 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +58 -19
- package/dist/Avatar/index.d.ts +2 -2
- package/dist/Avatar/index.d.ts.map +1 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +8 -4
- package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
- package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
- package/dist/Banner/Banner.d.ts +40 -15
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +51 -18
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +17 -4
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +5 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +26 -7
- package/dist/Calendar/Calendar.d.ts +3 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +13 -14
- package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
- package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
- package/dist/Calendar/getInitialFocusDate.js +62 -0
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +3 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +2 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +3 -3
- package/dist/Chat/ChatMessageList.d.ts +22 -3
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +6 -3
- package/dist/Chat/ChatTokenizedText.d.ts +2 -0
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +11 -6
- package/dist/Chat/useChatComposerTokens.js +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +10 -3
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +15 -4
- package/dist/CodeBlock/highlightRanges.js +1 -1
- package/dist/CodeBlock/highlightStyles.js +13 -13
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +3 -2
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +3 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- package/dist/DateInput/DateInput.d.ts +43 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +22 -2
- package/dist/DateInput/NativeDateField.d.ts +10 -0
- package/dist/DateInput/NativeDateField.d.ts.map +1 -0
- package/dist/DateInput/NativeDateField.js +477 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +38 -4
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +406 -12
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.d.ts +7 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +89 -58
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +3 -2
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +6 -2
- package/dist/HoverCard/HoverCard.d.ts +6 -0
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +52 -3
- package/dist/HoverCard/useHoverCard.d.ts +16 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +74 -26
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +6 -2
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +2 -19
- package/dist/Layer/LayerDepthContext.d.ts +52 -0
- package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
- package/dist/Layer/LayerDepthContext.js +66 -0
- package/dist/Layer/index.d.ts +3 -0
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +4 -0
- package/dist/Layer/layerStack.d.ts +98 -0
- package/dist/Layer/layerStack.d.ts.map +1 -0
- package/dist/Layer/layerStack.js +306 -0
- package/dist/Layer/useLayerDismissal.d.ts +93 -0
- package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
- package/dist/Layer/useLayerDismissal.js +91 -0
- package/dist/Lightbox/Lightbox.d.ts +1 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +103 -81
- package/dist/Markdown/index.d.ts +1 -1
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/parser.d.ts +38 -1
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +177 -29
- package/dist/MobileNav/MobileNav.d.ts +6 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +61 -36
- package/dist/MultiSelector/MultiSelector.d.ts +15 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +17 -6
- package/dist/MultiSelector/index.d.ts +1 -1
- package/dist/MultiSelector/index.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.js +5 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +3 -2
- package/dist/NumberInput/NumberInput.d.ts +1 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +27 -37
- package/dist/NumberInput/numberParser.d.ts +43 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -0
- package/dist/NumberInput/numberParser.js +293 -0
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +3 -2
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +3 -2
- package/dist/Overlay/Overlay.d.ts.map +1 -1
- package/dist/Overlay/Overlay.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +20 -17
- package/dist/PowerSearch/PowerSearch.d.ts +8 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +19 -6
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +19 -9
- package/dist/PowerSearch/types.d.ts +2 -0
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +14 -5
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +18 -5
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +3 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +3 -3
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +5 -0
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -3
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +8 -7
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +4 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -3
- package/dist/Spinner/Spinner.d.ts +3 -3
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +130 -78
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +6 -1
- package/dist/Stepper/Step.d.ts +140 -0
- package/dist/Stepper/Step.d.ts.map +1 -0
- package/dist/Stepper/Step.js +1045 -0
- package/dist/Stepper/StepStatus.d.ts +24 -0
- package/dist/Stepper/StepStatus.d.ts.map +1 -0
- package/dist/Stepper/StepStatus.js +1 -0
- package/dist/Stepper/Stepper.d.ts +93 -0
- package/dist/Stepper/Stepper.d.ts.map +1 -0
- package/dist/Stepper/Stepper.js +184 -0
- package/dist/Stepper/StepperContext.d.ts +41 -0
- package/dist/Stepper/StepperContext.d.ts.map +1 -0
- package/dist/Stepper/StepperContext.js +34 -0
- package/dist/Stepper/index.d.ts +8 -0
- package/dist/Stepper/index.d.ts.map +1 -0
- package/dist/Stepper/index.js +7 -0
- package/dist/Stepper/stepper.stylex.d.ts +15 -0
- package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
- package/dist/Stepper/stepper.stylex.js +20 -0
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +8 -3
- package/dist/TabList/Tab.d.ts +15 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +32 -7
- package/dist/TabList/TabList.d.ts +46 -7
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +353 -23
- package/dist/TabList/TabListContext.d.ts +11 -1
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +11 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +3 -2
- package/dist/TabList/index.d.ts +2 -2
- package/dist/TabList/index.d.ts.map +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +10 -2
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +3 -6
- package/dist/Table/TableRow.d.ts +16 -5
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +16 -5
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
- package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +19 -5
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
- package/dist/Table/types.d.ts +22 -4
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -0
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +6 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +9 -3
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +3 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +5 -3
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +2 -2
- package/dist/Tokenizer/Tokenizer.d.ts +3 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +2 -0
- package/dist/Tooltip/Tooltip.d.ts +5 -0
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +5 -0
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +39 -24
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +5 -4
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +3 -3
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +4 -3
- package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +68 -29
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -2
- package/dist/astryx.css +94 -7
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useFocusTrap.d.ts +7 -4
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +60 -95
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +3 -18
- package/dist/hooks/useMergedRefs.d.ts +18 -0
- package/dist/hooks/useMergedRefs.d.ts.map +1 -0
- package/dist/hooks/useMergedRefs.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +24 -4
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.js +5 -2
- package/dist/utils/groupItems.d.ts +5 -1
- package/dist/utils/groupItems.d.ts.map +1 -1
- package/dist/utils/groupItems.js +9 -9
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/isApplePlatform.d.ts +18 -0
- package/dist/utils/isApplePlatform.d.ts.map +1 -0
- package/dist/utils/isApplePlatform.js +37 -0
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +10 -1
- package/dist/utils/timeParser.d.ts +1 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +26 -12
- package/locales/en.json +31 -7
- package/locales/pseudo.json +18 -0
- package/package.json +8 -3
- package/src/AppShell/AppShell.tsx +3 -2
- package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
- package/src/AspectRatio/AspectRatio.test.tsx +57 -10
- package/src/AspectRatio/AspectRatio.tsx +40 -1
- package/src/Avatar/Avatar.doc.mjs +14 -3
- package/src/Avatar/Avatar.test.tsx +97 -0
- package/src/Avatar/Avatar.tsx +125 -52
- package/src/Avatar/index.ts +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
- package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
- package/src/AvatarGroup/AvatarGroup.tsx +15 -6
- package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
- package/src/Banner/Banner.doc.mjs +13 -11
- package/src/Banner/Banner.test.tsx +102 -15
- package/src/Banner/Banner.tsx +72 -25
- package/src/BottomSheet/BottomSheet.test.tsx +123 -0
- package/src/BottomSheet/BottomSheet.tsx +17 -4
- package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
- package/src/Button/Button.doc.mjs +22 -0
- package/src/Button/Button.test.tsx +13 -0
- package/src/Button/Button.tsx +5 -4
- package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
- package/src/ButtonGroup/ButtonGroup.test.tsx +391 -1
- package/src/ButtonGroup/ButtonGroup.tsx +23 -5
- package/src/Calendar/Calendar.doc.mjs +4 -3
- package/src/Calendar/Calendar.test.tsx +52 -0
- package/src/Calendar/Calendar.tsx +18 -15
- package/src/Calendar/getInitialFocusDate.test.ts +94 -0
- package/src/Calendar/getInitialFocusDate.ts +93 -0
- package/src/Carousel/Carousel.tsx +3 -2
- package/src/Chat/ChatComposerInput.tsx +5 -1
- package/src/Chat/ChatLayout.tsx +3 -2
- package/src/Chat/ChatMessageList.doc.mjs +9 -1
- package/src/Chat/ChatMessageList.test.tsx +46 -0
- package/src/Chat/ChatMessageList.tsx +28 -4
- package/src/Chat/ChatTokenizedText.tsx +17 -10
- package/src/Chat/useChatComposerTokens.ts +1 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
- package/src/CheckboxInput/CheckboxInput.tsx +8 -2
- package/src/ClickableCard/ClickableCard.tsx +3 -2
- package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
- package/src/CodeBlock/CodeBlock.test.tsx +37 -0
- package/src/CodeBlock/CodeBlock.tsx +20 -4
- package/src/CodeBlock/highlightRanges.ts +1 -1
- package/src/CodeBlock/highlightStyles.ts +13 -13
- package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
- package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
- package/src/ContextMenu/ContextMenu.tsx +4 -3
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.tsx +55 -2
- package/src/DateInput/DateInputTouch.test.tsx +68 -9
- package/src/DateInput/NativeDateField.test.tsx +565 -0
- package/src/DateInput/NativeDateField.tsx +623 -0
- package/src/DateInput/TouchDateField.tsx +38 -4
- package/src/DateInput/index.ts +1 -0
- package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
- package/src/DateTimeInput/DateTimeInput.tsx +556 -24
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/Dialog.doc.mjs +8 -3
- package/src/Dialog/Dialog.test.tsx +261 -1
- package/src/Dialog/Dialog.tsx +109 -58
- package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
- package/src/Field/Field.doc.mjs +13 -2
- package/src/Field/FieldLabel.test.tsx +29 -0
- package/src/Field/FieldLabel.tsx +7 -0
- package/src/FileInput/FileInput.tsx +3 -2
- package/src/Heading/Heading.test.tsx +23 -1
- package/src/Heading/Heading.tsx +6 -2
- package/src/HoverCard/HoverCard.doc.mjs +13 -2
- package/src/HoverCard/HoverCard.test.tsx +101 -4
- package/src/HoverCard/HoverCard.tsx +71 -3
- package/src/HoverCard/useHoverCard.tsx +101 -33
- package/src/Indicator/CheckboxIndicator.tsx +14 -8
- package/src/Indicator/Indicator.doc.mjs +2 -0
- package/src/Item/Item.tsx +5 -4
- package/src/Kbd/Kbd.tsx +2 -19
- package/src/Layer/LayerDepthContext.tsx +62 -0
- package/src/Layer/index.ts +9 -0
- package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
- package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
- package/src/Layer/layerStack.ts +362 -0
- package/src/Layer/useLayerDismissal.test.tsx +469 -0
- package/src/Layer/useLayerDismissal.ts +173 -0
- package/src/Layout/Layout.doc.mjs +2 -2
- package/src/Lightbox/Lightbox.doc.mjs +12 -0
- package/src/Lightbox/Lightbox.tsx +124 -102
- package/src/Link/Link.doc.mjs +39 -0
- package/src/Markdown/Markdown.doc.mjs +5 -0
- package/src/Markdown/incremental.test.ts +16 -2
- package/src/Markdown/index.ts +1 -0
- package/src/Markdown/parser.perf.test.ts +96 -1
- package/src/Markdown/parser.test.ts +145 -2
- package/src/Markdown/parser.ts +244 -29
- package/src/MobileNav/MobileNav.tsx +62 -36
- package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
- package/src/MultiSelector/MultiSelector.test.tsx +106 -0
- package/src/MultiSelector/MultiSelector.tsx +50 -6
- package/src/MultiSelector/index.ts +1 -0
- package/src/NavIcon/NavIcon.doc.mjs +8 -2
- package/src/NavIcon/NavIcon.test.tsx +9 -0
- package/src/NavIcon/NavIcon.tsx +5 -1
- package/src/NavMenu/NavHeadingMenu.tsx +3 -2
- package/src/NumberInput/NumberInput.doc.mjs +20 -0
- package/src/NumberInput/NumberInput.tsx +28 -29
- package/src/NumberInput/numberParser.test.ts +137 -0
- package/src/NumberInput/numberParser.ts +346 -0
- package/src/Outline/Outline.tsx +3 -2
- package/src/OverflowList/OverflowList.tsx +3 -2
- package/src/Overlay/Overlay.tsx +3 -2
- package/src/Popover/usePopover.tsx +31 -28
- package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
- package/src/PowerSearch/PowerSearch.test.tsx +240 -1
- package/src/PowerSearch/PowerSearch.tsx +34 -5
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +201 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +47 -1
- package/src/PowerSearch/PowerSearchValueEditor.tsx +15 -0
- package/src/PowerSearch/types.ts +2 -0
- package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
- package/src/PowerSearch/usePowerSearchSource.ts +13 -3
- package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
- package/src/ProgressBar/ProgressBar.test.tsx +24 -0
- package/src/ProgressBar/ProgressBar.tsx +28 -8
- package/src/Resizable/ResizeHandle.tsx +3 -2
- package/src/SegmentedControl/SegmentedControl.tsx +3 -2
- package/src/SelectableCard/SelectableCard.tsx +3 -2
- package/src/Selector/Selector.doc.mjs +12 -1
- package/src/Selector/Selector.test.tsx +45 -1
- package/src/Selector/Selector.tsx +11 -1
- package/src/SideNav/SideNav.doc.mjs +6 -6
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavHeading.tsx +12 -12
- package/src/SideNav/SideNavItem.tsx +4 -2
- package/src/Slider/Slider.tsx +3 -2
- package/src/Spinner/Spinner.test.tsx +147 -1
- package/src/Spinner/Spinner.tsx +120 -101
- package/src/StatusDot/StatusDot.doc.mjs +8 -2
- package/src/StatusDot/StatusDot.test.tsx +9 -0
- package/src/StatusDot/StatusDot.tsx +7 -1
- package/src/Stepper/Step.doc.mjs +98 -0
- package/src/Stepper/Step.tsx +1638 -0
- package/src/Stepper/StepStatus.ts +26 -0
- package/src/Stepper/Stepper.doc.mjs +370 -0
- package/src/Stepper/Stepper.test.tsx +1024 -0
- package/src/Stepper/Stepper.tsx +258 -0
- package/src/Stepper/StepperContext.ts +71 -0
- package/src/Stepper/index.ts +18 -0
- package/src/Stepper/stepper.stylex.ts +19 -0
- package/src/Switch/Switch.doc.mjs +2 -0
- package/src/Switch/Switch.test.tsx +10 -0
- package/src/Switch/Switch.tsx +6 -2
- package/src/TabList/Tab.doc.mjs +13 -1
- package/src/TabList/Tab.tsx +67 -7
- package/src/TabList/TabList.doc.mjs +22 -6
- package/src/TabList/TabList.test.tsx +559 -0
- package/src/TabList/TabList.tsx +490 -22
- package/src/TabList/TabListContext.ts +13 -2
- package/src/TabList/TabMenu.tsx +3 -2
- package/src/TabList/index.ts +6 -2
- package/src/Table/BaseTable.tsx +12 -4
- package/src/Table/Table.doc.mjs +9 -2
- package/src/Table/Table.test.tsx +132 -14
- package/src/Table/Table.tsx +3 -8
- package/src/Table/TableBody.doc.mjs +40 -0
- package/src/Table/TableFooter.doc.mjs +40 -0
- package/src/Table/TableHeader.doc.mjs +40 -0
- package/src/Table/TableRow.tsx +16 -5
- package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
- package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
- package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
- package/src/Table/types.ts +22 -4
- package/src/Table/useBaseTablePlugins.ts +5 -0
- package/src/Table/useTableGroupedRows.doc.mjs +5 -4
- package/src/Table/useTablePagination.doc.mjs +7 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +31 -0
- package/src/Text/Text.test.tsx +23 -1
- package/src/Text/Text.tsx +6 -2
- package/src/TextArea/TextArea.doc.mjs +8 -2
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +15 -8
- package/src/TextInput/TextInput.doc.mjs +10 -0
- package/src/TextInput/TextInput.tsx +3 -2
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.tsx +2 -2
- package/src/Timestamp/Timestamp.tsx +4 -2
- package/src/Toast/Toast.doc.mjs +6 -0
- package/src/Token/TokenLink.tsx +2 -2
- package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
- package/src/Tokenizer/Tokenizer.tsx +4 -0
- package/src/Toolbar/Toolbar.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.test.tsx +32 -0
- package/src/Tooltip/Tooltip.tsx +5 -0
- package/src/Tooltip/useTooltip.tsx +47 -24
- package/src/TopNav/TopNavHeading.tsx +5 -4
- package/src/TopNav/TopNavMegaMenu.tsx +3 -2
- package/src/TopNav/TopNavMenu.tsx +4 -3
- package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
- package/src/Typeahead/BaseTypeahead.tsx +85 -33
- package/src/Typeahead/Typeahead.doc.mjs +5 -0
- package/src/Typeahead/Typeahead.test.tsx +49 -0
- package/src/Typeahead/Typeahead.tsx +3 -2
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useContainerReveal.doc.mjs +2 -2
- package/src/hooks/useFocusTrap.test.tsx +14 -0
- package/src/hooks/useFocusTrap.ts +62 -111
- package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
- package/src/hooks/useHotkeys.ts +3 -18
- package/src/hooks/useMergedRefs.doc.mjs +79 -0
- package/src/hooks/useMergedRefs.test.tsx +62 -0
- package/src/hooks/useMergedRefs.ts +36 -0
- package/src/index.ts +1 -0
- package/src/theme/MediaTheme.doc.mjs +5 -5
- package/src/theme/derivedVarRegistry.test.ts +19 -3
- package/src/theme/derivedVarRegistry.ts +23 -4
- package/src/theme/generateThemeRules.test.ts +37 -0
- package/src/theme/syntax/tokens.ts +5 -2
- package/src/utils/groupItems.ts +12 -6
- package/src/utils/index.ts +1 -1
- package/src/utils/isApplePlatform.test.ts +61 -0
- package/src/utils/isApplePlatform.ts +37 -0
- package/src/utils/sharedResizeObserver.ts +10 -2
- package/src/utils/timeParser.test.ts +6 -1
- package/src/utils/timeParser.ts +35 -13
- package/src/__tests__/inputWidthContract.test.tsx +0 -69
|
@@ -276,6 +276,7 @@ export function MultiSelector({
|
|
|
276
276
|
hasSearch = false,
|
|
277
277
|
searchPlaceholder: searchPlaceholderFromProps,
|
|
278
278
|
triggerDisplay = 'count',
|
|
279
|
+
formatValue,
|
|
279
280
|
maxBadges = 3,
|
|
280
281
|
renderOption,
|
|
281
282
|
indicatorPosition = 'start',
|
|
@@ -576,12 +577,16 @@ export function MultiSelector({
|
|
|
576
577
|
}, [popover.isOpen, highlightedIndex, getItemId]);
|
|
577
578
|
|
|
578
579
|
// Build trigger display content
|
|
579
|
-
const
|
|
580
|
+
const selectedItems = useMemo(() => {
|
|
580
581
|
return optimisticValue.map(v => {
|
|
581
582
|
const item = selectableItems.find(i => i.value === v);
|
|
582
|
-
return
|
|
583
|
+
return {
|
|
584
|
+
value: v,
|
|
585
|
+
label: item?.label ?? v
|
|
586
|
+
};
|
|
583
587
|
});
|
|
584
588
|
}, [optimisticValue, selectableItems]);
|
|
589
|
+
const selectedLabels = useMemo(() => selectedItems.map(item => item.label), [selectedItems]);
|
|
585
590
|
const renderTriggerContent = useCallback(() => {
|
|
586
591
|
if (optimisticValue.length === 0) {
|
|
587
592
|
return /*#__PURE__*/_jsx("span", {
|
|
@@ -593,11 +598,11 @@ export function MultiSelector({
|
|
|
593
598
|
}
|
|
594
599
|
switch (triggerDisplay) {
|
|
595
600
|
case 'count':
|
|
596
|
-
return /*#__PURE__*/
|
|
601
|
+
return /*#__PURE__*/_jsx("span", {
|
|
597
602
|
...{
|
|
598
603
|
className: "xb3r6kr xlyipyv xuxw1ft"
|
|
599
604
|
},
|
|
600
|
-
children:
|
|
605
|
+
children: formatValue?.(selectedItems) ?? `${optimisticValue.length} selected`
|
|
601
606
|
});
|
|
602
607
|
case 'labels':
|
|
603
608
|
{
|
|
@@ -608,7 +613,7 @@ export function MultiSelector({
|
|
|
608
613
|
...{
|
|
609
614
|
className: "xb3r6kr xlyipyv xuxw1ft"
|
|
610
615
|
},
|
|
611
|
-
children: text
|
|
616
|
+
children: formatValue?.(selectedItems) ?? text
|
|
612
617
|
});
|
|
613
618
|
}
|
|
614
619
|
case 'badges':
|
|
@@ -631,7 +636,7 @@ export function MultiSelector({
|
|
|
631
636
|
});
|
|
632
637
|
}
|
|
633
638
|
}
|
|
634
|
-
}, [optimisticValue, triggerDisplay, selectedLabels, placeholder, maxBadges]);
|
|
639
|
+
}, [optimisticValue, triggerDisplay, selectedItems, selectedLabels, placeholder, formatValue, maxBadges]);
|
|
635
640
|
|
|
636
641
|
// Render search input
|
|
637
642
|
const renderSearch = useCallback(() => {
|
|
@@ -827,7 +832,13 @@ export function MultiSelector({
|
|
|
827
832
|
// A standalone divider between groups would orphan itself once its
|
|
828
833
|
// neighbors are filtered out, so skip it while searching.
|
|
829
834
|
if (!isSearching) {
|
|
835
|
+
// role="listbox" only permits option/group children; the divider
|
|
836
|
+
// carries no information the options don't, so it's hidden from
|
|
837
|
+
// the accessibility tree entirely rather than exposing
|
|
838
|
+
// role="separator" as a disallowed listbox child (axe
|
|
839
|
+
// aria-required-children).
|
|
830
840
|
elements.push(/*#__PURE__*/_jsx(Divider, {
|
|
841
|
+
"aria-hidden": "true",
|
|
831
842
|
xstyle: styles.divider
|
|
832
843
|
}, `divider-${i}`));
|
|
833
844
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @output Exports MultiSelector and types
|
|
4
4
|
* @position Public API entry point
|
|
5
5
|
*/
|
|
6
|
-
export { MultiSelector, type MultiSelectorProps, type MultiSelectorSize, type MultiSelectorStatusType, } from './MultiSelector';
|
|
6
|
+
export { MultiSelector, type MultiSelectorProps, type MultiSelectorSize, type MultiSelectorStatusType, type MultiSelectorSelectedItem, } from './MultiSelector';
|
|
7
7
|
export type { MultiSelectorOptionType, MultiSelectorOptionData, MultiSelectorDivider, MultiSelectorSection, MultiSelectorStatus, } from './types';
|
|
8
8
|
export { useMultiCombobox } from './hooks';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MultiSelector/index.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MultiSelector/index.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,GAC/B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavIcon.d.ts","sourceRoot":"","sources":["../../src/NavIcon/NavIcon.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAuB5C,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;OAGG;IACH,IAAI,EAAE,SAAS,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,YAAY,+
|
|
1
|
+
{"version":3,"file":"NavIcon.d.ts","sourceRoot":"","sources":["../../src/NavIcon/NavIcon.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAuB5C,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;OAGG;IACH,IAAI,EAAE,SAAS,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,YAAY,+BAkBd;yBAzBe,OAAO"}
|
package/dist/NavIcon/NavIcon.js
CHANGED
|
@@ -67,7 +67,11 @@ export function NavIcon({
|
|
|
67
67
|
}) {
|
|
68
68
|
return /*#__PURE__*/_jsx("span", {
|
|
69
69
|
ref: ref,
|
|
70
|
-
...mergeProps(themeProps('
|
|
70
|
+
...mergeProps(themeProps('nav-icon', undefined, {
|
|
71
|
+
// `navicon` ran the compound name together; themes styling it keep
|
|
72
|
+
// working until the next major.
|
|
73
|
+
legacyNames: ['navicon']
|
|
74
|
+
}), stylex.props(styles.base, xstyle), className, style),
|
|
71
75
|
...props,
|
|
72
76
|
children: icon
|
|
73
77
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavHeadingMenu.d.ts","sourceRoot":"","sources":["../../src/NavMenu/NavHeadingMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAuB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAIlE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAI5C,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"NavHeadingMenu.d.ts","sourceRoot":"","sources":["../../src/NavMenu/NavHeadingMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAuB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAIlE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAI5C,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAuB1B,MAAM,WAAW,mBAAoB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACpE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,QAAQ,EACR,IAAW,EACX,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,MAAM,GACtB,EAAE,mBAAmB,qBAiFrB;yBA1Fe,cAAc"}
|
|
@@ -15,11 +15,12 @@ import React, { useCallback, useMemo } from 'react';
|
|
|
15
15
|
import * as stylex from '@stylexjs/stylex';
|
|
16
16
|
import "../theme/tokens.stylex.js";
|
|
17
17
|
import { spacingVars } from "../theme/tokens.stylex.js";
|
|
18
|
-
import { mergeProps
|
|
18
|
+
import { mergeProps } from "../utils/index.js";
|
|
19
19
|
import { useListFocus } from "../hooks/useListFocus.js";
|
|
20
20
|
import { useTypeahead } from "../hooks/useTypeahead.js";
|
|
21
21
|
import { themeProps } from "../utils/themeProps.js";
|
|
22
22
|
import { NavHeadingMenuContext, useNavHeadingCloseContext } from "./NavMenuContext.js";
|
|
23
|
+
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
23
24
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
25
|
const styles = {
|
|
25
26
|
root: {
|
|
@@ -125,7 +126,7 @@ export function NavHeadingMenu({
|
|
|
125
126
|
return /*#__PURE__*/_jsx(NavHeadingMenuContext, {
|
|
126
127
|
value: ctx,
|
|
127
128
|
children: /*#__PURE__*/_jsx("div", {
|
|
128
|
-
ref:
|
|
129
|
+
ref: useMergedRefs(ref, listRef),
|
|
129
130
|
role: "menu",
|
|
130
131
|
onKeyDown: listKeyDown,
|
|
131
132
|
"data-testid": testId,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @position Core implementation; consumed by index.ts, tested by NumberInput.test.tsx
|
|
6
6
|
*
|
|
7
7
|
* SYNC: When modified, update these files to stay in sync:
|
|
8
|
+
* - /packages/core/src/NumberInput/numberParser.ts (locale-aware parsing)
|
|
8
9
|
* - /packages/core/src/NumberInput/NumberInput.doc.mjs (props table, features, implementation notes)
|
|
9
10
|
* - /packages/core/src/NumberInput/NumberInput.test.tsx (tests for new/changed behavior)
|
|
10
11
|
* - /packages/core/src/NumberInput/index.ts (exports if types change)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberInput.d.ts","sourceRoot":"","sources":["../../src/NumberInput/NumberInput.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"NumberInput.d.ts","sourceRoot":"","sources":["../../src/NumberInput/NumberInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by NumberInput.test.tsx
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update these files to stay in sync:
|
|
12
|
+
* - /packages/core/src/NumberInput/numberParser.ts (locale-aware parsing)
|
|
12
13
|
* - /packages/core/src/NumberInput/NumberInput.doc.mjs (props table, features, implementation notes)
|
|
13
14
|
* - /packages/core/src/NumberInput/NumberInput.test.tsx (tests for new/changed behavior)
|
|
14
15
|
* - /packages/core/src/NumberInput/index.ts (exports if types change)
|
|
@@ -91,7 +92,8 @@ import { groupStyles } from "../InputGroup/groupStyles.js";
|
|
|
91
92
|
|
|
92
93
|
import { isImeKeyEvent, mergeProps, mergeRefs } from "../utils/index.js";
|
|
93
94
|
import { themeProps } from "../utils/themeProps.js";
|
|
94
|
-
import { useTranslator } from "../i18n/index.js";
|
|
95
|
+
import { useTranslator, useLocale } from "../i18n/index.js";
|
|
96
|
+
import { formatEditableNumber, parseLocaleNumber } from "./numberParser.js";
|
|
95
97
|
|
|
96
98
|
/**
|
|
97
99
|
* Without `hasClear`, onChange only receives valid numbers.
|
|
@@ -99,16 +101,17 @@ import { useTranslator } from "../i18n/index.js";
|
|
|
99
101
|
*/
|
|
100
102
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
101
103
|
/**
|
|
102
|
-
*
|
|
104
|
+
* Read the typed or pasted text as a number, then apply the field's
|
|
105
|
+
* constraints.
|
|
103
106
|
* Returns null if the input is not a valid number or fails validation.
|
|
104
107
|
*/
|
|
105
108
|
function parseNumberInput(input, options) {
|
|
106
109
|
const trimmed = input.trim();
|
|
107
|
-
if (trimmed === ''
|
|
110
|
+
if (trimmed === '') {
|
|
108
111
|
return null;
|
|
109
112
|
}
|
|
110
|
-
const num =
|
|
111
|
-
if (!Number.isFinite(num)) {
|
|
113
|
+
const num = parseLocaleNumber(trimmed, options.locale);
|
|
114
|
+
if (num == null || !Number.isFinite(num)) {
|
|
112
115
|
return null;
|
|
113
116
|
}
|
|
114
117
|
|
|
@@ -231,6 +234,7 @@ export function NumberInput({
|
|
|
231
234
|
...rest
|
|
232
235
|
}) {
|
|
233
236
|
const t = useTranslator();
|
|
237
|
+
const locale = useLocale();
|
|
234
238
|
const isEffectivelyRequired = useResolvedRequired({
|
|
235
239
|
isRequired,
|
|
236
240
|
isOptional
|
|
@@ -280,6 +284,12 @@ export function NumberInput({
|
|
|
280
284
|
// The tooltip variant renders no message box; describe the input by the
|
|
281
285
|
// tooltip's content instead so the status is still announced.
|
|
282
286
|
statusTooltipDescribedBy, units ? unitsID : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null], inputGroup);
|
|
287
|
+
const parseInput = useCallback(text => parseNumberInput(text, {
|
|
288
|
+
min,
|
|
289
|
+
max,
|
|
290
|
+
isIntegerOnly,
|
|
291
|
+
locale
|
|
292
|
+
}), [isIntegerOnly, locale, max, min]);
|
|
283
293
|
const formattedValue = useMemo(() => {
|
|
284
294
|
if (value == null) {
|
|
285
295
|
return '';
|
|
@@ -296,20 +306,16 @@ export function NumberInput({
|
|
|
296
306
|
if (value == null) {
|
|
297
307
|
return '';
|
|
298
308
|
}
|
|
299
|
-
return isFocused ?
|
|
300
|
-
}, [formattedValue, isFocused, pendingInput, value]);
|
|
309
|
+
return isFocused ? formatEditableNumber(value, locale) : formattedValue;
|
|
310
|
+
}, [formattedValue, isFocused, locale, pendingInput, value]);
|
|
301
311
|
|
|
302
312
|
// Check if current pending input is valid (for styling purposes)
|
|
303
313
|
const isInputValid = useMemo(() => {
|
|
304
314
|
if (pendingInput === null || !pendingInput.trim()) {
|
|
305
315
|
return true;
|
|
306
316
|
}
|
|
307
|
-
return
|
|
308
|
-
|
|
309
|
-
max,
|
|
310
|
-
isIntegerOnly
|
|
311
|
-
}) !== null;
|
|
312
|
-
}, [pendingInput, min, max, isIntegerOnly]);
|
|
317
|
+
return parseInput(pendingInput) !== null;
|
|
318
|
+
}, [pendingInput, parseInput]);
|
|
313
319
|
|
|
314
320
|
// Handle input text change - update immediately if valid
|
|
315
321
|
const handleInputChange = useCallback(e => {
|
|
@@ -323,15 +329,11 @@ export function NumberInput({
|
|
|
323
329
|
setPendingInput(newValue);
|
|
324
330
|
|
|
325
331
|
// If the input is valid, update immediately
|
|
326
|
-
const parsed =
|
|
327
|
-
min,
|
|
328
|
-
max,
|
|
329
|
-
isIntegerOnly
|
|
330
|
-
});
|
|
332
|
+
const parsed = parseInput(newValue);
|
|
331
333
|
if (parsed !== null && parsed !== value) {
|
|
332
334
|
onChange(parsed);
|
|
333
335
|
}
|
|
334
|
-
}, [value, onChange,
|
|
336
|
+
}, [value, onChange, parseInput, isDisabled, isReadOnly]);
|
|
335
337
|
|
|
336
338
|
// Handle focus
|
|
337
339
|
const handleFocus = useCallback(e => {
|
|
@@ -349,11 +351,7 @@ export function NumberInput({
|
|
|
349
351
|
onChange(null);
|
|
350
352
|
}
|
|
351
353
|
} else {
|
|
352
|
-
const parsed =
|
|
353
|
-
min,
|
|
354
|
-
max,
|
|
355
|
-
isIntegerOnly
|
|
356
|
-
});
|
|
354
|
+
const parsed = parseInput(pendingInput);
|
|
357
355
|
if (parsed !== null && parsed !== value) {
|
|
358
356
|
onChange(parsed);
|
|
359
357
|
}
|
|
@@ -364,7 +362,7 @@ export function NumberInput({
|
|
|
364
362
|
setPendingInput(null);
|
|
365
363
|
setIsFocused(false);
|
|
366
364
|
onBlur?.(e);
|
|
367
|
-
}, [pendingInput, value, onChange,
|
|
365
|
+
}, [pendingInput, value, onChange, parseInput, onBlur, hasClear]);
|
|
368
366
|
const valueForStepping = useMemo(() => {
|
|
369
367
|
if (pendingInput === null) {
|
|
370
368
|
return value ?? null;
|
|
@@ -372,12 +370,8 @@ export function NumberInput({
|
|
|
372
370
|
if (pendingInput.trim() === '') {
|
|
373
371
|
return null;
|
|
374
372
|
}
|
|
375
|
-
return
|
|
376
|
-
|
|
377
|
-
max,
|
|
378
|
-
isIntegerOnly
|
|
379
|
-
}) ?? value ?? null;
|
|
380
|
-
}, [isIntegerOnly, max, min, pendingInput, value]);
|
|
373
|
+
return parseInput(pendingInput) ?? value ?? null;
|
|
374
|
+
}, [parseInput, pendingInput, value]);
|
|
381
375
|
const getNextValue = useCallback(direction => getSteppedValue({
|
|
382
376
|
currentValue: valueForStepping,
|
|
383
377
|
direction,
|
|
@@ -432,11 +426,7 @@ export function NumberInput({
|
|
|
432
426
|
onChange(null);
|
|
433
427
|
}
|
|
434
428
|
} else {
|
|
435
|
-
const parsed =
|
|
436
|
-
min,
|
|
437
|
-
max,
|
|
438
|
-
isIntegerOnly
|
|
439
|
-
});
|
|
429
|
+
const parsed = parseInput(pendingInput);
|
|
440
430
|
if (parsed !== null && parsed !== value) {
|
|
441
431
|
onChange(parsed);
|
|
442
432
|
}
|
|
@@ -445,7 +435,7 @@ export function NumberInput({
|
|
|
445
435
|
onEnter?.();
|
|
446
436
|
}
|
|
447
437
|
onKeyDown?.(e);
|
|
448
|
-
}, [pendingInput, value, onChange,
|
|
438
|
+
}, [pendingInput, value, onChange, parseInput, onEnter, onKeyDown, hasClear, stepValue]);
|
|
449
439
|
|
|
450
440
|
// React's delegated wheel listener can be passive, so use a native,
|
|
451
441
|
// explicitly non-passive listener to prevent page scrolling only when this
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file numberParser.ts
|
|
3
|
+
* @input Text a person typed or pasted, plus the resolved BCP 47 locale
|
|
4
|
+
* @output Exports parseLocaleNumber and formatEditableNumber
|
|
5
|
+
* @position Internal to NumberInput; not part of the public surface
|
|
6
|
+
*
|
|
7
|
+
* People paste numbers out of spreadsheets, and a spreadsheet writes them
|
|
8
|
+
* grouped, signed, and decorated. This reads those back. Everything locale
|
|
9
|
+
* specific — the grouping and decimal separators, the group sizes, the digit
|
|
10
|
+
* script — is derived from Intl and Unicode rather than a table, and anything
|
|
11
|
+
* that could mean two different numbers returns null so the field stays
|
|
12
|
+
* visibly invalid instead of committing a guess.
|
|
13
|
+
*
|
|
14
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
15
|
+
* - /packages/core/src/NumberInput/NumberInput.tsx
|
|
16
|
+
* - /packages/core/src/NumberInput/numberParser.test.ts
|
|
17
|
+
*/
|
|
18
|
+
import type { Locale } from '../i18n';
|
|
19
|
+
/**
|
|
20
|
+
* Read a number out of text the way a person in `locale` writes one: their
|
|
21
|
+
* grouping and decimal separators, their group sizes, their digit script, an
|
|
22
|
+
* optional currency symbol, and the shapes a spreadsheet pastes.
|
|
23
|
+
*
|
|
24
|
+
* Returns null rather than a guess. Grouping is validated, so en-US `1,23` —
|
|
25
|
+
* a comma that is neither a decimal point nor a well-formed group — is not
|
|
26
|
+
* silently read as 123, and neither is a number written for another locale.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```
|
|
30
|
+
* parseLocaleNumber('1,234,234,234', 'en-US') // 1234234234
|
|
31
|
+
* parseLocaleNumber('1,234,234,234', 'de-DE') // 1234234234
|
|
32
|
+
* parseLocaleNumber('1,5', 'de-DE') // 1.5
|
|
33
|
+
* parseLocaleNumber('1,5', 'en-US') // null
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseLocaleNumber(text: string, locale?: Locale): number | null;
|
|
37
|
+
/**
|
|
38
|
+
* The text shown while the field is focused: the plain machine number in the
|
|
39
|
+
* locale's decimal separator, so what a person sees mid-edit is what the
|
|
40
|
+
* parser reads back on blur.
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatEditableNumber(value: number, locale?: Locale): string;
|
|
43
|
+
//# sourceMappingURL=numberParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numberParser.d.ts","sourceRoot":"","sources":["../../src/NumberInput/numberParser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAsNpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAqEf;AAaD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAI3E"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file numberParser.ts
|
|
5
|
+
* @input Text a person typed or pasted, plus the resolved BCP 47 locale
|
|
6
|
+
* @output Exports parseLocaleNumber and formatEditableNumber
|
|
7
|
+
* @position Internal to NumberInput; not part of the public surface
|
|
8
|
+
*
|
|
9
|
+
* People paste numbers out of spreadsheets, and a spreadsheet writes them
|
|
10
|
+
* grouped, signed, and decorated. This reads those back. Everything locale
|
|
11
|
+
* specific — the grouping and decimal separators, the group sizes, the digit
|
|
12
|
+
* script — is derived from Intl and Unicode rather than a table, and anything
|
|
13
|
+
* that could mean two different numbers returns null so the field stays
|
|
14
|
+
* visibly invalid instead of committing a guess.
|
|
15
|
+
*
|
|
16
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
17
|
+
* - /packages/core/src/NumberInput/NumberInput.tsx
|
|
18
|
+
* - /packages/core/src/NumberInput/numberParser.test.ts
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const symbolsByLocale = new Map();
|
|
22
|
+
function getLocaleNumberSymbols(locale) {
|
|
23
|
+
const key = locale ?? '';
|
|
24
|
+
let symbols = symbolsByLocale.get(key);
|
|
25
|
+
if (symbols === undefined) {
|
|
26
|
+
let format;
|
|
27
|
+
try {
|
|
28
|
+
format = new Intl.NumberFormat(locale);
|
|
29
|
+
} catch {
|
|
30
|
+
format = new Intl.NumberFormat('en');
|
|
31
|
+
}
|
|
32
|
+
const parts = format.formatToParts(12345.6);
|
|
33
|
+
// A probe long enough to expose a second grouping size where one exists.
|
|
34
|
+
const groupSizes = format.formatToParts(11111111111).filter(part => part.type === 'integer').map(part => part.value.length);
|
|
35
|
+
const hasGrouping = groupSizes.length > 1;
|
|
36
|
+
symbols = {
|
|
37
|
+
// Normalized so the space-family separators compare equal to the plain
|
|
38
|
+
// space that input text is normalized to.
|
|
39
|
+
group: (parts.find(p => p.type === 'group')?.value ?? ',').normalize('NFKC'),
|
|
40
|
+
decimal: parts.find(p => p.type === 'decimal')?.value ?? '.',
|
|
41
|
+
primaryGroupSize: hasGrouping ? groupSizes[groupSizes.length - 1] : 3,
|
|
42
|
+
secondaryGroupSize: hasGrouping ? groupSizes[groupSizes.length - 2] : 3
|
|
43
|
+
};
|
|
44
|
+
symbolsByLocale.set(key, symbols);
|
|
45
|
+
}
|
|
46
|
+
return symbols;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Built at runtime rather than written as literals: Babel's
|
|
50
|
+
// transform-unicode-property-regex rewrites a `\p{...}` regex LITERAL into an
|
|
51
|
+
// enumerated character class, and the copy bundled with Next rejects the
|
|
52
|
+
// General_Category short names, failing the sandbox build. Property escapes are
|
|
53
|
+
// ES2018 and need no transform in any browser this package supports.
|
|
54
|
+
const DECIMAL_DIGIT = new RegExp('\\p{Nd}', 'u');
|
|
55
|
+
const LETTER = new RegExp('\\p{L}', 'u');
|
|
56
|
+
const CURRENCY = new RegExp('\\p{Sc}', 'u');
|
|
57
|
+
// Zero-width joiners, bidi isolates and the BOM Excel prepends.
|
|
58
|
+
const INVISIBLES = /[\u200B-\u200D\u200E\u200F\u061C\u2066-\u2069\uFEFF]/g;
|
|
59
|
+
// Hyphen last: inside the character class this builds, a leading one would
|
|
60
|
+
// open a range.
|
|
61
|
+
const MINUS_SIGNS = '\u2212\u2012\u2013-';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Value of any Unicode decimal digit. Each digit script lays its ten digits
|
|
65
|
+
* out consecutively, so walking back to the script's zero derives the value
|
|
66
|
+
* for Arabic-Indic, Devanagari, full-width and the rest without shipping a
|
|
67
|
+
* table of them. Returns null in the one shape the walk cannot resolve: two
|
|
68
|
+
* digit blocks adjacent in code space (the mathematical alphanumerics).
|
|
69
|
+
*/
|
|
70
|
+
function digitValue(char) {
|
|
71
|
+
const codePoint = char.codePointAt(0);
|
|
72
|
+
if (codePoint == null) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
for (let zero = codePoint; codePoint - zero < 10; zero--) {
|
|
76
|
+
if (!DECIMAL_DIGIT.test(String.fromCodePoint(zero - 1))) {
|
|
77
|
+
return codePoint - zero;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function toAsciiDigits(text) {
|
|
83
|
+
let out = '';
|
|
84
|
+
for (const char of text) {
|
|
85
|
+
if (!DECIMAL_DIGIT.test(char)) {
|
|
86
|
+
out += char;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const value = digitValue(char);
|
|
90
|
+
if (value == null) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
out += String(value);
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Reduce a digits-and-separators string to a plain machine number under one
|
|
100
|
+
* candidate reading, or null when it is not well formed under that reading.
|
|
101
|
+
* `minGroups` is how many grouping separators the reading has to see before it
|
|
102
|
+
* believes the separator is grouping at all.
|
|
103
|
+
*/
|
|
104
|
+
function readUnder(core, group, decimal, primaryGroupSize, secondaryGroupSize, minGroups) {
|
|
105
|
+
let intText = core;
|
|
106
|
+
let fracText = null;
|
|
107
|
+
if (decimal !== '' && core.includes(decimal)) {
|
|
108
|
+
const at = core.indexOf(decimal);
|
|
109
|
+
if (core.includes(decimal, at + decimal.length)) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
intText = core.slice(0, at);
|
|
113
|
+
fracText = core.slice(at + decimal.length);
|
|
114
|
+
if (!/^\d*$/.test(fracText)) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
let digits;
|
|
119
|
+
if (group !== '' && intText.includes(group)) {
|
|
120
|
+
const chunks = intText.split(group);
|
|
121
|
+
if (chunks.length - 1 < minGroups || !chunks.every(chunk => /^\d+$/.test(chunk))) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const first = chunks[0];
|
|
125
|
+
const last = chunks[chunks.length - 1];
|
|
126
|
+
if (last.length !== primaryGroupSize || first.length > secondaryGroupSize) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
for (let i = 1; i < chunks.length - 1; i++) {
|
|
130
|
+
if (chunks[i].length !== secondaryGroupSize) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
digits = chunks.join('');
|
|
135
|
+
} else {
|
|
136
|
+
if (!/^\d*$/.test(intText)) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
digits = intText;
|
|
140
|
+
}
|
|
141
|
+
if (digits === '' && (fracText == null || fracText === '')) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return fracText == null ? digits : `${digits}.${fracText}`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* A separator that no locale uses as a decimal point, so one well-formed group
|
|
149
|
+
* of it is already unambiguous. Everything else needs two before grouping
|
|
150
|
+
* beats the decimal-point reading.
|
|
151
|
+
*/
|
|
152
|
+
function isGroupOnlySeparator(separator) {
|
|
153
|
+
return /^[\s'\u2019\u00B7]$/.test(separator);
|
|
154
|
+
}
|
|
155
|
+
function toPlainNumber(core, locale) {
|
|
156
|
+
if (LETTER.test(core)) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const {
|
|
160
|
+
group,
|
|
161
|
+
decimal,
|
|
162
|
+
primaryGroupSize,
|
|
163
|
+
secondaryGroupSize
|
|
164
|
+
} = getLocaleNumberSymbols(locale);
|
|
165
|
+
const inLocale = readUnder(core, group, decimal, primaryGroupSize, secondaryGroupSize, 1);
|
|
166
|
+
if (inLocale != null) {
|
|
167
|
+
return inLocale;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// The locale could not read it. A repeated separator with three digits after
|
|
171
|
+
// each occurrence can only be grouping — a decimal point appears once — so
|
|
172
|
+
// that shape reads the same in every locale, which is what lets a
|
|
173
|
+
// `1,234,234,234` pasted out of a spreadsheet land in a de-DE app.
|
|
174
|
+
const separators = [...new Set(core.replace(/\d/g, ''))];
|
|
175
|
+
if (separators.length === 0 || separators.length > 2) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
for (const candidate of separators) {
|
|
179
|
+
const occurrences = core.split(candidate).length - 1;
|
|
180
|
+
const minGroups = isGroupOnlySeparator(candidate) ? 1 : 2;
|
|
181
|
+
if (occurrences < minGroups) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const other = separators.find(s => s !== candidate) ?? '';
|
|
185
|
+
if (other !== '' && core.split(other).length - 1 !== 1) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const read = readUnder(core, candidate, other, 3, 3, minGroups);
|
|
189
|
+
if (read != null) {
|
|
190
|
+
return read;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Read a number out of text the way a person in `locale` writes one: their
|
|
198
|
+
* grouping and decimal separators, their group sizes, their digit script, an
|
|
199
|
+
* optional currency symbol, and the shapes a spreadsheet pastes.
|
|
200
|
+
*
|
|
201
|
+
* Returns null rather than a guess. Grouping is validated, so en-US `1,23` —
|
|
202
|
+
* a comma that is neither a decimal point nor a well-formed group — is not
|
|
203
|
+
* silently read as 123, and neither is a number written for another locale.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```
|
|
207
|
+
* parseLocaleNumber('1,234,234,234', 'en-US') // 1234234234
|
|
208
|
+
* parseLocaleNumber('1,234,234,234', 'de-DE') // 1234234234
|
|
209
|
+
* parseLocaleNumber('1,5', 'de-DE') // 1.5
|
|
210
|
+
* parseLocaleNumber('1,5', 'en-US') // null
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
export function parseLocaleNumber(text, locale) {
|
|
214
|
+
const normalized = toAsciiDigits(text.normalize('NFKC').replace(INVISIBLES, ''));
|
|
215
|
+
if (normalized == null) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
let rest = normalized.trim();
|
|
219
|
+
let sign = 1;
|
|
220
|
+
|
|
221
|
+
// Accounting negatives: spreadsheets write -1234 as (1,234).
|
|
222
|
+
const accounting = /^\((.*)\)$/s.exec(rest);
|
|
223
|
+
if (accounting) {
|
|
224
|
+
sign = -1;
|
|
225
|
+
rest = accounting[1].trim();
|
|
226
|
+
}
|
|
227
|
+
rest = stripCurrency(rest);
|
|
228
|
+
|
|
229
|
+
// The sign lands on either end — RTL locales trail it, and Intl writes
|
|
230
|
+
// U+2212 where a keyboard writes a hyphen.
|
|
231
|
+
const leadingSign = new RegExp(`^([+${MINUS_SIGNS}])\\s*`).exec(rest);
|
|
232
|
+
if (leadingSign) {
|
|
233
|
+
sign = leadingSign[1] === '+' ? sign : -sign;
|
|
234
|
+
rest = rest.slice(leadingSign[0].length);
|
|
235
|
+
} else {
|
|
236
|
+
const trailingSign = new RegExp(`\\s*([+${MINUS_SIGNS}])$`).exec(rest);
|
|
237
|
+
if (trailingSign) {
|
|
238
|
+
sign = trailingSign[1] === '+' ? sign : -sign;
|
|
239
|
+
rest = rest.slice(0, rest.length - trailingSign[0].length);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
rest = stripCurrency(rest);
|
|
243
|
+
let exponent = 0;
|
|
244
|
+
const exponentMatch = /\s*[eE]\s*([+-]?\d+)$/.exec(rest);
|
|
245
|
+
if (exponentMatch) {
|
|
246
|
+
exponent = Number(exponentMatch[1]);
|
|
247
|
+
rest = rest.slice(0, rest.length - exponentMatch[0].length);
|
|
248
|
+
}
|
|
249
|
+
const core = rest.trim();
|
|
250
|
+
if (core === '') {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
const plain = toPlainNumber(core, locale);
|
|
254
|
+
if (plain == null) {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
const magnitude = Number(plain);
|
|
258
|
+
if (!Number.isFinite(magnitude)) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const scaled = exponent === 0 ? magnitude :
|
|
262
|
+
// 1.23 * 1e3 is 1229.9999999999998 in binary floating point, and a
|
|
263
|
+
// field that commits that instead of 1230 has not round-tripped.
|
|
264
|
+
Number((magnitude * 10 ** exponent).toPrecision(15));
|
|
265
|
+
if (!Number.isFinite(scaled)) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
const result = sign * scaled;
|
|
269
|
+
return Object.is(result, -0) ? 0 : result;
|
|
270
|
+
}
|
|
271
|
+
function stripCurrency(text) {
|
|
272
|
+
let out = text.trim();
|
|
273
|
+
if (CURRENCY.test(out.charAt(0))) {
|
|
274
|
+
out = out.slice(1).trim();
|
|
275
|
+
}
|
|
276
|
+
if (CURRENCY.test(out.charAt(out.length - 1))) {
|
|
277
|
+
out = out.slice(0, -1).trim();
|
|
278
|
+
}
|
|
279
|
+
return out;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* The text shown while the field is focused: the plain machine number in the
|
|
284
|
+
* locale's decimal separator, so what a person sees mid-edit is what the
|
|
285
|
+
* parser reads back on blur.
|
|
286
|
+
*/
|
|
287
|
+
export function formatEditableNumber(value, locale) {
|
|
288
|
+
const {
|
|
289
|
+
decimal
|
|
290
|
+
} = getLocaleNumberSymbols(locale);
|
|
291
|
+
const raw = String(value);
|
|
292
|
+
return decimal === '.' ? raw : raw.replace('.', decimal);
|
|
293
|
+
}
|