@astryxdesign/core 0.7.5 → 0.7.6-canary.5cd7a15
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/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 +4 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +10 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.js +16 -2
- 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/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/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +5 -2
- 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/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +7 -1
- package/dist/Spinner/Spinner.js +2 -2
- 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/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 +15 -1
- 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/useAdaptivePresentation.d.ts.map +1 -1
- package/dist/hooks/useAdaptivePresentation.js +4 -1
- 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 +3 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +3 -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.js +1 -1
- 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/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/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/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 +15 -3
- package/locales/pseudo.json +9 -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/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 +7 -1
- 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 +53 -0
- package/src/DropdownMenu/lazyMenuBottomSheet.ts +23 -6
- 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/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/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/MultiSelector.spec.md +7 -4
- package/src/MultiSelector/MultiSelector.test.tsx +118 -1
- package/src/MultiSelector/MultiSelector.tsx +6 -2
- 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/Slider/Slider.test.tsx +12 -0
- package/src/Slider/Slider.tsx +4 -1
- package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
- package/src/Spinner/Spinner.tsx +2 -2
- 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/Typeahead/Typeahead.test.tsx +40 -0
- package/src/Typeahead/Typeahead.tsx +12 -1
- 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/useAdaptivePresentation.ts +4 -1
- package/src/hooks/useMenuHover.ts +15 -1
- package/src/i18n/generated-locales/en.generated.ts +4 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +4 -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/defineTheme.ts +1 -1
- 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/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/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/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
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
waitFor,
|
|
31
31
|
within,
|
|
32
32
|
} from '@testing-library/react';
|
|
33
|
-
import React from 'react';
|
|
33
|
+
import React, {useRef} from 'react';
|
|
34
34
|
import {readFileSync} from 'node:fs';
|
|
35
35
|
import {type AnnounceFn, __resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
36
36
|
import {Button} from '../Button';
|
|
@@ -602,6 +602,173 @@ describe('ToastViewport keyboard reach + focus', () => {
|
|
|
602
602
|
expect(document.activeElement).toBe(dismiss);
|
|
603
603
|
});
|
|
604
604
|
|
|
605
|
+
it('moves focus to the neighbour when a control inside a toast raises its repeat and dismisses it', () => {
|
|
606
|
+
function OfflineFlow() {
|
|
607
|
+
const toast = useToast();
|
|
608
|
+
const dismissOfflineRef = useRef<(() => void) | null>(null);
|
|
609
|
+
const showOffline = (body: string) => {
|
|
610
|
+
dismissOfflineRef.current = toast({
|
|
611
|
+
uniqueID: 'offline',
|
|
612
|
+
isAutoHide: false,
|
|
613
|
+
body,
|
|
614
|
+
endContent: (
|
|
615
|
+
<button
|
|
616
|
+
type="button"
|
|
617
|
+
onClick={() => {
|
|
618
|
+
// A retry reports the state again, then closes the toast it
|
|
619
|
+
// was pressed in.
|
|
620
|
+
const dismissPressed = dismissOfflineRef.current;
|
|
621
|
+
showOffline('Still offline');
|
|
622
|
+
dismissPressed?.();
|
|
623
|
+
}}>
|
|
624
|
+
Retry
|
|
625
|
+
</button>
|
|
626
|
+
),
|
|
627
|
+
});
|
|
628
|
+
};
|
|
629
|
+
return (
|
|
630
|
+
<>
|
|
631
|
+
<button
|
|
632
|
+
type="button"
|
|
633
|
+
onClick={() => {
|
|
634
|
+
toast({isAutoHide: false, body: 'Alpha'});
|
|
635
|
+
toast({isAutoHide: false, body: 'Bravo'});
|
|
636
|
+
}}>
|
|
637
|
+
Show two
|
|
638
|
+
</button>
|
|
639
|
+
<button type="button" onClick={() => showOffline('Offline')}>
|
|
640
|
+
Show offline
|
|
641
|
+
</button>
|
|
642
|
+
</>
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
render(
|
|
646
|
+
<ToastViewport isTopLayer={false} maxVisible={2}>
|
|
647
|
+
<OfflineFlow />
|
|
648
|
+
</ToastViewport>,
|
|
649
|
+
);
|
|
650
|
+
act(() => {
|
|
651
|
+
fireEvent.click(screen.getByText('Show two'));
|
|
652
|
+
});
|
|
653
|
+
act(() => {
|
|
654
|
+
fireEvent.click(screen.getByText('Show offline'));
|
|
655
|
+
});
|
|
656
|
+
// Alpha waits hidden; Bravo and Offline show.
|
|
657
|
+
const retry = within(getToastWrapperByText('Offline')).getByRole('button', {
|
|
658
|
+
name: 'Retry',
|
|
659
|
+
});
|
|
660
|
+
retry.focus();
|
|
661
|
+
act(() => {
|
|
662
|
+
fireEvent.click(retry);
|
|
663
|
+
});
|
|
664
|
+
// Toast.spec.md FR10: focus moves to a control in a remaining toast, the
|
|
665
|
+
// neighbour of the dismissed one, not to the hidden oldest toast or the
|
|
666
|
+
// region.
|
|
667
|
+
expect(
|
|
668
|
+
getToastWrapperByText('Bravo').contains(document.activeElement),
|
|
669
|
+
).toBe(true);
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
it('moves focus into the replacement when a control inside the only toast raises its repeat and dismisses it', () => {
|
|
673
|
+
function OfflineFlow() {
|
|
674
|
+
const toast = useToast();
|
|
675
|
+
const dismissOfflineRef = useRef<(() => void) | null>(null);
|
|
676
|
+
const showOffline = (body: string) => {
|
|
677
|
+
dismissOfflineRef.current = toast({
|
|
678
|
+
uniqueID: 'offline',
|
|
679
|
+
isAutoHide: false,
|
|
680
|
+
body,
|
|
681
|
+
endContent: (
|
|
682
|
+
<button
|
|
683
|
+
type="button"
|
|
684
|
+
onClick={() => {
|
|
685
|
+
const dismissPressed = dismissOfflineRef.current;
|
|
686
|
+
showOffline('Still offline');
|
|
687
|
+
dismissPressed?.();
|
|
688
|
+
}}>
|
|
689
|
+
Retry
|
|
690
|
+
</button>
|
|
691
|
+
),
|
|
692
|
+
});
|
|
693
|
+
};
|
|
694
|
+
return (
|
|
695
|
+
<button type="button" onClick={() => showOffline('Offline')}>
|
|
696
|
+
Show offline
|
|
697
|
+
</button>
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
render(
|
|
701
|
+
<ToastViewport isTopLayer={false}>
|
|
702
|
+
<OfflineFlow />
|
|
703
|
+
</ToastViewport>,
|
|
704
|
+
);
|
|
705
|
+
act(() => {
|
|
706
|
+
fireEvent.click(screen.getByText('Show offline'));
|
|
707
|
+
});
|
|
708
|
+
const retry = within(getToastWrapperByText('Offline')).getByRole('button', {
|
|
709
|
+
name: 'Retry',
|
|
710
|
+
});
|
|
711
|
+
retry.focus();
|
|
712
|
+
act(() => {
|
|
713
|
+
fireEvent.click(retry);
|
|
714
|
+
});
|
|
715
|
+
// FR10: the replacement is the remaining toast, so focus goes into it.
|
|
716
|
+
expect(
|
|
717
|
+
getToastWrapperByText('Still offline').contains(document.activeElement),
|
|
718
|
+
).toBe(true);
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
it('moves focus to a toast that shows when a control inside a toast raises two toasts at the cap and dismisses its own', () => {
|
|
722
|
+
function UploadFlow() {
|
|
723
|
+
const toast = useToast();
|
|
724
|
+
const dismissSavedRef = useRef<(() => void) | null>(null);
|
|
725
|
+
return (
|
|
726
|
+
<button
|
|
727
|
+
type="button"
|
|
728
|
+
onClick={() => {
|
|
729
|
+
dismissSavedRef.current = toast({
|
|
730
|
+
isAutoHide: false,
|
|
731
|
+
body: 'Saved',
|
|
732
|
+
endContent: (
|
|
733
|
+
<button
|
|
734
|
+
type="button"
|
|
735
|
+
onClick={() => {
|
|
736
|
+
toast({isAutoHide: false, body: 'Uploading'});
|
|
737
|
+
toast({isAutoHide: false, body: 'Uploaded'});
|
|
738
|
+
dismissSavedRef.current?.();
|
|
739
|
+
}}>
|
|
740
|
+
Upload
|
|
741
|
+
</button>
|
|
742
|
+
),
|
|
743
|
+
});
|
|
744
|
+
}}>
|
|
745
|
+
Save
|
|
746
|
+
</button>
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
render(
|
|
750
|
+
<ToastViewport isTopLayer={false} maxVisible={1}>
|
|
751
|
+
<UploadFlow />
|
|
752
|
+
</ToastViewport>,
|
|
753
|
+
);
|
|
754
|
+
act(() => {
|
|
755
|
+
fireEvent.click(screen.getByText('Save'));
|
|
756
|
+
});
|
|
757
|
+
const upload = within(getToastWrapperByText('Saved')).getByRole('button', {
|
|
758
|
+
name: 'Upload',
|
|
759
|
+
});
|
|
760
|
+
upload.focus();
|
|
761
|
+
act(() => {
|
|
762
|
+
fireEvent.click(upload);
|
|
763
|
+
});
|
|
764
|
+
// FR10: with one visible place, "Uploaded" shows and "Uploading" waits
|
|
765
|
+
// hidden, so focus goes to "Uploaded", not to the hidden toast or the
|
|
766
|
+
// region.
|
|
767
|
+
expect(
|
|
768
|
+
getToastWrapperByText('Uploaded').contains(document.activeElement),
|
|
769
|
+
).toBe(true);
|
|
770
|
+
});
|
|
771
|
+
|
|
605
772
|
it('dismissing a focused toast moves focus to a remaining toast, not body', () => {
|
|
606
773
|
renderViewport(
|
|
607
774
|
<>
|
|
@@ -2061,6 +2228,413 @@ describe('toast announcements via singleton live regions', () => {
|
|
|
2061
2228
|
expect(within(viewport).getByText('Kept')).toBeInTheDocument();
|
|
2062
2229
|
expect(within(viewport).queryByText('Dropped')).not.toBeInTheDocument();
|
|
2063
2230
|
});
|
|
2231
|
+
|
|
2232
|
+
it('drops an ignored-collision toast while its namesake is still leaving', () => {
|
|
2233
|
+
renderViewport(
|
|
2234
|
+
<>
|
|
2235
|
+
<ShowToastButton
|
|
2236
|
+
options={{
|
|
2237
|
+
uniqueID: 'offline',
|
|
2238
|
+
collisionBehavior: 'ignore',
|
|
2239
|
+
isAutoHide: false,
|
|
2240
|
+
body: 'You are offline',
|
|
2241
|
+
}}
|
|
2242
|
+
triggerLabel="Show 1"
|
|
2243
|
+
/>
|
|
2244
|
+
<ShowToastButton
|
|
2245
|
+
options={{
|
|
2246
|
+
uniqueID: 'offline',
|
|
2247
|
+
collisionBehavior: 'ignore',
|
|
2248
|
+
isAutoHide: false,
|
|
2249
|
+
body: 'Still offline',
|
|
2250
|
+
}}
|
|
2251
|
+
triggerLabel="Show 2"
|
|
2252
|
+
/>
|
|
2253
|
+
</>,
|
|
2254
|
+
);
|
|
2255
|
+
act(() => {
|
|
2256
|
+
fireEvent.click(screen.getByText('Show 1'));
|
|
2257
|
+
});
|
|
2258
|
+
const first = getToastWrapperByText('You are offline');
|
|
2259
|
+
act(() => {
|
|
2260
|
+
fireEvent.click(
|
|
2261
|
+
within(first).getByRole('button', {name: 'Dismiss notification'}),
|
|
2262
|
+
);
|
|
2263
|
+
});
|
|
2264
|
+
// Toast.spec.md FR8: a leaving toast still holds its uniqueID, so the
|
|
2265
|
+
// ignored namesake is neither shown nor announced.
|
|
2266
|
+
act(() => {
|
|
2267
|
+
fireEvent.click(screen.getByText('Show 2'));
|
|
2268
|
+
});
|
|
2269
|
+
expect(announceSpy).toHaveBeenCalledTimes(1);
|
|
2270
|
+
expect(screen.queryByText('Still offline')).toBeNull();
|
|
2271
|
+
act(() => {
|
|
2272
|
+
completeExit(first.dataset.toastId ?? '');
|
|
2273
|
+
});
|
|
2274
|
+
expect(document.querySelectorAll('[data-toast-id]')).toHaveLength(0);
|
|
2275
|
+
});
|
|
2276
|
+
|
|
2277
|
+
it('lets a leaving toast finish its exit when a new toast arrives with no cap', () => {
|
|
2278
|
+
render(
|
|
2279
|
+
<ToastViewport isTopLayer={false} maxVisible={0}>
|
|
2280
|
+
<ShowToastButton
|
|
2281
|
+
options={{isAutoHide: false, body: 'Saved'}}
|
|
2282
|
+
triggerLabel="Show 1"
|
|
2283
|
+
/>
|
|
2284
|
+
<ShowToastButton
|
|
2285
|
+
options={{isAutoHide: false, body: 'Uploaded'}}
|
|
2286
|
+
triggerLabel="Show 2"
|
|
2287
|
+
/>
|
|
2288
|
+
</ToastViewport>,
|
|
2289
|
+
);
|
|
2290
|
+
act(() => {
|
|
2291
|
+
fireEvent.click(screen.getByText('Show 1'));
|
|
2292
|
+
});
|
|
2293
|
+
const first = getToastWrapperByText('Saved');
|
|
2294
|
+
const firstId = first.dataset.toastId ?? '';
|
|
2295
|
+
act(() => {
|
|
2296
|
+
fireEvent.click(
|
|
2297
|
+
within(first).getByRole('button', {name: 'Dismiss notification'}),
|
|
2298
|
+
);
|
|
2299
|
+
});
|
|
2300
|
+
// maxVisible={0} shows every toast (Toast.spec.md FR7), so the closing
|
|
2301
|
+
// toast keeps its row and collapses (FR5) while the new one arrives.
|
|
2302
|
+
act(() => {
|
|
2303
|
+
fireEvent.click(screen.getByText('Show 2'));
|
|
2304
|
+
});
|
|
2305
|
+
expect(getToastWrapperByText('Saved').dataset.toastId).toBe(firstId);
|
|
2306
|
+
expect(screen.getByText('Uploaded')).toBeInTheDocument();
|
|
2307
|
+
act(() => {
|
|
2308
|
+
completeExit(firstId);
|
|
2309
|
+
});
|
|
2310
|
+
expect(screen.queryByText('Saved')).toBeNull();
|
|
2311
|
+
expect(screen.getByText('Uploaded')).toBeInTheDocument();
|
|
2312
|
+
});
|
|
2313
|
+
|
|
2314
|
+
it('drops a second ignore toast with the same uniqueID raised in the same handler', () => {
|
|
2315
|
+
function ShowTwoIgnored() {
|
|
2316
|
+
const toast = useToast();
|
|
2317
|
+
return (
|
|
2318
|
+
<button
|
|
2319
|
+
type="button"
|
|
2320
|
+
onClick={() => {
|
|
2321
|
+
toast({
|
|
2322
|
+
uniqueID: 'offline',
|
|
2323
|
+
collisionBehavior: 'ignore',
|
|
2324
|
+
isAutoHide: false,
|
|
2325
|
+
body: 'You are offline',
|
|
2326
|
+
});
|
|
2327
|
+
toast({
|
|
2328
|
+
uniqueID: 'offline',
|
|
2329
|
+
collisionBehavior: 'ignore',
|
|
2330
|
+
isAutoHide: false,
|
|
2331
|
+
body: 'Still offline',
|
|
2332
|
+
});
|
|
2333
|
+
}}>
|
|
2334
|
+
Show twice
|
|
2335
|
+
</button>
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
render(
|
|
2339
|
+
<ToastViewport isTopLayer={false}>
|
|
2340
|
+
<ShowTwoIgnored />
|
|
2341
|
+
</ToastViewport>,
|
|
2342
|
+
);
|
|
2343
|
+
act(() => {
|
|
2344
|
+
fireEvent.click(screen.getByText('Show twice'));
|
|
2345
|
+
});
|
|
2346
|
+
// Toast.spec.md FR8 and ORD1: the ignored namesake is neither shown nor
|
|
2347
|
+
// announced, even before the first toast renders.
|
|
2348
|
+
expect(announceSpy).toHaveBeenCalledTimes(1);
|
|
2349
|
+
expect(announceSpy).toHaveBeenLastCalledWith('You are offline', 'polite');
|
|
2350
|
+
const rows = [...document.querySelectorAll('[data-toast-id]')];
|
|
2351
|
+
expect(rows).toHaveLength(1);
|
|
2352
|
+
expect(rows[0].textContent).toContain('You are offline');
|
|
2353
|
+
});
|
|
2354
|
+
|
|
2355
|
+
it('leaves no row behind when a new toast takes the last visible slot from a leaving one', () => {
|
|
2356
|
+
render(
|
|
2357
|
+
<ToastViewport isTopLayer={false} maxVisible={1}>
|
|
2358
|
+
<ShowToastButton
|
|
2359
|
+
options={{isAutoHide: false, body: 'Saved'}}
|
|
2360
|
+
triggerLabel="Show 1"
|
|
2361
|
+
/>
|
|
2362
|
+
<ShowToastButton
|
|
2363
|
+
options={{isAutoHide: false, body: 'Uploaded'}}
|
|
2364
|
+
triggerLabel="Show 2"
|
|
2365
|
+
/>
|
|
2366
|
+
</ToastViewport>,
|
|
2367
|
+
);
|
|
2368
|
+
act(() => {
|
|
2369
|
+
fireEvent.click(screen.getByText('Show 1'));
|
|
2370
|
+
});
|
|
2371
|
+
const first = getToastWrapperByText('Saved');
|
|
2372
|
+
act(() => {
|
|
2373
|
+
fireEvent.click(
|
|
2374
|
+
within(first).getByRole('button', {name: 'Dismiss notification'}),
|
|
2375
|
+
);
|
|
2376
|
+
});
|
|
2377
|
+
// A new toast arrives at once; with one visible slot it takes the place of
|
|
2378
|
+
// the leaving toast, which can no longer finish its exit on screen.
|
|
2379
|
+
act(() => {
|
|
2380
|
+
fireEvent.click(screen.getByText('Show 2'));
|
|
2381
|
+
});
|
|
2382
|
+
const second = getToastWrapperByText('Uploaded');
|
|
2383
|
+
act(() => {
|
|
2384
|
+
fireEvent.click(
|
|
2385
|
+
within(second).getByRole('button', {name: 'Dismiss notification'}),
|
|
2386
|
+
);
|
|
2387
|
+
});
|
|
2388
|
+
act(() => {
|
|
2389
|
+
completeExit(second.dataset.toastId ?? '');
|
|
2390
|
+
});
|
|
2391
|
+
// Nothing is left: no row comes back, and the landmark is gone.
|
|
2392
|
+
expect(document.querySelectorAll('[data-toast-id]')).toHaveLength(0);
|
|
2393
|
+
expect(screen.queryByRole('region', {name: 'Notifications'})).toBeNull();
|
|
2394
|
+
});
|
|
2395
|
+
|
|
2396
|
+
it('reports the namesake once when one handler shows a repeat and dismisses the namesake', () => {
|
|
2397
|
+
const onHide = vi.fn();
|
|
2398
|
+
function RepeatAndDismiss() {
|
|
2399
|
+
const toast = useToast();
|
|
2400
|
+
const dismissFirstRef = useRef<(() => void) | null>(null);
|
|
2401
|
+
return (
|
|
2402
|
+
<>
|
|
2403
|
+
<button
|
|
2404
|
+
type="button"
|
|
2405
|
+
onClick={() => {
|
|
2406
|
+
dismissFirstRef.current = toast({
|
|
2407
|
+
uniqueID: 'offline',
|
|
2408
|
+
isAutoHide: false,
|
|
2409
|
+
body: 'Offline',
|
|
2410
|
+
onHide,
|
|
2411
|
+
});
|
|
2412
|
+
}}>
|
|
2413
|
+
Show first
|
|
2414
|
+
</button>
|
|
2415
|
+
<button
|
|
2416
|
+
type="button"
|
|
2417
|
+
onClick={() => {
|
|
2418
|
+
toast({
|
|
2419
|
+
uniqueID: 'offline',
|
|
2420
|
+
isAutoHide: false,
|
|
2421
|
+
body: 'Still offline',
|
|
2422
|
+
});
|
|
2423
|
+
dismissFirstRef.current?.();
|
|
2424
|
+
}}>
|
|
2425
|
+
Repeat and dismiss
|
|
2426
|
+
</button>
|
|
2427
|
+
</>
|
|
2428
|
+
);
|
|
2429
|
+
}
|
|
2430
|
+
render(
|
|
2431
|
+
<ToastViewport isTopLayer={false}>
|
|
2432
|
+
<RepeatAndDismiss />
|
|
2433
|
+
</ToastViewport>,
|
|
2434
|
+
);
|
|
2435
|
+
act(() => {
|
|
2436
|
+
fireEvent.click(screen.getByText('Show first'));
|
|
2437
|
+
});
|
|
2438
|
+
act(() => {
|
|
2439
|
+
fireEvent.click(screen.getByText('Repeat and dismiss'));
|
|
2440
|
+
});
|
|
2441
|
+
// As on `main`: the repeat replaces its namesake in place, and the
|
|
2442
|
+
// namesake's dismissal reports it once.
|
|
2443
|
+
expect(onHide).toHaveBeenCalledTimes(1);
|
|
2444
|
+
const rows = [...document.querySelectorAll('[data-toast-id]')];
|
|
2445
|
+
expect(rows).toHaveLength(1);
|
|
2446
|
+
expect(rows[0].textContent).toContain('Still offline');
|
|
2447
|
+
});
|
|
2448
|
+
|
|
2449
|
+
it('leaves no row behind when one handler raises a toast at the cap and dismisses the one it pushed out', () => {
|
|
2450
|
+
const onHide = vi.fn();
|
|
2451
|
+
function UndoFlow() {
|
|
2452
|
+
const toast = useToast();
|
|
2453
|
+
const dismissDeletedRef = useRef<(() => void) | null>(null);
|
|
2454
|
+
return (
|
|
2455
|
+
<>
|
|
2456
|
+
<button
|
|
2457
|
+
type="button"
|
|
2458
|
+
onClick={() => {
|
|
2459
|
+
dismissDeletedRef.current = toast({
|
|
2460
|
+
isAutoHide: false,
|
|
2461
|
+
body: 'Deleted',
|
|
2462
|
+
onHide,
|
|
2463
|
+
});
|
|
2464
|
+
}}>
|
|
2465
|
+
Delete
|
|
2466
|
+
</button>
|
|
2467
|
+
<button
|
|
2468
|
+
type="button"
|
|
2469
|
+
onClick={() => {
|
|
2470
|
+
// An undo shows its confirmation, then dismisses its own toast.
|
|
2471
|
+
toast({isAutoHide: false, body: 'Restored'});
|
|
2472
|
+
dismissDeletedRef.current?.();
|
|
2473
|
+
}}>
|
|
2474
|
+
Undo
|
|
2475
|
+
</button>
|
|
2476
|
+
</>
|
|
2477
|
+
);
|
|
2478
|
+
}
|
|
2479
|
+
render(
|
|
2480
|
+
<ToastViewport isTopLayer={false} maxVisible={1}>
|
|
2481
|
+
<UndoFlow />
|
|
2482
|
+
</ToastViewport>,
|
|
2483
|
+
);
|
|
2484
|
+
act(() => {
|
|
2485
|
+
fireEvent.click(screen.getByText('Delete'));
|
|
2486
|
+
});
|
|
2487
|
+
act(() => {
|
|
2488
|
+
fireEvent.click(screen.getByText('Undo'));
|
|
2489
|
+
});
|
|
2490
|
+
expect(onHide).toHaveBeenCalledTimes(1);
|
|
2491
|
+
const restored = getToastWrapperByText('Restored');
|
|
2492
|
+
act(() => {
|
|
2493
|
+
fireEvent.click(
|
|
2494
|
+
within(restored).getByRole('button', {name: 'Dismiss notification'}),
|
|
2495
|
+
);
|
|
2496
|
+
});
|
|
2497
|
+
act(() => {
|
|
2498
|
+
completeExit(restored.dataset.toastId ?? '');
|
|
2499
|
+
});
|
|
2500
|
+
// Nothing is left: no row comes back, and the landmark is gone.
|
|
2501
|
+
expect(document.querySelectorAll('[data-toast-id]')).toHaveLength(0);
|
|
2502
|
+
expect(screen.queryByRole('region', {name: 'Notifications'})).toBeNull();
|
|
2503
|
+
});
|
|
2504
|
+
|
|
2505
|
+
it('reports a leaving toast once when it is dismissed again after a new toast pushed it out of view', () => {
|
|
2506
|
+
const onHide = vi.fn();
|
|
2507
|
+
function ShowPushDismiss() {
|
|
2508
|
+
const toast = useToast();
|
|
2509
|
+
const dismissFirstRef = useRef<(() => void) | null>(null);
|
|
2510
|
+
return (
|
|
2511
|
+
<>
|
|
2512
|
+
<button
|
|
2513
|
+
type="button"
|
|
2514
|
+
onClick={() => {
|
|
2515
|
+
dismissFirstRef.current = toast({
|
|
2516
|
+
isAutoHide: false,
|
|
2517
|
+
body: 'Saved',
|
|
2518
|
+
onHide,
|
|
2519
|
+
});
|
|
2520
|
+
}}>
|
|
2521
|
+
Show first
|
|
2522
|
+
</button>
|
|
2523
|
+
<button
|
|
2524
|
+
type="button"
|
|
2525
|
+
onClick={() => {
|
|
2526
|
+
toast({isAutoHide: false, body: 'Uploaded'});
|
|
2527
|
+
}}>
|
|
2528
|
+
Show second
|
|
2529
|
+
</button>
|
|
2530
|
+
<button type="button" onClick={() => dismissFirstRef.current?.()}>
|
|
2531
|
+
Dismiss first
|
|
2532
|
+
</button>
|
|
2533
|
+
</>
|
|
2534
|
+
);
|
|
2535
|
+
}
|
|
2536
|
+
render(
|
|
2537
|
+
<ToastViewport isTopLayer={false} maxVisible={1}>
|
|
2538
|
+
<ShowPushDismiss />
|
|
2539
|
+
</ToastViewport>,
|
|
2540
|
+
);
|
|
2541
|
+
act(() => {
|
|
2542
|
+
fireEvent.click(screen.getByText('Show first'));
|
|
2543
|
+
});
|
|
2544
|
+
// It starts leaving, and reports it.
|
|
2545
|
+
act(() => {
|
|
2546
|
+
fireEvent.click(screen.getByText('Dismiss first'));
|
|
2547
|
+
});
|
|
2548
|
+
expect(onHide).toHaveBeenCalledTimes(1);
|
|
2549
|
+
// A new toast takes the only visible slot: the leaving one leaves the list.
|
|
2550
|
+
act(() => {
|
|
2551
|
+
fireEvent.click(screen.getByText('Show second'));
|
|
2552
|
+
});
|
|
2553
|
+
// Its dismissal again reports nothing more.
|
|
2554
|
+
act(() => {
|
|
2555
|
+
fireEvent.click(screen.getByText('Dismiss first'));
|
|
2556
|
+
});
|
|
2557
|
+
expect(onHide).toHaveBeenCalledTimes(1);
|
|
2558
|
+
const rows = [...document.querySelectorAll('[data-toast-id]')];
|
|
2559
|
+
expect(rows).toHaveLength(1);
|
|
2560
|
+
expect(rows[0].textContent).toContain('Uploaded');
|
|
2561
|
+
});
|
|
2562
|
+
|
|
2563
|
+
it('reports nothing for a toast replaced before it rendered, however often one handler dismisses it', () => {
|
|
2564
|
+
const onHide = vi.fn();
|
|
2565
|
+
function ShowReplaceDismiss() {
|
|
2566
|
+
const toast = useToast();
|
|
2567
|
+
return (
|
|
2568
|
+
<button
|
|
2569
|
+
type="button"
|
|
2570
|
+
onClick={() => {
|
|
2571
|
+
const dismissFirst = toast({
|
|
2572
|
+
uniqueID: 'offline',
|
|
2573
|
+
isAutoHide: false,
|
|
2574
|
+
body: 'Offline',
|
|
2575
|
+
onHide,
|
|
2576
|
+
});
|
|
2577
|
+
toast({
|
|
2578
|
+
uniqueID: 'offline',
|
|
2579
|
+
isAutoHide: false,
|
|
2580
|
+
body: 'Still offline',
|
|
2581
|
+
});
|
|
2582
|
+
dismissFirst();
|
|
2583
|
+
dismissFirst();
|
|
2584
|
+
}}>
|
|
2585
|
+
Show, replace and dismiss
|
|
2586
|
+
</button>
|
|
2587
|
+
);
|
|
2588
|
+
}
|
|
2589
|
+
render(
|
|
2590
|
+
<ToastViewport isTopLayer={false}>
|
|
2591
|
+
<ShowReplaceDismiss />
|
|
2592
|
+
</ToastViewport>,
|
|
2593
|
+
);
|
|
2594
|
+
act(() => {
|
|
2595
|
+
fireEvent.click(screen.getByText('Show, replace and dismiss'));
|
|
2596
|
+
});
|
|
2597
|
+
// Toast.spec.md FR3: a toast replaced through uniqueID is not dismissed
|
|
2598
|
+
// and reports no onHide.
|
|
2599
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
2600
|
+
const rows = [...document.querySelectorAll('[data-toast-id]')];
|
|
2601
|
+
expect(rows).toHaveLength(1);
|
|
2602
|
+
expect(rows[0].textContent).toContain('Still offline');
|
|
2603
|
+
});
|
|
2604
|
+
|
|
2605
|
+
it('replaces a leaving namesake in place under overwrite and announces it again', () => {
|
|
2606
|
+
renderViewport(
|
|
2607
|
+
<>
|
|
2608
|
+
<ShowToastButton
|
|
2609
|
+
options={{uniqueID: 'upload', isAutoHide: false, body: 'Upload 30%'}}
|
|
2610
|
+
triggerLabel="Show 1"
|
|
2611
|
+
/>
|
|
2612
|
+
<ShowToastButton
|
|
2613
|
+
options={{uniqueID: 'upload', isAutoHide: false, body: 'Upload 31%'}}
|
|
2614
|
+
triggerLabel="Show 2"
|
|
2615
|
+
/>
|
|
2616
|
+
</>,
|
|
2617
|
+
);
|
|
2618
|
+
act(() => {
|
|
2619
|
+
fireEvent.click(screen.getByText('Show 1'));
|
|
2620
|
+
});
|
|
2621
|
+
const first = getToastWrapperByText('Upload 30%');
|
|
2622
|
+
act(() => {
|
|
2623
|
+
fireEvent.click(
|
|
2624
|
+
within(first).getByRole('button', {name: 'Dismiss notification'}),
|
|
2625
|
+
);
|
|
2626
|
+
});
|
|
2627
|
+
// Toast.spec.md FR8: an overwrite replaces its namesake in place even
|
|
2628
|
+
// while it is leaving, and is announced again.
|
|
2629
|
+
act(() => {
|
|
2630
|
+
fireEvent.click(screen.getByText('Show 2'));
|
|
2631
|
+
});
|
|
2632
|
+
expect(announceSpy).toHaveBeenLastCalledWith('Upload 31%', 'polite');
|
|
2633
|
+
expect(screen.queryByText('Upload 30%')).toBeNull();
|
|
2634
|
+
const rows = [...document.querySelectorAll('[data-toast-id]')];
|
|
2635
|
+
expect(rows).toHaveLength(1);
|
|
2636
|
+
expect(rows[0].textContent).toContain('Upload 31%');
|
|
2637
|
+
});
|
|
2064
2638
|
});
|
|
2065
2639
|
|
|
2066
2640
|
describe('toast timer lifecycle (#3589)', () => {
|
|
@@ -2084,6 +2658,150 @@ describe('toast timer lifecycle (#3589)', () => {
|
|
|
2084
2658
|
expect(onHide).toHaveBeenCalledTimes(1);
|
|
2085
2659
|
});
|
|
2086
2660
|
|
|
2661
|
+
// spec:Toast FR2/AR3: each pause condition is held on its own, so one
|
|
2662
|
+
// ending never resumes the timer while another still holds.
|
|
2663
|
+
function showPausableToast(onHide: () => void) {
|
|
2664
|
+
renderViewport(
|
|
2665
|
+
<ShowToastButton
|
|
2666
|
+
options={{
|
|
2667
|
+
body: 'Held',
|
|
2668
|
+
autoHideDuration: 3000,
|
|
2669
|
+
endContent: <Button label="Undo" />,
|
|
2670
|
+
onHide,
|
|
2671
|
+
}}
|
|
2672
|
+
triggerLabel="Show held"
|
|
2673
|
+
/>,
|
|
2674
|
+
);
|
|
2675
|
+
act(() => {
|
|
2676
|
+
fireEvent.click(screen.getByText('Show held'));
|
|
2677
|
+
});
|
|
2678
|
+
const viewport = screen.getByRole('region', {name: 'Notifications'});
|
|
2679
|
+
const card = within(viewport).getByText('Held').closest('[role="status"]');
|
|
2680
|
+
if (!(card instanceof HTMLElement)) {
|
|
2681
|
+
throw new Error('toast card not found');
|
|
2682
|
+
}
|
|
2683
|
+
return {card, action: within(card).getByRole('button', {name: 'Undo'})};
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
it('keeps the timer paused while focus is inside after the pointer leaves', () => {
|
|
2687
|
+
vi.useFakeTimers();
|
|
2688
|
+
try {
|
|
2689
|
+
const onHide = vi.fn();
|
|
2690
|
+
const {card, action} = showPausableToast(onHide);
|
|
2691
|
+
act(() => {
|
|
2692
|
+
fireEvent.mouseEnter(card);
|
|
2693
|
+
});
|
|
2694
|
+
act(() => {
|
|
2695
|
+
action.focus();
|
|
2696
|
+
});
|
|
2697
|
+
act(() => {
|
|
2698
|
+
fireEvent.mouseLeave(card);
|
|
2699
|
+
});
|
|
2700
|
+
act(() => {
|
|
2701
|
+
vi.advanceTimersByTime(60_000);
|
|
2702
|
+
});
|
|
2703
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
2704
|
+
// Focus leaving the card releases the last hold.
|
|
2705
|
+
act(() => {
|
|
2706
|
+
action.blur();
|
|
2707
|
+
});
|
|
2708
|
+
act(() => {
|
|
2709
|
+
vi.advanceTimersByTime(60_000);
|
|
2710
|
+
});
|
|
2711
|
+
expect(onHide).toHaveBeenCalledWith('auto');
|
|
2712
|
+
} finally {
|
|
2713
|
+
vi.useRealTimers();
|
|
2714
|
+
}
|
|
2715
|
+
});
|
|
2716
|
+
|
|
2717
|
+
it('keeps the timer paused while the pointer is over it after the window regains focus', () => {
|
|
2718
|
+
vi.useFakeTimers();
|
|
2719
|
+
try {
|
|
2720
|
+
const onHide = vi.fn();
|
|
2721
|
+
const {card} = showPausableToast(onHide);
|
|
2722
|
+
act(() => {
|
|
2723
|
+
fireEvent.blur(window);
|
|
2724
|
+
});
|
|
2725
|
+
act(() => {
|
|
2726
|
+
fireEvent.mouseEnter(card);
|
|
2727
|
+
});
|
|
2728
|
+
act(() => {
|
|
2729
|
+
fireEvent.focus(window);
|
|
2730
|
+
});
|
|
2731
|
+
act(() => {
|
|
2732
|
+
vi.advanceTimersByTime(60_000);
|
|
2733
|
+
});
|
|
2734
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
2735
|
+
act(() => {
|
|
2736
|
+
fireEvent.mouseLeave(card);
|
|
2737
|
+
});
|
|
2738
|
+
act(() => {
|
|
2739
|
+
vi.advanceTimersByTime(60_000);
|
|
2740
|
+
});
|
|
2741
|
+
expect(onHide).toHaveBeenCalledWith('auto');
|
|
2742
|
+
} finally {
|
|
2743
|
+
vi.useRealTimers();
|
|
2744
|
+
}
|
|
2745
|
+
});
|
|
2746
|
+
|
|
2747
|
+
it('releases the focus hold when the focused control is removed', () => {
|
|
2748
|
+
vi.useFakeTimers();
|
|
2749
|
+
try {
|
|
2750
|
+
const onHide = vi.fn();
|
|
2751
|
+
const {card, action} = showPausableToast(onHide);
|
|
2752
|
+
act(() => {
|
|
2753
|
+
fireEvent.mouseEnter(card);
|
|
2754
|
+
});
|
|
2755
|
+
act(() => {
|
|
2756
|
+
action.focus();
|
|
2757
|
+
});
|
|
2758
|
+
// A control that unmounts while focused fires no blur.
|
|
2759
|
+
act(() => {
|
|
2760
|
+
action.remove();
|
|
2761
|
+
});
|
|
2762
|
+
act(() => {
|
|
2763
|
+
fireEvent.mouseLeave(card);
|
|
2764
|
+
});
|
|
2765
|
+
act(() => {
|
|
2766
|
+
vi.advanceTimersByTime(60_000);
|
|
2767
|
+
});
|
|
2768
|
+
expect(onHide).toHaveBeenCalledWith('auto');
|
|
2769
|
+
} finally {
|
|
2770
|
+
vi.useRealTimers();
|
|
2771
|
+
}
|
|
2772
|
+
});
|
|
2773
|
+
|
|
2774
|
+
it('keeps the timer paused while focus moves between controls inside the card', () => {
|
|
2775
|
+
vi.useFakeTimers();
|
|
2776
|
+
try {
|
|
2777
|
+
const onHide = vi.fn();
|
|
2778
|
+
const {card, action} = showPausableToast(onHide);
|
|
2779
|
+
const dismiss = within(card)
|
|
2780
|
+
.getAllByRole('button')
|
|
2781
|
+
.find(button => button !== action);
|
|
2782
|
+
if (!dismiss) {
|
|
2783
|
+
throw new Error('dismiss button not found');
|
|
2784
|
+
}
|
|
2785
|
+
act(() => {
|
|
2786
|
+
action.focus();
|
|
2787
|
+
});
|
|
2788
|
+
act(() => {
|
|
2789
|
+
vi.advanceTimersByTime(2_000);
|
|
2790
|
+
});
|
|
2791
|
+
act(() => {
|
|
2792
|
+
dismiss.focus();
|
|
2793
|
+
});
|
|
2794
|
+
// Moving between the card's own controls neither restarts nor resumes
|
|
2795
|
+
// the timer.
|
|
2796
|
+
act(() => {
|
|
2797
|
+
vi.advanceTimersByTime(60_000);
|
|
2798
|
+
});
|
|
2799
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
2800
|
+
} finally {
|
|
2801
|
+
vi.useRealTimers();
|
|
2802
|
+
}
|
|
2803
|
+
});
|
|
2804
|
+
|
|
2087
2805
|
it('keeps a window-blur pause alive when another toast arrives', () => {
|
|
2088
2806
|
vi.useFakeTimers();
|
|
2089
2807
|
try {
|