@astryxdesign/core 0.1.8 → 0.1.9-canary.08c278e
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 +100 -0
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
- package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts +53 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +203 -49
- package/dist/Avatar/AvatarStatusDot.d.ts +33 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -0
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +33 -4
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +208 -6
- package/dist/Breadcrumbs/index.d.ts +5 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +9 -1
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +33 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +30 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +30 -2
- package/dist/Calendar/dayCellUtils.js +1 -1
- package/dist/Card/Card.d.ts +8 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +28 -2
- package/dist/Carousel/Carousel.d.ts +4 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +24 -4
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +46 -7
- package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +11 -1
- package/dist/Chat/ChatComposerInput.d.ts +20 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +36 -4
- package/dist/Chat/ChatContext.d.ts +33 -0
- package/dist/Chat/ChatContext.d.ts.map +1 -1
- package/dist/Chat/ChatContext.js +16 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +1 -1
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +4 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +7 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +18 -9
- package/dist/Chat/index.d.ts +2 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/index.js +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +2 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +22 -8
- package/dist/Chat/useSpeechRecognition.d.ts +0 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +1 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.js +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +11 -1
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +5 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +9 -2
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +3 -1
- package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
- package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +6 -1
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/DateInput/DateInput.d.ts +55 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +28 -2
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +3 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +18 -3
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +57 -6
- package/dist/Dialog/DialogContext.d.ts +7 -0
- package/dist/Dialog/DialogContext.d.ts.map +1 -1
- package/dist/Dialog/DialogContext.js +2 -2
- package/dist/Dialog/DialogHeader.d.ts +5 -2
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +6 -1
- package/dist/Divider/Divider.js +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +1 -2
- package/dist/DropdownMenu/DropdownMenuItem.js +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +2 -3
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +43 -16
- package/dist/FieldStatus/FieldStatus.d.ts +15 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +58 -6
- package/dist/FileInput/FileInput.d.ts +9 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +42 -20
- package/dist/HoverCard/HoverCard.d.ts +9 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/useHoverCard.d.ts +8 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -2
- package/dist/Icon/Icon.d.ts +7 -2
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Item/Item.d.ts +6 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +22 -1
- package/dist/Layer/useLayer.d.ts +6 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +2 -0
- package/dist/Lightbox/Lightbox.js +4 -4
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +6 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +41 -12
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +9 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +8 -1
- package/dist/Outline/Outline.d.ts +0 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +0 -1
- package/dist/OverflowList/OverflowList.d.ts +20 -3
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +29 -4
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +3 -9
- package/dist/PowerSearch/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.d.ts +9 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +16 -13
- package/dist/Selector/Selector.d.ts +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +7 -3
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +19 -2
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +3 -2
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/index.js +3 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts +13 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +4 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +87 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/TextArea/TextArea.d.ts +9 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +2 -0
- package/dist/TextInput/TextInput.d.ts +9 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +6 -1
- package/dist/Thumbnail/Thumbnail.d.ts +26 -5
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +97 -54
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
- package/dist/TimeInput/TimeInput.d.ts +9 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +17 -4
- package/dist/Timestamp/Timestamp.d.ts +3 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +8 -6
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +2 -5
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +10 -3
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +18 -4
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
- package/dist/TopNav/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeList.d.ts +12 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +2 -0
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +10 -4
- package/dist/TreeList/TreeListItem.d.ts +8 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +28 -8
- package/dist/TreeList/TreeListTypes.d.ts +25 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/TreeList/index.d.ts +2 -2
- package/dist/TreeList/index.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +1 -1
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +2 -0
- package/dist/astryx.css +41 -31
- package/dist/astryx.umd.js +51 -51
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/docs-types.d.ts +8 -0
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.d.ts +47 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -0
- package/dist/hooks/computeOverflow.js +213 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- package/dist/hooks/useDevWarning.d.ts +18 -0
- package/dist/hooks/useDevWarning.d.ts.map +1 -0
- package/dist/hooks/useDevWarning.js +49 -0
- package/dist/hooks/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useListFocus.d.ts +6 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +12 -4
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +36 -25
- package/dist/i18n/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +51 -0
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
- package/dist/utils/devWarning.d.ts +42 -0
- package/dist/utils/devWarning.d.ts.map +1 -0
- package/dist/utils/devWarning.js +88 -0
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +53 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/locales/en.json +32 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +24 -0
- package/package.json +1 -1
- package/src/AppShell/AppShell.tsx +6 -0
- package/src/AppShell/AppShellMobileContext.tsx +8 -0
- package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
- package/src/Avatar/Avatar.doc.mjs +60 -3
- package/src/Avatar/Avatar.test.tsx +281 -1
- package/src/Avatar/Avatar.tsx +324 -64
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +178 -21
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +125 -0
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -0
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +53 -9
- package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +284 -2
- package/src/Breadcrumbs/index.ts +27 -0
- package/src/Button/Button.doc.mjs +9 -0
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +27 -3
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
- package/src/ButtonGroup/ButtonGroup.tsx +32 -0
- package/src/Calendar/Calendar.doc.mjs +12 -1
- package/src/Calendar/Calendar.test.tsx +193 -0
- package/src/Calendar/Calendar.tsx +38 -16
- package/src/Calendar/dayCellUtils.test.ts +5 -0
- package/src/Calendar/dayCellUtils.ts +1 -1
- package/src/Card/Card.doc.mjs +9 -0
- package/src/Card/Card.test.tsx +21 -3
- package/src/Card/Card.tsx +35 -2
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Carousel/Carousel.test.tsx +53 -0
- package/src/Carousel/Carousel.tsx +34 -4
- package/src/Chat/ChatComposer.doc.mjs +12 -3
- package/src/Chat/ChatComposer.test.tsx +115 -0
- package/src/Chat/ChatComposer.tsx +73 -9
- package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
- package/src/Chat/ChatComposerDrawer.tsx +11 -1
- package/src/Chat/ChatComposerInput.doc.mjs +7 -0
- package/src/Chat/ChatComposerInput.test.tsx +103 -0
- package/src/Chat/ChatComposerInput.tsx +51 -5
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +4 -1
- package/src/Chat/ChatLayout.tsx +7 -5
- package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +11 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +25 -4
- package/src/Chat/index.ts +5 -1
- package/src/Chat/useChatStreamScroll.test.tsx +49 -0
- package/src/Chat/useChatStreamScroll.ts +27 -10
- package/src/Chat/useSpeechRecognition.ts +1 -1
- package/src/Chat/useTriggerMenu.tsx +4 -2
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxInput/CheckboxInput.tsx +1 -1
- package/src/CheckboxList/CheckboxList.test.tsx +81 -3
- package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
- package/src/CheckboxList/CheckboxListItem.tsx +41 -5
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +13 -3
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +10 -2
- package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.tsx +3 -1
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
- package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
- package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +193 -0
- package/src/DateInput/DateInput.doc.mjs +31 -0
- package/src/DateInput/DateInput.test.tsx +131 -0
- package/src/DateInput/DateInput.tsx +78 -3
- package/src/DateInput/index.ts +1 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +8 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +23 -0
- package/src/DateRangeInput/DateRangeInput.tsx +13 -3
- package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +147 -0
- package/src/DateTimeInput/DateTimeInput.tsx +42 -18
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.test.tsx +77 -4
- package/src/Dialog/Dialog.tsx +89 -5
- package/src/Dialog/DialogContext.ts +9 -2
- package/src/Dialog/DialogHeader.doc.mjs +2 -2
- package/src/Dialog/DialogHeader.tsx +9 -2
- package/src/Divider/Divider.tsx +2 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +169 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +1 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +1 -1
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/Field.tsx +6 -5
- package/src/Field/FieldLabel.tsx +9 -1
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +150 -40
- package/src/FieldStatus/FieldStatus.tsx +63 -5
- package/src/FileInput/FileInput.doc.mjs +17 -2
- package/src/FileInput/FileInput.test.tsx +135 -12
- package/src/FileInput/FileInput.tsx +53 -28
- package/src/HoverCard/HoverCard.doc.mjs +13 -0
- package/src/HoverCard/HoverCard.test.tsx +21 -2
- package/src/HoverCard/HoverCard.tsx +11 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +24 -2
- package/src/Icon/Icon.doc.mjs +3 -2
- package/src/Icon/Icon.tsx +7 -2
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.test.tsx +40 -18
- package/src/Item/Item.tsx +38 -2
- package/src/Layer/useLayer.tsx +8 -0
- package/src/Lightbox/Lightbox.tsx +4 -4
- package/src/List/List.test.tsx +9 -8
- package/src/MobileNav/MobileNav.tsx +12 -1
- package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
- package/src/MobileNav/MobileNavToggle.tsx +9 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +13 -2
- package/src/MultiSelector/MultiSelector.test.tsx +195 -3
- package/src/MultiSelector/MultiSelector.tsx +65 -12
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +15 -0
- package/src/NumberInput/NumberInput.test.tsx +82 -7
- package/src/NumberInput/NumberInput.tsx +21 -4
- package/src/Outline/Outline.tsx +0 -1
- package/src/OverflowList/OverflowList.doc.mjs +39 -6
- package/src/OverflowList/OverflowList.test.tsx +111 -0
- package/src/OverflowList/OverflowList.tsx +48 -8
- package/src/Pagination/Pagination.tsx +11 -3
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +29 -0
- package/src/PowerSearch/PowerSearch.test.tsx +43 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +46 -4
- package/src/SelectableCard/SelectableCard.tsx +29 -16
- package/src/Selector/Selector.doc.mjs +7 -0
- package/src/Selector/Selector.test.tsx +92 -0
- package/src/Selector/Selector.tsx +16 -2
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNavCollapseButton.tsx +6 -1
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.tsx +5 -1
- package/src/Slider/Slider.test.tsx +75 -2
- package/src/Slider/Slider.tsx +21 -5
- package/src/Switch/Switch.test.tsx +32 -1
- package/src/TabList/Tab.tsx +2 -2
- package/src/TabList/TabMenu.tsx +2 -2
- package/src/Table/BaseTable.tsx +3 -5
- package/src/Table/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
- package/src/Table/plugins/rowStatus/index.ts +7 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +16 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +19 -1
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -1
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
- package/src/Table/plugins/tree/useTableTreeData.tsx +128 -1
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
- package/src/Table/useBaseTablePlugins.ts +10 -6
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +29 -0
- package/src/Table/useTableTreeState.doc.mjs +2 -2
- package/src/TextArea/TextArea.doc.mjs +15 -0
- package/src/TextArea/TextArea.test.tsx +32 -1
- package/src/TextArea/TextArea.tsx +10 -0
- package/src/TextInput/TextInput.doc.mjs +15 -0
- package/src/TextInput/TextInput.test.tsx +44 -0
- package/src/TextInput/TextInput.tsx +13 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +142 -42
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.doc.mjs +15 -0
- package/src/TimeInput/TimeInput.test.tsx +99 -1
- package/src/TimeInput/TimeInput.tsx +29 -6
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +32 -0
- package/src/Timestamp/Timestamp.tsx +28 -8
- package/src/Toast/useToast.tsx +7 -8
- package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +30 -1
- package/src/Tokenizer/Tokenizer.test.tsx +206 -2
- package/src/Tokenizer/Tokenizer.tsx +26 -4
- package/src/TopNav/TopNav.test.tsx +125 -1
- package/src/TopNav/TopNavHeading.tsx +24 -8
- package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
- package/src/TopNav/TopNavMegaMenu.tsx +10 -4
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.doc.mjs +22 -0
- package/src/TreeList/TreeList.test.tsx +232 -0
- package/src/TreeList/TreeList.tsx +18 -2
- package/src/TreeList/TreeListBranches.tsx +16 -2
- package/src/TreeList/TreeListItem.tsx +52 -12
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/Typeahead/BaseTypeahead.tsx +1 -1
- package/src/Typeahead/Typeahead.doc.mjs +7 -0
- package/src/Typeahead/Typeahead.test.tsx +23 -0
- package/src/Typeahead/Typeahead.tsx +10 -0
- package/src/authoring/doc.ts +1 -3
- package/src/docs-types.ts +5 -0
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useListFocus.doc.mjs +3 -3
- package/src/hooks/useListFocus.test.tsx +67 -1
- package/src/hooks/useListFocus.ts +21 -5
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/resolve.ts +9 -21
- package/src/i18n/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +107 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
- package/src/utils/devWarning.test.ts +56 -0
- package/src/utils/devWarning.ts +102 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/plainDate.test.ts +22 -0
- package/src/utils/plainDate.ts +61 -0
- package/src/utils/types.ts +14 -0
package/src/hooks/useOverflow.ts
CHANGED
|
@@ -10,15 +10,20 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Measures children rendered in a hidden container to determine how many fit
|
|
12
12
|
* in the available width, without flickering. Uses ResizeObserver to react
|
|
13
|
-
* to container size changes.
|
|
13
|
+
* to container size changes. Supports an optional item cap (`maxVisibleItems`)
|
|
14
|
+
* and bounded multi-row wrapping (`maxRows`); the fit/clamp/row-packing math
|
|
15
|
+
* lives in the pure `computeOverflow` helper.
|
|
14
16
|
*
|
|
15
17
|
* SYNC: When modified, update:
|
|
16
18
|
* - /packages/core/src/hooks/index.ts
|
|
19
|
+
* - /packages/core/src/hooks/computeOverflow.ts (the pure computation)
|
|
17
20
|
*/
|
|
18
21
|
|
|
19
22
|
import {useState, useCallback, useRef} from 'react';
|
|
20
23
|
import {useIsomorphicLayoutEffect} from './useIsomorphicLayoutEffect';
|
|
21
24
|
import {observeResize, unobserveResize} from '../utils/sharedResizeObserver';
|
|
25
|
+
import {computeOverflow} from './computeOverflow';
|
|
26
|
+
import {useDevWarning} from './useDevWarning';
|
|
22
27
|
|
|
23
28
|
export interface UseOverflowOptions {
|
|
24
29
|
/**
|
|
@@ -33,6 +38,23 @@ export interface UseOverflowOptions {
|
|
|
33
38
|
*/
|
|
34
39
|
minVisibleItems?: number;
|
|
35
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Maximum number of items to ever show, even if they all fit. The ceiling
|
|
43
|
+
* partner to `minVisibleItems`. `undefined` means no cap. When it is less
|
|
44
|
+
* than `minVisibleItems`, the floor wins and a dev-only warning is emitted.
|
|
45
|
+
* @default undefined
|
|
46
|
+
*/
|
|
47
|
+
maxVisibleItems?: number;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Wrap items across up to this many rows before collapsing the rest into the
|
|
51
|
+
* overflow indicator. `undefined` (or `1`) keeps the single-line behavior.
|
|
52
|
+
* A number, not a boolean: unbounded wrapping is a plain flex-wrap layout,
|
|
53
|
+
* not overflow collapse. Assumes uniform row height.
|
|
54
|
+
* @default undefined
|
|
55
|
+
*/
|
|
56
|
+
maxRows?: number;
|
|
57
|
+
|
|
36
58
|
/**
|
|
37
59
|
* Which end to collapse items from.
|
|
38
60
|
* @default 'end'
|
|
@@ -61,6 +83,10 @@ export interface UseOverflowReturn {
|
|
|
61
83
|
visibleCount: number;
|
|
62
84
|
/** Whether any items are overflowing */
|
|
63
85
|
hasOverflow: boolean;
|
|
86
|
+
/** Number of rows the visible items occupy (1 for the single-line path) */
|
|
87
|
+
rows: number;
|
|
88
|
+
/** Measured max item height in pixels; used to size the multi-row container */
|
|
89
|
+
rowHeight: number;
|
|
64
90
|
}
|
|
65
91
|
|
|
66
92
|
/**
|
|
@@ -88,13 +114,25 @@ export function useOverflow(
|
|
|
88
114
|
const {
|
|
89
115
|
gap = 0,
|
|
90
116
|
minVisibleItems = 0,
|
|
117
|
+
maxVisibleItems,
|
|
118
|
+
maxRows,
|
|
91
119
|
collapseFrom = 'end',
|
|
92
120
|
behavior = 'observeSelf',
|
|
93
121
|
} = options;
|
|
94
122
|
|
|
123
|
+
useDevWarning(
|
|
124
|
+
'useOverflow',
|
|
125
|
+
`maxVisibleItems (${maxVisibleItems}) is less than ` +
|
|
126
|
+
`minVisibleItems (${minVisibleItems}); the floor wins and ` +
|
|
127
|
+
`minVisibleItems items will be shown.`,
|
|
128
|
+
maxVisibleItems != null && maxVisibleItems < minVisibleItems,
|
|
129
|
+
);
|
|
130
|
+
|
|
95
131
|
const observeParent = behavior === 'observeParent';
|
|
96
132
|
|
|
97
133
|
const [visibleCount, setVisibleCount] = useState(itemCount);
|
|
134
|
+
const [rows, setRows] = useState(1);
|
|
135
|
+
const [rowHeight, setRowHeight] = useState(0);
|
|
98
136
|
const containerElRef = useRef<HTMLElement | null>(null);
|
|
99
137
|
const measureElRef = useRef<HTMLElement | null>(null);
|
|
100
138
|
const observedElRef = useRef<HTMLElement | null>(null);
|
|
@@ -134,44 +172,45 @@ export function useOverflow(
|
|
|
134
172
|
if (children.length === 0) {
|
|
135
173
|
// eslint-disable-next-line @eslint-react/set-state-in-effect -- overflow count is derived from measured DOM widths
|
|
136
174
|
setVisibleCount(0);
|
|
175
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect -- derived from measured DOM
|
|
176
|
+
setRows(0);
|
|
137
177
|
return;
|
|
138
178
|
}
|
|
139
179
|
|
|
140
|
-
// Collect widths of all children
|
|
141
180
|
const widths = children.map(child => child.offsetWidth);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const reservedWidth = isLastItem
|
|
158
|
-
? 0
|
|
159
|
-
: indicatorWidth + (count > 0 || indicatorWidth > 0 ? gap : 0);
|
|
160
|
-
|
|
161
|
-
if (
|
|
162
|
-
candidateWidth + reservedWidth > availableWidth &&
|
|
163
|
-
count >= minVisibleItems
|
|
164
|
-
) {
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
totalWidth = candidateWidth;
|
|
169
|
-
count++;
|
|
170
|
-
}
|
|
181
|
+
const measuredRowHeight = children.reduce(
|
|
182
|
+
(max, child) => Math.max(max, child.offsetHeight || 0),
|
|
183
|
+
0,
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const {visibleCount: nextVisible, rows: nextRows} = computeOverflow({
|
|
187
|
+
widths,
|
|
188
|
+
gap,
|
|
189
|
+
availableWidth,
|
|
190
|
+
indicatorWidth,
|
|
191
|
+
minVisibleItems,
|
|
192
|
+
maxVisibleItems,
|
|
193
|
+
maxRows,
|
|
194
|
+
collapseFrom,
|
|
195
|
+
});
|
|
171
196
|
|
|
172
197
|
// eslint-disable-next-line @eslint-react/set-state-in-effect -- overflow count is derived from measured DOM widths
|
|
173
|
-
setVisibleCount(
|
|
174
|
-
|
|
198
|
+
setVisibleCount(nextVisible);
|
|
199
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect -- derived from measured DOM
|
|
200
|
+
setRows(prev => (prev === nextRows ? prev : nextRows));
|
|
201
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect -- derived from measured DOM
|
|
202
|
+
setRowHeight(prev =>
|
|
203
|
+
prev === measuredRowHeight ? prev : measuredRowHeight,
|
|
204
|
+
);
|
|
205
|
+
}, [
|
|
206
|
+
itemCount,
|
|
207
|
+
gap,
|
|
208
|
+
minVisibleItems,
|
|
209
|
+
maxVisibleItems,
|
|
210
|
+
maxRows,
|
|
211
|
+
collapseFrom,
|
|
212
|
+
observeParent,
|
|
213
|
+
]);
|
|
175
214
|
|
|
176
215
|
const containerRef = useCallback(
|
|
177
216
|
(el: HTMLElement | null) => {
|
|
@@ -217,5 +256,7 @@ export function useOverflow(
|
|
|
217
256
|
measureRef,
|
|
218
257
|
visibleCount,
|
|
219
258
|
hasOverflow,
|
|
259
|
+
rows,
|
|
260
|
+
rowHeight,
|
|
220
261
|
};
|
|
221
262
|
}
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
* SYNC: When modified, update these files to stay in sync:
|
|
16
16
|
* - /packages/core/src/i18n/InternationalizationProvider.tsx
|
|
17
17
|
* - /packages/core/src/i18n/t.client.ts
|
|
18
|
+
* - /packages/core/src/i18n/useDirection.ts
|
|
19
|
+
* - /packages/core/src/i18n/getLocaleDirection.ts
|
|
18
20
|
* - /packages/core/src/i18n/index.ts
|
|
19
21
|
*/
|
|
20
22
|
|
|
@@ -23,6 +25,7 @@ import type {Locale, MessagesByLocale, Overrides} from './types';
|
|
|
23
25
|
|
|
24
26
|
export interface InternationalizationContextValue {
|
|
25
27
|
locale: Locale;
|
|
28
|
+
direction: 'ltr' | 'rtl';
|
|
26
29
|
messages: MessagesByLocale;
|
|
27
30
|
overrides?: Overrides;
|
|
28
31
|
}
|
|
@@ -34,6 +37,7 @@ export interface InternationalizationContextValue {
|
|
|
34
37
|
export const InternationalizationContext =
|
|
35
38
|
createContext<InternationalizationContextValue>({
|
|
36
39
|
locale: 'en',
|
|
40
|
+
direction: 'ltr',
|
|
37
41
|
messages: {},
|
|
38
42
|
});
|
|
39
43
|
InternationalizationContext.displayName = 'InternationalizationContext';
|
|
@@ -20,7 +20,29 @@ export const docs = {
|
|
|
20
20
|
],
|
|
21
21
|
usage: {
|
|
22
22
|
description:
|
|
23
|
-
|
|
23
|
+
'Wraps your app to set the active locale and (optionally) merge additional translation catalogs + per-locale overrides. Astryx components inside the subtree resolve their strings against this context. If no provider is present, components fall back to the shipped English defaults.',
|
|
24
|
+
bestPractices: [
|
|
25
|
+
{
|
|
26
|
+
guidance: true,
|
|
27
|
+
description:
|
|
28
|
+
'Use shipped Astryx locale catalogs from `@astryxdesign/core/locales/*` when one exists for your target locale.',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
guidance: true,
|
|
32
|
+
description:
|
|
33
|
+
'Use a same-shape local catalog only when Astryx has not shipped that locale yet or you are testing in-progress translations.',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
guidance: true,
|
|
37
|
+
description:
|
|
38
|
+
'Use real BCP 47 tags such as `fr`, `pt-BR`, or `ar`; regional locales fall back to their base language before English.',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
guidance: false,
|
|
42
|
+
description:
|
|
43
|
+
'Cast custom catalog maps to `any`; the i18n package exports `MessagesByLocale` and `Catalog` for local catalog typing.',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
24
46
|
},
|
|
25
47
|
props: [
|
|
26
48
|
{
|
|
@@ -35,7 +57,7 @@ export const docs = {
|
|
|
35
57
|
type: 'MessagesByLocale',
|
|
36
58
|
required: false,
|
|
37
59
|
description:
|
|
38
|
-
'Optional map of BCP 47 tag to translation catalog.
|
|
60
|
+
'Optional map of BCP 47 tag to translation catalog. Import shipped catalogs from `@astryxdesign/core/locales/*`; the shipped "en" catalog is always available and does not need to be listed here.',
|
|
39
61
|
},
|
|
40
62
|
{
|
|
41
63
|
name: 'overrides',
|
|
@@ -51,6 +73,59 @@ export const docs = {
|
|
|
51
73
|
description: 'Content to render with the internationalization provider.',
|
|
52
74
|
},
|
|
53
75
|
],
|
|
76
|
+
examples: [
|
|
77
|
+
{
|
|
78
|
+
label: 'Load a shipped Astryx locale catalog',
|
|
79
|
+
code: `import type {ReactNode} from 'react';
|
|
80
|
+
import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
81
|
+
import frFR from '@astryxdesign/core/locales/fr-FR.json';
|
|
82
|
+
|
|
83
|
+
export function AppI18n({children}: {children: ReactNode}) {
|
|
84
|
+
return (
|
|
85
|
+
<InternationalizationProvider locale="fr-FR" messages={{'fr-FR': frFR}}>
|
|
86
|
+
{children}
|
|
87
|
+
</InternationalizationProvider>
|
|
88
|
+
);
|
|
89
|
+
}`,
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
label: 'Override one Astryx string',
|
|
93
|
+
code: `import type {ReactNode} from 'react';
|
|
94
|
+
import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
95
|
+
|
|
96
|
+
export function AppI18n({children}: {children: ReactNode}) {
|
|
97
|
+
return (
|
|
98
|
+
<InternationalizationProvider
|
|
99
|
+
locale="en"
|
|
100
|
+
overrides={{
|
|
101
|
+
en: {'@astryx.selector.placeholder': 'Choose...'},
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
{children}
|
|
105
|
+
</InternationalizationProvider>
|
|
106
|
+
);
|
|
107
|
+
}`,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
label: 'Provide a local fallback catalog',
|
|
111
|
+
code: `import type {ReactNode} from 'react';
|
|
112
|
+
import {
|
|
113
|
+
InternationalizationProvider,
|
|
114
|
+
type MessagesByLocale,
|
|
115
|
+
} from '@astryxdesign/core/i18n';
|
|
116
|
+
import ptBR from './locales/pt-BR.json';
|
|
117
|
+
|
|
118
|
+
const messages: MessagesByLocale = {'pt-BR': ptBR};
|
|
119
|
+
|
|
120
|
+
export function AppI18n({children}: {children: ReactNode}) {
|
|
121
|
+
return (
|
|
122
|
+
<InternationalizationProvider locale="pt-BR" messages={messages}>
|
|
123
|
+
{children}
|
|
124
|
+
</InternationalizationProvider>
|
|
125
|
+
);
|
|
126
|
+
}`,
|
|
127
|
+
},
|
|
128
|
+
],
|
|
54
129
|
};
|
|
55
130
|
|
|
56
131
|
/** @type {import('../docs-types').TranslationDoc} */
|
|
@@ -60,6 +135,28 @@ export const docsDense = {
|
|
|
60
135
|
usage: {
|
|
61
136
|
description:
|
|
62
137
|
'Wraps app to set active locale and (optionally) merge translation catalogs + per-locale overrides. Astryx components resolve strings against this context; missing keys fall back to shipped English.',
|
|
138
|
+
bestPractices: [
|
|
139
|
+
{
|
|
140
|
+
guidance: true,
|
|
141
|
+
description:
|
|
142
|
+
'Use shipped Astryx locale catalogs from `@astryxdesign/core/locales/*` when one exists for the target locale.',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
guidance: true,
|
|
146
|
+
description:
|
|
147
|
+
'Use a same-shape local catalog only when Astryx has not shipped that locale yet or when testing in-progress translations.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
guidance: true,
|
|
151
|
+
description:
|
|
152
|
+
'Use real BCP 47 tags like `fr`, `pt-BR`, or `ar`; regional locales fall back to base language before English.',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
guidance: false,
|
|
156
|
+
description:
|
|
157
|
+
'Cast custom catalog maps to `any`; the i18n package exports `MessagesByLocale` and `Catalog` for local catalog typing.',
|
|
158
|
+
},
|
|
159
|
+
],
|
|
63
160
|
},
|
|
64
161
|
propDescriptions: {
|
|
65
162
|
locale:
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
import {useMemo, type ReactNode} from 'react';
|
|
23
23
|
import {InternationalizationContext} from './InternationalizationContext';
|
|
24
|
+
import {getLocaleDirection} from './getLocaleDirection';
|
|
24
25
|
import type {Locale, MessagesByLocale, Overrides} from './types';
|
|
25
26
|
|
|
26
27
|
export interface InternationalizationProviderProps {
|
|
@@ -55,6 +56,13 @@ export interface InternationalizationProviderProps {
|
|
|
55
56
|
* ```
|
|
56
57
|
*/
|
|
57
58
|
overrides?: Overrides;
|
|
59
|
+
/**
|
|
60
|
+
* Optional explicit text direction override. When omitted, direction is derived
|
|
61
|
+
* from `locale` via `Intl.Locale.getTextInfo()`. Provide this to force a
|
|
62
|
+
* direction (e.g. RTL layout testing under an English catalog) or to skip the
|
|
63
|
+
* derivation when you already know the direction.
|
|
64
|
+
*/
|
|
65
|
+
dir?: 'ltr' | 'rtl';
|
|
58
66
|
children: ReactNode;
|
|
59
67
|
}
|
|
60
68
|
|
|
@@ -66,11 +74,13 @@ export function InternationalizationProvider({
|
|
|
66
74
|
locale,
|
|
67
75
|
messages,
|
|
68
76
|
overrides,
|
|
77
|
+
dir,
|
|
69
78
|
children,
|
|
70
79
|
}: InternationalizationProviderProps) {
|
|
80
|
+
const direction = dir ?? getLocaleDirection(locale);
|
|
71
81
|
const value = useMemo(
|
|
72
|
-
() => ({locale, messages: messages ?? {}, overrides}),
|
|
73
|
-
[locale, messages, overrides],
|
|
82
|
+
() => ({locale, direction, messages: messages ?? {}, overrides}),
|
|
83
|
+
[locale, direction, messages, overrides],
|
|
74
84
|
);
|
|
75
85
|
return (
|
|
76
86
|
<InternationalizationContext value={value}>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file getLocaleDirection.test.ts
|
|
5
|
+
* @input packages/core/src/i18n/getLocaleDirection.ts
|
|
6
|
+
* @output Unit tests for the server-safe locale → direction helper
|
|
7
|
+
* @position Colocated tests; targets LTR/RTL classification and the
|
|
8
|
+
* try/catch fallback for malformed input.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {describe, expect, test} from 'vitest';
|
|
12
|
+
import {getLocaleDirection} from '../getLocaleDirection';
|
|
13
|
+
|
|
14
|
+
describe('getLocaleDirection', () => {
|
|
15
|
+
test('returns ltr for English', () => {
|
|
16
|
+
expect(getLocaleDirection('en')).toBe('ltr');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('returns rtl for RTL languages', () => {
|
|
20
|
+
expect(getLocaleDirection('ar')).toBe('rtl');
|
|
21
|
+
expect(getLocaleDirection('he')).toBe('rtl');
|
|
22
|
+
expect(getLocaleDirection('fa')).toBe('rtl');
|
|
23
|
+
expect(getLocaleDirection('ur')).toBe('rtl');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('returns ltr for regional LTR tags', () => {
|
|
27
|
+
expect(getLocaleDirection('pt-BR')).toBe('ltr');
|
|
28
|
+
expect(getLocaleDirection('zh-CN')).toBe('ltr');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('falls back to ltr for a malformed locale without throwing', () => {
|
|
32
|
+
expect(() => getLocaleDirection('not_a_locale')).not.toThrow();
|
|
33
|
+
expect(getLocaleDirection('not_a_locale')).toBe('ltr');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('falls back to ltr for an empty string without throwing', () => {
|
|
37
|
+
expect(() => getLocaleDirection('')).not.toThrow();
|
|
38
|
+
expect(getLocaleDirection('')).toBe('ltr');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file useDirection.test.tsx
|
|
5
|
+
* @input packages/core/src/i18n/useDirection.ts, InternationalizationProvider
|
|
6
|
+
* @output Unit tests for the ambient text-direction hook
|
|
7
|
+
* @position Colocated tests; targets the default (no-provider) fallback,
|
|
8
|
+
* locale-derived direction, and the explicit `dir` override.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {ReactNode} from 'react';
|
|
12
|
+
import {describe, expect, test} from 'vitest';
|
|
13
|
+
import {renderHook} from '@testing-library/react';
|
|
14
|
+
import {useDirection} from '../useDirection';
|
|
15
|
+
import {InternationalizationProvider} from '../InternationalizationProvider';
|
|
16
|
+
|
|
17
|
+
describe('useDirection', () => {
|
|
18
|
+
test('returns ltr when rendered without a provider', () => {
|
|
19
|
+
const {result} = renderHook(() => useDirection());
|
|
20
|
+
expect(result.current).toBe('ltr');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('returns ltr under an English provider', () => {
|
|
24
|
+
const {result} = renderHook(() => useDirection(), {
|
|
25
|
+
wrapper: ({children}: {children: ReactNode}) => (
|
|
26
|
+
<InternationalizationProvider locale="en">
|
|
27
|
+
{children}
|
|
28
|
+
</InternationalizationProvider>
|
|
29
|
+
),
|
|
30
|
+
});
|
|
31
|
+
expect(result.current).toBe('ltr');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('returns rtl under an Arabic provider', () => {
|
|
35
|
+
const {result} = renderHook(() => useDirection(), {
|
|
36
|
+
wrapper: ({children}: {children: ReactNode}) => (
|
|
37
|
+
<InternationalizationProvider locale="ar">
|
|
38
|
+
{children}
|
|
39
|
+
</InternationalizationProvider>
|
|
40
|
+
),
|
|
41
|
+
});
|
|
42
|
+
expect(result.current).toBe('rtl');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('explicit dir="rtl" wins over an LTR locale', () => {
|
|
46
|
+
const {result} = renderHook(() => useDirection(), {
|
|
47
|
+
wrapper: ({children}: {children: ReactNode}) => (
|
|
48
|
+
<InternationalizationProvider locale="en" dir="rtl">
|
|
49
|
+
{children}
|
|
50
|
+
</InternationalizationProvider>
|
|
51
|
+
),
|
|
52
|
+
});
|
|
53
|
+
expect(result.current).toBe('rtl');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('explicit dir="ltr" wins over an RTL locale', () => {
|
|
57
|
+
const {result} = renderHook(() => useDirection(), {
|
|
58
|
+
wrapper: ({children}: {children: ReactNode}) => (
|
|
59
|
+
<InternationalizationProvider locale="ar" dir="ltr">
|
|
60
|
+
{children}
|
|
61
|
+
</InternationalizationProvider>
|
|
62
|
+
),
|
|
63
|
+
});
|
|
64
|
+
expect(result.current).toBe('ltr');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file getLocaleDirection.ts
|
|
5
|
+
* @input BCP 47 locale tag
|
|
6
|
+
* @output 'ltr' | 'rtl'
|
|
7
|
+
* @position Server-safe helper for computing text direction from a locale.
|
|
8
|
+
* Callable in React Server Components / Next.js layouts to set <html dir>.
|
|
9
|
+
*
|
|
10
|
+
* Uses Intl.Locale.getTextInfo() (CLDR-backed) with a try/catch fallback to
|
|
11
|
+
* 'ltr'. React 19 baseline covers all target browsers + Node ≥20; the older
|
|
12
|
+
* accessor form (`.textInfo`) is handled as a fallback for defensive parity.
|
|
13
|
+
*
|
|
14
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
15
|
+
* - /packages/core/src/i18n/InternationalizationProvider.tsx (uses this to derive default)
|
|
16
|
+
* - /packages/core/src/i18n/useDirection.ts (client-side hook counterpart)
|
|
17
|
+
* - /packages/core/src/i18n/index.ts (public export)
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export function getLocaleDirection(locale: string): 'ltr' | 'rtl' {
|
|
21
|
+
try {
|
|
22
|
+
const loc = new Intl.Locale(locale);
|
|
23
|
+
// @ts-expect-error — older engines expose accessor form `.textInfo`
|
|
24
|
+
const info = typeof loc.getTextInfo === 'function' ? loc.getTextInfo() : loc.textInfo;
|
|
25
|
+
return info?.direction === 'rtl' ? 'rtl' : 'ltr';
|
|
26
|
+
} catch {
|
|
27
|
+
return 'ltr';
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/i18n/index.ts
CHANGED
|
@@ -10,10 +10,14 @@
|
|
|
10
10
|
* The public API is deliberately small:
|
|
11
11
|
* - InternationalizationProvider — provider component
|
|
12
12
|
* - useTranslator — hook returning a translator function
|
|
13
|
+
* - useDirection — hook returning the ambient text direction
|
|
14
|
+
* - getLocaleDirection — server-safe locale → direction helper
|
|
13
15
|
* - Translator — interface for consumer-injected runtimes
|
|
14
16
|
*
|
|
15
17
|
* SYNC: When modified, update these files to stay in sync:
|
|
16
18
|
* - /packages/core/src/index.ts
|
|
19
|
+
* - /packages/core/src/i18n/useDirection.ts
|
|
20
|
+
* - /packages/core/src/i18n/getLocaleDirection.ts
|
|
17
21
|
*/
|
|
18
22
|
|
|
19
23
|
export {InternationalizationProvider} from './InternationalizationProvider';
|
|
@@ -22,6 +26,8 @@ export {InternationalizationContext} from './InternationalizationContext';
|
|
|
22
26
|
export type {InternationalizationContextValue} from './InternationalizationContext';
|
|
23
27
|
export {useTranslator} from './useTranslator';
|
|
24
28
|
export type {TranslatorFn} from './useTranslator';
|
|
29
|
+
export {useDirection} from './useDirection';
|
|
30
|
+
export {getLocaleDirection} from './getLocaleDirection';
|
|
25
31
|
export type {Translator} from './translator';
|
|
26
32
|
export type {
|
|
27
33
|
Locale,
|
package/src/i18n/resolve.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import IntlMessageFormat from 'intl-messageformat';
|
|
23
23
|
import type {Catalog, Locale, MessagesByLocale, Overrides} from './types';
|
|
24
24
|
import enSource from '../../locales/en.json' with {type: 'json'};
|
|
25
|
+
import {warnOnce, __resetDevWarnings} from '../utils/devWarning';
|
|
25
26
|
|
|
26
27
|
const EN_CATALOG = enSource as Catalog;
|
|
27
28
|
|
|
@@ -72,23 +73,6 @@ export function resolveLocaleChain(locale: Locale): Locale[] {
|
|
|
72
73
|
return chain;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
/**
|
|
76
|
-
* Missing-key warn-once tracking. Fires ONLY when a key is missing from
|
|
77
|
-
* every source including the shipped `en` catalog — that's a real bug
|
|
78
|
-
* (typo, stale catalog, deleted key). Fallback to `en` from a non-en
|
|
79
|
-
* locale is expected and silent, matching the FormatJS / i18next default
|
|
80
|
-
* of not spamming the console when a translation simply hasn't been
|
|
81
|
-
* written yet.
|
|
82
|
-
*/
|
|
83
|
-
const warnedMissing = new Set<string>();
|
|
84
|
-
|
|
85
|
-
function warnOnce(bucket: Set<string>, key: string, message: string): void {
|
|
86
|
-
if (!bucket.has(key)) {
|
|
87
|
-
bucket.add(key);
|
|
88
|
-
console.warn(message);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
76
|
function lookup(
|
|
93
77
|
key: string,
|
|
94
78
|
locale: Locale,
|
|
@@ -135,10 +119,14 @@ export function resolve(
|
|
|
135
119
|
const result = lookup(key, locale, messages, overrides);
|
|
136
120
|
|
|
137
121
|
if (result === null) {
|
|
122
|
+
// Fires ONLY when a key is missing from every source including the
|
|
123
|
+
// shipped `en` catalog — a real bug (typo, stale catalog, deleted key).
|
|
124
|
+
// Fallback to `en` from a non-en locale is expected and stays silent,
|
|
125
|
+
// matching the FormatJS / i18next default.
|
|
138
126
|
warnOnce(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
`
|
|
127
|
+
`astryx-i18n:${locale}::${key}`,
|
|
128
|
+
'astryx-i18n',
|
|
129
|
+
`missing key: ${key} (locale: ${locale})`,
|
|
142
130
|
);
|
|
143
131
|
return key;
|
|
144
132
|
}
|
|
@@ -161,5 +149,5 @@ export function resolve(
|
|
|
161
149
|
*/
|
|
162
150
|
export function __resetForTests(): void {
|
|
163
151
|
formatterCache.clear();
|
|
164
|
-
|
|
152
|
+
__resetDevWarnings();
|
|
165
153
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useDirection.ts
|
|
7
|
+
* @input InternationalizationContext (via use())
|
|
8
|
+
* @output 'ltr' | 'rtl'
|
|
9
|
+
* @position Client hook for reading the ambient text direction. Returns 'ltr'
|
|
10
|
+
* when called outside a provider (matches the silent-en-fallback pattern of
|
|
11
|
+
* useTranslator).
|
|
12
|
+
*
|
|
13
|
+
* Use this in components that need to swap directional icons, mirror
|
|
14
|
+
* behavioral logic (slider math, keyboard nav), or apply direction-specific
|
|
15
|
+
* styling that CSS logical properties can't express.
|
|
16
|
+
*
|
|
17
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
18
|
+
* - /packages/core/src/i18n/InternationalizationContext.ts
|
|
19
|
+
* - /packages/core/src/i18n/getLocaleDirection.ts (server-safe counterpart)
|
|
20
|
+
* - /packages/core/src/i18n/index.ts
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import {use} from 'react';
|
|
24
|
+
import {InternationalizationContext} from './InternationalizationContext';
|
|
25
|
+
|
|
26
|
+
export function useDirection(): 'ltr' | 'rtl' {
|
|
27
|
+
const ctx = use(InternationalizationContext);
|
|
28
|
+
return ctx.direction;
|
|
29
|
+
}
|
package/src/reset.css
CHANGED
|
@@ -360,32 +360,6 @@
|
|
|
360
360
|
-webkit-tap-highlight-color: transparent;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
-
/* ===========================================================================
|
|
364
|
-
Touch Devices
|
|
365
|
-
=========================================================================== */
|
|
366
|
-
|
|
367
|
-
/*
|
|
368
|
-
* Suppress focus-visible outlines on touch-only devices.
|
|
369
|
-
*
|
|
370
|
-
* Focus rings exist to show keyboard users where focus is. On devices
|
|
371
|
-
* with no hover capability and a coarse pointer (phones, tablets),
|
|
372
|
-
* there's no keyboard navigation — focus rings are visual noise that
|
|
373
|
-
* can flash on tap, on dialog open (showModal auto-focus), or on
|
|
374
|
-
* programmatic focus.
|
|
375
|
-
*
|
|
376
|
-
* This targets touch-only devices specifically:
|
|
377
|
-
* - (hover: none) — no hover capability (not a mouse)
|
|
378
|
-
* - (pointer: coarse) — imprecise pointer (finger, not stylus)
|
|
379
|
-
*
|
|
380
|
-
* Hybrid devices (laptop with touchscreen) are NOT affected because
|
|
381
|
-
* their primary pointer is fine (trackpad/mouse) and hover is available.
|
|
382
|
-
*/
|
|
383
|
-
@media (hover: none) and (pointer: coarse) {
|
|
384
|
-
:where(:focus-visible) {
|
|
385
|
-
outline: none;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
363
|
/* ===========================================================================
|
|
390
364
|
Color Scheme
|
|
391
365
|
=========================================================================== */
|