@astryxdesign/core 0.7.5 → 0.7.6-canary.0ef60dd
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/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +5 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +12 -3
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +7 -1
- package/dist/BottomSheet/BottomSheet.js +1 -1
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +2 -1
- package/dist/BottomSheet/useSheetGestures.d.ts +12 -0
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +30 -3
- package/dist/Button/Button.js +4 -4
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +6 -5
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +37 -4
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +12 -4
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +101 -15
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +8 -3
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +23 -12
- package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
- package/dist/DateTimeInput/NativeTimeSegment.js +5 -4
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +4 -3
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +34 -9
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +5 -4
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +2 -1
- package/dist/Drawer/Drawer.d.ts +1 -0
- package/dist/Drawer/Drawer.d.ts.map +1 -1
- package/dist/Drawer/Drawer.js +7 -2
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +7 -3
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +20 -2
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.js +31 -3
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -16
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +2 -1
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +4 -4
- package/dist/Field/InputClearButton.js +3 -3
- package/dist/Field/PanelSearchInput.js +2 -2
- package/dist/FieldStatus/FieldStatus.js +2 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +7 -1
- package/dist/Heading/Heading.js +1 -1
- package/dist/Icon/Icon.js +1 -1
- package/dist/Indicator/CheckIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckIndicator.js +2 -1
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +3 -1
- package/dist/Indicator/RadioIndicator.d.ts.map +1 -1
- package/dist/Indicator/RadioIndicator.js +3 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +2 -1
- package/dist/Item/ItemSwipeLayer.js +1 -1
- package/dist/Layer/popoverOperations.d.ts +27 -0
- package/dist/Layer/popoverOperations.d.ts.map +1 -0
- package/dist/Layer/popoverOperations.js +159 -0
- package/dist/Layer/useLayer.d.ts +1 -1
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +93 -59
- package/dist/Layout/Layout.js +1 -1
- package/dist/Layout/LayoutContent.js +1 -1
- package/dist/Layout/LayoutFooter.js +1 -1
- package/dist/Layout/LayoutHeader.js +1 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +5 -0
- package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +5 -4
- package/dist/List/List.js +1 -1
- package/dist/List/ListItem.js +3 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +7 -2
- package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +7 -6
- package/dist/MultiSelector/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +26 -10
- package/dist/NumberInput/NumberInput.d.ts +3 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +3 -3
- package/dist/NumberInput/numberParser.d.ts +3 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -1
- package/dist/NumberInput/numberParser.js +7 -44
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +16 -12
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +28 -2
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +4 -1
- package/dist/Selector/useSelectorPresentation.d.ts +8 -1
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
- package/dist/Selector/useSelectorPresentation.js +20 -4
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +10 -2
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +3 -3
- package/dist/Stack/Stack.js +1 -1
- package/dist/Stack/StackItem.js +1 -1
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +16 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
- package/dist/Text/Text.js +1 -1
- package/dist/Text/useTruncation.d.ts.map +1 -1
- package/dist/Text/useTruncation.js +23 -5
- package/dist/TextArea/TextArea.d.ts +1 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +13 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -3
- package/dist/TimeInput/TimeInput.d.ts +6 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +21 -14
- package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
- package/dist/TimeInput/TouchTimeField.js +5 -4
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +2 -2
- package/dist/Timestamp/TimestampHoverCard.js +4 -4
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +60 -20
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +82 -51
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +13 -2
- package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +2 -1
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +3 -0
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +1 -0
- package/dist/Typeahead/Typeahead.d.ts +1 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +9 -1
- package/dist/astryx.css +20 -4
- package/dist/gestures/GestureArena.d.ts +6 -0
- package/dist/gestures/GestureArena.d.ts.map +1 -1
- package/dist/gestures/GestureArena.js +39 -0
- package/dist/gestures/GestureHost.d.ts +352 -0
- package/dist/gestures/GestureHost.d.ts.map +1 -0
- package/dist/gestures/GestureHost.js +1773 -0
- package/dist/gestures/GestureRecognizer.d.ts +10 -0
- package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/GestureRecognizer.js +16 -0
- package/dist/gestures/LongPressGestureRecognizer.d.ts +1 -0
- package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/LongPressGestureRecognizer.js +3 -0
- package/dist/gestures/PanGestureRecognizer.d.ts +1 -0
- package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/PanGestureRecognizer.js +3 -0
- package/dist/gestures/PinchGestureRecognizer.d.ts +31 -0
- package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/PinchGestureRecognizer.js +128 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +71 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.js +223 -0
- package/dist/gestures/SwipeGestureRecognizer.d.ts +37 -0
- package/dist/gestures/SwipeGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/SwipeGestureRecognizer.js +148 -0
- package/dist/gestures/TapGestureRecognizer.d.ts +1 -0
- package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/TapGestureRecognizer.js +3 -0
- package/dist/gestures/VelocityTracker.d.ts +6 -2
- package/dist/gestures/VelocityTracker.d.ts.map +1 -1
- package/dist/gestures/VelocityTracker.js +7 -3
- package/dist/gestures/haptics.d.ts +65 -0
- package/dist/gestures/haptics.d.ts.map +1 -0
- package/dist/gestures/haptics.js +182 -0
- package/dist/gestures/nativeScroll.d.ts +42 -0
- package/dist/gestures/nativeScroll.d.ts.map +1 -0
- package/dist/gestures/nativeScroll.js +228 -0
- package/dist/gestures/touchAction.d.ts +60 -0
- package/dist/gestures/touchAction.d.ts.map +1 -0
- package/dist/gestures/touchAction.js +157 -0
- package/dist/gestures/touchActionRule.d.ts +34 -0
- package/dist/gestures/touchActionRule.d.ts.map +1 -0
- package/dist/gestures/touchActionRule.js +140 -0
- package/dist/gestures/types.d.ts +18 -7
- package/dist/gestures/types.d.ts.map +1 -1
- package/dist/gestures/types.js +22 -2
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/modalAnnounce.d.ts.map +1 -1
- package/dist/hooks/modalAnnounce.js +107 -61
- package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
- package/dist/hooks/useAdaptivePresentation.js +4 -1
- package/dist/hooks/useAnnounce.d.ts +101 -42
- package/dist/hooks/useAnnounce.d.ts.map +1 -1
- package/dist/hooks/useAnnounce.js +161 -75
- package/dist/hooks/useAnnounceRenderedText.d.ts +11 -3
- package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
- package/dist/hooks/useAnnounceRenderedText.js +5 -3
- package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
- package/dist/hooks/useBusyAnnouncement.js +6 -12
- package/dist/hooks/useMenuHover.d.ts.map +1 -1
- package/dist/hooks/useMenuHover.js +12 -1
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +5 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +5 -0
- package/dist/motion/animator.d.ts +7 -1
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +119 -27
- package/dist/theme/defineTheme.d.ts +19 -5
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +64 -4
- package/dist/theme/domainTokens/domainTokenDefaults.d.ts +3 -0
- package/dist/theme/domainTokens/domainTokenDefaults.d.ts.map +1 -0
- package/dist/theme/domainTokens/domainTokenDefaults.js +19 -0
- package/dist/theme/domainTokens/index.d.ts +5 -4
- package/dist/theme/domainTokens/index.d.ts.map +1 -1
- package/dist/theme/domainTokens/index.js +5 -9
- package/dist/theme/index.d.ts +1 -0
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/motionKnobs.d.ts +56 -0
- package/dist/theme/motionKnobs.d.ts.map +1 -0
- package/dist/theme/motionKnobs.js +48 -0
- package/dist/theme/resolveThemeValues.d.ts +11 -4
- package/dist/theme/resolveThemeValues.d.ts.map +1 -1
- package/dist/theme/resolveThemeValues.js +40 -4
- package/dist/theme/themeAdaptations.d.ts +7 -3
- package/dist/theme/themeAdaptations.d.ts.map +1 -1
- package/dist/theme/themeAdaptations.js +36 -7
- package/dist/theme/themeMotion.d.ts +96 -0
- package/dist/theme/themeMotion.d.ts.map +1 -0
- package/dist/theme/themeMotion.js +177 -0
- package/dist/theme/tokenReferences.d.ts +31 -0
- package/dist/theme/tokenReferences.d.ts.map +1 -0
- package/dist/theme/tokenReferences.js +132 -0
- package/dist/theme/tokens.d.ts +1 -0
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +9 -129
- package/dist/theme/tokens.stylex.d.ts +12 -0
- package/dist/theme/tokens.stylex.d.ts.map +1 -1
- package/dist/theme/tokens.stylex.js +12 -0
- package/dist/utils/focusReturn.d.ts +17 -1
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +11 -4
- package/dist/utils/getNodeText.d.ts +8 -0
- package/dist/utils/getNodeText.d.ts.map +1 -0
- package/dist/utils/getNodeText.js +37 -0
- package/dist/utils/interactionModality.d.ts +11 -2
- package/dist/utils/interactionModality.d.ts.map +1 -1
- package/dist/utils/interactionModality.js +58 -5
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +17 -8
- package/dist/utils/plainDate.d.ts +2 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +46 -3
- package/dist/utils/presentation.d.ts +50 -0
- package/dist/utils/presentation.d.ts.map +1 -0
- package/dist/utils/presentation.js +125 -0
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +20 -1
- package/dist/utils/primaryClick.d.ts +11 -0
- package/dist/utils/primaryClick.d.ts.map +1 -0
- package/dist/utils/primaryClick.js +25 -0
- package/dist/utils/timeFormat.d.ts +47 -0
- package/dist/utils/timeFormat.d.ts.map +1 -0
- package/dist/utils/timeFormat.js +240 -0
- package/dist/utils/touchPresentation.d.ts.map +1 -1
- package/dist/utils/touchPresentation.js +5 -3
- package/dist/utils/touchPresentation.stylex.d.ts +15 -0
- package/dist/utils/touchPresentation.stylex.d.ts.map +1 -0
- package/dist/utils/touchPresentation.stylex.js +33 -0
- package/dist/utils/unicodeDigits.d.ts +20 -0
- package/dist/utils/unicodeDigits.d.ts.map +1 -0
- package/dist/utils/unicodeDigits.js +70 -0
- package/locales/en.json +23 -3
- package/locales/pseudo.json +15 -0
- package/package.json +5 -4
- package/src/AlertDialog/AlertDialog.tsx +6 -5
- package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +18 -6
- package/src/Avatar/Avatar.spec.md +22 -22
- package/src/Avatar/Avatar.tsx +18 -1
- package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +126 -0
- package/src/Badge/Badge.doc.mjs +1 -1
- package/src/Badge/Badge.tsx +19 -2
- package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +260 -0
- package/src/BottomSheet/BottomSheet.test.tsx +46 -0
- package/src/BottomSheet/BottomSheet.tsx +1 -1
- package/src/BottomSheet/BottomSheetPanel.tsx +2 -1
- package/src/BottomSheet/useSheetGestures.test.ts +52 -0
- package/src/BottomSheet/useSheetGestures.ts +37 -6
- package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +18 -6
- package/src/Button/Button.tsx +4 -4
- package/src/Calendar/Calendar.spec.md +87 -48
- package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +21 -7
- package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
- package/src/CheckboxInput/CheckboxInput.tsx +6 -5
- package/src/ClickableCard/ClickableCard.test.tsx +96 -0
- package/src/ClickableCard/ClickableCard.tsx +48 -4
- package/src/Collapsible/Collapsible.spec.md +2 -0
- package/src/Collapsible/CollapsibleGroup.spec.md +57 -29
- package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +18 -7
- package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +18 -6
- package/src/ComplexSelector/ComplexSelector.test.tsx +37 -0
- package/src/ContextMenu/ContextMenu.test.tsx +35 -0
- package/src/DateInput/DateInput.test.tsx +115 -3
- package/src/DateInput/DateInput.tsx +29 -14
- package/src/DateInput/DateInputTouch.test.tsx +76 -0
- package/src/DateInput/MonthScroller.tsx +106 -20
- package/src/DateInput/MonthScrollerSettle.test.tsx +165 -0
- package/src/DateInput/TouchDateField.tsx +14 -3
- package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +46 -3
- package/src/DateRangeInput/DateRangeInput.tsx +16 -12
- package/src/DateTimeInput/DateTimeInput.doc.mjs +10 -8
- package/src/DateTimeInput/DateTimeInput.spec.md +75 -51
- package/src/DateTimeInput/DateTimeInput.test.tsx +81 -0
- package/src/DateTimeInput/DateTimeInput.tsx +46 -24
- package/src/DateTimeInput/NativeTimeSegment.tsx +4 -6
- package/src/DateTimeInput/TouchDateTimeField.tsx +3 -7
- package/src/Dialog/Dialog.test.tsx +216 -2
- package/src/Dialog/Dialog.tsx +42 -9
- package/src/Dialog/DialogHeader.tsx +5 -4
- package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +202 -0
- package/src/Divider/Divider.tsx +2 -1
- package/src/Drawer/Drawer.spec.md +111 -80
- package/src/Drawer/Drawer.test.tsx +35 -0
- package/src/Drawer/Drawer.tsx +13 -2
- package/src/Drawer/DrawerHeader.spec.md +181 -0
- package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +267 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +41 -0
- package/src/DropdownMenu/DropdownMenu.tsx +10 -3
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +34 -0
- package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -5
- package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +19 -7
- package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +21 -9
- package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +60 -0
- package/src/DropdownMenu/lazyMenuBottomSheet.ts +36 -7
- package/src/DropdownMenu/renderDropdownItems.tsx +24 -19
- package/src/EmptyState/EmptyState.tsx +2 -1
- package/src/Field/FieldLabel.tsx +5 -4
- package/src/Field/InputClearButton.tsx +3 -3
- package/src/Field/PanelSearchInput.tsx +2 -2
- package/src/FieldStatus/FieldStatus.tsx +2 -2
- package/src/FileInput/FileInput.test.tsx +21 -0
- package/src/FileInput/FileInput.tsx +4 -1
- package/src/FormLayout/FormLayout.spec.md +7 -8
- package/src/Heading/Heading.tsx +1 -1
- package/src/Icon/Icon.tsx +1 -1
- package/src/Indicator/CheckIndicator.spec.md +47 -42
- package/src/Indicator/CheckIndicator.tsx +2 -1
- package/src/Indicator/CheckboxIndicator.spec.md +40 -37
- package/src/Indicator/CheckboxIndicator.tsx +3 -1
- package/src/Indicator/Indicator.spec.md +188 -0
- package/src/Indicator/RadioIndicator.tsx +3 -1
- package/src/Item/Item.tsx +2 -1
- package/src/Item/ItemSwipeLayer.tsx +1 -1
- package/src/Kbd/Kbd.spec.md +81 -38
- package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +126 -0
- package/src/Layer/popoverOperations.test.ts +205 -0
- package/src/Layer/popoverOperations.ts +172 -0
- package/src/Layer/useLayer.test.tsx +348 -1
- package/src/Layer/useLayer.tsx +118 -71
- package/src/Layout/Layout.spec.md +127 -131
- package/src/Layout/Layout.tsx +1 -1
- package/src/Layout/LayoutContent.spec.md +205 -0
- package/src/Layout/LayoutContent.tsx +1 -1
- package/src/Layout/LayoutFooter.spec.md +190 -0
- package/src/Layout/LayoutFooter.tsx +1 -1
- package/src/Layout/LayoutHeader.spec.md +193 -0
- package/src/Layout/LayoutHeader.tsx +1 -1
- package/src/Layout/LayoutPanel.spec.md +194 -0
- package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +18 -6
- package/src/Lightbox/Lightbox.test.tsx +18 -0
- package/src/Lightbox/Lightbox.tsx +5 -0
- package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +8 -4
- package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
- package/src/List/List.tsx +1 -1
- package/src/List/ListItem.spec.md +205 -0
- package/src/List/ListItem.tsx +3 -3
- package/src/MetadataList/MetadataList.spec.md +187 -0
- package/src/MetadataList/MetadataListItem.spec.md +165 -0
- package/src/MobileNav/MobileNav.test.tsx +15 -0
- package/src/MobileNav/MobileNav.tsx +9 -1
- package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +89 -0
- package/src/MoreMenu/MoreMenu.test.tsx +11 -0
- package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +7 -8
- package/src/MultiSelector/MultiSelector.spec.md +7 -4
- package/src/MultiSelector/MultiSelector.test.tsx +270 -1
- package/src/MultiSelector/MultiSelector.tsx +25 -10
- package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +8 -1
- package/src/NavMenu/NavHeadingMenu.spec.md +1 -5
- package/src/NumberInput/NumberInput.doc.mjs +13 -7
- package/src/NumberInput/NumberInput.spec.md +59 -37
- package/src/NumberInput/NumberInput.tsx +13 -3
- package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
- package/src/NumberInput/numberParser.ts +7 -45
- package/src/ProgressBar/ProgressBar.test.tsx +108 -32
- package/src/ProgressBar/ProgressBar.tsx +58 -10
- package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +21 -9
- package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +831 -0
- package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +21 -14
- package/src/Resizable/useResizable.test.ts +43 -0
- package/src/Resizable/useResizable.ts +32 -9
- package/src/SegmentedControl/SegmentedControl.test.tsx +84 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +11 -5
- package/src/Selector/Selector.test.tsx +90 -1
- package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +8 -1
- package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +8 -1
- package/src/Selector/useSelectorPresentation.ts +31 -3
- package/src/SideNav/SideNav.test.tsx +27 -0
- package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +176 -51
- package/src/Skeleton/Skeleton.tsx +3 -1
- package/src/Slider/Slider.test.tsx +31 -0
- package/src/Slider/Slider.tsx +8 -3
- package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
- package/src/Spinner/Spinner.tsx +5 -3
- package/src/Stack/Stack.tsx +1 -1
- package/src/Stack/StackItem.tsx +1 -1
- package/src/TabList/TabList.test.tsx +58 -4
- package/src/TabList/TabList.tsx +16 -1
- package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +163 -0
- package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
- package/src/Text/Text.tsx +1 -1
- package/src/Text/useTruncation.test.tsx +128 -1
- package/src/Text/useTruncation.ts +23 -5
- package/src/TextArea/TextArea.spec.md +10 -13
- package/src/TextArea/TextArea.test.tsx +60 -0
- package/src/TextArea/TextArea.tsx +15 -1
- package/src/TextInput/TextInput.test.tsx +21 -0
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/TimeInput/NativeTimeInput.test.tsx +17 -0
- package/src/TimeInput/Presentation.test.tsx +21 -0
- package/src/TimeInput/TimeInput.doc.mjs +8 -8
- package/src/TimeInput/TimeInput.spec.md +45 -48
- package/src/TimeInput/TimeInput.test.tsx +76 -0
- package/src/TimeInput/TimeInput.tsx +36 -18
- package/src/TimeInput/TouchTimeField.tsx +4 -6
- package/src/Timestamp/Timestamp.spec.md +6 -12
- package/src/Timestamp/Timestamp.test.tsx +30 -5
- package/src/Timestamp/Timestamp.tsx +6 -2
- package/src/Timestamp/TimestampHoverCard.tsx +4 -4
- package/src/Toast/Toast.spec.md +14 -20
- package/src/Toast/Toast.tsx +104 -36
- package/src/Toast/ToastViewport.test.tsx +719 -1
- package/src/Toast/ToastViewport.tsx +100 -50
- package/src/Tokenizer/Tokenizer.spec.md +5 -3
- package/src/Tokenizer/Tokenizer.test.tsx +68 -0
- package/src/Tokenizer/Tokenizer.tsx +14 -2
- package/src/Tokenizer/TokenizerBottomSheet.test.tsx +15 -4
- package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
- package/src/Toolbar/Toolbar.spec.md +5 -6
- package/src/Toolbar/Toolbar.test.tsx +30 -0
- package/src/Toolbar/Toolbar.tsx +2 -1
- package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +18 -6
- package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +18 -7
- package/src/TopNav/TopNav.test.tsx +27 -0
- package/src/TopNav/TopNavMegaMenu.test.tsx +21 -0
- package/src/TopNav/TopNavMegaMenu.tsx +4 -1
- package/src/TopNav/TopNavMenu.test.tsx +17 -0
- package/src/TopNav/TopNavMenu.tsx +1 -0
- package/src/Typeahead/Typeahead.test.tsx +40 -0
- package/src/Typeahead/Typeahead.tsx +12 -1
- package/src/__tests__/pressState.ts +8 -4
- package/src/gestures/GestureArena.ts +35 -0
- package/src/gestures/GestureHost.ts +2065 -0
- package/src/gestures/GestureRecognizer.ts +18 -0
- package/src/gestures/LongPressGestureRecognizer.ts +4 -0
- package/src/gestures/PanGestureRecognizer.ts +4 -0
- package/src/gestures/PinchGestureRecognizer.ts +148 -0
- package/src/gestures/ScreenEdgePanGestureRecognizer.ts +256 -0
- package/src/gestures/SwipeGestureRecognizer.ts +197 -0
- package/src/gestures/TapGestureRecognizer.ts +4 -0
- package/src/gestures/VelocityTracker.ts +10 -3
- package/src/gestures/__tests__/GestureHost.test.ts +2087 -0
- package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
- package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
- package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +498 -0
- package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +108 -0
- package/src/gestures/__tests__/arena.test.ts +5 -0
- package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +193 -0
- package/src/gestures/__tests__/browser/build-fixture.mjs +46 -0
- package/src/gestures/__tests__/browser/fixture.ts +307 -0
- package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +1137 -0
- package/src/gestures/__tests__/browserNegotiation.test.ts +293 -0
- package/src/gestures/__tests__/haptics.test.ts +187 -0
- package/src/gestures/__tests__/harness.ts +21 -2
- package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
- package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
- package/src/gestures/haptics.ts +203 -0
- package/src/gestures/nativeScroll.ts +277 -0
- package/src/gestures/touchAction.ts +191 -0
- package/src/gestures/touchActionRule.ts +157 -0
- package/src/gestures/types.ts +30 -9
- package/src/hooks/index.ts +5 -1
- package/src/hooks/modalAnnounce.ts +129 -72
- package/src/hooks/useAdaptivePresentation.ts +4 -1
- package/src/hooks/useAnnounce.doc.mjs +35 -3
- package/src/hooks/useAnnounce.replace.test.tsx +516 -0
- package/src/hooks/useAnnounce.ts +209 -102
- package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +10 -1
- package/src/hooks/useAnnounceRenderedText.ts +17 -3
- package/src/hooks/useBusyAnnouncement.ts +7 -10
- package/src/hooks/useMenuHover.ts +15 -1
- package/src/i18n/generated-locales/en.generated.ts +6 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +6 -0
- package/src/motion/README.md +11 -1
- package/src/motion/animator.test.ts +151 -3
- package/src/motion/animator.ts +149 -33
- package/src/theme/Theme.doc.mjs +1 -1
- package/src/theme/defineTheme.ts +117 -8
- package/src/theme/derivedVarRegistry.test.ts +4 -0
- package/src/theme/domainTokens/domainTokenDefaults.ts +19 -0
- package/src/theme/domainTokens/index.ts +6 -10
- package/src/theme/expandMotionScale.test.ts +1 -1
- package/src/theme/index.ts +5 -0
- package/src/theme/motionKnobs.ts +82 -0
- package/src/theme/resolveThemeValues.ts +68 -6
- package/src/theme/themeAdaptations.ts +52 -12
- package/src/theme/themeMotion.test.ts +620 -0
- package/src/theme/themeMotion.ts +221 -0
- package/src/theme/tokenReferences.ts +149 -0
- package/src/theme/tokens.stylex.ts +10 -0
- package/src/theme/tokens.ts +15 -158
- package/src/utils/focusReturn.ts +17 -6
- package/src/utils/getNodeText.test.ts +24 -0
- package/src/utils/getNodeText.ts +37 -0
- package/src/utils/interactionModality.test.ts +45 -1
- package/src/utils/interactionModality.ts +64 -5
- package/src/utils/interactionOverlay.stylex.ts +12 -3
- package/src/utils/plainDate.test.ts +90 -0
- package/src/utils/plainDate.ts +58 -3
- package/src/utils/presentation.test.ts +380 -0
- package/src/utils/presentation.ts +180 -0
- package/src/utils/pressFeedback.test.ts +138 -0
- package/src/utils/pressFeedback.ts +34 -11
- package/src/utils/pressPaintPriority.test.ts +80 -0
- package/src/utils/primaryClick.test.ts +38 -0
- package/src/utils/primaryClick.ts +28 -0
- package/src/utils/timeFormat.test.ts +204 -0
- package/src/utils/timeFormat.ts +314 -0
- package/src/utils/touchPresentation.stylex.ts +43 -0
- package/src/utils/touchPresentation.test.ts +140 -1
- package/src/utils/touchPresentation.ts +5 -3
- package/src/utils/unicodeDigits.test.ts +44 -0
- package/src/utils/unicodeDigits.ts +71 -0
|
@@ -87,23 +87,30 @@ async function runState(
|
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// cores, so the default 60s ran out mid-loop on whichever state it reached.
|
|
96
|
-
// Budget it like the other whole-inventory sweeps (Button, Checkbox).
|
|
97
|
-
test.setTimeout(3 * 60 * 1000);
|
|
98
|
-
const cdp = await page.context().newCDPSession(page);
|
|
90
|
+
// Checking coverage runs every state again, which on a loaded runner nears
|
|
91
|
+
// the per-test timeout as one test. It runs as one serial part per state,
|
|
92
|
+
// sharing their results, then one check over all of them.
|
|
93
|
+
test.describe('every window-splitter expectation is exercised by a ResizeHandle state', () => {
|
|
94
|
+
test.describe.configure({mode: 'serial'});
|
|
99
95
|
const results: BindingResult[] = [];
|
|
96
|
+
|
|
100
97
|
for (const state of RESIZE_HANDLE_BINDING_STATES) {
|
|
101
|
-
|
|
98
|
+
test(`runs ${state.id}`, async ({page}) => {
|
|
99
|
+
const cdp = await page.context().newCDPSession(page);
|
|
100
|
+
results.push(await runState(page, cdp, state));
|
|
101
|
+
});
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
|
|
104
|
+
test('no expectation is left unexercised', () => {
|
|
105
|
+
// Every part ran in this worker; this test alone proves nothing.
|
|
106
|
+
expect(results.map(result => result.state).sort()).toEqual(
|
|
107
|
+
RESIZE_HANDLE_BINDING_STATES.map(state => state.id).sort(),
|
|
108
|
+
);
|
|
109
|
+
expect(neverExercised(results)).toEqual([]);
|
|
110
|
+
expect(
|
|
111
|
+
unmatchedKnownFailures(RESIZE_HANDLE_KNOWN_FAILURES, results),
|
|
112
|
+
).toEqual([]);
|
|
113
|
+
});
|
|
107
114
|
});
|
|
108
115
|
|
|
109
116
|
for (const state of RESIZE_HANDLE_BINDING_STATES) {
|
|
@@ -1680,3 +1680,46 @@ describe('ResizableProps source compatibility (AST-010 API5)', () => {
|
|
|
1680
1680
|
expect(prePr._onResizeCancel).toBeUndefined();
|
|
1681
1681
|
});
|
|
1682
1682
|
});
|
|
1683
|
+
|
|
1684
|
+
describe('useResizable window reads after a commit', () => {
|
|
1685
|
+
// React re-reads a useSyncExternalStore snapshot after the commit whenever
|
|
1686
|
+
// getSnapshot is a new function, and a window size read after the DOM has
|
|
1687
|
+
// changed forces a layout of the whole page. A re-render with unchanged
|
|
1688
|
+
// inputs reads the window during render only.
|
|
1689
|
+
function readsAfterCommit(direction: 'horizontal' | 'vertical') {
|
|
1690
|
+
const reads = {count: 0};
|
|
1691
|
+
const width = vi.spyOn(window, 'innerWidth', 'get');
|
|
1692
|
+
const height = vi.spyOn(window, 'innerHeight', 'get');
|
|
1693
|
+
width.mockImplementation(() => {
|
|
1694
|
+
reads.count += 1;
|
|
1695
|
+
return 1024;
|
|
1696
|
+
});
|
|
1697
|
+
height.mockImplementation(() => {
|
|
1698
|
+
reads.count += 1;
|
|
1699
|
+
return 768;
|
|
1700
|
+
});
|
|
1701
|
+
function Region({tick}: {tick: number}) {
|
|
1702
|
+
useResizable({defaultSize: 240, direction});
|
|
1703
|
+
// Runs in the commit, before passive effects: every read counted
|
|
1704
|
+
// after it happened after the DOM changed.
|
|
1705
|
+
useLayoutEffect(() => {
|
|
1706
|
+
reads.count = 0;
|
|
1707
|
+
});
|
|
1708
|
+
return createElement('div', {'data-tick': tick});
|
|
1709
|
+
}
|
|
1710
|
+
const {rerender} = render(createElement(Region, {tick: 0}));
|
|
1711
|
+
act(() => rerender(createElement(Region, {tick: 1})));
|
|
1712
|
+
const count = reads.count;
|
|
1713
|
+
width.mockRestore();
|
|
1714
|
+
height.mockRestore();
|
|
1715
|
+
return count;
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
it('reads the window width again only during render, not after the commit', () => {
|
|
1719
|
+
expect(readsAfterCommit('horizontal')).toBe(0);
|
|
1720
|
+
});
|
|
1721
|
+
|
|
1722
|
+
it('reads the window height again only during render, not after the commit', () => {
|
|
1723
|
+
expect(readsAfterCommit('vertical')).toBe(0);
|
|
1724
|
+
});
|
|
1725
|
+
});
|
|
@@ -306,6 +306,34 @@ const SERVER_BASIS = 1200;
|
|
|
306
306
|
|
|
307
307
|
/** A store that never changes on its own; the snapshot is re-read on render. */
|
|
308
308
|
const noopSubscribe = () => () => {};
|
|
309
|
+
|
|
310
|
+
// The window snapshots are module functions, so their identity is stable:
|
|
311
|
+
// React re-reads a snapshot after the commit whenever getSnapshot is a new
|
|
312
|
+
// function, and a window size read after the DOM changed forces a layout of
|
|
313
|
+
// the whole page. With these, the window is read during render only.
|
|
314
|
+
|
|
315
|
+
/** The viewport width, the basis without a container. */
|
|
316
|
+
function readViewportBasis(): number {
|
|
317
|
+
return typeof window === 'undefined' ? SERVER_BASIS : window.innerWidth;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function readServerBasis(): number {
|
|
321
|
+
return SERVER_BASIS;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** The window's extent along a horizontal hook's axis. */
|
|
325
|
+
function readWindowWidth(): number | null {
|
|
326
|
+
return typeof window === 'undefined' ? null : window.innerWidth;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** The window's extent along a vertical hook's axis. */
|
|
330
|
+
function readWindowHeight(): number | null {
|
|
331
|
+
return typeof window === 'undefined' ? null : window.innerHeight;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function readNoWindowExtent(): null {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
309
337
|
const DEFAULT_SIZE_FALLBACK = 250;
|
|
310
338
|
const RESIZABLE_SIZE_GUIDANCE =
|
|
311
339
|
'Use a non-negative number of pixels, an exact "Npx" string, an exact ' +
|
|
@@ -698,8 +726,8 @@ function useSingleResizable(config: UseResizableSingleConfig): ResizableRegion {
|
|
|
698
726
|
);
|
|
699
727
|
const viewportBasis = useSyncExternalStore(
|
|
700
728
|
subscribeToViewport,
|
|
701
|
-
|
|
702
|
-
|
|
729
|
+
readViewportBasis,
|
|
730
|
+
readServerBasis,
|
|
703
731
|
);
|
|
704
732
|
|
|
705
733
|
// The window's extent along the hook's axis, for the REPORTED maximum of an
|
|
@@ -710,13 +738,8 @@ function useSingleResizable(config: UseResizableSingleConfig): ResizableRegion {
|
|
|
710
738
|
// (component:Resizable Performance and resources).
|
|
711
739
|
const windowExtent = useSyncExternalStore(
|
|
712
740
|
noopSubscribe,
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
? null
|
|
716
|
-
: direction === 'vertical'
|
|
717
|
-
? window.innerHeight
|
|
718
|
-
: window.innerWidth,
|
|
719
|
-
() => null,
|
|
741
|
+
direction === 'vertical' ? readWindowHeight : readWindowWidth,
|
|
742
|
+
readNoWindowExtent,
|
|
720
743
|
);
|
|
721
744
|
|
|
722
745
|
// With a container, its content box is the basis; without one, the released
|
|
@@ -562,6 +562,90 @@ describe('SegmentedControl disabled state', () => {
|
|
|
562
562
|
expect(handleChange).not.toHaveBeenCalled();
|
|
563
563
|
});
|
|
564
564
|
|
|
565
|
+
it("does not run a caller's onClick on a disabled segment", async () => {
|
|
566
|
+
const user = userEvent.setup({pointerEventsCheck: 0});
|
|
567
|
+
const handleClick = vi.fn();
|
|
568
|
+
const handleChange = vi.fn();
|
|
569
|
+
|
|
570
|
+
render(
|
|
571
|
+
<SegmentedControl value="grid" onChange={handleChange} label="View mode">
|
|
572
|
+
<SegmentedControlItem value="grid" label="Grid" />
|
|
573
|
+
<SegmentedControlItem
|
|
574
|
+
value="list"
|
|
575
|
+
label="List"
|
|
576
|
+
isDisabled
|
|
577
|
+
onClick={handleClick}
|
|
578
|
+
/>
|
|
579
|
+
</SegmentedControl>,
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
await user.click(screen.getByRole('radio', {name: 'List'}));
|
|
583
|
+
expect(handleClick).not.toHaveBeenCalled();
|
|
584
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
it("does not run a caller's onClick when the whole group is disabled", async () => {
|
|
588
|
+
const user = userEvent.setup({pointerEventsCheck: 0});
|
|
589
|
+
const handleClick = vi.fn();
|
|
590
|
+
|
|
591
|
+
render(
|
|
592
|
+
<SegmentedControl
|
|
593
|
+
value="grid"
|
|
594
|
+
onChange={() => {}}
|
|
595
|
+
label="View mode"
|
|
596
|
+
isDisabled>
|
|
597
|
+
<SegmentedControlItem value="grid" label="Grid" />
|
|
598
|
+
<SegmentedControlItem value="list" label="List" onClick={handleClick} />
|
|
599
|
+
</SegmentedControl>,
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
await user.click(screen.getByRole('radio', {name: 'List'}));
|
|
603
|
+
expect(handleClick).not.toHaveBeenCalled();
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
it("does not run a caller's onClick on a focusable disabled segment", async () => {
|
|
607
|
+
// A group disabled with a reason keeps its selected segment in the tab
|
|
608
|
+
// order, so Enter and Space can reach it and synthesize a click.
|
|
609
|
+
const user = userEvent.setup({pointerEventsCheck: 0});
|
|
610
|
+
const handleClick = vi.fn();
|
|
611
|
+
|
|
612
|
+
render(
|
|
613
|
+
<SegmentedControl
|
|
614
|
+
value="grid"
|
|
615
|
+
onChange={() => {}}
|
|
616
|
+
label="View mode"
|
|
617
|
+
isDisabled
|
|
618
|
+
disabledMessage="Choose a project to switch views">
|
|
619
|
+
<SegmentedControlItem value="grid" label="Grid" onClick={handleClick} />
|
|
620
|
+
<SegmentedControlItem value="list" label="List" />
|
|
621
|
+
</SegmentedControl>,
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
const selected = screen.getByRole('radio', {name: 'Grid'});
|
|
625
|
+
selected.focus();
|
|
626
|
+
expect(selected).toHaveFocus();
|
|
627
|
+
await user.keyboard('{Enter}');
|
|
628
|
+
await user.keyboard(' ');
|
|
629
|
+
expect(handleClick).not.toHaveBeenCalled();
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
it("still runs a caller's onClick on an enabled segment", async () => {
|
|
633
|
+
const user = userEvent.setup({pointerEventsCheck: 0});
|
|
634
|
+
const handleClick = vi.fn();
|
|
635
|
+
const handleChange = vi.fn();
|
|
636
|
+
|
|
637
|
+
render(
|
|
638
|
+
<SegmentedControl value="grid" onChange={handleChange} label="View mode">
|
|
639
|
+
<SegmentedControlItem value="grid" label="Grid" />
|
|
640
|
+
<SegmentedControlItem value="list" label="List" onClick={handleClick} />
|
|
641
|
+
</SegmentedControl>,
|
|
642
|
+
);
|
|
643
|
+
|
|
644
|
+
await user.click(screen.getByRole('radio', {name: 'List'}));
|
|
645
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
646
|
+
expect(handleChange).toHaveBeenCalledWith('list');
|
|
647
|
+
});
|
|
648
|
+
|
|
565
649
|
it('skips disabled items during keyboard navigation', async () => {
|
|
566
650
|
const user = userEvent.setup();
|
|
567
651
|
const handleChange = vi.fn();
|
|
@@ -210,11 +210,17 @@ export function SegmentedControlItem({
|
|
|
210
210
|
|
|
211
211
|
// Consumer-first: a consumer onClick can call preventDefault() to opt out of
|
|
212
212
|
// selection; otherwise selection proceeds when enabled and not selected.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
213
|
+
// A disabled segment invokes no caller callback (spec:AST-085 FR2), so the
|
|
214
|
+
// consumer onClick is left out while it is disabled, including the selected
|
|
215
|
+
// segment of a group disabled with a reason, which stays focusable.
|
|
216
|
+
const handleClick = composeEventHandlers(
|
|
217
|
+
isItemDisabled ? undefined : onClickProp,
|
|
218
|
+
() => {
|
|
219
|
+
if (!isItemDisabled && !isSelected) {
|
|
220
|
+
ctx.onChange(value);
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
);
|
|
218
224
|
|
|
219
225
|
const iconElement = icon ? (
|
|
220
226
|
<span {...stylex.props(styles.icon, iconSizeStyles[size])}>{icon}</span>
|
|
@@ -9,7 +9,15 @@
|
|
|
9
9
|
* SYNC: When Selector.tsx API changes, update these tests.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
describe,
|
|
14
|
+
it,
|
|
15
|
+
expect,
|
|
16
|
+
vi,
|
|
17
|
+
beforeAll,
|
|
18
|
+
beforeEach,
|
|
19
|
+
afterEach,
|
|
20
|
+
} from 'vitest';
|
|
13
21
|
import {readFileSync} from 'node:fs';
|
|
14
22
|
import {
|
|
15
23
|
act,
|
|
@@ -61,6 +69,15 @@ function generateThemeTestCSS(theme: Parameters<typeof generateThemeCSS>[0]) {
|
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
// Mock showPopover and hidePopover methods since they're not implemented in jsdom
|
|
72
|
+
// The bottom-sheet presentation renders BottomSheet through React.lazy. Its
|
|
73
|
+
// first import transforms the BottomSheet module tree, which on a loaded
|
|
74
|
+
// runner takes longer than a query's 1 s wait, so the first sheet test timed
|
|
75
|
+
// out before the dialog existed. Load the module once up front: lazy() then
|
|
76
|
+
// resolves from the module cache and every sheet test waits only on the open.
|
|
77
|
+
beforeAll(async () => {
|
|
78
|
+
await import('../BottomSheet/BottomSheet');
|
|
79
|
+
});
|
|
80
|
+
|
|
64
81
|
beforeEach(() => {
|
|
65
82
|
// The live regions are a document-level singleton; start each test clean.
|
|
66
83
|
__resetLiveRegionsForTest();
|
|
@@ -276,6 +293,13 @@ function expectSilentBusySpinner() {
|
|
|
276
293
|
expect(screen.queryByRole('status', {name: 'Loading'})).toBeNull();
|
|
277
294
|
}
|
|
278
295
|
|
|
296
|
+
// The bottom sheet is loaded on demand (SelectorBottomSheet's lazy import).
|
|
297
|
+
// Loading its module is not part of an open, so the file waits for it once
|
|
298
|
+
// here, and each test's open waits only for the open.
|
|
299
|
+
beforeAll(async () => {
|
|
300
|
+
await import('../BottomSheet/BottomSheet');
|
|
301
|
+
});
|
|
302
|
+
|
|
279
303
|
describe('Selector', () => {
|
|
280
304
|
it('uses a bottom sheet and closes after a selection when requested', async () => {
|
|
281
305
|
const user = userEvent.setup();
|
|
@@ -4271,6 +4295,71 @@ describe('Selector popup theme target', () => {
|
|
|
4271
4295
|
});
|
|
4272
4296
|
});
|
|
4273
4297
|
|
|
4298
|
+
describe('Selector light dismiss focus (spec:Popover AR4)', () => {
|
|
4299
|
+
function closeByLightDismiss() {
|
|
4300
|
+
const popover = document.querySelector('[popover]') as HTMLElement;
|
|
4301
|
+
act(() => {
|
|
4302
|
+
popover.dispatchEvent(
|
|
4303
|
+
Object.assign(new Event('toggle'), {
|
|
4304
|
+
oldState: 'open',
|
|
4305
|
+
newState: 'closed',
|
|
4306
|
+
}),
|
|
4307
|
+
);
|
|
4308
|
+
});
|
|
4309
|
+
}
|
|
4310
|
+
|
|
4311
|
+
it('leaves focus on the field a press moved it to', async () => {
|
|
4312
|
+
const user = userEvent.setup();
|
|
4313
|
+
render(
|
|
4314
|
+
<>
|
|
4315
|
+
<Selector
|
|
4316
|
+
label="Fruit"
|
|
4317
|
+
options={OPTIONS}
|
|
4318
|
+
value="Banana"
|
|
4319
|
+
onChange={() => {}}
|
|
4320
|
+
placement="below"
|
|
4321
|
+
/>
|
|
4322
|
+
<input aria-label="Notes" />
|
|
4323
|
+
</>,
|
|
4324
|
+
);
|
|
4325
|
+
const trigger = screen.getByRole('combobox');
|
|
4326
|
+
await user.click(trigger);
|
|
4327
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
4328
|
+
|
|
4329
|
+
// The press on another field focuses it before the browser's light
|
|
4330
|
+
// dismiss closes the list.
|
|
4331
|
+
const notes = screen.getByRole('textbox', {name: 'Notes'});
|
|
4332
|
+
act(() => {
|
|
4333
|
+
notes.focus();
|
|
4334
|
+
});
|
|
4335
|
+
closeByLightDismiss();
|
|
4336
|
+
|
|
4337
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
4338
|
+
expect(notes).toHaveFocus();
|
|
4339
|
+
});
|
|
4340
|
+
|
|
4341
|
+
it('returns focus to the trigger when the press lands on nothing focusable', async () => {
|
|
4342
|
+
const user = userEvent.setup();
|
|
4343
|
+
render(
|
|
4344
|
+
<Selector
|
|
4345
|
+
label="Fruit"
|
|
4346
|
+
options={OPTIONS}
|
|
4347
|
+
value="Banana"
|
|
4348
|
+
onChange={() => {}}
|
|
4349
|
+
placement="below"
|
|
4350
|
+
/>,
|
|
4351
|
+
);
|
|
4352
|
+
const trigger = screen.getByRole('combobox');
|
|
4353
|
+
await user.click(trigger);
|
|
4354
|
+
act(() => {
|
|
4355
|
+
(document.activeElement as HTMLElement | null)?.blur();
|
|
4356
|
+
});
|
|
4357
|
+
closeByLightDismiss();
|
|
4358
|
+
|
|
4359
|
+
expect(trigger).toHaveFocus();
|
|
4360
|
+
});
|
|
4361
|
+
});
|
|
4362
|
+
|
|
4274
4363
|
describe('Selector option-row theme target', () => {
|
|
4275
4364
|
const ROW_OPTIONS = ['Apple', 'Banana', 'Orange'];
|
|
4276
4365
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import {cleanup, render, screen, waitFor, within} from '@testing-library/react';
|
|
6
6
|
import userEvent from '@testing-library/user-event';
|
|
7
|
-
import {describe, expect, it} from 'vitest';
|
|
7
|
+
import {beforeAll, describe, expect, it} from 'vitest';
|
|
8
8
|
import {
|
|
9
9
|
COMBOBOX_PATTERN,
|
|
10
10
|
expectAccessibilitySpec,
|
|
@@ -20,6 +20,13 @@ import {SELECTOR_COMBOBOX_KNOWN_FAILURES} from './Combobox.a11y.known-failures';
|
|
|
20
20
|
|
|
21
21
|
installListboxDialogStubs();
|
|
22
22
|
|
|
23
|
+
// The bottom sheet is loaded on demand (SelectorBottomSheet's lazy import).
|
|
24
|
+
// Loading its module is not part of an open, so the file waits for it once
|
|
25
|
+
// here, and each scenario's open waits only for the open.
|
|
26
|
+
beforeAll(async () => {
|
|
27
|
+
await import('../../BottomSheet/BottomSheet');
|
|
28
|
+
});
|
|
29
|
+
|
|
23
30
|
const hidden = {hidden: true} as const;
|
|
24
31
|
|
|
25
32
|
function subjectFor(scenario: SelectorComboboxScenario): HTMLElement {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import {cleanup, render, screen, within} from '@testing-library/react';
|
|
11
11
|
import userEvent from '@testing-library/user-event';
|
|
12
|
-
import {describe, expect, it} from 'vitest';
|
|
12
|
+
import {beforeAll, describe, expect, it} from 'vitest';
|
|
13
13
|
import {
|
|
14
14
|
expectAccessibilitySpec,
|
|
15
15
|
LISTBOX_PATTERN,
|
|
@@ -20,6 +20,13 @@ import {installListboxDialogStubs} from './Listbox.a11y.dom';
|
|
|
20
20
|
|
|
21
21
|
installListboxDialogStubs();
|
|
22
22
|
|
|
23
|
+
// The bottom sheet is loaded on demand (SelectorBottomSheet's lazy import).
|
|
24
|
+
// Loading its module is not part of an open, so the file waits for it once
|
|
25
|
+
// here, and each scenario's open waits only for the open.
|
|
26
|
+
beforeAll(async () => {
|
|
27
|
+
await import('../../BottomSheet/BottomSheet');
|
|
28
|
+
});
|
|
29
|
+
|
|
23
30
|
const scenarios = LISTBOX_SCENARIOS.filter(
|
|
24
31
|
scenario => scenario.component === 'Selector',
|
|
25
32
|
);
|
|
@@ -34,6 +34,13 @@ interface UseSelectorPresentationOptions {
|
|
|
34
34
|
onShow: () => void;
|
|
35
35
|
popoverOptions: Omit<UsePopoverOptions, 'onHide' | 'onShow'>;
|
|
36
36
|
triggerRef: RefObject<HTMLElement | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Return focus to the trigger on every close, even when a press already
|
|
39
|
+
* moved focus to another element. A caller-rendered trigger needs this
|
|
40
|
+
* (spec:AST-055 AR3); the built-in trigger leaves focus where the press put
|
|
41
|
+
* it (spec:Popover AR4).
|
|
42
|
+
*/
|
|
43
|
+
isFocusReturnAlways?: boolean;
|
|
37
44
|
}
|
|
38
45
|
|
|
39
46
|
interface SelectorPresentationController {
|
|
@@ -55,6 +62,7 @@ export function useSelectorPresentation({
|
|
|
55
62
|
onShow,
|
|
56
63
|
popoverOptions,
|
|
57
64
|
triggerRef,
|
|
65
|
+
isFocusReturnAlways = false,
|
|
58
66
|
}: UseSelectorPresentationOptions): SelectorPresentationController {
|
|
59
67
|
const resolvedPresentation = useAdaptivePresentation(presentation);
|
|
60
68
|
const activePresentationRef =
|
|
@@ -68,6 +76,9 @@ export function useSelectorPresentation({
|
|
|
68
76
|
const onHideRef = useRef(onHide);
|
|
69
77
|
const onShowRef = useRef(onShow);
|
|
70
78
|
const didShowPopoverRef = useRef(false);
|
|
79
|
+
// The open list's container, read when the popover hides to tell focus that
|
|
80
|
+
// is still inside the list from focus that moved to another element.
|
|
81
|
+
const popoverContentRef = useRef<HTMLDivElement | null>(null);
|
|
71
82
|
const {
|
|
72
83
|
isFocusRingSuppressed,
|
|
73
84
|
onFocusReturnTargetFocus,
|
|
@@ -78,10 +89,26 @@ export function useSelectorPresentation({
|
|
|
78
89
|
onShowRef.current = onShow;
|
|
79
90
|
|
|
80
91
|
const handlePopoverHide = useCallback(() => {
|
|
81
|
-
prepareFocusReturn();
|
|
82
92
|
onHideRef.current();
|
|
83
|
-
triggerRef.current
|
|
84
|
-
|
|
93
|
+
const trigger = triggerRef.current;
|
|
94
|
+
// A light dismiss caused by pressing another focusable element has already
|
|
95
|
+
// moved focus there; taking it back would leave the next key on this
|
|
96
|
+
// closed Selector (spec:Popover AR4 returns focus only when it would
|
|
97
|
+
// otherwise be lost). Escape, a choice in the list, or a press on nothing
|
|
98
|
+
// focusable still returns focus to the trigger.
|
|
99
|
+
const active = document.activeElement;
|
|
100
|
+
const focusLandedElsewhere =
|
|
101
|
+
!isFocusReturnAlways &&
|
|
102
|
+
active instanceof HTMLElement &&
|
|
103
|
+
active !== document.body &&
|
|
104
|
+
active !== trigger &&
|
|
105
|
+
!popoverContentRef.current?.contains(active);
|
|
106
|
+
if (focusLandedElsewhere) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
prepareFocusReturn();
|
|
110
|
+
trigger?.focus();
|
|
111
|
+
}, [isFocusReturnAlways, prepareFocusReturn, triggerRef]);
|
|
85
112
|
const handlePopoverShow = useCallback(() => {
|
|
86
113
|
didShowPopoverRef.current = true;
|
|
87
114
|
resetFocusReturn();
|
|
@@ -92,6 +119,7 @@ export function useSelectorPresentation({
|
|
|
92
119
|
onHide: handlePopoverHide,
|
|
93
120
|
onShow: handlePopoverShow,
|
|
94
121
|
});
|
|
122
|
+
popoverContentRef.current = popover.contentRef.current;
|
|
95
123
|
const {hide: hidePopover, show: showPopover} = popover;
|
|
96
124
|
|
|
97
125
|
const show = useCallback((): boolean => {
|
|
@@ -492,6 +492,33 @@ describe('SideNavHeading', () => {
|
|
|
492
492
|
);
|
|
493
493
|
});
|
|
494
494
|
|
|
495
|
+
it('moves focus one item per arrow key in a NavHeadingMenu (APG menu)', async () => {
|
|
496
|
+
__resetMenuPressForTest();
|
|
497
|
+
const user = userEvent.setup();
|
|
498
|
+
render(
|
|
499
|
+
<SideNavHeading
|
|
500
|
+
heading="My App"
|
|
501
|
+
menu={
|
|
502
|
+
<NavHeadingMenu>
|
|
503
|
+
<NavHeadingMenuItem label="One" onClick={() => {}} />
|
|
504
|
+
<NavHeadingMenuItem label="Two" onClick={() => {}} />
|
|
505
|
+
<NavHeadingMenuItem label="Three" onClick={() => {}} />
|
|
506
|
+
</NavHeadingMenu>
|
|
507
|
+
}
|
|
508
|
+
/>,
|
|
509
|
+
);
|
|
510
|
+
await user.click(screen.getByRole('button', {name: 'Open menu'}));
|
|
511
|
+
const item = (name: string) =>
|
|
512
|
+
screen.getByRole('menuitem', {name, hidden: true});
|
|
513
|
+
item('One').focus();
|
|
514
|
+
fireEvent.keyDown(item('One'), {key: 'ArrowDown'});
|
|
515
|
+
expect(item('Two')).toHaveFocus();
|
|
516
|
+
fireEvent.keyDown(item('Two'), {key: 'ArrowDown'});
|
|
517
|
+
expect(item('Three')).toHaveFocus();
|
|
518
|
+
fireEvent.keyDown(item('Three'), {key: 'ArrowUp'});
|
|
519
|
+
expect(item('Two')).toHaveFocus();
|
|
520
|
+
});
|
|
521
|
+
|
|
495
522
|
it('closes when a mouse pressed on a NavHeadingMenu item is released outside the menu (useMenuPress FR3)', async () => {
|
|
496
523
|
__resetMenuPressForTest();
|
|
497
524
|
const user = userEvent.setup();
|