@astryxdesign/core 0.4.5 → 0.4.6-canary.cea9ecd
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 +134 -0
- package/dist/Avatar/Avatar.d.ts +10 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +139 -30
- package/dist/Avatar/AvatarStatusDot.d.ts +2 -1
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +30 -4
- package/dist/Avatar/AvatarStatusLabelContext.d.ts +39 -0
- package/dist/Avatar/AvatarStatusLabelContext.d.ts.map +1 -0
- package/dist/Avatar/AvatarStatusLabelContext.js +41 -0
- package/dist/AvatarGroup/AvatarGroup.d.ts +3 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +15 -9
- package/dist/Blockquote/Blockquote.d.ts +4 -3
- package/dist/Blockquote/Blockquote.d.ts.map +1 -1
- package/dist/Blockquote/Blockquote.js +9 -10
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +21 -5
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +47 -34
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +7 -7
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +21 -12
- package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
- package/dist/Calendar/styles.d.ts +2 -2
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +5 -5
- package/dist/Center/Center.d.ts +23 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +12 -6
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +3 -3
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +2 -2
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +2 -2
- package/dist/Chat/useChatDictation.d.ts +1 -1
- package/dist/Chat/useChatDictation.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.d.ts +1 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +4 -3
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +2 -2
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +5 -5
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +4 -4
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +1 -1
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +2 -2
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +3 -3
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +6 -6
- package/dist/DateInput/DateInput.d.ts +31 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +90 -22
- package/dist/DateInput/MonthScroller.d.ts +35 -0
- package/dist/DateInput/MonthScroller.d.ts.map +1 -0
- package/dist/DateInput/MonthScroller.js +658 -0
- package/dist/DateInput/MonthYearWheels.d.ts +24 -0
- package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
- package/dist/DateInput/MonthYearWheels.js +114 -0
- package/dist/DateInput/TouchDateField.d.ts +10 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -0
- package/dist/DateInput/TouchDateField.js +810 -0
- package/dist/DateInput/Wheel.d.ts +41 -0
- package/dist/DateInput/Wheel.d.ts.map +1 -0
- package/dist/DateInput/Wheel.js +315 -0
- package/dist/DateInput/monthGeometry.d.ts +65 -0
- package/dist/DateInput/monthGeometry.d.ts.map +1 -0
- package/dist/DateInput/monthGeometry.js +98 -0
- package/dist/DateInput/tokens.stylex.d.ts +63 -0
- package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
- package/dist/DateInput/tokens.stylex.js +74 -0
- package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
- package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
- package/dist/DateInput/useOwnScrollGesture.js +202 -0
- package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
- package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
- package/dist/DateInput/usePointerDragScroll.js +216 -0
- package/dist/DateInput/useScrollSettle.d.ts +26 -0
- package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
- package/dist/DateInput/useScrollSettle.js +149 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +17 -14
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +17 -14
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +3 -3
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +2 -2
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +2 -2
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +2 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +4 -4
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +6 -0
- package/dist/Field/inputStyles.stylex.d.ts +1 -1
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +5 -5
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +6 -6
- package/dist/HoverCard/HoverCard.d.ts +13 -3
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/index.d.ts +1 -1
- package/dist/HoverCard/index.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.d.ts +17 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +78 -9
- package/dist/InputGroup/InputGroup.js +1 -1
- package/dist/Item/Item.d.ts +9 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +52 -14
- package/dist/Layer/index.d.ts +4 -2
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +2 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +3 -2
- package/dist/Layer/useTouchTrigger.d.ts +113 -0
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
- package/dist/Layer/useTouchTrigger.js +241 -0
- package/dist/Layout/container.stylex.d.ts +4 -2
- package/dist/Layout/container.stylex.d.ts.map +1 -1
- package/dist/Layout/container.stylex.js +19 -11
- package/dist/Layout/index.d.ts +1 -0
- package/dist/Layout/index.d.ts.map +1 -1
- package/dist/Layout/index.js +4 -0
- package/dist/Layout/padding.stylex.d.ts +315 -12
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +389 -12
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +5 -4
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +6 -6
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +1 -1
- package/dist/MobileNav/MobileNav.d.ts +1 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +24 -6
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +8 -8
- package/dist/NavItem/navItemStyles.stylex.d.ts +4 -4
- package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
- package/dist/NavItem/navItemStyles.stylex.js +4 -4
- package/dist/NavMenu/NavHeadingMenuItem.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenuItem.js +3 -3
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +36 -8
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +3 -3
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +2 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +11 -12
- package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchToken.js +3 -1
- package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +23 -8
- package/dist/RadioList/RadioListItem.d.ts +2 -2
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +70 -40
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +7 -7
- package/dist/Section/Section.d.ts +36 -1
- package/dist/Section/Section.d.ts.map +1 -1
- package/dist/Section/Section.js +12 -2
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +7 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +3 -3
- package/dist/Selector/Selector.d.ts +26 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +93 -20
- package/dist/Selector/SelectorOption.d.ts +14 -1
- package/dist/Selector/SelectorOption.d.ts.map +1 -1
- package/dist/Selector/SelectorOption.js +6 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
- package/dist/Selector/SelectorRowLayoutContext.js +27 -0
- package/dist/Selector/types.d.ts +1 -0
- package/dist/Selector/types.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +4 -4
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +3 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +7 -7
- package/dist/Stack/Stack.d.ts +23 -1
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +12 -6
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +2 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +1 -1
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +3 -3
- package/dist/Table/TableRow.js +4 -4
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +2 -2
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +2 -2
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +2 -2
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +3 -3
- package/dist/TextArea/TextArea.js +1 -1
- package/dist/TextInput/TextInput.js +1 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +3 -3
- package/dist/TimeInput/TimeInput.js +2 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +6 -4
- package/dist/Timestamp/formatInstant.d.ts +3 -2
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +8 -8
- package/dist/Timestamp/tooltipEntries.d.ts +2 -1
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.js +5 -3
- package/dist/Toast/Toast.d.ts +4 -3
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +10 -7
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +6 -6
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +1 -1
- package/dist/Tooltip/Tooltip.d.ts +16 -3
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.js +2 -0
- package/dist/Tooltip/index.d.ts +1 -1
- package/dist/Tooltip/index.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +21 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +71 -13
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +4 -4
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +3 -3
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +2 -2
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +2 -2
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +4 -4
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +7 -7
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +2 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +1 -1
- package/dist/astryx.css +124 -62
- package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
- package/dist/hooks/containerReveal.stylex.js +18 -18
- package/dist/hooks/scrollbarGutter.d.ts +28 -0
- package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
- package/dist/hooks/scrollbarGutter.js +103 -0
- package/dist/hooks/useAutoMediaMode.d.ts +31 -0
- package/dist/hooks/useAutoMediaMode.d.ts.map +1 -0
- package/dist/hooks/useAutoMediaMode.js +201 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +1 -1
- package/dist/hooks/useListFocus.d.ts +5 -2
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +12 -6
- package/dist/hooks/useScrollLock.d.ts +4 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.js +13 -1
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +2 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +6 -0
- package/dist/i18n/useCollator.d.ts +12 -0
- package/dist/i18n/useCollator.d.ts.map +1 -0
- package/dist/i18n/useCollator.js +40 -0
- package/dist/i18n/useLocale.d.ts +3 -0
- package/dist/i18n/useLocale.d.ts.map +1 -0
- package/dist/i18n/useLocale.js +31 -0
- package/dist/theme/MediaTheme.d.ts +25 -5
- package/dist/theme/MediaTheme.d.ts.map +1 -1
- package/dist/theme/MediaTheme.js +31 -6
- package/dist/theme/defineTheme.d.ts +5 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +5 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +66 -5
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/syntax/index.d.ts +6 -0
- package/dist/theme/syntax/index.d.ts.map +1 -1
- package/dist/theme/syntax/index.js +7 -2
- package/dist/utils/dateParser.d.ts +4 -3
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +8 -8
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/plainDate.d.ts +5 -2
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +20 -4
- package/locales/en.json +28 -0
- package/locales/pseudo.json +21 -0
- package/package.json +3 -3
- package/src/Avatar/Avatar.doc.mjs +10 -6
- package/src/Avatar/Avatar.test.tsx +219 -1
- package/src/Avatar/Avatar.tsx +179 -37
- package/src/Avatar/AvatarStatusDot.tsx +30 -4
- package/src/Avatar/AvatarStatusLabelContext.ts +47 -0
- package/src/AvatarGroup/AvatarGroup.doc.mjs +10 -6
- package/src/AvatarGroup/AvatarGroup.test.tsx +62 -0
- package/src/AvatarGroup/AvatarGroup.tsx +3 -1
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +31 -8
- package/src/Banner/Banner.doc.mjs +2 -0
- package/src/Blockquote/Blockquote.doc.mjs +30 -7
- package/src/Blockquote/Blockquote.test.tsx +34 -3
- package/src/Blockquote/Blockquote.tsx +11 -9
- package/src/BottomSheet/BottomSheet.doc.mjs +3 -3
- package/src/BottomSheet/BottomSheet.test.tsx +24 -0
- package/src/BottomSheet/BottomSheetPanel.test.tsx +91 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +58 -3
- package/src/Breadcrumbs/BreadcrumbItem.tsx +36 -23
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +26 -2
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -0
- package/src/Button/Button.tsx +12 -9
- package/src/Calendar/Calendar.tsx +15 -9
- package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
- package/src/Calendar/styles.ts +8 -5
- package/src/Center/Center.doc.mjs +48 -0
- package/src/Center/Center.test.tsx +158 -0
- package/src/Center/Center.tsx +50 -9
- package/src/Chat/ChatComposer.tsx +11 -5
- package/src/Chat/ChatComposerDrawer.tsx +4 -1
- package/src/Chat/ChatToolCalls.tsx +13 -4
- package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
- package/src/Chat/useChatDictation.ts +1 -1
- package/src/Chat/useSpeechRecognition.ts +5 -3
- package/src/Chat/useTriggerMenu.tsx +4 -1
- package/src/CheckboxInput/CheckboxInput.tsx +5 -2
- package/src/Citation/Citation.test.tsx +6 -1
- package/src/Citation/Citation.tsx +11 -5
- package/src/ClickableCard/ClickableCard.tsx +7 -4
- package/src/CodeBlock/CodeBlock.tsx +4 -1
- package/src/Collapsible/Collapsible.tsx +5 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +6 -3
- package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
- package/src/ComplexSelector/ComplexSelector.tsx +14 -7
- package/src/DateInput/DateInput.test.tsx +17 -1
- package/src/DateInput/DateInput.tsx +93 -21
- package/src/DateInput/DateInputTouch.test.tsx +2582 -0
- package/src/DateInput/MonthScroller.tsx +878 -0
- package/src/DateInput/MonthYearWheels.tsx +147 -0
- package/src/DateInput/TouchDateField.tsx +1223 -0
- package/src/DateInput/Wheel.tsx +473 -0
- package/src/DateInput/monthGeometry.ts +118 -0
- package/src/DateInput/tokens.stylex.ts +99 -0
- package/src/DateInput/useOwnScrollGesture.ts +227 -0
- package/src/DateInput/usePointerDragScroll.ts +220 -0
- package/src/DateInput/useScrollSettle.ts +164 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
- package/src/DateRangeInput/DateRangeInput.tsx +31 -13
- package/src/DateTimeInput/DateTimeInput.tsx +25 -9
- package/src/Dialog/Dialog.test.tsx +24 -0
- package/src/Dialog/Dialog.tsx +3 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +5 -2
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -2
- package/src/Field/Field.doc.mjs +2 -0
- package/src/Field/FieldLabel.tsx +9 -3
- package/src/Field/InputClearButton.test.tsx +110 -3
- package/src/Field/InputClearButton.tsx +38 -0
- package/src/Field/inputStyles.stylex.ts +17 -13
- package/src/FileInput/FileInput.tsx +15 -8
- package/src/FormLayout/FormLayout.doc.mjs +1 -1
- package/src/HoverCard/HoverCard.doc.mjs +18 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -0
- package/src/HoverCard/HoverCard.tsx +22 -2
- package/src/HoverCard/index.ts +1 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +103 -7
- package/src/InputGroup/InputGroup.tsx +1 -1
- package/src/Item/Item.doc.mjs +1 -0
- package/src/Item/Item.test.tsx +50 -0
- package/src/Item/Item.tsx +54 -6
- package/src/Layer/index.ts +10 -0
- package/src/Layer/useLayer.tsx +13 -2
- package/src/Layer/useTouchTrigger.test.ts +70 -0
- package/src/Layer/useTouchTrigger.ts +366 -0
- package/src/Layout/Layout.doc.mjs +18 -0
- package/src/Layout/container.stylex.ts +11 -3
- package/src/Layout/index.ts +4 -0
- package/src/Layout/overlayPaddingReset.test.tsx +222 -0
- package/src/Layout/padding.stylex.ts +192 -12
- package/src/Lightbox/Lightbox.tsx +11 -3
- package/src/Link/Link.tsx +9 -6
- package/src/MetadataList/MetadataList.tsx +4 -1
- package/src/MobileNav/MobileNav.tsx +61 -5
- package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
- package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
- package/src/MultiSelector/MultiSelector.test.tsx +1 -1
- package/src/MultiSelector/MultiSelector.tsx +26 -10
- package/src/NavItem/navItemStyles.stylex.ts +7 -4
- package/src/NavMenu/NavHeadingMenuItem.tsx +6 -3
- package/src/NumberInput/NumberInput.doc.mjs +24 -0
- package/src/NumberInput/NumberInput.test.tsx +138 -0
- package/src/NumberInput/NumberInput.tsx +47 -8
- package/src/Outline/Outline.tsx +5 -2
- package/src/Pagination/Pagination.tsx +5 -2
- package/src/Popover/Popover.test.tsx +27 -1
- package/src/PowerSearch/PowerSearch.tsx +17 -8
- package/src/PowerSearch/PowerSearchToken.tsx +3 -0
- package/src/PowerSearch/formatFilterValue.test.ts +22 -2
- package/src/PowerSearch/formatFilterValue.ts +31 -6
- package/src/RadioList/RadioList.doc.mjs +1 -1
- package/src/RadioList/RadioList.test.tsx +170 -2
- package/src/RadioList/RadioListItem.tsx +88 -53
- package/src/Resizable/ResizeHandle.test.tsx +22 -0
- package/src/Resizable/ResizeHandle.tsx +25 -7
- package/src/Section/Section.doc.mjs +55 -0
- package/src/Section/Section.test.tsx +201 -4
- package/src/Section/Section.tsx +69 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +15 -3
- package/src/SelectableCard/SelectableCard.tsx +6 -3
- package/src/Selector/Selector.doc.mjs +16 -2
- package/src/Selector/Selector.test.tsx +525 -1
- package/src/Selector/Selector.tsx +180 -25
- package/src/Selector/SelectorOption.doc.mjs +7 -0
- package/src/Selector/SelectorOption.tsx +21 -0
- package/src/Selector/SelectorRowLayoutContext.ts +32 -0
- package/src/Selector/types.ts +4 -4
- package/src/SideNav/SideNavHeading.tsx +14 -5
- package/src/SideNav/SideNavItem.tsx +9 -3
- package/src/Slider/Slider.tsx +25 -6
- package/src/Stack/Stack.doc.mjs +72 -0
- package/src/Stack/Stack.test.tsx +156 -0
- package/src/Stack/Stack.tsx +50 -8
- package/src/Switch/Switch.tsx +5 -2
- package/src/TabList/Tab.tsx +4 -1
- package/src/TabList/TabMenu.tsx +9 -3
- package/src/Table/TableRow.tsx +4 -4
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +6 -2
- package/src/Table/plugins/filtering/useTableFiltering.tsx +4 -1
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +10 -3
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +6 -3
- package/src/Table/plugins/sortable/useTableSortable.tsx +4 -1
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
- package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
- package/src/Table/plugins/tree/useTableTreeData.tsx +10 -4
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.tsx +1 -1
- package/src/TextInput/TextInput.tsx +1 -1
- package/src/Thumbnail/Thumbnail.tsx +9 -3
- package/src/TimeInput/TimeInput.tsx +1 -1
- package/src/Timestamp/Timestamp.test.tsx +27 -7
- package/src/Timestamp/Timestamp.tsx +8 -4
- package/src/Timestamp/formatInstant.ts +9 -7
- package/src/Timestamp/tooltipEntries.test.ts +11 -6
- package/src/Timestamp/tooltipEntries.ts +6 -2
- package/src/Toast/Toast.tsx +9 -7
- package/src/Token/Token.tsx +14 -5
- package/src/Tokenizer/Tokenizer.tsx +4 -1
- package/src/Tooltip/Tooltip.doc.mjs +18 -0
- package/src/Tooltip/Tooltip.test.tsx +254 -1
- package/src/Tooltip/Tooltip.tsx +22 -2
- package/src/Tooltip/index.ts +1 -0
- package/src/Tooltip/useTooltip.doc.mjs +2 -0
- package/src/Tooltip/useTooltip.tsx +99 -21
- package/src/TopNav/TopNavHeading.tsx +13 -4
- package/src/TopNav/TopNavItem.tsx +6 -3
- package/src/TopNav/TopNavMegaMenu.tsx +5 -2
- package/src/TopNav/TopNavMegaMenuItem.tsx +5 -2
- package/src/TopNav/TopNavMenu.tsx +10 -4
- package/src/TreeList/TreeListItem.tsx +22 -7
- package/src/Typeahead/BaseTypeahead.tsx +5 -2
- package/src/Typeahead/Typeahead.tsx +4 -1
- package/src/hooks/containerReveal.stylex.ts +54 -18
- package/src/hooks/scrollbarGutter.test.ts +167 -0
- package/src/hooks/scrollbarGutter.ts +121 -0
- package/src/hooks/useAutoMediaMode.test.ts +109 -0
- package/src/hooks/useAutoMediaMode.ts +233 -0
- package/src/hooks/useInputStatusIcon.tsx +4 -1
- package/src/hooks/useListFocus.doc.mjs +2 -2
- package/src/hooks/useListFocus.test.tsx +65 -3
- package/src/hooks/useListFocus.ts +15 -7
- package/src/hooks/useScrollLock.doc.mjs +4 -4
- package/src/hooks/useScrollLock.test.ts +73 -0
- package/src/hooks/useScrollLock.ts +14 -0
- package/src/i18n/InternationalizationContext.ts +2 -0
- package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
- package/src/i18n/__tests__/useCollator.test.tsx +115 -0
- package/src/i18n/__tests__/useLocale.test.tsx +52 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/useCollator.doc.mjs +84 -0
- package/src/i18n/useCollator.ts +44 -0
- package/src/i18n/useLocale.doc.mjs +70 -0
- package/src/i18n/useLocale.ts +34 -0
- package/src/i18n/useTranslator.doc.mjs +1 -1
- package/src/reset.css +9 -2
- package/src/reset.test.ts +22 -0
- package/src/theme/MediaTheme.doc.mjs +23 -4
- package/src/theme/MediaTheme.dom.test.tsx +97 -0
- package/src/theme/MediaTheme.tsx +42 -7
- package/src/theme/defineTheme.test.ts +9 -3
- package/src/theme/defineTheme.ts +5 -0
- package/src/theme/derivedVarRegistry.test.ts +19 -5
- package/src/theme/derivedVarRegistry.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +118 -0
- package/src/theme/generateThemeRules.ts +83 -5
- package/src/theme/index.ts +1 -1
- package/src/theme/syntax/index.ts +6 -2
- package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
- package/src/utils/dateParser.test.ts +20 -0
- package/src/utils/dateParser.ts +14 -7
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +6 -0
- package/src/utils/plainDate.ts +21 -4
|
@@ -17,6 +17,9 @@ describe('useScrollLock', () => {
|
|
|
17
17
|
afterEach(() => {
|
|
18
18
|
cleanup();
|
|
19
19
|
document.body.style.cssText = '';
|
|
20
|
+
document.documentElement.style.cssText = '';
|
|
21
|
+
// @ts-expect-error -- drop the viewport stub so jsdom's own value comes back
|
|
22
|
+
delete document.documentElement.clientWidth;
|
|
20
23
|
vi.restoreAllMocks();
|
|
21
24
|
});
|
|
22
25
|
|
|
@@ -69,4 +72,74 @@ describe('useScrollLock', () => {
|
|
|
69
72
|
expect(document.body.style.left).toBe('');
|
|
70
73
|
expect(document.body.style.right).toBe('');
|
|
71
74
|
});
|
|
75
|
+
|
|
76
|
+
it('holds the page still across the scrollbar it hides', () => {
|
|
77
|
+
// A 1024px window over a 1009px layout viewport = a 15px classic
|
|
78
|
+
// scrollbar. Pinning the body hides it, which would widen the page by
|
|
79
|
+
// those 15px and reflow everything sideways.
|
|
80
|
+
Object.defineProperty(window, 'innerWidth', {
|
|
81
|
+
value: 1024,
|
|
82
|
+
configurable: true,
|
|
83
|
+
writable: true,
|
|
84
|
+
});
|
|
85
|
+
Object.defineProperty(document.documentElement, 'clientWidth', {
|
|
86
|
+
value: 1009,
|
|
87
|
+
configurable: true,
|
|
88
|
+
});
|
|
89
|
+
vi.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
|
90
|
+
|
|
91
|
+
const lock = renderHook(() => useScrollLock(true));
|
|
92
|
+
|
|
93
|
+
expect(document.documentElement.style.scrollbarGutter).toBe('stable');
|
|
94
|
+
|
|
95
|
+
lock.unmount();
|
|
96
|
+
|
|
97
|
+
expect(document.documentElement.style.scrollbarGutter).toBe('');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('leaves the page alone when the scrollbar is an overlay one', () => {
|
|
101
|
+
Object.defineProperty(window, 'innerWidth', {
|
|
102
|
+
value: 1024,
|
|
103
|
+
configurable: true,
|
|
104
|
+
writable: true,
|
|
105
|
+
});
|
|
106
|
+
Object.defineProperty(document.documentElement, 'clientWidth', {
|
|
107
|
+
value: 1024,
|
|
108
|
+
configurable: true,
|
|
109
|
+
});
|
|
110
|
+
vi.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
|
111
|
+
|
|
112
|
+
const lock = renderHook(() => useScrollLock(true));
|
|
113
|
+
|
|
114
|
+
expect(document.documentElement.style.scrollbarGutter).toBe('');
|
|
115
|
+
expect(document.body.style.paddingRight).toBe('');
|
|
116
|
+
|
|
117
|
+
lock.unmount();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('holds the gutter for the outermost overlay only, and gives it back once', () => {
|
|
121
|
+
Object.defineProperty(window, 'innerWidth', {
|
|
122
|
+
value: 1024,
|
|
123
|
+
configurable: true,
|
|
124
|
+
writable: true,
|
|
125
|
+
});
|
|
126
|
+
Object.defineProperty(document.documentElement, 'clientWidth', {
|
|
127
|
+
value: 1009,
|
|
128
|
+
configurable: true,
|
|
129
|
+
});
|
|
130
|
+
vi.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
|
131
|
+
|
|
132
|
+
const first = renderHook(() => useScrollLock(true));
|
|
133
|
+
const second = renderHook(() => useScrollLock(true));
|
|
134
|
+
|
|
135
|
+
expect(document.documentElement.style.scrollbarGutter).toBe('stable');
|
|
136
|
+
|
|
137
|
+
first.unmount();
|
|
138
|
+
|
|
139
|
+
expect(document.documentElement.style.scrollbarGutter).toBe('stable');
|
|
140
|
+
|
|
141
|
+
second.unmount();
|
|
142
|
+
|
|
143
|
+
expect(document.documentElement.style.scrollbarGutter).toBe('');
|
|
144
|
+
});
|
|
72
145
|
});
|
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SYNC: When modified, update:
|
|
15
15
|
* - /packages/core/src/hooks/index.ts
|
|
16
|
+
* - /packages/core/src/hooks/scrollbarGutter.ts
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
import {useEffect} from 'react';
|
|
20
|
+
import {holdScrollbarGutter, type ScrollbarGutterHold} from './scrollbarGutter';
|
|
19
21
|
|
|
20
22
|
interface ScrollLockSnapshot {
|
|
21
23
|
scrollX: number;
|
|
@@ -25,6 +27,7 @@ interface ScrollLockSnapshot {
|
|
|
25
27
|
top: string;
|
|
26
28
|
left: string;
|
|
27
29
|
right: string;
|
|
30
|
+
gutter: ScrollbarGutterHold;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
let lockCount = 0;
|
|
@@ -38,6 +41,10 @@ let originalBodyState: ScrollLockSnapshot | null = null;
|
|
|
38
41
|
* does not prevent body scroll behind modals. Restores scroll position
|
|
39
42
|
* on unlock.
|
|
40
43
|
*
|
|
44
|
+
* Pinning also hides the document's scrollbar, so the gutter that scrollbar
|
|
45
|
+
* occupied is held open for the duration of the lock — without it the page
|
|
46
|
+
* reflows sideways by ~15px the moment an overlay opens.
|
|
47
|
+
*
|
|
41
48
|
* @example
|
|
42
49
|
* ```
|
|
43
50
|
* useScrollLock(isOpen);
|
|
@@ -55,6 +62,9 @@ export function useScrollLock(isLocked: boolean): void {
|
|
|
55
62
|
const scrollX = window.scrollX;
|
|
56
63
|
const scrollY = window.scrollY;
|
|
57
64
|
|
|
65
|
+
// Taken before the pinning styles below hide the scrollbar.
|
|
66
|
+
const gutter = holdScrollbarGutter(body);
|
|
67
|
+
|
|
58
68
|
originalBodyState = {
|
|
59
69
|
scrollX,
|
|
60
70
|
scrollY,
|
|
@@ -63,6 +73,7 @@ export function useScrollLock(isLocked: boolean): void {
|
|
|
63
73
|
top: body.style.top,
|
|
64
74
|
left: body.style.left,
|
|
65
75
|
right: body.style.right,
|
|
76
|
+
gutter,
|
|
66
77
|
};
|
|
67
78
|
|
|
68
79
|
body.style.overflow = 'hidden';
|
|
@@ -70,6 +81,8 @@ export function useScrollLock(isLocked: boolean): void {
|
|
|
70
81
|
body.style.top = `-${scrollY}px`;
|
|
71
82
|
body.style.left = '0';
|
|
72
83
|
body.style.right = '0';
|
|
84
|
+
|
|
85
|
+
gutter.settle();
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
lockCount += 1;
|
|
@@ -89,6 +102,7 @@ export function useScrollLock(isLocked: boolean): void {
|
|
|
89
102
|
body.style.top = state.top;
|
|
90
103
|
body.style.left = state.left;
|
|
91
104
|
body.style.right = state.right;
|
|
105
|
+
state.gutter.release();
|
|
92
106
|
window.scrollTo(state.scrollX, state.scrollY);
|
|
93
107
|
};
|
|
94
108
|
}, [isLocked]);
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* - /packages/core/src/i18n/InternationalizationProvider.tsx
|
|
17
17
|
* - /packages/core/src/i18n/t.client.ts
|
|
18
18
|
* - /packages/core/src/i18n/useDirection.ts
|
|
19
|
+
* - /packages/core/src/i18n/useLocale.ts
|
|
20
|
+
* - /packages/core/src/i18n/useCollator.ts
|
|
19
21
|
* - /packages/core/src/i18n/getLocaleDirection.ts
|
|
20
22
|
* - /packages/core/src/i18n/index.ts
|
|
21
23
|
*/
|
|
@@ -23,7 +23,11 @@ import {describe, test, expect} from 'vitest';
|
|
|
23
23
|
import {render, screen} from '@testing-library/react';
|
|
24
24
|
import React, {useMemo} from 'react';
|
|
25
25
|
import {PowerSearch, usePowerSearchConfig} from '../../PowerSearch';
|
|
26
|
-
import type {
|
|
26
|
+
import type {
|
|
27
|
+
FieldDefinition,
|
|
28
|
+
PowerSearchConfig,
|
|
29
|
+
PowerSearchFilter,
|
|
30
|
+
} from '../../PowerSearch';
|
|
27
31
|
import {InternationalizationProvider} from '../InternationalizationProvider';
|
|
28
32
|
import pseudoCatalog from '../../../locales/pseudo.json';
|
|
29
33
|
|
|
@@ -112,6 +116,38 @@ describe('PowerSearch × i18n — end to end', () => {
|
|
|
112
116
|
expect(screen.getByText(/Name: contient/)).toBeInTheDocument();
|
|
113
117
|
});
|
|
114
118
|
|
|
119
|
+
test('date tokens update when the provider locale changes', () => {
|
|
120
|
+
const config: PowerSearchConfig = {
|
|
121
|
+
name: 'Dates',
|
|
122
|
+
fields: [
|
|
123
|
+
{
|
|
124
|
+
key: 'created',
|
|
125
|
+
label: 'Created',
|
|
126
|
+
defaultOperator: 'is',
|
|
127
|
+
operators: [{key: 'is', label: 'is', value: {type: 'date_absolute'}}],
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
const filters: PowerSearchFilter[] = [
|
|
132
|
+
{
|
|
133
|
+
field: 'created',
|
|
134
|
+
operator: 'is',
|
|
135
|
+
value: {type: 'date_absolute', unixSeconds: 1769342400},
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
const search = (locale: string) => (
|
|
139
|
+
<InternationalizationProvider locale={locale}>
|
|
140
|
+
<PowerSearch config={config} filters={filters} onChange={() => {}} />
|
|
141
|
+
</InternationalizationProvider>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const {rerender} = render(search('en-US'));
|
|
145
|
+
expect(screen.getByText('Jan 25, 2026')).toBeInTheDocument();
|
|
146
|
+
|
|
147
|
+
rerender(search('de-DE'));
|
|
148
|
+
expect(screen.getByText('25. Jan. 2026')).toBeInTheDocument();
|
|
149
|
+
});
|
|
150
|
+
|
|
115
151
|
test('resultCount ICU plural swaps under provider overrides', () => {
|
|
116
152
|
render(
|
|
117
153
|
<InternationalizationProvider
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file useCollator.test.tsx
|
|
5
|
+
* @input packages/core/src/i18n/useCollator.ts, InternationalizationProvider
|
|
6
|
+
* @output Unit tests for the internal provider-aware Intl.Collator hook
|
|
7
|
+
* @position Colocated tests; targets the default (no-provider) fallback,
|
|
8
|
+
* locale-driven comparison order, option threading, and memoization.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {ReactNode} from 'react';
|
|
12
|
+
import {describe, expect, test} from 'vitest';
|
|
13
|
+
import {render, renderHook} from '@testing-library/react';
|
|
14
|
+
import {useCollator} from '../useCollator';
|
|
15
|
+
import {InternationalizationProvider} from '../InternationalizationProvider';
|
|
16
|
+
|
|
17
|
+
function wrapperFor(locale: string) {
|
|
18
|
+
return ({children}: {children: ReactNode}) => (
|
|
19
|
+
<InternationalizationProvider locale={locale}>
|
|
20
|
+
{children}
|
|
21
|
+
</InternationalizationProvider>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('useCollator', () => {
|
|
26
|
+
test('compares using the en fallback when rendered without a provider', () => {
|
|
27
|
+
const {result} = renderHook(() => useCollator());
|
|
28
|
+
expect(result.current.compare('a', 'b')).toBeLessThan(0);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('orders "ä" before "z" under Swedish, and after "z" under German', () => {
|
|
32
|
+
const {result: sv} = renderHook(() => useCollator(), {
|
|
33
|
+
wrapper: wrapperFor('sv-SE'),
|
|
34
|
+
});
|
|
35
|
+
expect(['z', 'ä'].sort((a, b) => sv.current.compare(a, b))).toEqual([
|
|
36
|
+
'z',
|
|
37
|
+
'ä',
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
const {result: de} = renderHook(() => useCollator(), {
|
|
41
|
+
wrapper: wrapperFor('de-DE'),
|
|
42
|
+
});
|
|
43
|
+
expect(['z', 'ä'].sort((a, b) => de.current.compare(a, b))).toEqual([
|
|
44
|
+
'ä',
|
|
45
|
+
'z',
|
|
46
|
+
]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('threads options through to the underlying Intl.Collator (numeric)', () => {
|
|
50
|
+
const {result} = renderHook(() => useCollator({numeric: true}));
|
|
51
|
+
expect(
|
|
52
|
+
['item2', 'item10'].sort((a, b) => result.current.compare(a, b)),
|
|
53
|
+
).toEqual(['item2', 'item10']);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('without numeric, orders "item10" before "item2" lexicographically', () => {
|
|
57
|
+
const {result} = renderHook(() => useCollator());
|
|
58
|
+
expect(
|
|
59
|
+
['item2', 'item10'].sort((a, b) => result.current.compare(a, b)),
|
|
60
|
+
).toEqual(['item10', 'item2']);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('memoizes the collator when locale and options identity are unchanged', () => {
|
|
64
|
+
const options = {numeric: true} satisfies Intl.CollatorOptions;
|
|
65
|
+
const {result, rerender} = renderHook(
|
|
66
|
+
({collatorOptions}) => useCollator(collatorOptions),
|
|
67
|
+
{
|
|
68
|
+
initialProps: {collatorOptions: options},
|
|
69
|
+
wrapper: wrapperFor('en'),
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
const first = result.current;
|
|
73
|
+
rerender({collatorOptions: options});
|
|
74
|
+
expect(result.current).toBe(first);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('rebuilds the collator when options identity changes', () => {
|
|
78
|
+
const {result, rerender} = renderHook(
|
|
79
|
+
({collatorOptions}) => useCollator(collatorOptions),
|
|
80
|
+
{
|
|
81
|
+
initialProps: {
|
|
82
|
+
collatorOptions: {numeric: true} satisfies Intl.CollatorOptions,
|
|
83
|
+
},
|
|
84
|
+
wrapper: wrapperFor('en'),
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
const first = result.current;
|
|
88
|
+
rerender({collatorOptions: {numeric: true}});
|
|
89
|
+
expect(result.current).not.toBe(first);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('re-renders with a new collator when the provider locale changes', () => {
|
|
93
|
+
let latestCollator: Intl.Collator | undefined;
|
|
94
|
+
function Probe() {
|
|
95
|
+
latestCollator = useCollator();
|
|
96
|
+
const order = ['z', 'ä'].sort((a, b) => latestCollator!.compare(a, b));
|
|
97
|
+
return <span data-testid="order">{order.join(',')}</span>;
|
|
98
|
+
}
|
|
99
|
+
const {getByTestId, rerender} = render(
|
|
100
|
+
<InternationalizationProvider locale="sv-SE">
|
|
101
|
+
<Probe />
|
|
102
|
+
</InternationalizationProvider>,
|
|
103
|
+
);
|
|
104
|
+
expect(getByTestId('order').textContent).toBe('z,ä');
|
|
105
|
+
const svCollator = latestCollator;
|
|
106
|
+
|
|
107
|
+
rerender(
|
|
108
|
+
<InternationalizationProvider locale="de-DE">
|
|
109
|
+
<Probe />
|
|
110
|
+
</InternationalizationProvider>,
|
|
111
|
+
);
|
|
112
|
+
expect(getByTestId('order').textContent).toBe('ä,z');
|
|
113
|
+
expect(latestCollator).not.toBe(svCollator);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file useLocale.test.tsx
|
|
5
|
+
* @input packages/core/src/i18n/useLocale.ts, InternationalizationProvider
|
|
6
|
+
* @output Unit tests for the internal provider-aware locale accessor
|
|
7
|
+
* @position Colocated tests; targets the default (no-provider) fallback, the
|
|
8
|
+
* provider locale, and re-rendering when the provider locale changes.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {ReactNode} from 'react';
|
|
12
|
+
import {describe, expect, test} from 'vitest';
|
|
13
|
+
import {render, renderHook} from '@testing-library/react';
|
|
14
|
+
import {useLocale} from '../useLocale';
|
|
15
|
+
import {InternationalizationProvider} from '../InternationalizationProvider';
|
|
16
|
+
|
|
17
|
+
describe('useLocale', () => {
|
|
18
|
+
test('returns en when rendered without a provider', () => {
|
|
19
|
+
const {result} = renderHook(() => useLocale());
|
|
20
|
+
expect(result.current).toBe('en');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('returns the provider locale', () => {
|
|
24
|
+
const {result} = renderHook(() => useLocale(), {
|
|
25
|
+
wrapper: ({children}: {children: ReactNode}) => (
|
|
26
|
+
<InternationalizationProvider locale="fr">
|
|
27
|
+
{children}
|
|
28
|
+
</InternationalizationProvider>
|
|
29
|
+
),
|
|
30
|
+
});
|
|
31
|
+
expect(result.current).toBe('fr');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('re-renders with the new locale when the provider locale changes', () => {
|
|
35
|
+
function Probe() {
|
|
36
|
+
return <span data-testid="locale">{useLocale()}</span>;
|
|
37
|
+
}
|
|
38
|
+
const {getByTestId, rerender} = render(
|
|
39
|
+
<InternationalizationProvider locale="en">
|
|
40
|
+
<Probe />
|
|
41
|
+
</InternationalizationProvider>,
|
|
42
|
+
);
|
|
43
|
+
expect(getByTestId('locale').textContent).toBe('en');
|
|
44
|
+
|
|
45
|
+
rerender(
|
|
46
|
+
<InternationalizationProvider locale="ja-JP">
|
|
47
|
+
<Probe />
|
|
48
|
+
</InternationalizationProvider>,
|
|
49
|
+
);
|
|
50
|
+
expect(getByTestId('locale').textContent).toBe('ja-JP');
|
|
51
|
+
});
|
|
52
|
+
});
|
package/src/i18n/index.ts
CHANGED
|
@@ -10,12 +10,16 @@
|
|
|
10
10
|
* The public API is deliberately small:
|
|
11
11
|
* - InternationalizationProvider — provider component
|
|
12
12
|
* - useTranslator — hook returning a translator function
|
|
13
|
+
* - useLocale — hook returning the provider locale
|
|
14
|
+
* - useCollator — provider-bound locale-aware comparison
|
|
13
15
|
* - useDirection — hook returning the ambient text direction
|
|
14
16
|
* - getLocaleDirection — server-safe locale → direction helper
|
|
15
17
|
* - Translator — interface for consumer-injected runtimes
|
|
16
18
|
*
|
|
17
19
|
* SYNC: When modified, update these files to stay in sync:
|
|
18
20
|
* - /packages/core/src/index.ts
|
|
21
|
+
* - /packages/core/src/i18n/useLocale.ts
|
|
22
|
+
* - /packages/core/src/i18n/useCollator.ts
|
|
19
23
|
* - /packages/core/src/i18n/useDirection.ts
|
|
20
24
|
* - /packages/core/src/i18n/getLocaleDirection.ts
|
|
21
25
|
*/
|
|
@@ -26,6 +30,8 @@ export {InternationalizationContext} from './InternationalizationContext';
|
|
|
26
30
|
export type {InternationalizationContextValue} from './InternationalizationContext';
|
|
27
31
|
export {useTranslator} from './useTranslator';
|
|
28
32
|
export type {TranslatorFn} from './useTranslator';
|
|
33
|
+
export {useLocale} from './useLocale';
|
|
34
|
+
export {useCollator} from './useCollator';
|
|
29
35
|
export {useDirection} from './useDirection';
|
|
30
36
|
export {getLocaleDirection} from './getLocaleDirection';
|
|
31
37
|
export type {Translator} from './translator';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').HookDoc} */
|
|
4
|
+
export const docs = {
|
|
5
|
+
name: 'useCollator',
|
|
6
|
+
displayName: 'useCollator',
|
|
7
|
+
category: 'utilities',
|
|
8
|
+
keywords: [
|
|
9
|
+
'i18n',
|
|
10
|
+
'internationalization',
|
|
11
|
+
'locale',
|
|
12
|
+
'collation',
|
|
13
|
+
'compare',
|
|
14
|
+
'sort',
|
|
15
|
+
'table',
|
|
16
|
+
'hook',
|
|
17
|
+
],
|
|
18
|
+
params: [
|
|
19
|
+
{
|
|
20
|
+
name: 'options',
|
|
21
|
+
type: 'Intl.CollatorOptions',
|
|
22
|
+
description:
|
|
23
|
+
'Optional collation behavior such as numeric ordering, sensitivity, punctuation handling, and case order.',
|
|
24
|
+
required: false,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
returns: [
|
|
28
|
+
{
|
|
29
|
+
name: 'collator',
|
|
30
|
+
type: 'Intl.Collator',
|
|
31
|
+
description:
|
|
32
|
+
'A memoized collator bound to the active InternationalizationProvider locale.',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
usage: {
|
|
36
|
+
description:
|
|
37
|
+
'Returns the sanctioned locale-aware comparator for custom sorting. The collator is recreated when the provider locale or an option changes.',
|
|
38
|
+
bestPractices: [
|
|
39
|
+
{
|
|
40
|
+
guidance: true,
|
|
41
|
+
description:
|
|
42
|
+
'Reuse collator.compare in custom Table comparators and other user-visible string ordering.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
guidance: false,
|
|
46
|
+
description:
|
|
47
|
+
'Construct Intl.Collator directly or call localeCompare; those bypass the provider-backed locale contract.',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
relatedComponents: ['InternationalizationProvider', 'Table'],
|
|
52
|
+
relatedHooks: ['useLocale'],
|
|
53
|
+
importPath: '@astryxdesign/core',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** @type {import('@astryxdesign/cli/authoring').HookTranslationDoc} */
|
|
57
|
+
export const docsDense = {
|
|
58
|
+
description:
|
|
59
|
+
'Returns a memoized Intl.Collator bound to the active InternationalizationProvider locale.',
|
|
60
|
+
paramDescriptions: {
|
|
61
|
+
options:
|
|
62
|
+
'optional Intl.CollatorOptions: numeric ordering, sensitivity, punctuation, case order, etc.',
|
|
63
|
+
},
|
|
64
|
+
returnDescriptions: {
|
|
65
|
+
collator:
|
|
66
|
+
'memoized provider-bound collator for locale-aware comparison and sorting.',
|
|
67
|
+
},
|
|
68
|
+
usage: {
|
|
69
|
+
description:
|
|
70
|
+
'Use collator.compare for custom user-visible string ordering instead of raw Intl.Collator or localeCompare.',
|
|
71
|
+
bestPractices: [
|
|
72
|
+
{
|
|
73
|
+
guidance: true,
|
|
74
|
+
description:
|
|
75
|
+
'Reuse collator.compare in custom Table comparators and string sorting.',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
guidance: false,
|
|
79
|
+
description:
|
|
80
|
+
'Construct raw Intl.Collator or call localeCompare directly.',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useCollator.ts
|
|
7
|
+
* @input InternationalizationContext (via use()), optional Intl.CollatorOptions
|
|
8
|
+
* @output A memoized Intl.Collator bound to the active locale
|
|
9
|
+
* @position Public provider-aware string-comparison hook. Exported from the
|
|
10
|
+
* i18n barrel for components, sibling packages, and consumers that need
|
|
11
|
+
* locale-correct sorting without constructing a raw Intl.Collator. Raw
|
|
12
|
+
* collator construction stays centralized in this hook.
|
|
13
|
+
*
|
|
14
|
+
* Falls back to `'en'` when called outside a provider, matching the
|
|
15
|
+
* useTranslator/useDirection/useLocale fallback.
|
|
16
|
+
*
|
|
17
|
+
* SYNC: When modified, update:
|
|
18
|
+
* - /packages/core/src/i18n/InternationalizationContext.ts
|
|
19
|
+
* - /packages/core/src/i18n/useLocale.ts
|
|
20
|
+
* - /packages/core/src/i18n/useCollator.doc.mjs
|
|
21
|
+
* - /packages/core/src/i18n/index.ts
|
|
22
|
+
* - /packages/core/src/i18n/__tests__/useCollator.test.tsx
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import {use, useMemo} from 'react';
|
|
26
|
+
import {InternationalizationContext} from './InternationalizationContext';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns an `Intl.Collator` for the active provider locale, memoized across
|
|
30
|
+
* renders where the locale and options object are unchanged.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```
|
|
34
|
+
* const collator = useCollator({numeric: true});
|
|
35
|
+
* const sorted = [...items].sort((a, b) => collator.compare(a.name, b.name));
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function useCollator(options?: Intl.CollatorOptions): Intl.Collator {
|
|
39
|
+
const ctx = use(InternationalizationContext);
|
|
40
|
+
return useMemo(
|
|
41
|
+
() => new Intl.Collator(ctx.locale, options),
|
|
42
|
+
[ctx.locale, options],
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').HookDoc} */
|
|
4
|
+
export const docs = {
|
|
5
|
+
name: 'useLocale',
|
|
6
|
+
displayName: 'useLocale',
|
|
7
|
+
category: 'utilities',
|
|
8
|
+
keywords: [
|
|
9
|
+
'i18n',
|
|
10
|
+
'internationalization',
|
|
11
|
+
'localization',
|
|
12
|
+
'locale',
|
|
13
|
+
'language',
|
|
14
|
+
'provider',
|
|
15
|
+
'hook',
|
|
16
|
+
],
|
|
17
|
+
params: [],
|
|
18
|
+
returns: [
|
|
19
|
+
{
|
|
20
|
+
name: 'locale',
|
|
21
|
+
type: 'Locale',
|
|
22
|
+
description:
|
|
23
|
+
"The active InternationalizationProvider BCP 47 locale. Falls back to 'en' when no provider is present.",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
usage: {
|
|
27
|
+
description:
|
|
28
|
+
'Reads the authoritative Astryx locale. Use it to thread the provider locale into pure formatting helpers and sibling-package APIs; do not derive a second locale from navigator.language or a hardcoded literal.',
|
|
29
|
+
bestPractices: [
|
|
30
|
+
{
|
|
31
|
+
guidance: true,
|
|
32
|
+
description:
|
|
33
|
+
'Pass the returned locale to pure Astryx helpers or package APIs that require an explicit locale.',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
guidance: false,
|
|
37
|
+
description:
|
|
38
|
+
'Use navigator.language or a hardcoded display locale as a fallback; InternationalizationProvider is the locale source.',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
relatedComponents: ['InternationalizationProvider'],
|
|
43
|
+
relatedHooks: ['useCollator', 'useTranslator', 'useDirection'],
|
|
44
|
+
importPath: '@astryxdesign/core',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** @type {import('@astryxdesign/cli/authoring').HookTranslationDoc} */
|
|
48
|
+
export const docsDense = {
|
|
49
|
+
description:
|
|
50
|
+
"Returns the active InternationalizationProvider locale, falling back to 'en' without a provider.",
|
|
51
|
+
usage: {
|
|
52
|
+
description:
|
|
53
|
+
'Use as the sole locale source for pure formatting helpers and sibling-package APIs.',
|
|
54
|
+
bestPractices: [
|
|
55
|
+
{
|
|
56
|
+
guidance: true,
|
|
57
|
+
description:
|
|
58
|
+
'Thread this locale into pure helpers requiring an explicit locale.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
guidance: false,
|
|
62
|
+
description:
|
|
63
|
+
'Fall back to navigator.language or a hardcoded display locale.',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
returnDescriptions: {
|
|
68
|
+
locale: "active provider BCP 47 locale; 'en' without a provider.",
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useLocale.ts
|
|
7
|
+
* @input InternationalizationContext (via use())
|
|
8
|
+
* @output The active BCP 47 locale tag
|
|
9
|
+
* @position Public provider-aware locale accessor. Exported from the i18n
|
|
10
|
+
* barrel for components, sibling packages, and consumers that must thread
|
|
11
|
+
* the provider locale into pure formatting helpers. Returns `'en'` when
|
|
12
|
+
* called outside a provider, matching useTranslator/useDirection.
|
|
13
|
+
*
|
|
14
|
+
* This is the approved way to read the locale that feeds a formatting helper
|
|
15
|
+
* (`plainDateFormat`, `formatInstant`, chart formatters, …) or `useCollator()`.
|
|
16
|
+
* Reading `InternationalizationContext` directly for just its `locale` field,
|
|
17
|
+
* or reaching for `navigator.language`/a hardcoded literal, bypasses that
|
|
18
|
+
* provider-backed contract.
|
|
19
|
+
*
|
|
20
|
+
* SYNC: When modified, update:
|
|
21
|
+
* - /packages/core/src/i18n/InternationalizationContext.ts
|
|
22
|
+
* - /packages/core/src/i18n/useLocale.doc.mjs
|
|
23
|
+
* - /packages/core/src/i18n/index.ts
|
|
24
|
+
* - /packages/core/src/i18n/__tests__/useLocale.test.tsx
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import {use} from 'react';
|
|
28
|
+
import {InternationalizationContext} from './InternationalizationContext';
|
|
29
|
+
import type {Locale} from './types';
|
|
30
|
+
|
|
31
|
+
export function useLocale(): Locale {
|
|
32
|
+
const ctx = use(InternationalizationContext);
|
|
33
|
+
return ctx.locale;
|
|
34
|
+
}
|
package/src/reset.css
CHANGED
|
@@ -262,9 +262,16 @@
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
/*
|
|
265
|
-
*
|
|
265
|
+
* Disabled elements take back any interactive cursor: a control that will
|
|
266
|
+
* not respond must not answer the pointer as though it will. `default`
|
|
267
|
+
* rather than `not-allowed` — a disabled control sealed behind
|
|
268
|
+
* `pointer-events: none` shows whatever its ancestor shows, and one cursor
|
|
269
|
+
* everywhere beats a stronger one we can only paint on half of them.
|
|
270
|
+
* Covers [aria-disabled] too: astryx keeps a disabled control focusable
|
|
271
|
+
* that way wherever its reason must stay discoverable (Button with a
|
|
272
|
+
* tooltip, Selector's trigger, SideNavItem).
|
|
266
273
|
*/
|
|
267
|
-
:where(:disabled) {
|
|
274
|
+
:where(:disabled, [aria-disabled='true']) {
|
|
268
275
|
cursor: default;
|
|
269
276
|
}
|
|
270
277
|
|