@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
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file useAnnounce.replace.test.tsx
|
|
5
|
+
* @input Uses vitest, Testing Library, useAnnounce, and an Astryx Dialog and
|
|
6
|
+
* BottomSheet
|
|
7
|
+
* @output Proof of spec:AST-086 FR9 and FR14 for `useAnnounce({hasReplace})`:
|
|
8
|
+
* each message such an instance writes withdraws its previous one while it
|
|
9
|
+
* is not yet exposed, whatever their urgencies, on the shared channel,
|
|
10
|
+
* inside an open modal and in the commit that presents one; messages from
|
|
11
|
+
* other instances, and from instances without `hasReplace`, still join; a
|
|
12
|
+
* share another instance holds stays; an exposed message is left alone, and
|
|
13
|
+
* taking it back later touches no other announcer's words, in a modal's
|
|
14
|
+
* container or held for its close; the instance's hold on its message
|
|
15
|
+
* follows the words when a modal hands them on (it leaves the
|
|
16
|
+
* accessibility tree, exits, closes, or a step is left) or its write frame
|
|
17
|
+
* finds it unexposed; an empty message clears
|
|
18
|
+
* @position Core a11y tests beside the hook
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
act,
|
|
23
|
+
fireEvent,
|
|
24
|
+
render,
|
|
25
|
+
renderHook,
|
|
26
|
+
screen,
|
|
27
|
+
} from '@testing-library/react';
|
|
28
|
+
import {useEffect, useState} from 'react';
|
|
29
|
+
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
|
|
30
|
+
import {BottomSheet} from '../BottomSheet/BottomSheet';
|
|
31
|
+
import {Dialog} from '../Dialog/Dialog';
|
|
32
|
+
import {__resetLiveRegionsForTest, useAnnounce} from './useAnnounce';
|
|
33
|
+
|
|
34
|
+
const shared = (politeness = 'polite') =>
|
|
35
|
+
document.querySelector(`[data-astryx-live-region="${politeness}"]`);
|
|
36
|
+
const regionIn = (dialog: Element, politeness = 'polite') =>
|
|
37
|
+
dialog.querySelector(
|
|
38
|
+
`:scope > [data-astryx-modal-live-region="${politeness}"]`,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
async function nextFrame() {
|
|
42
|
+
await act(
|
|
43
|
+
async () =>
|
|
44
|
+
new Promise<void>(resolve => requestAnimationFrame(() => resolve())),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** jsdom has no showModal(); stand in for a dialog opened modally. */
|
|
49
|
+
function stubDialogs() {
|
|
50
|
+
HTMLDialogElement.prototype.showModal = vi.fn(function (
|
|
51
|
+
this: HTMLDialogElement,
|
|
52
|
+
) {
|
|
53
|
+
this.setAttribute('open', '');
|
|
54
|
+
this.dataset.modal = 'true';
|
|
55
|
+
});
|
|
56
|
+
HTMLDialogElement.prototype.close = vi.fn(function (this: HTMLDialogElement) {
|
|
57
|
+
this.removeAttribute('open');
|
|
58
|
+
delete this.dataset.modal;
|
|
59
|
+
this.dispatchEvent(new Event('close'));
|
|
60
|
+
});
|
|
61
|
+
const matches = Element.prototype.matches;
|
|
62
|
+
vi.spyOn(Element.prototype, 'matches').mockImplementation(function (
|
|
63
|
+
this: Element,
|
|
64
|
+
selector: string,
|
|
65
|
+
) {
|
|
66
|
+
return selector === ':modal'
|
|
67
|
+
? this instanceof HTMLDialogElement &&
|
|
68
|
+
this.open &&
|
|
69
|
+
this.dataset.modal === 'true'
|
|
70
|
+
: matches.call(this, selector);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const REPLACE = {hasReplace: true} as const;
|
|
75
|
+
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
__resetLiveRegionsForTest();
|
|
78
|
+
});
|
|
79
|
+
afterEach(() => {
|
|
80
|
+
vi.restoreAllMocks();
|
|
81
|
+
__resetLiveRegionsForTest();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('useAnnounce({hasReplace}) on the shared channel (spec:AST-086 FR9)', () => {
|
|
85
|
+
it('says only the latest of its messages written in one frame', async () => {
|
|
86
|
+
const {result} = renderHook(() => useAnnounce(REPLACE));
|
|
87
|
+
result.current('1 result');
|
|
88
|
+
result.current('Create "Urg"');
|
|
89
|
+
result.current('Create "Urgent"');
|
|
90
|
+
await nextFrame();
|
|
91
|
+
expect(shared()?.textContent).toBe('Create "Urgent"');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('still joins another instance’s message written in the same frame', async () => {
|
|
95
|
+
const {result} = renderHook(() => ({
|
|
96
|
+
count: useAnnounce(REPLACE),
|
|
97
|
+
other: useAnnounce(),
|
|
98
|
+
}));
|
|
99
|
+
result.current.other('Filter applied');
|
|
100
|
+
result.current.count('3 results');
|
|
101
|
+
result.current.count('2 results');
|
|
102
|
+
await nextFrame();
|
|
103
|
+
expect(shared()?.textContent).toBe('Filter applied 2 results');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('keeps joining the messages of an instance without hasReplace', async () => {
|
|
107
|
+
const {result} = renderHook(() => useAnnounce());
|
|
108
|
+
result.current('Added Design');
|
|
109
|
+
result.current('Removed Eng');
|
|
110
|
+
await nextFrame();
|
|
111
|
+
expect(shared()?.textContent).toBe('Added Design Removed Eng');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('withdraws only its own share of words another instance also wrote', async () => {
|
|
115
|
+
const {result} = renderHook(() => ({
|
|
116
|
+
first: useAnnounce(REPLACE),
|
|
117
|
+
second: useAnnounce(REPLACE),
|
|
118
|
+
}));
|
|
119
|
+
result.current.first('1 result');
|
|
120
|
+
result.current.second('1 result');
|
|
121
|
+
result.current.first('2 results');
|
|
122
|
+
await nextFrame();
|
|
123
|
+
// The second instance still holds "1 result".
|
|
124
|
+
expect(shared()?.textContent).toBe('1 result 2 results');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('leaves a message that was already exposed: the next one starts fresh', async () => {
|
|
128
|
+
const {result} = renderHook(() => useAnnounce(REPLACE));
|
|
129
|
+
result.current('1 result');
|
|
130
|
+
await nextFrame();
|
|
131
|
+
expect(shared()?.textContent).toBe('1 result');
|
|
132
|
+
result.current('2 results');
|
|
133
|
+
await nextFrame();
|
|
134
|
+
expect(shared()?.textContent).toBe('2 results');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('leaves another announcer’s equal words written after its own message was exposed', async () => {
|
|
138
|
+
const {result} = renderHook(() => ({
|
|
139
|
+
count: useAnnounce(REPLACE),
|
|
140
|
+
other: useAnnounce(),
|
|
141
|
+
}));
|
|
142
|
+
result.current.count('1 result');
|
|
143
|
+
await nextFrame();
|
|
144
|
+
result.current.other('1 result');
|
|
145
|
+
result.current.count('2 results');
|
|
146
|
+
await nextFrame();
|
|
147
|
+
expect(shared()?.textContent).toBe('1 result 2 results');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('withdraws its polite message for an assertive one, which is spoken in the assertive region', async () => {
|
|
151
|
+
const {result} = renderHook(() => useAnnounce(REPLACE));
|
|
152
|
+
result.current('3 results');
|
|
153
|
+
result.current('Search failed', 'assertive');
|
|
154
|
+
await nextFrame();
|
|
155
|
+
expect(shared('polite')?.textContent ?? '').toBe('');
|
|
156
|
+
expect(shared('assertive')?.textContent).toBe('Search failed');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('clears the region on an empty message', async () => {
|
|
160
|
+
const {result} = renderHook(() => useAnnounce(REPLACE));
|
|
161
|
+
result.current('1 result');
|
|
162
|
+
await nextFrame();
|
|
163
|
+
result.current('');
|
|
164
|
+
await nextFrame();
|
|
165
|
+
expect(shared()?.textContent ?? '').toBe('');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('useAnnounce({hasReplace}) inside an Astryx modal (spec:AST-086 FR14)', () => {
|
|
170
|
+
beforeEach(() => {
|
|
171
|
+
stubDialogs();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
function Typist({
|
|
175
|
+
messages,
|
|
176
|
+
}: {
|
|
177
|
+
messages: ReadonlyArray<readonly [string, 'polite' | 'assertive']>;
|
|
178
|
+
}) {
|
|
179
|
+
const announce = useAnnounce(REPLACE);
|
|
180
|
+
return (
|
|
181
|
+
<button
|
|
182
|
+
type="button"
|
|
183
|
+
onClick={() => {
|
|
184
|
+
for (const [message, politeness] of messages) {
|
|
185
|
+
announce(message, politeness);
|
|
186
|
+
}
|
|
187
|
+
}}>
|
|
188
|
+
Type
|
|
189
|
+
</button>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
it('withdraws its unexposed message in the modal’s container', async () => {
|
|
194
|
+
render(
|
|
195
|
+
<Dialog isOpen onOpenChange={() => {}} aria-label="Modal">
|
|
196
|
+
<Typist
|
|
197
|
+
messages={[
|
|
198
|
+
['1 result', 'polite'],
|
|
199
|
+
['Create "Urgent"', 'polite'],
|
|
200
|
+
]}
|
|
201
|
+
/>
|
|
202
|
+
</Dialog>,
|
|
203
|
+
);
|
|
204
|
+
const dialog = screen.getByRole('dialog', {name: 'Modal'});
|
|
205
|
+
await nextFrame();
|
|
206
|
+
fireEvent.click(screen.getByRole('button', {name: 'Type'}));
|
|
207
|
+
await nextFrame();
|
|
208
|
+
expect(regionIn(dialog)?.textContent).toBe('Create "Urgent"');
|
|
209
|
+
expect(shared()?.textContent ?? '').toBe('');
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('withdraws across the modal’s two containers', async () => {
|
|
213
|
+
render(
|
|
214
|
+
<Dialog isOpen onOpenChange={() => {}} aria-label="Modal">
|
|
215
|
+
<Typist
|
|
216
|
+
messages={[
|
|
217
|
+
['3 results', 'polite'],
|
|
218
|
+
['Search failed', 'assertive'],
|
|
219
|
+
]}
|
|
220
|
+
/>
|
|
221
|
+
</Dialog>,
|
|
222
|
+
);
|
|
223
|
+
const dialog = screen.getByRole('dialog', {name: 'Modal'});
|
|
224
|
+
await nextFrame();
|
|
225
|
+
fireEvent.click(screen.getByRole('button', {name: 'Type'}));
|
|
226
|
+
await nextFrame();
|
|
227
|
+
expect(regionIn(dialog, 'polite')?.textContent ?? '').toBe('');
|
|
228
|
+
expect(regionIn(dialog, 'assertive')?.textContent).toBe('Search failed');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// A `hasReplace` count and a plain announcer that may say the same words.
|
|
232
|
+
function CountAndOther() {
|
|
233
|
+
const count = useAnnounce(REPLACE);
|
|
234
|
+
const other = useAnnounce();
|
|
235
|
+
return (
|
|
236
|
+
<>
|
|
237
|
+
<button type="button" onClick={() => count('1 result')}>
|
|
238
|
+
Count
|
|
239
|
+
</button>
|
|
240
|
+
<button type="button" onClick={() => count('2 results')}>
|
|
241
|
+
Recount
|
|
242
|
+
</button>
|
|
243
|
+
<button
|
|
244
|
+
type="button"
|
|
245
|
+
onClick={() => {
|
|
246
|
+
other('1 result');
|
|
247
|
+
count('1 result');
|
|
248
|
+
}}>
|
|
249
|
+
Both
|
|
250
|
+
</button>
|
|
251
|
+
<button
|
|
252
|
+
type="button"
|
|
253
|
+
onClick={() => {
|
|
254
|
+
other('1 result');
|
|
255
|
+
count('2 results');
|
|
256
|
+
}}>
|
|
257
|
+
Next
|
|
258
|
+
</button>
|
|
259
|
+
</>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
it('leaves another announcer’s equal words in the container after its own message was exposed', async () => {
|
|
264
|
+
render(
|
|
265
|
+
<Dialog isOpen onOpenChange={() => {}} aria-label="Modal">
|
|
266
|
+
<CountAndOther />
|
|
267
|
+
</Dialog>,
|
|
268
|
+
);
|
|
269
|
+
const dialog = screen.getByRole('dialog', {name: 'Modal'});
|
|
270
|
+
await nextFrame();
|
|
271
|
+
fireEvent.click(screen.getByRole('button', {name: 'Count'}));
|
|
272
|
+
// Written, then taken by assistive technology a frame later.
|
|
273
|
+
await nextFrame();
|
|
274
|
+
await nextFrame();
|
|
275
|
+
expect(regionIn(dialog)?.textContent).toBe('1 result');
|
|
276
|
+
// The plain announcer's "1 result" is not the count's spoken one.
|
|
277
|
+
fireEvent.click(screen.getByRole('button', {name: 'Next'}));
|
|
278
|
+
await nextFrame();
|
|
279
|
+
expect(regionIn(dialog)?.textContent).toBe('1 result 2 results');
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
/** A sheet that runs its exit with the announcers inside it. */
|
|
283
|
+
function ExitingSheet() {
|
|
284
|
+
const [isOpen, setIsOpen] = useState(true);
|
|
285
|
+
return (
|
|
286
|
+
<BottomSheet isOpen={isOpen} onOpenChange={setIsOpen} label="Sheet">
|
|
287
|
+
<CountAndOther />
|
|
288
|
+
<button type="button" onClick={() => setIsOpen(false)}>
|
|
289
|
+
Done
|
|
290
|
+
</button>
|
|
291
|
+
</BottomSheet>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
it('takes back only its own share of words held while its sheet exits', async () => {
|
|
296
|
+
render(<ExitingSheet />);
|
|
297
|
+
const sheet = document.querySelector<HTMLDialogElement>('dialog')!;
|
|
298
|
+
await nextFrame();
|
|
299
|
+
fireEvent.click(screen.getByRole('button', {name: 'Done'}));
|
|
300
|
+
// Open but inert and aria-hidden through its exit: the words are held
|
|
301
|
+
// for the real close (reach the controls by element).
|
|
302
|
+
expect(sheet).toHaveAttribute('inert');
|
|
303
|
+
fireEvent.click(screen.getByText('Both'));
|
|
304
|
+
fireEvent.click(screen.getByText('Next'));
|
|
305
|
+
act(() => {
|
|
306
|
+
sheet.close();
|
|
307
|
+
});
|
|
308
|
+
await nextFrame();
|
|
309
|
+
await nextFrame();
|
|
310
|
+
// The plain announcer still holds "1 result"; the count's was taken back.
|
|
311
|
+
expect(shared()?.textContent).toBe('1 result 2 results');
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('leaves words held later when its own held words were already delivered', async () => {
|
|
315
|
+
render(
|
|
316
|
+
<Dialog isOpen onOpenChange={() => {}} aria-label="Modal">
|
|
317
|
+
<CountAndOther />
|
|
318
|
+
</Dialog>,
|
|
319
|
+
);
|
|
320
|
+
const dialog = screen.getByRole('dialog', {name: 'Modal'});
|
|
321
|
+
await nextFrame();
|
|
322
|
+
// Out of the accessibility tree, as through an exit, and back.
|
|
323
|
+
const setHidden = async (hidden: boolean) => {
|
|
324
|
+
await act(async () => {
|
|
325
|
+
if (hidden) {
|
|
326
|
+
dialog.setAttribute('aria-hidden', 'true');
|
|
327
|
+
} else {
|
|
328
|
+
dialog.removeAttribute('aria-hidden');
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
await setHidden(true);
|
|
333
|
+
fireEvent.click(screen.getByText('Count'));
|
|
334
|
+
// Exposed again: the held words are delivered and spoken.
|
|
335
|
+
await setHidden(false);
|
|
336
|
+
await nextFrame();
|
|
337
|
+
await nextFrame();
|
|
338
|
+
expect(regionIn(dialog)?.textContent).toBe('1 result');
|
|
339
|
+
// Hidden again: the plain announcer's "1 result" is held now, and the
|
|
340
|
+
// count's delivered one is not among the held words.
|
|
341
|
+
await setHidden(true);
|
|
342
|
+
fireEvent.click(screen.getByText('Next'));
|
|
343
|
+
await setHidden(false);
|
|
344
|
+
await nextFrame();
|
|
345
|
+
expect(regionIn(dialog)?.textContent).toBe('1 result 2 results');
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('withdraws its message handed off as its Dialog leaves the accessibility tree, once the Dialog is back', async () => {
|
|
349
|
+
render(
|
|
350
|
+
<Dialog isOpen onOpenChange={() => {}} aria-label="Modal">
|
|
351
|
+
<CountAndOther />
|
|
352
|
+
</Dialog>,
|
|
353
|
+
);
|
|
354
|
+
const dialog = screen.getByRole('dialog', {name: 'Modal'});
|
|
355
|
+
await nextFrame();
|
|
356
|
+
// Written, then the Dialog leaves the tree before the words are exposed:
|
|
357
|
+
// they are handed off, and held while the Dialog still covers the page.
|
|
358
|
+
fireEvent.click(screen.getByRole('button', {name: 'Count'}));
|
|
359
|
+
await act(async () => {
|
|
360
|
+
dialog.setAttribute('aria-hidden', 'true');
|
|
361
|
+
});
|
|
362
|
+
fireEvent.click(screen.getByText('Recount'));
|
|
363
|
+
await act(async () => {
|
|
364
|
+
dialog.removeAttribute('aria-hidden');
|
|
365
|
+
});
|
|
366
|
+
await nextFrame();
|
|
367
|
+
await nextFrame();
|
|
368
|
+
expect(regionIn(dialog)?.textContent).toBe('2 results');
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('withdraws its message handed off as its sheet exits, once the sheet has closed', async () => {
|
|
372
|
+
render(<ExitingSheet />);
|
|
373
|
+
const sheet = document.querySelector<HTMLDialogElement>('dialog')!;
|
|
374
|
+
await nextFrame();
|
|
375
|
+
// Written, and the sheet starts its exit before the words are exposed.
|
|
376
|
+
fireEvent.click(screen.getByRole('button', {name: 'Count'}));
|
|
377
|
+
fireEvent.click(screen.getByRole('button', {name: 'Done'}));
|
|
378
|
+
expect(sheet).toHaveAttribute('inert');
|
|
379
|
+
// The sheet's provider sees the exit and hands the words off.
|
|
380
|
+
await act(async () => {});
|
|
381
|
+
fireEvent.click(screen.getByText('Recount'));
|
|
382
|
+
act(() => {
|
|
383
|
+
sheet.close();
|
|
384
|
+
});
|
|
385
|
+
await nextFrame();
|
|
386
|
+
await nextFrame();
|
|
387
|
+
expect(shared()?.textContent).toBe('2 results');
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('withdraws its message handed to the entering step when its step is left before the words are exposed', async () => {
|
|
391
|
+
function Flow() {
|
|
392
|
+
const [step, setStep] = useState(1);
|
|
393
|
+
return (
|
|
394
|
+
<>
|
|
395
|
+
<Dialog isOpen={step === 1} onOpenChange={() => {}} aria-label="One">
|
|
396
|
+
<CountAndOther />
|
|
397
|
+
<button type="button" onClick={() => setStep(2)}>
|
|
398
|
+
Continue
|
|
399
|
+
</button>
|
|
400
|
+
</Dialog>
|
|
401
|
+
<Dialog isOpen={step === 2} onOpenChange={() => {}} aria-label="Two">
|
|
402
|
+
<span>Step two</span>
|
|
403
|
+
</Dialog>
|
|
404
|
+
</>
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
render(<Flow />);
|
|
408
|
+
await nextFrame();
|
|
409
|
+
// The count is written from step one, which closes in the same update
|
|
410
|
+
// that opens step two, before the words are exposed.
|
|
411
|
+
fireEvent.click(screen.getByRole('button', {name: 'Count'}));
|
|
412
|
+
fireEvent.click(screen.getByRole('button', {name: 'Continue'}));
|
|
413
|
+
// Step one's provider sees the close and hands the words to step two.
|
|
414
|
+
await act(async () => {});
|
|
415
|
+
const two = screen.getByRole('dialog', {name: 'Two'});
|
|
416
|
+
// The count's next message (step one's content stays mounted, closed)
|
|
417
|
+
// takes back its words from step two, and is heard on the page.
|
|
418
|
+
fireEvent.click(screen.getByText('Recount'));
|
|
419
|
+
await nextFrame();
|
|
420
|
+
await nextFrame();
|
|
421
|
+
expect(regionIn(two)?.textContent ?? '').toBe('');
|
|
422
|
+
expect(shared()?.textContent).toBe('2 results');
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
it('withdraws its message handed to the page as its Dialog closes before the words are exposed', async () => {
|
|
426
|
+
function Host() {
|
|
427
|
+
const [isOpen, setIsOpen] = useState(true);
|
|
428
|
+
return (
|
|
429
|
+
<Dialog isOpen={isOpen} onOpenChange={setIsOpen} aria-label="Modal">
|
|
430
|
+
<CountAndOther />
|
|
431
|
+
<button type="button" onClick={() => setIsOpen(false)}>
|
|
432
|
+
Close
|
|
433
|
+
</button>
|
|
434
|
+
</Dialog>
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
render(<Host />);
|
|
438
|
+
await nextFrame();
|
|
439
|
+
fireEvent.click(screen.getByRole('button', {name: 'Count'}));
|
|
440
|
+
fireEvent.click(screen.getByRole('button', {name: 'Close'}));
|
|
441
|
+
// The provider sees the close and hands the words to the page.
|
|
442
|
+
await act(async () => {});
|
|
443
|
+
// The count's next message (the closed Dialog's content stays mounted)
|
|
444
|
+
// takes back its words from the page channel.
|
|
445
|
+
fireEvent.click(screen.getByText('Recount'));
|
|
446
|
+
await nextFrame();
|
|
447
|
+
expect(shared()?.textContent).toBe('2 results');
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it('withdraws its message redirected in the write frame when its Dialog stopped being exposed unseen', async () => {
|
|
451
|
+
render(
|
|
452
|
+
<Dialog isOpen onOpenChange={() => {}} aria-label="Modal">
|
|
453
|
+
<CountAndOther />
|
|
454
|
+
</Dialog>,
|
|
455
|
+
);
|
|
456
|
+
const dialog = screen.getByRole('dialog', {name: 'Modal'});
|
|
457
|
+
await nextFrame();
|
|
458
|
+
const exposed: string[] = [];
|
|
459
|
+
const record = new MutationObserver(() => {
|
|
460
|
+
const text = shared()?.textContent ?? '';
|
|
461
|
+
if (text !== '' && text !== exposed.at(-1)) {
|
|
462
|
+
exposed.push(text);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
record.observe(document.body, {
|
|
466
|
+
subtree: true,
|
|
467
|
+
childList: true,
|
|
468
|
+
characterData: true,
|
|
469
|
+
});
|
|
470
|
+
fireEvent.click(screen.getByRole('button', {name: 'Count'}));
|
|
471
|
+
// No longer a modal, through no attribute its provider watches: the
|
|
472
|
+
// write frame finds it unexposed and sends the words to the page.
|
|
473
|
+
delete dialog.dataset.modal;
|
|
474
|
+
await nextFrame();
|
|
475
|
+
fireEvent.click(screen.getByText('Recount'));
|
|
476
|
+
await nextFrame();
|
|
477
|
+
await nextFrame();
|
|
478
|
+
await nextFrame();
|
|
479
|
+
record.disconnect();
|
|
480
|
+
expect(exposed).toEqual(['2 results']);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it('withdraws a message deferred in the commit that presents the Dialog', async () => {
|
|
484
|
+
function OpeningCount() {
|
|
485
|
+
const announce = useAnnounce(REPLACE);
|
|
486
|
+
useEffect(() => {
|
|
487
|
+
// Both before the Dialog's own Effect has presented it.
|
|
488
|
+
announce('1 result');
|
|
489
|
+
announce('2 results');
|
|
490
|
+
}, [announce]);
|
|
491
|
+
return <span>Results</span>;
|
|
492
|
+
}
|
|
493
|
+
function Host() {
|
|
494
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
495
|
+
return (
|
|
496
|
+
<>
|
|
497
|
+
<button type="button" onClick={() => setIsOpen(true)}>
|
|
498
|
+
Open
|
|
499
|
+
</button>
|
|
500
|
+
{isOpen && (
|
|
501
|
+
<Dialog isOpen onOpenChange={setIsOpen} aria-label="Edit">
|
|
502
|
+
<OpeningCount />
|
|
503
|
+
</Dialog>
|
|
504
|
+
)}
|
|
505
|
+
</>
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
render(<Host />);
|
|
509
|
+
fireEvent.click(screen.getByRole('button', {name: 'Open'}));
|
|
510
|
+
const dialog = screen.getByRole('dialog', {name: 'Edit'});
|
|
511
|
+
await nextFrame();
|
|
512
|
+
await nextFrame();
|
|
513
|
+
expect(regionIn(dialog)?.textContent).toBe('2 results');
|
|
514
|
+
expect(shared()?.textContent ?? '').toBe('');
|
|
515
|
+
});
|
|
516
|
+
});
|