@astryxdesign/core 0.5.0 → 0.5.1-canary.f64186a
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 +222 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +45 -20
- package/dist/AspectRatio/AspectRatio.d.ts +6 -6
- package/dist/Avatar/Avatar.d.ts +25 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +43 -9
- package/dist/Avatar/index.d.ts +2 -2
- package/dist/Avatar/index.d.ts.map +1 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +5 -2
- package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
- package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +11 -7
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +26 -2
- package/dist/Banner/Banner.d.ts +10 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +11 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +8 -7
- package/dist/Calendar/Calendar.d.ts +4 -2
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +15 -21
- package/dist/Calendar/hooks/useCalendarDays.js +4 -6
- package/dist/Calendar/hooks/useCalendarNavigation.js +4 -6
- package/dist/Calendar/styles.d.ts +5 -20
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +15 -17
- package/dist/Card/Card.d.ts +12 -12
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +17 -9
- package/dist/Card/index.d.ts +35 -1
- package/dist/Card/index.d.ts.map +1 -1
- package/dist/Card/index.js +21 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +108 -7
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +7 -1
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +15 -4
- package/dist/CodeBlock/highlightRanges.js +1 -1
- package/dist/CodeBlock/highlightStyles.js +13 -13
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +2 -7
- package/dist/ComplexSelector/ComplexSelector.d.ts +10 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +14 -7
- package/dist/DateInput/DateInput.d.ts +43 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +22 -5
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +5 -3
- package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
- package/dist/DateInput/MonthYearWheels.js +6 -4
- package/dist/DateInput/NativeDateField.d.ts +10 -0
- package/dist/DateInput/NativeDateField.d.ts.map +1 -0
- package/dist/DateInput/NativeDateField.js +494 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +52 -25
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +1 -0
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateInput/nativeDateSegments.d.ts +22 -0
- package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
- package/dist/DateInput/nativeDateSegments.js +111 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +3 -5
- package/dist/DateTimeInput/DateTimeInput.d.ts +23 -24
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +35 -10
- package/dist/DateTimeInput/TouchDateTimeField.d.ts +6 -0
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -0
- package/dist/DateTimeInput/TouchDateTimeField.js +1021 -0
- package/dist/Dialog/Dialog.d.ts +16 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +28 -7
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -13
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -1
- package/dist/Field/InputClearButton.d.ts +9 -3
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +14 -3
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +0 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +104 -3
- package/dist/HoverCard/useHoverCard.d.ts +14 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -1
- package/dist/Icon/Icon.d.ts +4 -2
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/defaultIcons.d.ts +3 -2
- package/dist/Icon/defaultIcons.d.ts.map +1 -1
- package/dist/Icon/defaultIcons.js +7 -0
- package/dist/Icon/globalIconRegistry.d.ts +13 -0
- package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
- package/dist/Icon/globalIconRegistry.js +34 -6
- package/dist/Icon/index.d.ts +1 -1
- package/dist/Icon/index.d.ts.map +1 -1
- package/dist/Icon/useIcon.d.ts +5 -2
- package/dist/Icon/useIcon.d.ts.map +1 -1
- package/dist/Icon/useIcon.js +3 -0
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +6 -2
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +2 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +2 -26
- package/dist/Layer/gestureCounter.d.ts +8 -0
- package/dist/Layer/gestureCounter.d.ts.map +1 -0
- package/dist/Layer/gestureCounter.js +53 -0
- package/dist/Layer/useLayer.d.ts +23 -13
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +146 -24
- package/dist/List/List.d.ts +1 -1
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +15 -4
- package/dist/Markdown/Markdown.d.ts +1 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +20 -7
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +5 -3
- package/dist/MetadataList/MetadataListItem.d.ts +1 -1
- package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
- package/dist/MetadataList/MetadataListItem.js +4 -1
- package/dist/MultiSelector/MultiSelector.d.ts +18 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +58 -11
- package/dist/MultiSelector/hooks.d.ts +7 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +3 -2
- package/dist/NavIcon/NavIcon.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.js +5 -1
- package/dist/NavItem/navItemStyles.stylex.d.ts +0 -8
- package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
- package/dist/NavItem/navItemStyles.stylex.js +0 -2
- package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +7 -4
- package/dist/NumberInput/NumberInput.d.ts +6 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +95 -126
- package/dist/NumberInput/numberInputCommit.d.ts +34 -0
- package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
- package/dist/NumberInput/numberInputCommit.js +71 -0
- package/dist/NumberInput/numberParser.d.ts +64 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -0
- package/dist/NumberInput/numberParser.js +350 -0
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +2 -3
- package/dist/OverflowList/OverflowList.d.ts +41 -1
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +43 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +8 -14
- package/dist/Popover/usePopover.d.ts +15 -41
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +26 -7
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +91 -18
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +4 -2
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +18 -5
- package/dist/Resizable/useResizable.d.ts +19 -1
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +104 -38
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +9 -0
- package/dist/Selector/Selector.d.ts +18 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +92 -21
- package/dist/Selector/hooks.d.ts +7 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +3 -2
- package/dist/SideNav/SideNav.d.ts +6 -1
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +57 -27
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +5 -4
- package/dist/SideNav/SideNavItem.d.ts +29 -4
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +75 -20
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +34 -2
- package/dist/Spinner/Spinner.d.ts +3 -1
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +199 -20
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +6 -1
- package/dist/Stepper/Step.d.ts.map +1 -1
- package/dist/Stepper/Step.js +7 -6
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +5 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +6 -1
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +3 -6
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +34 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +25 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +0 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +13 -8
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +10 -18
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +10 -5
- package/dist/Toast/Toast.d.ts +17 -2
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +77 -11
- package/dist/Toast/ToastViewport.d.ts +1 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +76 -21
- package/dist/Toast/index.d.ts +1 -1
- package/dist/Toast/index.d.ts.map +1 -1
- package/dist/Toast/types.d.ts +38 -0
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Toast/useToastGesture.d.ts +26 -0
- package/dist/Toast/useToastGesture.d.ts.map +1 -0
- package/dist/Toast/useToastGesture.js +223 -0
- package/dist/Token/Token.d.ts +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +23 -12
- package/dist/Token/TokenLink.d.ts +1 -1
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +5 -2
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +31 -21
- package/dist/TopNav/TopNavHeading.js +2 -2
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +3 -3
- package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +30 -9
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +3 -3
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +21 -6
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +7 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +2 -2
- package/dist/Typeahead/BaseTypeahead.d.ts +33 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +51 -8
- package/dist/Typeahead/Typeahead.d.ts +8 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +2 -0
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +7 -2
- package/dist/astryx.css +87 -22
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +3 -25
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +14 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +46 -10
- package/dist/theme/defineTheme.d.ts +9 -3
- 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 +24 -4
- package/dist/theme/generateThemeRules.d.ts +21 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +26 -0
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.js +5 -2
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +6 -7
- package/dist/utils/dateParser.d.ts +5 -8
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +10 -11
- package/dist/utils/focusOutline.stylex.d.ts +25 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
- package/dist/utils/focusOutline.stylex.js +15 -0
- package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
- package/dist/utils/interactionOverlay.stylex.js +42 -0
- package/dist/utils/isApplePlatform.d.ts +18 -0
- package/dist/utils/isApplePlatform.d.ts.map +1 -0
- package/dist/utils/isApplePlatform.js +37 -0
- package/dist/utils/plainDate.d.ts +11 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +20 -4
- package/locales/af-ZA.json +7 -7
- package/locales/ar-SA.json +7 -7
- package/locales/ca-ES.json +6 -6
- package/locales/cs-CZ.json +7 -7
- package/locales/da-DK.json +7 -7
- package/locales/de-DE.json +7 -7
- package/locales/el-GR.json +7 -7
- package/locales/en.json +178 -6
- package/locales/es-ES.json +6 -6
- package/locales/fi-FI.json +7 -7
- package/locales/fr-FR.json +7 -7
- package/locales/he-IL.json +7 -7
- package/locales/hu-HU.json +7 -7
- package/locales/it-IT.json +7 -7
- package/locales/ja-JP.json +7 -7
- package/locales/ko-KR.json +7 -7
- package/locales/nl-NL.json +7 -7
- package/locales/no-NO.json +7 -7
- package/locales/pl-PL.json +7 -7
- package/locales/pseudo.json +130 -1
- package/locales/pt-BR.json +7 -7
- package/locales/pt-PT.json +7 -7
- package/locales/ro-RO.json +7 -7
- package/locales/ru-RU.json +7 -7
- package/locales/sr-SP.json +7 -7
- package/locales/sv-SE.json +7 -7
- package/locales/tr-TR.json +7 -7
- package/locales/uk-UA.json +7 -7
- package/locales/vi-VN.json +7 -7
- package/locales/zh-CN.json +7 -7
- package/locales/zh-TW.json +7 -7
- package/package.json +4 -5
- package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
- package/src/AlertDialog/AlertDialog.test.tsx +211 -2
- package/src/AlertDialog/AlertDialog.tsx +62 -20
- package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
- package/src/AspectRatio/AspectRatio.tsx +6 -6
- package/src/Avatar/Avatar.doc.mjs +12 -2
- package/src/Avatar/Avatar.test.tsx +80 -0
- package/src/Avatar/Avatar.tsx +64 -14
- package/src/Avatar/index.ts +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
- package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
- package/src/AvatarGroup/AvatarGroup.tsx +12 -4
- package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
- package/src/Badge/Badge.doc.mjs +3 -2
- package/src/Badge/Badge.test.tsx +32 -3
- package/src/Badge/Badge.tsx +42 -1
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +76 -11
- package/src/Banner/Banner.tsx +21 -2
- package/src/Button/Button.doc.mjs +2 -1
- package/src/Button/Button.test.tsx +19 -4
- package/src/Button/Button.tsx +9 -29
- package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
- package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
- package/src/Calendar/Calendar.doc.mjs +3 -3
- package/src/Calendar/Calendar.test.tsx +112 -0
- package/src/Calendar/Calendar.tsx +18 -16
- package/src/Calendar/hooks/useCalendarDays.ts +4 -4
- package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
- package/src/Calendar/styles.ts +48 -42
- package/src/Card/Card.doc.mjs +10 -7
- package/src/Card/Card.test.tsx +113 -19
- package/src/Card/Card.tsx +67 -89
- package/src/Card/index.ts +36 -1
- package/src/Carousel/Carousel.doc.mjs +3 -0
- package/src/Carousel/Carousel.test.tsx +360 -0
- package/src/Carousel/Carousel.tsx +116 -15
- package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
- package/src/CheckboxInput/CheckboxInput.tsx +5 -0
- package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
- package/src/CodeBlock/CodeBlock.test.tsx +37 -0
- package/src/CodeBlock/CodeBlock.tsx +20 -4
- package/src/CodeBlock/highlightRanges.ts +1 -1
- package/src/CodeBlock/highlightStyles.ts +13 -13
- package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
- package/src/ComplexSelector/ComplexSelector.doc.mjs +7 -0
- package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
- package/src/ComplexSelector/ComplexSelector.tsx +22 -12
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.test.tsx +9 -4
- package/src/DateInput/DateInput.tsx +54 -3
- package/src/DateInput/DateInputTouch.test.tsx +146 -32
- package/src/DateInput/MonthScroller.tsx +5 -1
- package/src/DateInput/MonthYearWheels.tsx +7 -4
- package/src/DateInput/NativeDateField.test.tsx +635 -0
- package/src/DateInput/NativeDateField.tsx +641 -0
- package/src/DateInput/TouchDateField.tsx +83 -33
- package/src/DateInput/Wheel.tsx +1 -0
- package/src/DateInput/index.ts +1 -0
- package/src/DateInput/nativeDateSegments.ts +127 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +2 -2
- package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
- package/src/DateRangeInput/DateRangeInput.tsx +8 -13
- package/src/DateTimeInput/DateTimeInput.doc.mjs +38 -21
- package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
- package/src/DateTimeInput/DateTimeInput.tsx +54 -20
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
- package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
- package/src/Dialog/Dialog.test.tsx +185 -18
- package/src/Dialog/Dialog.tsx +35 -11
- package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
- package/src/DropdownMenu/DropdownMenu.tsx +4 -13
- package/src/Field/FieldLabel.test.tsx +29 -0
- package/src/Field/FieldLabel.tsx +7 -0
- package/src/Field/InputClearButton.test.tsx +15 -1
- package/src/Field/InputClearButton.tsx +28 -4
- package/src/Heading/Heading.tsx +0 -1
- package/src/HoverCard/HoverCard.doc.mjs +8 -2
- package/src/HoverCard/HoverCard.test.tsx +154 -4
- package/src/HoverCard/HoverCard.tsx +137 -3
- package/src/HoverCard/useHoverCard.tsx +23 -3
- package/src/Icon/Icon.test.tsx +55 -1
- package/src/Icon/Icon.tsx +5 -3
- package/src/Icon/defaultIcons.tsx +11 -2
- package/src/Icon/globalIconRegistry.test.tsx +16 -3
- package/src/Icon/globalIconRegistry.tsx +37 -6
- package/src/Icon/index.ts +1 -0
- package/src/Icon/useIcon.ts +9 -2
- package/src/Indicator/CheckboxIndicator.tsx +14 -8
- package/src/Indicator/Indicator.doc.mjs +2 -0
- package/src/Item/Item.tsx +2 -7
- package/src/Kbd/Kbd.test.tsx +0 -17
- package/src/Kbd/Kbd.tsx +2 -26
- package/src/Layer/gestureCounter.ts +57 -0
- package/src/Layer/useLayer.test.tsx +368 -16
- package/src/Layer/useLayer.tsx +208 -35
- package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
- package/src/List/List.test.tsx +38 -0
- package/src/List/List.tsx +8 -1
- package/src/Markdown/Markdown.test.tsx +37 -0
- package/src/Markdown/Markdown.tsx +16 -5
- package/src/Markdown/parser.test.ts +33 -0
- package/src/Markdown/parser.ts +9 -3
- package/src/MetadataList/MetadataList.test.tsx +75 -2
- package/src/MetadataList/MetadataListItem.tsx +5 -2
- package/src/MultiSelector/MultiSelector.doc.mjs +22 -1
- package/src/MultiSelector/MultiSelector.test.tsx +205 -0
- package/src/MultiSelector/MultiSelector.tsx +103 -16
- package/src/MultiSelector/hooks.ts +9 -2
- package/src/NavIcon/NavIcon.doc.mjs +8 -2
- package/src/NavIcon/NavIcon.test.tsx +9 -0
- package/src/NavIcon/NavIcon.tsx +5 -1
- package/src/NavItem/navItemStyles.stylex.ts +0 -8
- package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
- package/src/NavMenu/NavHeadingMenu.tsx +7 -4
- package/src/NumberInput/NumberInput.doc.mjs +26 -7
- package/src/NumberInput/NumberInput.test.tsx +563 -8
- package/src/NumberInput/NumberInput.tsx +77 -131
- package/src/NumberInput/numberInputCommit.test.ts +72 -0
- package/src/NumberInput/numberInputCommit.ts +103 -0
- package/src/NumberInput/numberParser.docblock.test.ts +234 -0
- package/src/NumberInput/numberParser.test.ts +222 -0
- package/src/NumberInput/numberParser.ts +403 -0
- package/src/Outline/Outline.tsx +2 -4
- package/src/OverflowList/OverflowList.doc.mjs +102 -21
- package/src/OverflowList/OverflowList.test.tsx +550 -4
- package/src/OverflowList/OverflowList.tsx +100 -2
- package/src/Pagination/Pagination.test.tsx +3 -2
- package/src/Popover/Popover.doc.mjs +2 -2
- package/src/Popover/Popover.test.tsx +38 -0
- package/src/Popover/Popover.tsx +28 -66
- package/src/Popover/usePopover.tsx +44 -5
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
- package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
- package/src/PowerSearch/formatFilterValue.test.ts +16 -1
- package/src/PowerSearch/formatFilterValue.ts +2 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
- package/src/ProgressBar/ProgressBar.test.tsx +24 -0
- package/src/ProgressBar/ProgressBar.tsx +28 -8
- package/src/Resizable/Resizable.doc.mjs +2 -2
- package/src/Resizable/useResizable.doc.mjs +21 -2
- package/src/Resizable/useResizable.test.ts +421 -0
- package/src/Resizable/useResizable.ts +133 -48
- package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
- package/src/SelectableCard/SelectableCard.tsx +16 -0
- package/src/Selector/Selector.doc.mjs +14 -0
- package/src/Selector/Selector.source-build.test.mjs +65 -0
- package/src/Selector/Selector.test.tsx +301 -0
- package/src/Selector/Selector.tsx +145 -32
- package/src/Selector/hooks.ts +17 -2
- package/src/SideNav/SideNav.doc.mjs +2 -2
- package/src/SideNav/SideNav.test.tsx +1069 -6
- package/src/SideNav/SideNav.tsx +109 -38
- package/src/SideNav/SideNavHeading.tsx +5 -2
- package/src/SideNav/SideNavItem.doc.mjs +24 -3
- package/src/SideNav/SideNavItem.tsx +134 -44
- package/src/Slider/Slider.test.tsx +106 -1
- package/src/Slider/Slider.tsx +52 -1
- package/src/Spinner/Spinner.doc.mjs +17 -5
- package/src/Spinner/Spinner.test.tsx +164 -0
- package/src/Spinner/Spinner.tsx +252 -22
- package/src/StatusDot/StatusDot.doc.mjs +8 -2
- package/src/StatusDot/StatusDot.test.tsx +9 -0
- package/src/StatusDot/StatusDot.tsx +7 -1
- package/src/Stepper/Step.doc.mjs +1 -1
- package/src/Stepper/Step.tsx +7 -14
- package/src/Switch/Switch.doc.mjs +2 -0
- package/src/Switch/Switch.test.tsx +10 -0
- package/src/Switch/Switch.tsx +3 -0
- package/src/Table/BaseTable.tsx +6 -1
- package/src/Table/Table.doc.mjs +5 -3
- package/src/Table/Table.tsx +3 -8
- package/src/Table/TableBody.doc.mjs +2 -2
- package/src/Table/TableFooter.doc.mjs +1 -1
- package/src/Table/TableHeader.doc.mjs +1 -1
- package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
- package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
- package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
- package/src/Table/useTableGroupedRows.doc.mjs +3 -3
- package/src/Table/useTablePagination.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +1 -1
- package/src/Text/Text.test.tsx +44 -0
- package/src/Text/Text.tsx +0 -1
- package/src/TextArea/TextArea.doc.mjs +12 -2
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +34 -22
- package/src/Timestamp/Timestamp.test.tsx +89 -0
- package/src/Timestamp/Timestamp.tsx +8 -8
- package/src/Timestamp/formatInstant.ts +5 -0
- package/src/Toast/Toast.doc.mjs +213 -44
- package/src/Toast/Toast.tsx +118 -23
- package/src/Toast/ToastViewport.test.tsx +1434 -8
- package/src/Toast/ToastViewport.tsx +85 -14
- package/src/Toast/index.ts +2 -0
- package/src/Toast/types.ts +43 -5
- package/src/Toast/useToastGesture.ts +361 -0
- package/src/Token/Token.test.tsx +95 -0
- package/src/Token/Token.tsx +19 -17
- package/src/Token/TokenLink.tsx +12 -3
- package/src/Tokenizer/Tokenizer.doc.mjs +16 -3
- package/src/Tokenizer/Tokenizer.test.tsx +161 -0
- package/src/Tokenizer/Tokenizer.tsx +49 -24
- package/src/TopNav/TopNavHeading.tsx +2 -2
- package/src/TopNav/TopNavItem.tsx +3 -7
- package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
- package/src/TopNav/TopNavMegaMenu.tsx +47 -4
- package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
- package/src/TopNav/TopNavMenu.test.tsx +133 -1
- package/src/TopNav/TopNavMenu.tsx +38 -5
- package/src/TreeList/TreeList.test.tsx +49 -0
- package/src/TreeList/TreeList.tsx +7 -2
- package/src/TreeList/TreeListItem.tsx +2 -7
- package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
- package/src/Typeahead/BaseTypeahead.tsx +96 -6
- package/src/Typeahead/Typeahead.doc.mjs +6 -0
- package/src/Typeahead/Typeahead.test.tsx +154 -0
- package/src/Typeahead/Typeahead.tsx +9 -0
- package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
- package/src/Typeahead/TypeaheadItem.tsx +8 -1
- package/src/hooks/useAnnounce.doc.mjs +96 -0
- package/src/hooks/useDevWarning.doc.mjs +96 -0
- package/src/hooks/useHotkeys.test.ts +0 -18
- package/src/hooks/useHotkeys.ts +3 -25
- package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
- package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
- package/src/hooks/useInteractiveRole.doc.mjs +119 -0
- package/src/hooks/useLongPress.doc.mjs +123 -0
- package/src/hooks/useOverflow.doc.mjs +58 -17
- package/src/hooks/useOverflow.ts +16 -4
- package/src/hooks/useTypeahead.doc.mjs +153 -0
- package/src/index.ts +2 -0
- package/src/raw-import.d.ts +14 -0
- package/src/theme/Theme.test.tsx +104 -2
- package/src/theme/Theme.tsx +49 -14
- package/src/theme/defineTheme.test.ts +23 -0
- package/src/theme/defineTheme.ts +12 -3
- package/src/theme/derivedVarRegistry.test.ts +87 -3
- package/src/theme/derivedVarRegistry.ts +23 -4
- package/src/theme/generateThemeRules.test.ts +99 -1
- package/src/theme/generateThemeRules.ts +28 -0
- package/src/theme/syntax/tokens.ts +5 -2
- package/src/theme/useTheme.test.tsx +10 -0
- package/src/theme/useTheme.ts +16 -10
- package/src/utils/dateParser.test.ts +34 -2
- package/src/utils/dateParser.ts +11 -14
- package/src/utils/focusOutline.stylex.ts +50 -0
- package/src/utils/interactionOverlay.stylex.ts +74 -0
- package/src/utils/isApplePlatform.test.ts +61 -0
- package/src/utils/isApplePlatform.ts +37 -0
- package/src/utils/plainDate.test.ts +46 -0
- package/src/utils/plainDate.ts +18 -3
|
@@ -43,6 +43,7 @@ export interface DerivedVarEntry {
|
|
|
43
43
|
* entries share the same property.
|
|
44
44
|
*/
|
|
45
45
|
export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
|
|
46
|
+
avatar: [{property: 'borderRadius', vars: ['--_avatar-radius']}],
|
|
46
47
|
banner: [{property: 'borderRadius', vars: ['--_banner-radius']}],
|
|
47
48
|
button: [{property: 'borderRadius', vars: ['--_button-radius']}],
|
|
48
49
|
card: [
|
|
@@ -66,13 +67,13 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
|
|
|
66
67
|
{property: 'padding', vars: ['--_dropdown-menu-padding']},
|
|
67
68
|
],
|
|
68
69
|
field: [{property: 'borderRadius', vars: ['--_field-radius']}],
|
|
69
|
-
|
|
70
|
+
'hover-card': [{property: 'borderRadius', vars: ['--_hovercard-radius']}],
|
|
70
71
|
'number-input': [
|
|
71
72
|
{property: 'padding', expand: 'container'},
|
|
72
73
|
{property: 'borderRadius', vars: ['--_field-radius']},
|
|
73
74
|
],
|
|
74
75
|
popover: [{property: 'borderRadius', vars: ['--_popover-radius']}],
|
|
75
|
-
'
|
|
76
|
+
'progress-bar-mark': [
|
|
76
77
|
{property: 'width', vars: ['--_progressbar-mark-width'], replaces: true},
|
|
77
78
|
{property: 'height', vars: ['--_progressbar-mark-height'], replaces: true},
|
|
78
79
|
],
|
|
@@ -81,7 +82,7 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
|
|
|
81
82
|
{property: 'borderRadius', vars: ['--_segmented-control-radius']},
|
|
82
83
|
{property: 'padding', vars: ['--_segmented-control-padding']},
|
|
83
84
|
],
|
|
84
|
-
|
|
85
|
+
'text-area': [
|
|
85
86
|
{
|
|
86
87
|
property: 'paddingInline',
|
|
87
88
|
vars: ['--_textarea-inline-padding'],
|
|
@@ -90,6 +91,21 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
|
|
|
90
91
|
],
|
|
91
92
|
};
|
|
92
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Deprecated component keys → the key that superseded them.
|
|
96
|
+
*
|
|
97
|
+
* A renamed target keeps emitting its old class, so a theme written against
|
|
98
|
+
* the old key still selects the element. Without this the rule would land but
|
|
99
|
+
* its derived vars would not expand, and the half that travels through a var
|
|
100
|
+
* (a hover card's radius, a text area's inline padding) would silently do
|
|
101
|
+
* nothing. Drop these with the classes, in the next major.
|
|
102
|
+
*/
|
|
103
|
+
const DEPRECATED_REGISTRY_KEYS: Record<string, string> = {
|
|
104
|
+
hovercard: 'hover-card',
|
|
105
|
+
'progressbar-mark': 'progress-bar-mark',
|
|
106
|
+
textarea: 'text-area',
|
|
107
|
+
};
|
|
108
|
+
|
|
93
109
|
/**
|
|
94
110
|
* Look up derived var entries for a component + CSS property.
|
|
95
111
|
* Returns matching entries in priority order, or empty array if none.
|
|
@@ -98,7 +114,10 @@ export function getDerivedVars(
|
|
|
98
114
|
component: string,
|
|
99
115
|
property: string,
|
|
100
116
|
): DerivedVarEntry[] {
|
|
101
|
-
const
|
|
117
|
+
const renamedTo = DEPRECATED_REGISTRY_KEYS[component];
|
|
118
|
+
const entries =
|
|
119
|
+
derivedVarRegistry[component] ??
|
|
120
|
+
(renamedTo ? derivedVarRegistry[renamedTo] : undefined);
|
|
102
121
|
if (!entries) {
|
|
103
122
|
return [];
|
|
104
123
|
}
|
|
@@ -7,7 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import {describe, it, expect} from 'vitest';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
dataTokenDefaults,
|
|
12
|
+
defineTheme,
|
|
13
|
+
generateThemeCSS,
|
|
14
|
+
generateThemeRules,
|
|
15
|
+
} from './index';
|
|
16
|
+
import {generateDataTokenDefaultsCSS} from './generateThemeRules';
|
|
11
17
|
|
|
12
18
|
const defaultInput = {
|
|
13
19
|
name: 'default',
|
|
@@ -702,3 +708,95 @@ describe('physical padding longhands', () => {
|
|
|
702
708
|
expect(rule).not.toContain('--_dropdown-menu-padding');
|
|
703
709
|
});
|
|
704
710
|
});
|
|
711
|
+
|
|
712
|
+
describe('renamed theme targets', () => {
|
|
713
|
+
// The renamed targets emit both classes, so a rule written against either
|
|
714
|
+
// key selects the element. What is easy to miss is the derived-var half: a
|
|
715
|
+
// key the registry does not know still emits a rule, minus every var the
|
|
716
|
+
// component actually reads — the same silent nothing a misspelled key gives.
|
|
717
|
+
it('expands derived vars for a renamed key and its deprecated spelling', () => {
|
|
718
|
+
const rules = (component: string, styles: Record<string, string>) =>
|
|
719
|
+
generateThemeRules(
|
|
720
|
+
defineTheme({
|
|
721
|
+
name: `test-renamed-${component}`,
|
|
722
|
+
components: {[component]: {base: styles}},
|
|
723
|
+
}),
|
|
724
|
+
).join('\n');
|
|
725
|
+
|
|
726
|
+
const hoverCard = rules('hover-card', {borderRadius: '9px'});
|
|
727
|
+
expect(hoverCard).toContain('.astryx-hover-card');
|
|
728
|
+
expect(hoverCard).toContain('--_hovercard-radius: 9px');
|
|
729
|
+
expect(rules('hovercard', {borderRadius: '9px'})).toContain(
|
|
730
|
+
'--_hovercard-radius: 9px',
|
|
731
|
+
);
|
|
732
|
+
|
|
733
|
+
const textArea = rules('text-area', {paddingInline: '11px'});
|
|
734
|
+
expect(textArea).toContain('.astryx-text-area');
|
|
735
|
+
expect(textArea).toContain('--_textarea-inline-padding: 11px');
|
|
736
|
+
expect(rules('textarea', {paddingInline: '11px'})).toContain(
|
|
737
|
+
'--_textarea-inline-padding: 11px',
|
|
738
|
+
);
|
|
739
|
+
|
|
740
|
+
const mark = rules('progress-bar-mark', {width: '3px'});
|
|
741
|
+
expect(mark).toContain('.astryx-progress-bar-mark');
|
|
742
|
+
expect(mark).toContain('--_progressbar-mark-width: 3px');
|
|
743
|
+
expect(rules('progressbar-mark', {width: '3px'})).toContain(
|
|
744
|
+
'--_progressbar-mark-width: 3px',
|
|
745
|
+
);
|
|
746
|
+
});
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
describe('data visualization tokens', () => {
|
|
750
|
+
const scopeBlock = (theme: Parameters<typeof generateThemeRules>[0]) =>
|
|
751
|
+
generateThemeRules(theme).find(r => r.includes(':scope'));
|
|
752
|
+
|
|
753
|
+
it('seeds the whole palette once, at :root', () => {
|
|
754
|
+
const css = generateDataTokenDefaultsCSS();
|
|
755
|
+
|
|
756
|
+
expect(css.startsWith(':root {')).toBe(true);
|
|
757
|
+
for (const [name, value] of Object.entries(dataTokenDefaults)) {
|
|
758
|
+
expect(css).toContain(`${name}: ${value};`);
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
it('leaves the defaults out of a theme scope block', () => {
|
|
763
|
+
// A scope block that re-declared them would shadow a parent theme's
|
|
764
|
+
// override in every nested <Theme>, which no other token family does.
|
|
765
|
+
expect(scopeBlock(defineTheme({name: 'data-bare'}))).toBeUndefined();
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
it("puts only the theme's own data token in its scope block", () => {
|
|
769
|
+
const block = scopeBlock(
|
|
770
|
+
defineTheme({
|
|
771
|
+
name: 'data-override',
|
|
772
|
+
tokens: {'--color-data-categorical-blue': ['#123456', '#654321']},
|
|
773
|
+
}),
|
|
774
|
+
)!;
|
|
775
|
+
|
|
776
|
+
expect(block).toContain(
|
|
777
|
+
'--color-data-categorical-blue: light-dark(#123456, #654321);',
|
|
778
|
+
);
|
|
779
|
+
expect(block.match(/--color-data-/g)).toHaveLength(1);
|
|
780
|
+
expect(block).not.toContain('--color-data-categorical-orange');
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
it('keeps the palette out of the scoped stylesheet', () => {
|
|
784
|
+
// The palette's own contents are asserted once, against
|
|
785
|
+
// `dataTokenDefaults`, in `seeds the whole palette once, at :root` above.
|
|
786
|
+
const {component, prose} = generateThemeCSS(
|
|
787
|
+
defineTheme({name: 'data-css'}),
|
|
788
|
+
);
|
|
789
|
+
|
|
790
|
+
expect(component).not.toContain('--color-data-');
|
|
791
|
+
expect(prose).not.toContain('--color-data-');
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
it('keeps generateThemeCSS to its two scoped blocks', () => {
|
|
795
|
+
// The defaults are theme-independent, so they are not part of the theme
|
|
796
|
+
// CSS contract: `astryx theme build` formats them from the public
|
|
797
|
+
// `dataTokenDefaults` export instead.
|
|
798
|
+
expect(
|
|
799
|
+
Object.keys(generateThemeCSS(defineTheme({name: 'data-shape'}))).sort(),
|
|
800
|
+
).toEqual(['component', 'prose']);
|
|
801
|
+
});
|
|
802
|
+
});
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type {DefinedTheme} from './defineTheme';
|
|
19
19
|
import {parseStyleKey} from '../utils/parseStyleKey';
|
|
20
20
|
import {getDerivedVars} from './derivedVarRegistry';
|
|
21
|
+
import {dataTokenDefaults} from './domainTokens/dataTokens';
|
|
21
22
|
import {cssVar, classPrefix, dataAttrNamespace} from '../naming';
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -758,6 +759,30 @@ export function generateOnMediaCSS(theme: DefinedTheme): string {
|
|
|
758
759
|
return `@scope (${scopeSelector}) to (${THEME_SCOPE_TO}) {\n${inner}\n}`;
|
|
759
760
|
}
|
|
760
761
|
|
|
762
|
+
/**
|
|
763
|
+
* The `--color-data-*` defaults as one unscoped `:root` block.
|
|
764
|
+
*
|
|
765
|
+
* Core tokens reach CSS once, at `:root`, from StyleX's `defineVars` output in
|
|
766
|
+
* `@layer astryx-base`; a theme's own scope block then carries only the tokens
|
|
767
|
+
* that theme overrides, which is why a nested theme inherits its parent's
|
|
768
|
+
* override instead of shadowing it. Data tokens are not StyleX vars, so nothing
|
|
769
|
+
* declares them — this is their equivalent, and callers put it in
|
|
770
|
+
* `@layer astryx-base` so a theme's override wins by layer rather than by
|
|
771
|
+
* specificity. Seeding it per theme scope instead re-declares the default
|
|
772
|
+
* inside every nested theme, which is the shadowing this shape avoids.
|
|
773
|
+
*
|
|
774
|
+
* @internal Not exported from `@astryxdesign/core/theme`: the `<Theme>`
|
|
775
|
+
* runtime is the only caller. `astryx theme build` formats the same block from
|
|
776
|
+
* the public `dataTokenDefaults` export, and a CLI test asserts the two are
|
|
777
|
+
* byte-identical.
|
|
778
|
+
*/
|
|
779
|
+
export function generateDataTokenDefaultsCSS(): string {
|
|
780
|
+
const declarations = Object.entries(dataTokenDefaults)
|
|
781
|
+
.map(([prop, value]) => ` ${prop}: ${value};`)
|
|
782
|
+
.join('\n');
|
|
783
|
+
return `:root {\n${declarations}\n}`;
|
|
784
|
+
}
|
|
785
|
+
|
|
761
786
|
/**
|
|
762
787
|
* Generate layered CSS for a theme — runtime path.
|
|
763
788
|
*
|
|
@@ -768,6 +793,9 @@ export function generateOnMediaCSS(theme: DefinedTheme): string {
|
|
|
768
793
|
* This separation ensures prose defaults (what bare HTML looks like in a theme)
|
|
769
794
|
* sit at reset-layer priority where any class-based style wins, while component
|
|
770
795
|
* overrides sit above StyleX so themes can restyle components intentionally.
|
|
796
|
+
*
|
|
797
|
+
* The theme-independent `--color-data-*` defaults are not part of this output:
|
|
798
|
+
* see `generateDataTokenDefaultsCSS`.
|
|
771
799
|
*/
|
|
772
800
|
export function generateThemeCSS(theme: DefinedTheme): ThemeCSSOutput {
|
|
773
801
|
const {component, prose} = generateThemeRulesSplit(theme);
|
|
@@ -44,8 +44,11 @@ export const syntaxTokenDefaults = {
|
|
|
44
44
|
'--color-syntax-attribute': 'var(--color-text-teal)',
|
|
45
45
|
// property -> cyan text (object properties)
|
|
46
46
|
'--color-syntax-property': 'var(--color-text-cyan)',
|
|
47
|
-
// punctuation ->
|
|
48
|
-
|
|
47
|
+
// punctuation -> secondary text (brackets, semicolons). Not disabled text:
|
|
48
|
+
// disabled grey is calibrated to fail AA on purpose (WCAG exempts inactive
|
|
49
|
+
// controls), and punctuation in a code sample is normal, always-active
|
|
50
|
+
// text — see #5386.
|
|
51
|
+
'--color-syntax-punctuation': 'var(--color-text-secondary)',
|
|
49
52
|
// background -> muted surface
|
|
50
53
|
'--color-syntax-background': 'var(--color-background-muted)',
|
|
51
54
|
} as const;
|
|
@@ -108,6 +108,16 @@ describe('useTheme', () => {
|
|
|
108
108
|
expect(result.current.token('--color-text-primary')).toBe('#DFE2E5');
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
+
it('keeps the token resolver and return object stable across rerenders', () => {
|
|
112
|
+
const {result, rerender} = renderHook(() => useTheme());
|
|
113
|
+
const first = result.current;
|
|
114
|
+
|
|
115
|
+
rerender();
|
|
116
|
+
|
|
117
|
+
expect(result.current.token).toBe(first.token);
|
|
118
|
+
expect(result.current).toBe(first);
|
|
119
|
+
});
|
|
120
|
+
|
|
111
121
|
it('returns empty string for unknown tokens', () => {
|
|
112
122
|
const {result} = renderHook(() => useTheme(), {
|
|
113
123
|
wrapper: ({children}) => wrapper({children, mode: 'light'}),
|
package/src/theme/useTheme.ts
CHANGED
|
@@ -21,7 +21,13 @@
|
|
|
21
21
|
* - /packages/core/src/theme/index.ts
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
createContext,
|
|
26
|
+
use,
|
|
27
|
+
useCallback,
|
|
28
|
+
useMemo,
|
|
29
|
+
useSyncExternalStore,
|
|
30
|
+
} from 'react';
|
|
25
31
|
import type {ThemeMode} from './types';
|
|
26
32
|
import type {DefinedTheme} from './defineTheme';
|
|
27
33
|
import {resolveThemeTokens} from './tokens';
|
|
@@ -281,14 +287,14 @@ export function useTheme(): UseThemeReturn {
|
|
|
281
287
|
[theme, effectiveMode],
|
|
282
288
|
);
|
|
283
289
|
|
|
284
|
-
const token = (
|
|
285
|
-
|
|
286
|
-
|
|
290
|
+
const token = useCallback(
|
|
291
|
+
(name: string): string => tokens[name] ?? '',
|
|
292
|
+
[tokens],
|
|
293
|
+
);
|
|
294
|
+
const name = theme?.name ?? 'default';
|
|
287
295
|
|
|
288
|
-
return
|
|
289
|
-
name:
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
tokens,
|
|
293
|
-
};
|
|
296
|
+
return useMemo(
|
|
297
|
+
() => ({name, mode: effectiveMode, token, tokens}),
|
|
298
|
+
[name, effectiveMode, token, tokens],
|
|
299
|
+
);
|
|
294
300
|
}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* SYNC: When dateParser.ts changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect} from 'vitest';
|
|
13
|
-
import {parseDateInput} from './dateParser';
|
|
12
|
+
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
+
import {isLocaleDayFirst, parseDateInput} from './dateParser';
|
|
14
14
|
|
|
15
15
|
describe('parseDateInput', () => {
|
|
16
16
|
describe('ISO format (YYYY-MM-DD)', () => {
|
|
@@ -280,6 +280,14 @@ describe('parseDateInput', () => {
|
|
|
280
280
|
describe('ambiguous numeric formats follow the passed locale (#5074)', () => {
|
|
281
281
|
// Both numbers are <= 12, so the day/month order is genuinely ambiguous
|
|
282
282
|
// and resolved by isLocaleDayFirst(locale) rather than the host locale.
|
|
283
|
+
it('defaults ambiguous input to English month-first order', () => {
|
|
284
|
+
expect(parseDateInput('3/4/2026')).toEqual({
|
|
285
|
+
year: 2026,
|
|
286
|
+
month: 3,
|
|
287
|
+
day: 4,
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
|
|
283
291
|
it('reads month-first for en-US', () => {
|
|
284
292
|
expect(parseDateInput('3/4/2026', 'en-US')).toEqual({
|
|
285
293
|
year: 2026,
|
|
@@ -297,6 +305,30 @@ describe('parseDateInput', () => {
|
|
|
297
305
|
});
|
|
298
306
|
});
|
|
299
307
|
|
|
308
|
+
describe('isLocaleDayFirst', () => {
|
|
309
|
+
it('defaults to English month-first order', () => {
|
|
310
|
+
expect(isLocaleDayFirst()).toBe(false);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('requests Gregorian calendar data for locale ordering', () => {
|
|
314
|
+
const OriginalDateTimeFormat = globalThis.Intl.DateTimeFormat;
|
|
315
|
+
const dateTimeFormatSpy = vi
|
|
316
|
+
.spyOn(globalThis.Intl, 'DateTimeFormat')
|
|
317
|
+
.mockImplementation(function DateTimeFormat(locale, options) {
|
|
318
|
+
return new OriginalDateTimeFormat(locale, options);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
isLocaleDayFirst('en-US-u-ca-buddhist');
|
|
323
|
+
expect(dateTimeFormatSpy).toHaveBeenCalledWith('en-US-u-ca-buddhist', {
|
|
324
|
+
calendar: 'gregory',
|
|
325
|
+
});
|
|
326
|
+
} finally {
|
|
327
|
+
dateTimeFormatSpy.mockRestore();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
300
332
|
describe('edge cases', () => {
|
|
301
333
|
it('returns null for empty string', () => {
|
|
302
334
|
expect(parseDateInput('')).toBeNull();
|
package/src/utils/dateParser.ts
CHANGED
|
@@ -23,10 +23,10 @@ export {
|
|
|
23
23
|
* Detects if the locale uses day-first date format (DD/MM/YYYY).
|
|
24
24
|
* US and a few others use month-first (MM/DD/YYYY).
|
|
25
25
|
*/
|
|
26
|
-
export function isLocaleDayFirst(locale
|
|
27
|
-
const parts = new Intl.DateTimeFormat(locale
|
|
28
|
-
|
|
29
|
-
);
|
|
26
|
+
export function isLocaleDayFirst(locale: Locale = 'en'): boolean {
|
|
27
|
+
const parts = new Intl.DateTimeFormat(locale, {
|
|
28
|
+
calendar: 'gregory',
|
|
29
|
+
}).formatToParts(new Date(2000, 0, 15));
|
|
30
30
|
const dayIndex = parts.findIndex(p => p.type === 'day');
|
|
31
31
|
const monthIndex = parts.findIndex(p => p.type === 'month');
|
|
32
32
|
return dayIndex < monthIndex;
|
|
@@ -35,20 +35,17 @@ export function isLocaleDayFirst(locale?: Locale): boolean {
|
|
|
35
35
|
/**
|
|
36
36
|
* Parses user input into a PlainDate.
|
|
37
37
|
*
|
|
38
|
-
* Supports
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* - Numeric formats without year: "1/25", "25/1" (defaults to current year)
|
|
44
|
-
*
|
|
45
|
-
* For ambiguous numeric formats (both numbers ≤ 12), uses locale preference.
|
|
38
|
+
* Supports ISO dates, English month names, and ASCII numeric dates with or
|
|
39
|
+
* without a year. For ambiguous ASCII numeric input where both fields are at
|
|
40
|
+
* most 12, `locale` selects month-first versus day-first order. It does not
|
|
41
|
+
* localize month-name parsing, accept non-ASCII digits, or provide a general
|
|
42
|
+
* locale-aware parser.
|
|
46
43
|
*
|
|
47
44
|
* @returns PlainDate if valid, null if unparseable
|
|
48
45
|
*/
|
|
49
46
|
export function parseDateInput(
|
|
50
47
|
input: string,
|
|
51
|
-
locale
|
|
48
|
+
locale: Locale = 'en',
|
|
52
49
|
): PlainDate | null {
|
|
53
50
|
const trimmed = input.trim();
|
|
54
51
|
if (!trimmed) {
|
|
@@ -157,7 +154,7 @@ function parseNumericDate(
|
|
|
157
154
|
first: number,
|
|
158
155
|
second: number,
|
|
159
156
|
year: number,
|
|
160
|
-
locale
|
|
157
|
+
locale: Locale,
|
|
161
158
|
): PlainDate | null {
|
|
162
159
|
let day: number;
|
|
163
160
|
let month: number;
|
|
@@ -124,6 +124,52 @@ export const focusOutlineStyles = stylex.create({
|
|
|
124
124
|
},
|
|
125
125
|
outlineOffset: {default: '0', ':has(:focus-visible)': FOCUS_OUTLINE_OFFSET},
|
|
126
126
|
},
|
|
127
|
+
/**
|
|
128
|
+
* Like {@link focusOutlineStyles.focusWithin}, but only for the element's
|
|
129
|
+
* FIRST child — for a wrapper that paints the ring on behalf of one primary
|
|
130
|
+
* control while its siblings ring themselves.
|
|
131
|
+
*
|
|
132
|
+
* `focusWithin` matches any descendant, so a row holding more than one tab
|
|
133
|
+
* stop lights the whole row *on top of* the focused control's own ring: two
|
|
134
|
+
* outlines for one tab stop. Scoping to `> :first-child` keeps the ring the
|
|
135
|
+
* primary's, and leaves every sibling control ringing itself.
|
|
136
|
+
*
|
|
137
|
+
* The wrapper owns the coupling: the primary has to be its first child, and
|
|
138
|
+
* the wrapper must not be a tab stop (its own `:focus-visible` would never
|
|
139
|
+
* match). Pair it with {@link focusOutlineStyles.suppressed} on the primary.
|
|
140
|
+
*/
|
|
141
|
+
focusWithinFirstChild: {
|
|
142
|
+
outlineWidth: {
|
|
143
|
+
default: '0',
|
|
144
|
+
':has(> :first-child:focus-visible)': focusOutlineLonghands.outlineWidth,
|
|
145
|
+
},
|
|
146
|
+
outlineStyle: {
|
|
147
|
+
default: 'none',
|
|
148
|
+
':has(> :first-child:focus-visible)': focusOutlineLonghands.outlineStyle,
|
|
149
|
+
},
|
|
150
|
+
outlineColor: {
|
|
151
|
+
default: null,
|
|
152
|
+
':has(> :first-child:focus-visible)': focusOutlineLonghands.outlineColor,
|
|
153
|
+
},
|
|
154
|
+
outlineOffset: {
|
|
155
|
+
default: '0',
|
|
156
|
+
':has(> :first-child:focus-visible)': FOCUS_OUTLINE_OFFSET,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
/**
|
|
160
|
+
* Draws no ring, and keeps the UA's own off — for an element whose ring an
|
|
161
|
+
* ancestor paints.
|
|
162
|
+
*
|
|
163
|
+
* The reset is not optional. Every other style here suppresses the browser
|
|
164
|
+
* default through its `default` branch, so dropping the ring from a control
|
|
165
|
+
* drops that suppression with it, and a bare `<a>` or `<button>` goes back
|
|
166
|
+
* to the UA focus ring — painted *inside* the ancestor's.
|
|
167
|
+
*/
|
|
168
|
+
suppressed: {
|
|
169
|
+
outlineWidth: '0',
|
|
170
|
+
outlineStyle: 'none',
|
|
171
|
+
outlineOffset: '0',
|
|
172
|
+
},
|
|
127
173
|
publishFocusVisibleVars: {
|
|
128
174
|
'--_focus-outline': {
|
|
129
175
|
default: 'none',
|
|
@@ -168,6 +214,10 @@ function makeFocusOutlineProps(style: StyleXPropsArg) {
|
|
|
168
214
|
export const focusOutlineProps = {
|
|
169
215
|
focusVisible: makeFocusOutlineProps(focusOutlineStyles.focusVisible),
|
|
170
216
|
focusWithin: makeFocusOutlineProps(focusOutlineStyles.focusWithin),
|
|
217
|
+
focusWithinFirstChild: makeFocusOutlineProps(
|
|
218
|
+
focusOutlineStyles.focusWithinFirstChild,
|
|
219
|
+
),
|
|
220
|
+
suppressed: makeFocusOutlineProps(focusOutlineStyles.suppressed),
|
|
171
221
|
publishFocusVisibleVars: makeFocusOutlineProps(
|
|
172
222
|
focusOutlineStyles.publishFocusVisibleVars,
|
|
173
223
|
),
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @astryx/no-hover-on-disabled -- Every hover branch is
|
|
4
|
+
* nested beneath ENABLED below. Keeping that shared guard outside the media
|
|
5
|
+
* branch is what gives hover and active matching generated specificity. */
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @file Shared hover and pressed overlay states
|
|
9
|
+
* @input Uses StyleX and the semantic interaction-overlay color tokens
|
|
10
|
+
* @output Exports reusable background-color and background-image state styles
|
|
11
|
+
* @position Internal styling utility for interactive core surfaces
|
|
12
|
+
*
|
|
13
|
+
* Keep the enabled guard outside the individual states. StyleX assigns an
|
|
14
|
+
* extra priority bucket (and generated selector specificity) to media-nested
|
|
15
|
+
* rules. Repeating `:active` inside the hover-capable branch gives hover and
|
|
16
|
+
* press the same generated specificity; StyleX's native pseudo-state ordering
|
|
17
|
+
* then emits `:active` last. The bare `:active` branch remains the touch
|
|
18
|
+
* fallback, where `(hover: hover)` does not match.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import * as stylex from '@stylexjs/stylex';
|
|
22
|
+
import {colorVars} from '../theme/tokens.stylex';
|
|
23
|
+
|
|
24
|
+
const ENABLED = ':where(:not(:disabled,[aria-disabled="true"]))';
|
|
25
|
+
const HOVER_HOVER = '@media (hover: hover)';
|
|
26
|
+
|
|
27
|
+
const hoverImage = `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`;
|
|
28
|
+
const pressedImage = `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`;
|
|
29
|
+
const neutralImage = `linear-gradient(${colorVars['--color-neutral']}, ${colorVars['--color-neutral']})`;
|
|
30
|
+
|
|
31
|
+
export const interactionOverlayStyles = stylex.create({
|
|
32
|
+
backgroundColor: {
|
|
33
|
+
backgroundColor: {
|
|
34
|
+
default: 'transparent',
|
|
35
|
+
[ENABLED]: {
|
|
36
|
+
default: null,
|
|
37
|
+
':active': colorVars['--color-overlay-pressed'],
|
|
38
|
+
[HOVER_HOVER]: {
|
|
39
|
+
default: null,
|
|
40
|
+
':hover': colorVars['--color-overlay-hover'],
|
|
41
|
+
':active': colorVars['--color-overlay-pressed'],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
backgroundImage: {
|
|
47
|
+
backgroundImage: {
|
|
48
|
+
default: null,
|
|
49
|
+
[ENABLED]: {
|
|
50
|
+
default: null,
|
|
51
|
+
':active': pressedImage,
|
|
52
|
+
[HOVER_HOVER]: {
|
|
53
|
+
default: null,
|
|
54
|
+
':hover': hoverImage,
|
|
55
|
+
':active': pressedImage,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
backgroundImageOnNeutral: {
|
|
61
|
+
backgroundImage: {
|
|
62
|
+
default: neutralImage,
|
|
63
|
+
[ENABLED]: {
|
|
64
|
+
default: null,
|
|
65
|
+
':active': `${pressedImage}, ${neutralImage}`,
|
|
66
|
+
[HOVER_HOVER]: {
|
|
67
|
+
default: null,
|
|
68
|
+
':hover': `${hoverImage}, ${neutralImage}`,
|
|
69
|
+
':active': `${pressedImage}, ${neutralImage}`,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file isApplePlatform.test.ts
|
|
5
|
+
* @input Uses vitest, isApplePlatform
|
|
6
|
+
* @output Unit tests for isApplePlatform
|
|
7
|
+
* @position Testing; validates isApplePlatform.ts implementation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
11
|
+
import {isApplePlatform} from './isApplePlatform';
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
vi.unstubAllGlobals();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('isApplePlatform', () => {
|
|
18
|
+
it('trusts a client-hints platform that names one', () => {
|
|
19
|
+
vi.stubGlobal('navigator', {
|
|
20
|
+
userAgentData: {platform: 'macOS'},
|
|
21
|
+
platform: 'Win32',
|
|
22
|
+
});
|
|
23
|
+
expect(isApplePlatform()).toBe(true);
|
|
24
|
+
|
|
25
|
+
vi.stubGlobal('navigator', {
|
|
26
|
+
userAgentData: {platform: 'Windows'},
|
|
27
|
+
platform: 'MacIntel',
|
|
28
|
+
});
|
|
29
|
+
expect(isApplePlatform()).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it.each([
|
|
33
|
+
['blank', ''],
|
|
34
|
+
['whitespace', ' '],
|
|
35
|
+
['the spec Unknown sentinel', 'Unknown'],
|
|
36
|
+
['unknown in any case', 'UNKNOWN'],
|
|
37
|
+
['a non-string', null],
|
|
38
|
+
])('falls through to navigator.platform on %s', (_label, platform) => {
|
|
39
|
+
vi.stubGlobal('navigator', {
|
|
40
|
+
userAgentData: {platform},
|
|
41
|
+
platform: 'MacIntel',
|
|
42
|
+
});
|
|
43
|
+
expect(isApplePlatform()).toBe(true);
|
|
44
|
+
|
|
45
|
+
vi.stubGlobal('navigator', {userAgentData: {platform}, platform: 'Win32'});
|
|
46
|
+
expect(isApplePlatform()).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('falls back to navigator.platform when client hints are absent', () => {
|
|
50
|
+
vi.stubGlobal('navigator', {platform: 'iPhone'});
|
|
51
|
+
expect(isApplePlatform()).toBe(true);
|
|
52
|
+
|
|
53
|
+
vi.stubGlobal('navigator', {platform: 'Linux x86_64'});
|
|
54
|
+
expect(isApplePlatform()).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('answers false when there is no navigator at all', () => {
|
|
58
|
+
vi.stubGlobal('navigator', undefined);
|
|
59
|
+
expect(isApplePlatform()).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file isApplePlatform.ts
|
|
5
|
+
* @input Reads navigator.userAgentData.platform and navigator.platform
|
|
6
|
+
* @output Exports isApplePlatform
|
|
7
|
+
* @position Internal util; the single platform detection behind useHotkeys and Kbd
|
|
8
|
+
*
|
|
9
|
+
* Deliberately absent from utils/index.ts: packages/core/src/index.ts does
|
|
10
|
+
* `export * from './utils'`, so naming it there would publish it as API.
|
|
11
|
+
* Import it by path, as interactionModality is imported.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Detects whether the current platform is macOS/iOS.
|
|
16
|
+
* Prefers the User-Agent Client Hints API when it names a platform (modern
|
|
17
|
+
* Chrome/Edge), falls back to navigator.platform (deprecated but universally
|
|
18
|
+
* supported) when it names none.
|
|
19
|
+
*/
|
|
20
|
+
export function isApplePlatform(): boolean {
|
|
21
|
+
if (typeof navigator === 'undefined') {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const uaData = 'userAgentData' in navigator ? navigator.userAgentData : null;
|
|
25
|
+
if (uaData && typeof uaData === 'object' && 'platform' in uaData) {
|
|
26
|
+
const uaPlatform = (uaData as {platform?: unknown}).platform;
|
|
27
|
+
const named = typeof uaPlatform === 'string' ? uaPlatform.trim() : '';
|
|
28
|
+
// A value that names nothing is no answer, not a negative one: builds that
|
|
29
|
+
// rewrite their client-hints identity ship '', and 'Unknown' is the spec's
|
|
30
|
+
// own sentinel for "cannot say". Both fall through rather than reading as
|
|
31
|
+
// "not Apple".
|
|
32
|
+
if (named !== '' && named.toLowerCase() !== 'unknown') {
|
|
33
|
+
return /mac/i.test(named);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return /Mac|iPhone|iPad|iPod/.test(navigator.platform ?? '');
|
|
37
|
+
}
|