@astryxdesign/core 0.5.0 → 0.5.1-canary.046f6ea
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/i18n/InternationalizationContext.d.ts +2 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +3 -1
- package/dist/i18n/resolve.d.ts +1 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +37 -38
- package/dist/i18n/useTranslator.d.ts.map +1 -1
- package/dist/i18n/useTranslator.js +2 -3
- 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 +4 -4
- 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 +3 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
- package/src/CheckboxInput/CheckboxInput.tsx +5 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
- 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 +9 -2
- package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
- package/src/ComplexSelector/ComplexSelector.tsx +22 -12
- package/src/DateInput/DateInput.doc.mjs +17 -1
- 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 +3 -3
- package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
- package/src/DateRangeInput/DateRangeInput.tsx +8 -13
- package/src/DateTimeInput/DateTimeInput.doc.mjs +39 -22
- 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/Field.doc.mjs +1 -1
- 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/FieldStatus/FieldStatus.doc.mjs +1 -1
- package/src/FileInput/FileInput.doc.mjs +1 -1
- 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 +3 -1
- package/src/InputGroup/InputGroup.doc.mjs +1 -1
- 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 +23 -2
- 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 +27 -8
- 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/PowerSearch.doc.mjs +1 -1
- 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/RadioList/RadioList.doc.mjs +1 -1
- 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 +15 -1
- 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.doc.mjs +2 -2
- 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 +3 -1
- 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 +13 -3
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +34 -22
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.doc.mjs +1 -1
- 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 +17 -4
- 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 +7 -1
- 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/i18n/InternationalizationContext.ts +3 -0
- package/src/i18n/InternationalizationProvider.tsx +8 -1
- package/src/i18n/__tests__/resolve.test.ts +23 -1
- package/src/i18n/resolve.ts +46 -49
- package/src/i18n/useTranslator.ts +2 -7
- 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
|
@@ -13,7 +13,10 @@ import {useState} from 'react';
|
|
|
13
13
|
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
14
14
|
import {render, screen, act, fireEvent, waitFor} from '@testing-library/react';
|
|
15
15
|
import userEvent from '@testing-library/user-event';
|
|
16
|
+
import * as stylex from '@stylexjs/stylex';
|
|
16
17
|
import {Slider} from './Slider';
|
|
18
|
+
import {focusOutlineStyles} from '../utils/focusOutline.stylex';
|
|
19
|
+
import {__resetInteractionModalityForTest} from '../utils/interactionModality';
|
|
17
20
|
|
|
18
21
|
// Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
|
|
19
22
|
// reflects its open state via a `popover-open` attribute the tests can assert.
|
|
@@ -854,7 +857,7 @@ describe('Slider', () => {
|
|
|
854
857
|
/>,
|
|
855
858
|
);
|
|
856
859
|
const thumb = screen.getByRole('slider');
|
|
857
|
-
thumb.focus();
|
|
860
|
+
act(() => thumb.focus());
|
|
858
861
|
await user.keyboard('{ArrowRight}');
|
|
859
862
|
expect(onChange).not.toHaveBeenCalled();
|
|
860
863
|
});
|
|
@@ -902,4 +905,106 @@ describe('Slider', () => {
|
|
|
902
905
|
]).toEqual([]);
|
|
903
906
|
});
|
|
904
907
|
});
|
|
908
|
+
|
|
909
|
+
describe('focus ring modality', () => {
|
|
910
|
+
beforeEach(() => {
|
|
911
|
+
__resetInteractionModalityForTest();
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
// The ring is a stylex class, so derive it from the same source the
|
|
915
|
+
// component applies rather than hardcoding a hash.
|
|
916
|
+
const RING = stylex
|
|
917
|
+
.props(focusOutlineStyles.focusVisible)
|
|
918
|
+
.className!.split(' ');
|
|
919
|
+
const isRinged = (el: HTMLElement) =>
|
|
920
|
+
RING.every(c => el.classList.contains(c));
|
|
921
|
+
|
|
922
|
+
// The track has no layout in jsdom; pointer maths needs a real rect.
|
|
923
|
+
const grabTrack = (thumb: HTMLElement) => {
|
|
924
|
+
const track = thumb.parentElement!;
|
|
925
|
+
track.getBoundingClientRect = () => ({
|
|
926
|
+
left: 0,
|
|
927
|
+
top: 0,
|
|
928
|
+
right: 200,
|
|
929
|
+
bottom: 20,
|
|
930
|
+
width: 200,
|
|
931
|
+
height: 20,
|
|
932
|
+
x: 0,
|
|
933
|
+
y: 0,
|
|
934
|
+
toJSON: () => {},
|
|
935
|
+
});
|
|
936
|
+
fireEvent.pointerDown(track, {clientX: 100, clientY: 10, pointerId: 1});
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
it('rings when the thumb is reached with the keyboard', async () => {
|
|
940
|
+
const user = userEvent.setup();
|
|
941
|
+
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
942
|
+
await user.tab();
|
|
943
|
+
expect(isRinged(screen.getByRole('slider'))).toBe(true);
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
it('does not ring when the thumb is grabbed with the mouse', () => {
|
|
947
|
+
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
948
|
+
const thumb = screen.getByRole('slider');
|
|
949
|
+
grabTrack(thumb);
|
|
950
|
+
expect(thumb).toHaveFocus();
|
|
951
|
+
expect(isRinged(thumb)).toBe(false);
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
it('drops the ring when the mouse grabs a thumb that already had it', async () => {
|
|
955
|
+
const user = userEvent.setup();
|
|
956
|
+
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
957
|
+
await user.tab();
|
|
958
|
+
const thumb = screen.getByRole('slider');
|
|
959
|
+
expect(isRinged(thumb)).toBe(true);
|
|
960
|
+
// Already focused, so focus() fires no focus event.
|
|
961
|
+
grabTrack(thumb);
|
|
962
|
+
expect(isRinged(thumb)).toBe(false);
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
it('brings the ring back when an arrow key follows a mouse drag', () => {
|
|
966
|
+
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
967
|
+
const thumb = screen.getByRole('slider');
|
|
968
|
+
grabTrack(thumb);
|
|
969
|
+
expect(isRinged(thumb)).toBe(false);
|
|
970
|
+
fireEvent.keyDown(thumb, {key: 'ArrowRight'});
|
|
971
|
+
expect(isRinged(thumb)).toBe(true);
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
it('leaves the ring off for a modifier chord after a mouse drag', () => {
|
|
975
|
+
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
976
|
+
const thumb = screen.getByRole('slider');
|
|
977
|
+
grabTrack(thumb);
|
|
978
|
+
// Copying or reloading is not navigation, and the mouse is still on it.
|
|
979
|
+
fireEvent.keyDown(thumb, {key: 'c', metaKey: true});
|
|
980
|
+
expect(isRinged(thumb)).toBe(false);
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
it('drops the ring on blur', async () => {
|
|
984
|
+
const user = userEvent.setup();
|
|
985
|
+
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
986
|
+
await user.tab();
|
|
987
|
+
const thumb = screen.getByRole('slider');
|
|
988
|
+
expect(isRinged(thumb)).toBe(true);
|
|
989
|
+
act(() => thumb.blur());
|
|
990
|
+
expect(isRinged(thumb)).toBe(false);
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
it('rings the range thumb the keyboard reached, not its sibling', async () => {
|
|
994
|
+
const user = userEvent.setup();
|
|
995
|
+
render(
|
|
996
|
+
<Slider
|
|
997
|
+
label="Price"
|
|
998
|
+
value={[20, 80] as [number, number]}
|
|
999
|
+
onChange={vi.fn()}
|
|
1000
|
+
/>,
|
|
1001
|
+
);
|
|
1002
|
+
await user.tab();
|
|
1003
|
+
await user.tab();
|
|
1004
|
+
const thumbs = screen.getAllByRole('slider');
|
|
1005
|
+
expect(thumbs[1]).toHaveFocus();
|
|
1006
|
+
expect(isRinged(thumbs[1])).toBe(true);
|
|
1007
|
+
expect(isRinged(thumbs[0])).toBe(false);
|
|
1008
|
+
});
|
|
1009
|
+
});
|
|
905
1010
|
});
|
package/src/Slider/Slider.tsx
CHANGED
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import {
|
|
20
|
+
useEffect,
|
|
20
21
|
useId,
|
|
21
22
|
useMemo,
|
|
22
23
|
useRef,
|
|
23
24
|
useState,
|
|
24
25
|
useCallback,
|
|
26
|
+
type FocusEvent,
|
|
25
27
|
type KeyboardEvent,
|
|
26
28
|
type PointerEvent,
|
|
27
29
|
} from 'react';
|
|
@@ -42,6 +44,10 @@ import {VisuallyHidden} from '../VisuallyHidden';
|
|
|
42
44
|
import type {InputStatus} from '../Field/types';
|
|
43
45
|
import {mergeProps, rtlStyles} from '../utils';
|
|
44
46
|
import {focusOutlineStyles} from '../utils/focusOutline.stylex';
|
|
47
|
+
import {
|
|
48
|
+
getInteractionModality,
|
|
49
|
+
trackInteractionModality,
|
|
50
|
+
} from '../utils/interactionModality';
|
|
45
51
|
import {isRtlElement} from '../hooks/isRtlElement';
|
|
46
52
|
import type {BaseProps} from '../BaseProps';
|
|
47
53
|
import type {SizeValue} from '../utils/types';
|
|
@@ -493,6 +499,36 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
493
499
|
const draggingThumbRef = useRef<number | null>(null);
|
|
494
500
|
const [draggingThumb, setDraggingThumb] = useState<number | null>(null);
|
|
495
501
|
|
|
502
|
+
// A thumb is a div[role="slider"], and `handlePointerDown` focuses it from
|
|
503
|
+
// script after preventDefault — which Chromium treats as focus-visible, so
|
|
504
|
+
// dragging with a mouse drew the keyboard ring (measured: `:focus-visible`
|
|
505
|
+
// true on pointerdown). Gate the ring on how the user last interacted; the
|
|
506
|
+
// CSS condition stays `:focus-visible`, this only narrows it.
|
|
507
|
+
const [keyboardFocusThumb, setKeyboardFocusThumb] = useState<number | null>(
|
|
508
|
+
null,
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
useEffect(() => {
|
|
512
|
+
trackInteractionModality();
|
|
513
|
+
}, []);
|
|
514
|
+
|
|
515
|
+
const handleThumbFocus = useCallback(
|
|
516
|
+
(thumbIndex: number, _e: FocusEvent<HTMLDivElement>) => {
|
|
517
|
+
// A disabled thumb draws no ring even when it stays focusable for its
|
|
518
|
+
// reason tooltip, so there is nothing to track for one.
|
|
519
|
+
setKeyboardFocusThumb(
|
|
520
|
+
!isDisabled && getInteractionModality() === 'keyboard'
|
|
521
|
+
? thumbIndex
|
|
522
|
+
: null,
|
|
523
|
+
);
|
|
524
|
+
},
|
|
525
|
+
[isDisabled],
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
const handleThumbBlur = useCallback((_e: FocusEvent<HTMLDivElement>) => {
|
|
529
|
+
setKeyboardFocusThumb(null);
|
|
530
|
+
}, []);
|
|
531
|
+
|
|
496
532
|
// Disabled-reason tooltip. This is a *separate* useTooltip instance from the
|
|
497
533
|
// per-thumb value bubble (the `<Tooltip>` component below): it anchors to the
|
|
498
534
|
// track container and fires on hover/focus of the whole control. Disabled
|
|
@@ -679,6 +715,10 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
679
715
|
const thumbs = track.querySelectorAll<HTMLElement>('[role="slider"]');
|
|
680
716
|
thumbs[thumbIndex]?.focus();
|
|
681
717
|
}
|
|
718
|
+
// Also clear it explicitly: focusing an already-focused thumb fires no
|
|
719
|
+
// focus event, so a thumb the user had tabbed to would keep its ring
|
|
720
|
+
// through the drag.
|
|
721
|
+
setKeyboardFocusThumb(null);
|
|
682
722
|
|
|
683
723
|
if (
|
|
684
724
|
typeof (e.currentTarget as HTMLElement).setPointerCapture === 'function'
|
|
@@ -717,6 +757,13 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
717
757
|
if (isDisabled) {
|
|
718
758
|
return;
|
|
719
759
|
}
|
|
760
|
+
// Unlike a text field, a thumb has no caret to show where input is
|
|
761
|
+
// going, so a keypress after a mouse drag must bring the ring back.
|
|
762
|
+
// Ask the utility rather than assuming: a modifier chord (⌘R, ⌃C) is
|
|
763
|
+
// not navigation and must not re-ring a thumb the mouse is holding.
|
|
764
|
+
if (getInteractionModality() === 'keyboard') {
|
|
765
|
+
setKeyboardFocusThumb(thumbIndex);
|
|
766
|
+
}
|
|
720
767
|
const currentVal = values[thumbIndex];
|
|
721
768
|
let newVal: number;
|
|
722
769
|
|
|
@@ -843,6 +890,8 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
843
890
|
aria-labelledby={!isRange ? labelID : undefined}
|
|
844
891
|
aria-describedby={ariaDescribedBy}
|
|
845
892
|
onKeyDown={e => handleKeyDown(thumbIndex, e)}
|
|
893
|
+
onFocus={e => handleThumbFocus(thumbIndex, e)}
|
|
894
|
+
onBlur={handleThumbBlur}
|
|
846
895
|
{...mergeProps(
|
|
847
896
|
themeProps('slider-thumb', {
|
|
848
897
|
orientation,
|
|
@@ -854,7 +903,9 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
854
903
|
? styles.thumbHorizontal
|
|
855
904
|
: rtlStyles.centerInline('50%'),
|
|
856
905
|
!isDisabled && styles.thumbHover,
|
|
857
|
-
!isDisabled &&
|
|
906
|
+
!isDisabled &&
|
|
907
|
+
keyboardFocusThumb === thumbIndex &&
|
|
908
|
+
focusOutlineStyles.focusVisible,
|
|
858
909
|
isDisabled && styles.thumbDisabled,
|
|
859
910
|
),
|
|
860
911
|
undefined,
|
|
@@ -10,8 +10,8 @@ export const docs = {
|
|
|
10
10
|
props: [
|
|
11
11
|
{
|
|
12
12
|
name: 'size',
|
|
13
|
-
type: "'sm' | 'md' | 'lg'",
|
|
14
|
-
description: 'Spinner size (10px, 14px, 18px).',
|
|
13
|
+
type: "'sm' | 'md' | 'lg' | 'xl'",
|
|
14
|
+
description: 'Spinner size — ring diameter (10px, 14px, 18px, 28px).',
|
|
15
15
|
default: "'md'",
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -43,6 +43,12 @@ export const docs = {
|
|
|
43
43
|
targets: [
|
|
44
44
|
{className: 'astryx-spinner', visualProps: ['size', 'shade']},
|
|
45
45
|
],
|
|
46
|
+
vars: [
|
|
47
|
+
{name: '--spinner-diameter', description: "Diameter of the drawn ring. Set it on a size-variant target to retheme what each named size resolves to, e.g. spinner: { 'size:xl': { '--spinner-diameter': '2.5rem' } }. The rendered box is this plus the stroke width on each side, and follows automatically. Any length works — rem, em and calc() are resolved before the ring is drawn.", default: '10px (sm), 14px (md), 18px (lg), 28px (xl)'},
|
|
48
|
+
{name: '--spinner-stroke-width', description: 'Stroke width of both circles the ring is drawn from — the moving arc and the track behind it. Set it per size alongside the diameter. One stroke width drives both, so 0 is honoured as a zero-width stroke and paints nothing at all rather than falling back to the default — for an arc with no track behind it, set --spinner-track-color to transparent instead.', default: '2px (sm), 3px (md), 3px (lg), 4px (xl)'},
|
|
49
|
+
{name: '--spinner-color', description: "Color of the moving arc. Defaults to the shade's token, so set it on a shade-variant target to retheme one shade — spinner: { 'shade:subtle': { '--spinner-color': 'var(--color-text-tertiary)' } } — or on the base target to retheme all four. Accepts any color notation, including var(), color-mix() and currentColor.", default: 'var(--color-accent) (default), var(--color-text-secondary) (subtle), var(--color-on-dark) (onMedia), currentColor (inherit)'},
|
|
50
|
+
{name: '--spinner-track-color', description: 'Color of the track the arc travels on. Set it to `transparent` for an arc with no track. The onMedia and inherit shades draw the track at reduced alpha (30%) so it reads against an arbitrary backdrop; that fade applies to a themed color too.', default: 'var(--color-track) (default, subtle), var(--color-on-dark) (onMedia), currentColor (inherit)'},
|
|
51
|
+
],
|
|
46
52
|
},
|
|
47
53
|
usage: {
|
|
48
54
|
description:
|
|
@@ -63,8 +69,8 @@ export const docsZh = {
|
|
|
63
69
|
props: [
|
|
64
70
|
{
|
|
65
71
|
name: 'size',
|
|
66
|
-
type: "'sm' | 'md' | 'lg'",
|
|
67
|
-
description: '
|
|
72
|
+
type: "'sm' | 'md' | 'lg' | 'xl'",
|
|
73
|
+
description: '旋转器尺寸——环直径(10px、14px、18px、28px)。',
|
|
68
74
|
default: "'md'",
|
|
69
75
|
},
|
|
70
76
|
{
|
|
@@ -95,6 +101,12 @@ export const docsZh = {
|
|
|
95
101
|
targets: [
|
|
96
102
|
{className: 'astryx-spinner', visualProps: ['size', 'shade']},
|
|
97
103
|
],
|
|
104
|
+
vars: [
|
|
105
|
+
{name: '--spinner-diameter', description: "绘制环的直径。在尺寸变体目标上设置,以重新定义每个命名尺寸的解析值,例如 spinner: { 'size:xl': { '--spinner-diameter': '2.5rem' } }。渲染盒子的尺寸为该值加上两侧的描边宽度,并自动跟随。支持任意长度单位——rem、em 与 calc() 会在绘制前解析。", default: '10px (sm), 14px (md), 18px (lg), 28px (xl)'},
|
|
106
|
+
{name: '--spinner-stroke-width', description: '绘制环的两个圆——移动圆弧与其后的轨道——的描边宽度。与直径一起按尺寸设置。同一个描边宽度同时驱动两者,因此 0 会被采纳为零宽描边——什么都不绘制,而不会回退到默认值;若想要没有轨道的圆弧,请改将 --spinner-track-color 设为 transparent。', default: '2px (sm), 3px (md), 3px (lg), 4px (xl)'},
|
|
107
|
+
{name: '--spinner-color', description: "运动圆弧的颜色。默认取所在 shade 的令牌,因此可在 shade 变体目标上设置以重新定义单个 shade——spinner: { 'shade:subtle': { '--spinner-color': 'var(--color-text-tertiary)' } }——或在 base 目标上设置以覆盖全部四种。接受任意颜色写法,包括 var()、color-mix() 与 currentColor。", default: 'var(--color-accent)(default)、var(--color-text-secondary)(subtle)、var(--color-on-dark)(onMedia)、currentColor(inherit)'},
|
|
108
|
+
{name: '--spinner-track-color', description: '圆弧所在轨道的颜色。设为 `transparent` 可得到无轨道的圆弧。onMedia 与 inherit 两种 shade 会以降低的透明度(30%)绘制轨道,以便在任意背景上可辨;该淡化同样作用于主题化的颜色。', default: 'var(--color-track)(default、subtle)、var(--color-on-dark)(onMedia)、currentColor(inherit)'},
|
|
109
|
+
],
|
|
98
110
|
},
|
|
99
111
|
usage: {
|
|
100
112
|
description:
|
|
@@ -121,7 +133,7 @@ export const docsDense = {
|
|
|
121
133
|
],
|
|
122
134
|
},
|
|
123
135
|
propDescriptions: {
|
|
124
|
-
size: 'Spinner size (10px, 14px, 18px).',
|
|
136
|
+
size: 'Spinner size — ring diameter (10px, 14px, 18px, 28px).',
|
|
125
137
|
shade: 'Color shade for light or dark backgrounds.',
|
|
126
138
|
label: 'Visible content below spinner. String auto-sets aria-label.',
|
|
127
139
|
'aria-label': 'A11y name for screen readers. Defaults to label or "Loading".',
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
13
|
import {render, screen} from '@testing-library/react';
|
|
14
14
|
import {Spinner} from './Spinner';
|
|
15
|
+
import {defineTheme} from '../theme/defineTheme';
|
|
16
|
+
import {generateThemeCSS} from '../theme/generateThemeRules';
|
|
15
17
|
|
|
16
18
|
/** sm/md/lg/xl, as Spinner.tsx defines them. */
|
|
17
19
|
const SIZES = {
|
|
@@ -140,6 +142,85 @@ describe('Spinner', () => {
|
|
|
140
142
|
const spinner = screen.getByTestId('spinner');
|
|
141
143
|
expect(spinner.tagName.toLowerCase()).toBe('span');
|
|
142
144
|
});
|
|
145
|
+
|
|
146
|
+
// The box has always been sized by an inline width/height written after the
|
|
147
|
+
// caller's `style`, so the component's own size wins over a `style={{width}}`
|
|
148
|
+
// passed in. Making the geometry themeable changed what that value is made
|
|
149
|
+
// of — a composed var rather than a number — and deliberately not where it is
|
|
150
|
+
// written: moving the sizing into a rule would have handed a caller's inline
|
|
151
|
+
// width a precedence over the box it has never had. This pins the precedence
|
|
152
|
+
// itself, which is the part a consumer could be depending on.
|
|
153
|
+
describe('box sizing', () => {
|
|
154
|
+
it.each(Object.entries(SIZES))(
|
|
155
|
+
'falls back to the %s frame where no stylesheet has declared the var',
|
|
156
|
+
(size, {diameter, border}) => {
|
|
157
|
+
render(
|
|
158
|
+
<Spinner size={size as keyof typeof SIZES} data-testid="spinner" />,
|
|
159
|
+
);
|
|
160
|
+
const box = screen.getByTestId('spinner');
|
|
161
|
+
const expected = `var(--_spinner-box-size, ${diameter + border * 2}px)`;
|
|
162
|
+
expect(box.style.width).toBe(expected);
|
|
163
|
+
expect(box.style.height).toBe(expected);
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
it('keeps its own size over a width the caller passes in style', () => {
|
|
168
|
+
render(
|
|
169
|
+
<Spinner
|
|
170
|
+
size="xl"
|
|
171
|
+
style={{width: 999, height: 999, opacity: 0.5}}
|
|
172
|
+
data-testid="spinner"
|
|
173
|
+
/>,
|
|
174
|
+
);
|
|
175
|
+
const box = screen.getByTestId('spinner');
|
|
176
|
+
expect(box.style.width).toBe('var(--_spinner-box-size, 36px)');
|
|
177
|
+
expect(box.style.height).toBe('var(--_spinner-box-size, 36px)');
|
|
178
|
+
// Everything else the caller passed still applies — only the two
|
|
179
|
+
// properties the box owns are taken back.
|
|
180
|
+
expect(box.style.opacity).toBe('0.5');
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// The themed geometry resolves in the cascade — jsdom implements no layout
|
|
185
|
+
// and no custom-property registration, so no test here can reach what a
|
|
186
|
+
// theme actually draws; that is verified in a browser and the numbers are in
|
|
187
|
+
// the PR. What IS a contract a unit test can hold is the routing: a theme
|
|
188
|
+
// writes an override against the documented key, and it has to come out on
|
|
189
|
+
// the selector the component reads from.
|
|
190
|
+
describe('a theme reaches the spinner through its public vars', () => {
|
|
191
|
+
const cssFor = (
|
|
192
|
+
components: Parameters<typeof defineTheme>[0]['components'],
|
|
193
|
+
) =>
|
|
194
|
+
generateThemeCSS(defineTheme({name: 'spinner-theming', components}))
|
|
195
|
+
.component;
|
|
196
|
+
|
|
197
|
+
it('scopes a themed size to that size variant', () => {
|
|
198
|
+
// Asserting the whole rule, not just the declaration: the same var on
|
|
199
|
+
// the bare `.astryx-spinner` would resize every size at once, which is
|
|
200
|
+
// the bug a size-variant key exists to avoid.
|
|
201
|
+
expect(
|
|
202
|
+
cssFor({spinner: {'size:xl': {'--spinner-diameter': '2.5rem'}}}),
|
|
203
|
+
).toContain('.astryx-spinner.xl {\n --spinner-diameter: 2.5rem;');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('scopes a themed color to that shade variant', () => {
|
|
207
|
+
expect(
|
|
208
|
+
cssFor({
|
|
209
|
+
spinner: {'shade:subtle': {'--spinner-track-color': 'transparent'}},
|
|
210
|
+
}),
|
|
211
|
+
).toContain(
|
|
212
|
+
'.astryx-spinner.subtle {\n --spinner-track-color: transparent;',
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('lets the base target set a value for every size and shade', () => {
|
|
217
|
+
expect(
|
|
218
|
+
cssFor({spinner: {base: {'--spinner-color': 'var(--color-brand)'}}}),
|
|
219
|
+
).toContain(
|
|
220
|
+
'.astryx-spinner {\n --spinner-color: var(--color-brand);',
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
143
224
|
});
|
|
144
225
|
|
|
145
226
|
describe('Spinner ring', () => {
|
|
@@ -196,6 +277,28 @@ describe('Spinner ring', () => {
|
|
|
196
277
|
);
|
|
197
278
|
});
|
|
198
279
|
|
|
280
|
+
// The authored dash is the size's own absolute pattern, and stays that way:
|
|
281
|
+
// it is what a render with no stylesheet draws, and it is byte-for-byte the
|
|
282
|
+
// pattern this component drew before the geometry became themeable. Scaling
|
|
283
|
+
// with a themed diameter is the rule's job — it composes the same two
|
|
284
|
+
// lengths out of the resolved diameter — and deliberately not `pathLength`'s,
|
|
285
|
+
// which rescales against the path length the UA measures on its own
|
|
286
|
+
// approximation of the circle and shortens the default arc by 0.64%.
|
|
287
|
+
it.each(Object.entries(SIZES))(
|
|
288
|
+
'leaves the %s arc its own absolute dash, with no pathLength',
|
|
289
|
+
(size, {diameter}) => {
|
|
290
|
+
render(
|
|
291
|
+
<Spinner size={size as keyof typeof SIZES} data-testid="spinner" />,
|
|
292
|
+
);
|
|
293
|
+
const {track, arc} = circles();
|
|
294
|
+
const [on, off] = dashOf(arc);
|
|
295
|
+
expect(on + off).toBeCloseTo(Math.PI * diameter, 6);
|
|
296
|
+
expect(arc.getAttribute('pathLength')).toBeNull();
|
|
297
|
+
// The track is a full ring, so it needs neither.
|
|
298
|
+
expect(track.getAttribute('pathLength')).toBeNull();
|
|
299
|
+
},
|
|
300
|
+
);
|
|
301
|
+
|
|
199
302
|
// The whole point of the SVG ring: the colours come off the cascade, so
|
|
200
303
|
// nothing has to resolve them in JS. A read reaching the paint path again
|
|
201
304
|
// fails here.
|
|
@@ -268,3 +371,64 @@ describe('Spinner ring', () => {
|
|
|
268
371
|
}
|
|
269
372
|
});
|
|
270
373
|
});
|
|
374
|
+
|
|
375
|
+
describe('geometry var registration', () => {
|
|
376
|
+
/** The shape `registerSpinnerVars` passes; jsdom implements no real one. */
|
|
377
|
+
type Descriptor = {
|
|
378
|
+
name: string;
|
|
379
|
+
syntax: string;
|
|
380
|
+
inherits: boolean;
|
|
381
|
+
initialValue: string;
|
|
382
|
+
};
|
|
383
|
+
const stubRegisterProperty = (fn: (d: Descriptor) => void) => {
|
|
384
|
+
(
|
|
385
|
+
CSS as unknown as {registerProperty: (d: Descriptor) => void}
|
|
386
|
+
).registerProperty = fn;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
afterEach(() => {
|
|
390
|
+
delete (CSS as unknown as {registerProperty?: unknown}).registerProperty;
|
|
391
|
+
vi.resetModules();
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('registers when the module is imported, not when a spinner mounts', async () => {
|
|
395
|
+
// Registering an inherited property with an `initial-value` invalidates
|
|
396
|
+
// style for the whole document. A spinner mounts onto a page that has
|
|
397
|
+
// already rendered, so paying it there is paying it on the full tree —
|
|
398
|
+
// measured at 29ms against 12ms on an 11k-element page. At import the page
|
|
399
|
+
// is whatever has rendered so far, which for a bundle in the head is
|
|
400
|
+
// nothing. This pins the timing: it fails if the call moves back into a
|
|
401
|
+
// ref callback, an effect, or the component body.
|
|
402
|
+
const registerProperty = vi.fn<(d: Descriptor) => void>();
|
|
403
|
+
stubRegisterProperty(registerProperty);
|
|
404
|
+
|
|
405
|
+
vi.resetModules();
|
|
406
|
+
await import('./Spinner');
|
|
407
|
+
|
|
408
|
+
expect(registerProperty.mock.calls.map(([d]) => d.name)).toEqual([
|
|
409
|
+
'--_spinner-ring-diameter',
|
|
410
|
+
'--_spinner-ring-stroke',
|
|
411
|
+
]);
|
|
412
|
+
// Both are `<length>` with an initial value, which is what makes a themed
|
|
413
|
+
// `0` mean `0px` inside the `calc()` rather than poisoning it.
|
|
414
|
+
for (const [descriptor] of registerProperty.mock.calls) {
|
|
415
|
+
expect(descriptor.syntax).toBe('<length>');
|
|
416
|
+
expect(descriptor.inherits).toBe(true);
|
|
417
|
+
expect(descriptor.initialValue).toBe('0px');
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('survives a second evaluation, and does not need the DOM', async () => {
|
|
422
|
+
// Two copies of the package on one page, or a fast-refresh re-evaluation:
|
|
423
|
+
// registerProperty throws on a duplicate rather than replacing, and the
|
|
424
|
+
// existing registration is this same one.
|
|
425
|
+
const registerProperty = vi.fn<(d: Descriptor) => void>(() => {
|
|
426
|
+
throw new Error('InvalidModificationError');
|
|
427
|
+
});
|
|
428
|
+
stubRegisterProperty(registerProperty);
|
|
429
|
+
|
|
430
|
+
vi.resetModules();
|
|
431
|
+
await expect(import('./Spinner')).resolves.toBeDefined();
|
|
432
|
+
expect(registerProperty).toHaveBeenCalledTimes(2);
|
|
433
|
+
});
|
|
434
|
+
});
|