@astryxdesign/core 0.7.5 → 0.7.6-canary.0d71e8d
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/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +183 -5
- package/dist/AppShell/observeMainOverflow.d.ts +9 -0
- package/dist/AppShell/observeMainOverflow.d.ts.map +1 -0
- package/dist/AppShell/observeMainOverflow.js +125 -0
- 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/Carousel/Carousel.d.ts +3 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +12 -3
- 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/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +41 -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/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +11 -7
- package/dist/DateInput/usePointerDragScroll.d.ts +10 -1
- package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -1
- package/dist/DateInput/usePointerDragScroll.js +25 -9
- package/dist/DateInput/useScrollSettle.d.ts +3 -1
- package/dist/DateInput/useScrollSettle.d.ts.map +1 -1
- package/dist/DateInput/useScrollSettle.js +37 -8
- 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 +35 -22
- 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.d.ts +3 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +3 -2
- package/dist/FileInput/FileInput.d.ts +3 -0
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +34 -13
- 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 +21 -7
- 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 +120 -65
- 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/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +8 -3
- package/dist/List/List.js +1 -1
- package/dist/List/ListItem.js +3 -3
- package/dist/Markdown/plugins/headingLinks.a11y.chromium.spec.js +1 -1
- 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/NavMenu/NavHeadingMenuItem.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenuItem.js +5 -29
- package/dist/NumberInput/NumberInput.d.ts +3 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +26 -5
- 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/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +27 -0
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +32 -12
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +10 -3
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +37 -30
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +16 -12
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +11 -3
- 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/SideNav/SideNavItem.d.ts +2 -2
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +18 -7
- 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/Stepper/Step.d.ts.map +1 -1
- package/dist/Stepper/Step.js +26 -6
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +10 -3
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +16 -1
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +36 -10
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +46 -58
- 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 +101 -54
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +7 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +16 -2
- package/dist/Token/Token.d.ts +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +52 -5
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +14 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +44 -7
- package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
- package/dist/Tokenizer/TokenizerClearAllMessageContext.d.ts +2 -0
- package/dist/Tokenizer/TokenizerClearAllMessageContext.d.ts.map +1 -0
- package/dist/Tokenizer/TokenizerClearAllMessageContext.js +17 -0
- 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/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +27 -4
- package/dist/Typeahead/BaseTypeahead.d.ts +4 -4
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +43 -7
- package/dist/Typeahead/Typeahead.d.ts +1 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +43 -9
- package/dist/astryx.css +25 -4
- package/dist/gestures/GestureArena.d.ts +32 -1
- package/dist/gestures/GestureArena.d.ts.map +1 -1
- package/dist/gestures/GestureArena.js +110 -9
- package/dist/gestures/GestureHost.d.ts +351 -0
- package/dist/gestures/GestureHost.d.ts.map +1 -0
- package/dist/gestures/GestureHost.js +1773 -0
- package/dist/gestures/GestureRecognizer.d.ts +13 -1
- package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/GestureRecognizer.js +19 -1
- 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/PressTracker.d.ts +112 -0
- package/dist/gestures/PressTracker.d.ts.map +1 -0
- package/dist/gestures/PressTracker.js +267 -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/index.d.ts +37 -0
- package/dist/gestures/index.d.ts.map +1 -0
- package/dist/gestures/index.js +25 -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/gestures/useGestureRecognizer.d.ts +56 -0
- package/dist/gestures/useGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/useGestureRecognizer.js +226 -0
- 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/scrollKeyboardDelegation.d.ts.map +1 -1
- package/dist/hooks/scrollKeyboardDelegation.js +7 -3
- 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/hooks/useScrollOverflow.d.ts +2 -1
- package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
- package/dist/hooks/useScrollOverflow.js +56 -10
- package/dist/i18n/generated-locales/af-ZA.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/af-ZA.generated.js +0 -5
- package/dist/i18n/generated-locales/ar-SA.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/ar-SA.generated.js +0 -5
- package/dist/i18n/generated-locales/ca-ES.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/ca-ES.generated.js +0 -5
- package/dist/i18n/generated-locales/cs-CZ.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/cs-CZ.generated.js +0 -5
- package/dist/i18n/generated-locales/da-DK.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/da-DK.generated.js +0 -5
- package/dist/i18n/generated-locales/de-DE.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/de-DE.generated.js +0 -5
- package/dist/i18n/generated-locales/el-GR.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/el-GR.generated.js +0 -5
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +8 -5
- package/dist/i18n/generated-locales/es-ES.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/es-ES.generated.js +0 -5
- package/dist/i18n/generated-locales/fi-FI.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/fi-FI.generated.js +0 -5
- package/dist/i18n/generated-locales/fr-FR.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/fr-FR.generated.js +0 -5
- package/dist/i18n/generated-locales/he-IL.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/he-IL.generated.js +0 -5
- package/dist/i18n/generated-locales/hu-HU.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/hu-HU.generated.js +0 -5
- package/dist/i18n/generated-locales/it-IT.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/it-IT.generated.js +0 -5
- package/dist/i18n/generated-locales/ja-JP.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/ja-JP.generated.js +0 -5
- package/dist/i18n/generated-locales/ko-KR.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/ko-KR.generated.js +0 -5
- package/dist/i18n/generated-locales/nl-NL.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/nl-NL.generated.js +0 -5
- package/dist/i18n/generated-locales/no-NO.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/no-NO.generated.js +0 -5
- package/dist/i18n/generated-locales/pl-PL.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pl-PL.generated.js +0 -5
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +8 -5
- package/dist/i18n/generated-locales/pt-BR.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pt-BR.generated.js +0 -5
- package/dist/i18n/generated-locales/pt-PT.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pt-PT.generated.js +0 -5
- package/dist/i18n/generated-locales/ro-RO.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/ro-RO.generated.js +0 -5
- package/dist/i18n/generated-locales/ru-RU.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/ru-RU.generated.js +0 -5
- package/dist/i18n/generated-locales/sr-SP.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/sr-SP.generated.js +0 -5
- package/dist/i18n/generated-locales/sv-SE.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/sv-SE.generated.js +0 -5
- package/dist/i18n/generated-locales/tr-TR.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/tr-TR.generated.js +0 -5
- package/dist/i18n/generated-locales/uk-UA.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/uk-UA.generated.js +0 -5
- package/dist/i18n/generated-locales/vi-VN.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/vi-VN.generated.js +0 -5
- package/dist/i18n/generated-locales/zh-CN.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/zh-CN.generated.js +0 -5
- package/dist/i18n/generated-locales/zh-TW.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/zh-TW.generated.js +0 -5
- package/dist/i18n/useListFormatter.d.ts +9 -0
- package/dist/i18n/useListFormatter.d.ts.map +1 -0
- package/dist/i18n/useListFormatter.js +41 -0
- package/dist/motion/animator.d.ts +83 -8
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +701 -119
- package/dist/motion/coast.d.ts +4 -1
- package/dist/motion/coast.d.ts.map +1 -1
- package/dist/motion/coast.js +4 -2
- package/dist/motion/reducedMotion.d.ts.map +1 -1
- package/dist/motion/reducedMotion.js +6 -2
- package/dist/motion/reducedMotionPlan.d.ts +7 -0
- package/dist/motion/reducedMotionPlan.d.ts.map +1 -1
- package/dist/motion/reducedMotionPlan.js +14 -1
- package/dist/motion/resolveMotion.d.ts +42 -0
- package/dist/motion/resolveMotion.d.ts.map +1 -0
- package/dist/motion/resolveMotion.js +43 -0
- package/dist/motion/roleValue.d.ts +2 -1
- package/dist/motion/roleValue.d.ts.map +1 -1
- package/dist/motion/roleValue.js +2 -1
- package/dist/motion/uikit/timing.d.ts +7 -1
- package/dist/motion/uikit/timing.d.ts.map +1 -1
- package/dist/motion/uikit/timing.js +19 -1
- 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/focusOutline.stylex.d.ts +6 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
- package/dist/utils/focusOutline.stylex.js +7 -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/sharedMutationObserver.d.ts +19 -11
- package/dist/utils/sharedMutationObserver.d.ts.map +1 -1
- package/dist/utils/sharedMutationObserver.js +66 -26
- 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 +2 -2
- package/dist/utils/touchPresentation.d.ts.map +1 -1
- package/dist/utils/touchPresentation.js +13 -8
- 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/touchQueries.d.ts +13 -0
- package/dist/utils/touchQueries.d.ts.map +1 -0
- package/dist/utils/touchQueries.js +15 -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/dist/utils/useFocusAcrossSwap.d.ts +19 -0
- package/dist/utils/useFocusAcrossSwap.d.ts.map +1 -0
- package/dist/utils/useFocusAcrossSwap.js +41 -0
- package/locales/af-ZA.json +0 -21
- package/locales/ar-SA.json +0 -21
- package/locales/ca-ES.json +0 -21
- package/locales/cs-CZ.json +0 -21
- package/locales/da-DK.json +0 -21
- package/locales/de-DE.json +0 -21
- package/locales/el-GR.json +0 -21
- package/locales/en.json +35 -23
- package/locales/es-ES.json +0 -21
- package/locales/fi-FI.json +0 -21
- package/locales/fr-FR.json +0 -21
- package/locales/he-IL.json +0 -21
- package/locales/hu-HU.json +0 -21
- package/locales/it-IT.json +0 -21
- package/locales/ja-JP.json +0 -21
- package/locales/ko-KR.json +0 -21
- package/locales/nl-NL.json +0 -21
- package/locales/no-NO.json +0 -21
- package/locales/pl-PL.json +0 -21
- package/locales/pseudo.json +23 -14
- package/locales/pt-BR.json +0 -21
- package/locales/pt-PT.json +0 -21
- package/locales/ro-RO.json +0 -21
- package/locales/ru-RU.json +0 -21
- package/locales/sr-SP.json +0 -21
- package/locales/sv-SE.json +0 -21
- package/locales/tr-TR.json +0 -21
- package/locales/uk-UA.json +0 -21
- package/locales/vi-VN.json +0 -21
- package/locales/zh-CN.json +0 -21
- package/locales/zh-TW.json +0 -21
- 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/AppShell/AppShell.doc.mjs +1 -1
- package/src/AppShell/AppShell.spec.md +9 -12
- package/src/AppShell/AppShell.test.tsx +164 -2
- package/src/AppShell/AppShell.tsx +225 -5
- package/src/AppShell/__tests__/AppShellMainKeyboard.a11y.browser.spec.ts +534 -0
- package/src/AppShell/observeMainOverflow.test.ts +173 -0
- package/src/AppShell/observeMainOverflow.ts +143 -0
- 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/Carousel.doc.mjs +1 -1
- package/src/Carousel/Carousel.spec.md +9 -9
- package/src/Carousel/Carousel.test.tsx +124 -3
- package/src/Carousel/Carousel.tsx +10 -2
- package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
- package/src/Carousel/__tests__/Carousel.a11y.known-failures.ts +1 -16
- package/src/Chat/ChatComposer.spec.md +75 -59
- package/src/Chat/ChatComposerTokenElement.spec.md +45 -33
- package/src/Chat/ChatDictationButton.spec.md +126 -81
- package/src/Chat/ChatLayout.spec.md +41 -36
- package/src/Chat/ChatLayoutScrollButton.spec.md +87 -103
- package/src/Chat/ChatMessage.spec.md +64 -65
- package/src/Chat/ChatSendButton.spec.md +78 -67
- package/src/CheckboxInput/CheckboxInput.tsx +6 -5
- package/src/Citation/Citation.spec.md +60 -47
- package/src/ClickableCard/ClickableCard.test.tsx +96 -0
- package/src/ClickableCard/ClickableCard.tsx +48 -4
- package/src/CodeBlock/__tests__/CodeBlockCopyClearance.a11y.chromium.spec.ts +38 -3
- 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 +148 -0
- package/src/ComplexSelector/ComplexSelector.tsx +41 -4
- package/src/ContextMenu/ContextMenu.spec.md +84 -56
- package/src/ContextMenu/ContextMenu.test.tsx +35 -0
- package/src/ContextMenu/ContextMenuItem.spec.md +132 -0
- package/src/DateInput/DateInput.spec.md +74 -57
- package/src/DateInput/DateInput.test.tsx +115 -3
- package/src/DateInput/DateInput.tsx +29 -14
- package/src/DateInput/DateInputTouch.test.tsx +120 -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/Wheel.tsx +9 -6
- package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
- package/src/DateInput/usePointerDragScroll.ts +34 -10
- package/src/DateInput/useScrollSettle.ts +38 -7
- 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.spec.md +198 -218
- package/src/DropdownMenu/DropdownMenu.test.tsx +158 -0
- package/src/DropdownMenu/DropdownMenu.tsx +43 -21
- package/src/DropdownMenu/DropdownMenuCheckboxItem.spec.md +192 -0
- package/src/DropdownMenu/DropdownMenuDivider.spec.md +25 -31
- package/src/DropdownMenu/DropdownMenuGroup.spec.md +145 -0
- package/src/DropdownMenu/DropdownMenuItem.spec.md +48 -42
- package/src/DropdownMenu/DropdownMenuRadioGroup.spec.md +34 -37
- package/src/DropdownMenu/DropdownMenuRadioItem.spec.md +54 -53
- package/src/DropdownMenu/DropdownMenuSubMenu.spec.md +47 -41
- 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.spec.md +35 -29
- 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 +9 -2
- package/src/FieldStatus/__tests__/FieldStatusAudit.a11y.chromium.spec.ts +477 -0
- package/src/FileInput/FileInput.test.tsx +159 -0
- package/src/FileInput/FileInput.tsx +34 -6
- package/src/FileInput/__tests__/FileInputAudit.a11y.chromium.spec.ts +796 -0
- package/src/FormLayout/FormLayout.spec.md +11 -20
- 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.test.tsx +60 -0
- package/src/Item/Item.tsx +16 -8
- 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 +426 -4
- package/src/Layer/useLayer.tsx +145 -77
- 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/Link.spec.md +3 -2
- package/src/Link/Link.tsx +11 -0
- package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
- package/src/Link/__tests__/Link.truncation.a11y.chromium.spec.ts +58 -0
- package/src/List/List.tsx +1 -1
- package/src/List/ListItem.spec.md +205 -0
- package/src/List/ListItem.tsx +3 -3
- package/src/Markdown/plugins/headingLinks.a11y.chromium.spec.ts +1 -1
- 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/NavMenu/NavHeadingMenuItem.tsx +5 -39
- package/src/NumberInput/NumberInput.doc.mjs +13 -7
- package/src/NumberInput/NumberInput.spec.md +59 -37
- package/src/NumberInput/NumberInput.test.tsx +68 -7
- package/src/NumberInput/NumberInput.tsx +44 -4
- package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
- package/src/NumberInput/numberParser.ts +7 -45
- package/src/Outline/Outline.spec.md +165 -69
- package/src/Outline/Outline.test.tsx +67 -2
- package/src/Outline/Outline.tsx +23 -0
- package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +3 -4
- package/src/OverflowList/OverflowList.spec.md +102 -55
- package/src/Pagination/Pagination.spec.md +158 -84
- package/src/Popover/Popover.test.tsx +84 -0
- package/src/Popover/Popover.tsx +34 -14
- package/src/Popover/__tests__/PopoverSecondDocument.a11y.chromium.spec.ts +70 -8
- package/src/Popover/usePopover.tsx +10 -3
- package/src/PowerSearch/PowerSearch.test.tsx +24 -0
- package/src/PowerSearch/PowerSearch.tsx +42 -31
- package/src/ProgressBar/ProgressBar.spec.md +143 -119
- 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/RadioList/RadioList.spec.md +1 -1
- package/src/RadioList/RadioList.test.tsx +84 -0
- package/src/RadioList/RadioListItem.tsx +11 -2
- package/src/Resizable/Resizable.spec.md +144 -124
- 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 +151 -4
- package/src/SideNav/SideNavItem.spec.md +14 -24
- package/src/SideNav/SideNavItem.tsx +27 -10
- 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/Stepper/Step.spec.md +36 -42
- package/src/Stepper/Step.tsx +33 -6
- package/src/Stepper/Stepper.doc.mjs +1 -1
- package/src/Stepper/Stepper.test.tsx +69 -7
- package/src/Switch/Switch.spec.md +1 -1
- package/src/Switch/Switch.test.tsx +66 -1
- package/src/Switch/Switch.tsx +11 -3
- 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/Table.spec.md +1 -1
- package/src/Table/Table.test.tsx +32 -0
- package/src/Table/Table.tsx +43 -11
- package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
- package/src/Table/__tests__/Table.a11y.states.ts +1 -5
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +73 -144
- package/src/Table/plugins/sortable/useTableSortable.tsx +44 -73
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +9 -21
- 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 +58 -61
- 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 +15 -24
- package/src/Toast/Toast.tsx +104 -36
- package/src/Toast/ToastViewport.test.tsx +798 -1
- package/src/Toast/ToastViewport.tsx +121 -53
- package/src/ToggleButton/ToggleButton.test.tsx +27 -0
- package/src/ToggleButton/ToggleButtonGroup.tsx +20 -1
- package/src/Token/Token.doc.mjs +2 -2
- package/src/Token/Token.spec.md +52 -61
- package/src/Token/Token.test.tsx +104 -0
- package/src/Token/Token.tsx +75 -5
- package/src/Token/TokenLink.tsx +21 -7
- package/src/Tokenizer/Tokenizer.spec.md +18 -4
- package/src/Tokenizer/Tokenizer.test.tsx +176 -0
- package/src/Tokenizer/Tokenizer.tsx +48 -12
- package/src/Tokenizer/TokenizerBottomSheet.test.tsx +23 -4
- package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
- package/src/Tokenizer/TokenizerClearAllMessageContext.ts +21 -0
- 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/TreeList/TreeList.test.tsx +26 -0
- package/src/TreeList/TreeListItem.tsx +26 -4
- package/src/Typeahead/BaseTypeahead.doc.mjs +3 -3
- package/src/Typeahead/BaseTypeahead.spec.md +45 -45
- package/src/Typeahead/BaseTypeahead.tsx +48 -9
- package/src/Typeahead/Typeahead.test.tsx +294 -11
- package/src/Typeahead/Typeahead.tsx +51 -9
- package/src/__tests__/internalModulesNotExperimental.test.ts +88 -0
- package/src/__tests__/pressState.ts +8 -4
- package/src/gestures/GestureArena.ts +111 -11
- package/src/gestures/GestureHost.ts +2064 -0
- package/src/gestures/GestureRecognizer.ts +21 -1
- package/src/gestures/LongPressGestureRecognizer.ts +4 -0
- package/src/gestures/PanGestureRecognizer.ts +4 -0
- package/src/gestures/PinchGestureRecognizer.ts +148 -0
- package/src/gestures/PressTracker.ts +386 -0
- package/src/gestures/README.md +420 -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 +2136 -0
- package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
- package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
- package/src/gestures/__tests__/PressTracker.test.ts +275 -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 +40 -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 +52 -4
- package/src/gestures/__tests__/pressTrackerFactory.test.ts +59 -0
- package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
- package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
- package/src/gestures/__tests__/useGestureRecognizer.test.tsx +570 -0
- package/src/gestures/haptics.ts +203 -0
- package/src/gestures/index.ts +79 -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/gestures/useGestureRecognizer.ts +305 -0
- package/src/hooks/index.ts +5 -1
- package/src/hooks/modalAnnounce.ts +129 -72
- package/src/hooks/scrollKeyboardDelegation.test.ts +33 -0
- package/src/hooks/scrollKeyboardDelegation.ts +9 -3
- 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/hooks/useScrollOverflow.doc.mjs +1 -1
- package/src/hooks/useScrollOverflow.test.tsx +102 -1
- package/src/hooks/useScrollOverflow.ts +59 -10
- package/src/i18n/__tests__/useListFormatter.test.tsx +58 -0
- package/src/i18n/generated-locales/af-ZA.generated.ts +0 -7
- package/src/i18n/generated-locales/ar-SA.generated.ts +0 -6
- package/src/i18n/generated-locales/ca-ES.generated.ts +0 -7
- package/src/i18n/generated-locales/cs-CZ.generated.ts +0 -6
- package/src/i18n/generated-locales/da-DK.generated.ts +0 -6
- package/src/i18n/generated-locales/de-DE.generated.ts +0 -6
- package/src/i18n/generated-locales/el-GR.generated.ts +0 -7
- package/src/i18n/generated-locales/en.generated.ts +9 -6
- package/src/i18n/generated-locales/es-ES.generated.ts +0 -7
- package/src/i18n/generated-locales/fi-FI.generated.ts +0 -6
- package/src/i18n/generated-locales/fr-FR.generated.ts +0 -7
- package/src/i18n/generated-locales/he-IL.generated.ts +0 -6
- package/src/i18n/generated-locales/hu-HU.generated.ts +0 -6
- package/src/i18n/generated-locales/it-IT.generated.ts +0 -7
- package/src/i18n/generated-locales/ja-JP.generated.ts +0 -6
- package/src/i18n/generated-locales/ko-KR.generated.ts +0 -6
- package/src/i18n/generated-locales/nl-NL.generated.ts +0 -6
- package/src/i18n/generated-locales/no-NO.generated.ts +0 -6
- package/src/i18n/generated-locales/pl-PL.generated.ts +0 -7
- package/src/i18n/generated-locales/pseudo.generated.ts +9 -6
- package/src/i18n/generated-locales/pt-BR.generated.ts +0 -7
- package/src/i18n/generated-locales/pt-PT.generated.ts +0 -7
- package/src/i18n/generated-locales/ro-RO.generated.ts +0 -6
- package/src/i18n/generated-locales/ru-RU.generated.ts +0 -7
- package/src/i18n/generated-locales/sr-SP.generated.ts +0 -6
- package/src/i18n/generated-locales/sv-SE.generated.ts +0 -6
- package/src/i18n/generated-locales/tr-TR.generated.ts +0 -7
- package/src/i18n/generated-locales/uk-UA.generated.ts +0 -7
- package/src/i18n/generated-locales/vi-VN.generated.ts +0 -6
- package/src/i18n/generated-locales/zh-CN.generated.ts +0 -6
- package/src/i18n/generated-locales/zh-TW.generated.ts +0 -6
- package/src/i18n/useListFormatter.ts +42 -0
- package/src/motion/MEASUREMENTS.md +2 -1
- package/src/motion/README.md +113 -33
- package/src/motion/__tests__/animator.interaction.browser.spec.ts +843 -0
- package/src/motion/__tests__/motionBundle.ts +14 -0
- package/src/motion/animator.test.ts +1125 -32
- package/src/motion/animator.ts +932 -130
- package/src/motion/coast.ts +10 -3
- package/src/motion/reducedMotion.ts +12 -2
- package/src/motion/reducedMotionPlan.test.ts +26 -0
- package/src/motion/reducedMotionPlan.ts +20 -1
- package/src/motion/resolveMotion.test.ts +123 -0
- package/src/motion/resolveMotion.ts +68 -0
- package/src/motion/roleValue.ts +2 -1
- package/src/motion/roles.test.ts +21 -4
- package/src/motion/uikit/tableImports.test.ts +293 -0
- package/src/motion/uikit/timing.ts +15 -1
- package/src/motion/uikit/values.test.ts +23 -12
- 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/focusOutline.stylex.ts +28 -0
- 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/pressGesture.test.ts +9 -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/sharedMutationObserver.test.ts +54 -1
- package/src/utils/sharedMutationObserver.ts +87 -29
- 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 +13 -8
- package/src/utils/touchQueries.ts +15 -0
- package/src/utils/unicodeDigits.test.ts +44 -0
- package/src/utils/unicodeDigits.ts +71 -0
- package/src/utils/useFocusAcrossSwap.ts +55 -0
|
@@ -0,0 +1,843 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file animator.interaction.browser.spec.ts
|
|
5
|
+
* @input The motion source (animator, springs, spring math) bundled with
|
|
6
|
+
* esbuild onto a blank fixture page; the interaction harness's screencast,
|
|
7
|
+
* busy-main-thread and trace instruments; Chromium and WebKit on the phone
|
|
8
|
+
* profile
|
|
9
|
+
* @output Proof that the animator's motion runs on the compositor
|
|
10
|
+
* (`spec:AST-094` FR5): a spring keeps advancing every frame through a 1 s
|
|
11
|
+
* main-thread block, on its analytic curve; a spring that ends inside the
|
|
12
|
+
* block keeps its end state; no Layout or Paint runs while it animates
|
|
13
|
+
* (Chromium trace); the engine plays the analytic curve when seeked; a
|
|
14
|
+
* finished animation leaves within a frame or two of the curve's end; a
|
|
15
|
+
* fade-in on an element its stylesheet hides stays visible once it retires;
|
|
16
|
+
* a dialog's ::backdrop follows the curve and holds its end state; a frame
|
|
17
|
+
* painted before the compositor has a curve shows the element where it is;
|
|
18
|
+
* a role variable set on a scope changes nothing, as the per-role tables
|
|
19
|
+
* stay internal (DEC-15)
|
|
20
|
+
* @position Browser proof for animator.ts, run by `pnpm test:interaction`;
|
|
21
|
+
* jsdom runs no animations
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import {fileURLToPath} from 'node:url';
|
|
25
|
+
import {
|
|
26
|
+
blockMainThread,
|
|
27
|
+
busyWindowProof,
|
|
28
|
+
countBetween,
|
|
29
|
+
markElement,
|
|
30
|
+
startScreencast,
|
|
31
|
+
traceRendering,
|
|
32
|
+
trackMarker,
|
|
33
|
+
} from '@astryxdesign/interaction-harness';
|
|
34
|
+
import {expect, test, type Page} from '@playwright/test';
|
|
35
|
+
import {build} from 'esbuild';
|
|
36
|
+
import type {Animator, MotionHandle} from '../animator';
|
|
37
|
+
import type * as MotionBundle from './motionBundle';
|
|
38
|
+
|
|
39
|
+
let script = '';
|
|
40
|
+
|
|
41
|
+
test.beforeAll(async () => {
|
|
42
|
+
const result = await build({
|
|
43
|
+
entryPoints: [fileURLToPath(new URL('./motionBundle.ts', import.meta.url))],
|
|
44
|
+
bundle: true,
|
|
45
|
+
write: false,
|
|
46
|
+
format: 'iife',
|
|
47
|
+
globalName: 'Motion',
|
|
48
|
+
target: 'es2022',
|
|
49
|
+
});
|
|
50
|
+
script = result.outputFiles[0].text;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A slow, critically damped spring: over 1 px per frame through the whole
|
|
55
|
+
* block, so every frame inside it has to move.
|
|
56
|
+
*/
|
|
57
|
+
const SLOW = {response: 2, dampingRatio: 1};
|
|
58
|
+
/** Settles about 450 ms into the block. */
|
|
59
|
+
const FAST = {response: 0.25, dampingRatio: 1};
|
|
60
|
+
const TRAVEL = 300;
|
|
61
|
+
/** One frame at 60 Hz, in ms. */
|
|
62
|
+
const FRAME_MS = 1000 / 60;
|
|
63
|
+
/** The marker chip sits this far inside the box\u2019s top-left corner. */
|
|
64
|
+
const MARKER_INSET = 8;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Waits for the held-dip call to end: on the call's own `finished`, then on
|
|
68
|
+
* the browser's own animations still running or waiting for their first
|
|
69
|
+
* frame, never on a count of frames. The dip lands on a timer due on the
|
|
70
|
+
* call's clock, which a loaded page runs whenever it can, so a frame window
|
|
71
|
+
* can close before the landing. Reads no animator value: a call would look
|
|
72
|
+
* for the start again.
|
|
73
|
+
*/
|
|
74
|
+
async function dipDone(page: Page) {
|
|
75
|
+
await page.evaluate(async () => {
|
|
76
|
+
await (window as unknown as {dip: MotionHandle}).dip.finished;
|
|
77
|
+
const box = document.getElementById('box') as HTMLElement;
|
|
78
|
+
await Promise.all(
|
|
79
|
+
box
|
|
80
|
+
.getAnimations()
|
|
81
|
+
.filter(
|
|
82
|
+
animation => animation.pending || animation.playState === 'running',
|
|
83
|
+
)
|
|
84
|
+
.map(async animation =>
|
|
85
|
+
animation.finished.catch((error: unknown) => {
|
|
86
|
+
// A retired animation's cancel rejects its finished with an
|
|
87
|
+
// AbortError; any other rejection is a real failure.
|
|
88
|
+
if (!(
|
|
89
|
+
error instanceof DOMException && error.name === 'AbortError'
|
|
90
|
+
)) {
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}),
|
|
94
|
+
),
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// A real navigation (not setContent): the page keeps its own window.
|
|
100
|
+
async function open(page: Page) {
|
|
101
|
+
const html = `<!doctype html><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
102
|
+
<style>
|
|
103
|
+
html, body { margin: 0; background: #fff; }
|
|
104
|
+
#box { position: absolute; top: 40px; left: 0; width: 48px; height: 48px; background: #36c; }
|
|
105
|
+
</style>
|
|
106
|
+
<div id="box"></div>
|
|
107
|
+
<script>${script}</script>
|
|
108
|
+
<script>window.animator = Motion.createAnimator(document.getElementById('box'));</script>`;
|
|
109
|
+
await page.route('http://motion.test/', async route =>
|
|
110
|
+
route.fulfill({contentType: 'text/html', body: html}),
|
|
111
|
+
);
|
|
112
|
+
await page.goto('http://motion.test/');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Starts a spring of TRAVEL px on x, blocks the main thread for 1 s mid-flight
|
|
117
|
+
* and returns the screencast frames with the run\u2019s clock (epoch ms).
|
|
118
|
+
*/
|
|
119
|
+
async function blockedRun(
|
|
120
|
+
page: Page,
|
|
121
|
+
spring: {response: number; dampingRatio: number},
|
|
122
|
+
) {
|
|
123
|
+
await open(page);
|
|
124
|
+
const box = page.locator('#box');
|
|
125
|
+
await markElement(box, {inset: MARKER_INSET});
|
|
126
|
+
const cast = await startScreencast(page);
|
|
127
|
+
// The curve starts when the browser commits it (handle.started).
|
|
128
|
+
const start = await page.evaluate(
|
|
129
|
+
async ({spring: s, travel}) => {
|
|
130
|
+
const handle = window.animator.animate({x: travel}, {spring: s});
|
|
131
|
+
return performance.timeOrigin + (await handle.started);
|
|
132
|
+
},
|
|
133
|
+
{spring, travel: TRAVEL},
|
|
134
|
+
);
|
|
135
|
+
// The page blocks itself in the frame that sees the curve 40 ms in, however
|
|
136
|
+
// loaded the machine is.
|
|
137
|
+
const busy = await blockMainThread(page, 1000, {
|
|
138
|
+
during: box,
|
|
139
|
+
minProgressMs: 40,
|
|
140
|
+
});
|
|
141
|
+
await page.waitForTimeout(200);
|
|
142
|
+
const tracked = await trackMarker(page, await cast.stop());
|
|
143
|
+
return {start, busy, tracked};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
test('a spring keeps advancing every frame through a 1 s main-thread block, on its curve', async ({
|
|
147
|
+
page,
|
|
148
|
+
browserName,
|
|
149
|
+
}) => {
|
|
150
|
+
const {start, busy, tracked} = await blockedRun(page, SLOW);
|
|
151
|
+
const proof = busyWindowProof(tracked, busy, {axis: 'x', settledWithin: 2});
|
|
152
|
+
test
|
|
153
|
+
.info()
|
|
154
|
+
.annotations.push({type: 'busy window', description: proof.summary});
|
|
155
|
+
expect(busy.to - busy.from).toBeGreaterThanOrEqual(1000);
|
|
156
|
+
// The harness's verdict: no stall over two dropped frames, and nearly
|
|
157
|
+
// every expected frame moved (what a loaded runner still meets and a
|
|
158
|
+
// main-thread animation never does). It sets no display-rate bound.
|
|
159
|
+
expect(proof.verdict.failures, proof.summary).toEqual([]);
|
|
160
|
+
expect(proof.monotonic).toBe(true);
|
|
161
|
+
// And it is the spring: placing each frame inside the block on the
|
|
162
|
+
// analytic curve (inverting it at the frame's position) gives the same time
|
|
163
|
+
// offset for every frame. Chromium stamps frames on the page's clock, so its
|
|
164
|
+
// offset is also near zero; WebKit's screencast clock is rebased, so only
|
|
165
|
+
// the spread is judged there.
|
|
166
|
+
const inside = tracked.filter(
|
|
167
|
+
f => f.box != null && f.t > busy.from + 20 && f.t < busy.to - 20,
|
|
168
|
+
);
|
|
169
|
+
expect(inside.length).toBeGreaterThan(30);
|
|
170
|
+
const offsets = await page.evaluate(
|
|
171
|
+
({spring, travel, frames}) => {
|
|
172
|
+
const solved = Motion.solveSpring(Motion.toSpring(spring), {
|
|
173
|
+
from: 0,
|
|
174
|
+
to: travel,
|
|
175
|
+
});
|
|
176
|
+
return frames.map(({t, x}) => {
|
|
177
|
+
let lo = 0;
|
|
178
|
+
let hi = 3;
|
|
179
|
+
for (let i = 0; i < 60; i++) {
|
|
180
|
+
const mid = (lo + hi) / 2;
|
|
181
|
+
if (solved.value(mid) < x) {
|
|
182
|
+
lo = mid;
|
|
183
|
+
} else {
|
|
184
|
+
hi = mid;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return t - lo * 1000;
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
spring: SLOW,
|
|
192
|
+
travel: TRAVEL,
|
|
193
|
+
frames: inside.map(f => ({
|
|
194
|
+
t: f.t - start,
|
|
195
|
+
x: (f.box?.x ?? NaN) - MARKER_INSET,
|
|
196
|
+
})),
|
|
197
|
+
},
|
|
198
|
+
);
|
|
199
|
+
const sorted = [...offsets].sort((x, y) => x - y);
|
|
200
|
+
const median = sorted[Math.floor(sorted.length / 2)];
|
|
201
|
+
const spread =
|
|
202
|
+
sorted[Math.floor(sorted.length * 0.9)] -
|
|
203
|
+
sorted[Math.floor(sorted.length * 0.1)];
|
|
204
|
+
test.info().annotations.push({
|
|
205
|
+
type: 'time offset of the frames on the curve',
|
|
206
|
+
description: JSON.stringify({median, spread}),
|
|
207
|
+
});
|
|
208
|
+
expect(spread).toBeLessThan(25);
|
|
209
|
+
if (browserName === 'chromium') {
|
|
210
|
+
expect(Math.abs(median)).toBeLessThan(20);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test('a spring that ends inside the block keeps showing its end state', async ({
|
|
215
|
+
page,
|
|
216
|
+
}) => {
|
|
217
|
+
const {busy, tracked} = await blockedRun(page, FAST);
|
|
218
|
+
// Frames from the block's start on, through the frames after it: a screen
|
|
219
|
+
// that holds still sends no frames, so a fallback to an older value would
|
|
220
|
+
// show up as a new frame.
|
|
221
|
+
const after = tracked.filter(f => f.box != null && f.t > busy.from + 20);
|
|
222
|
+
const xs = after.map(f => (f.box?.x ?? NaN) - MARKER_INSET);
|
|
223
|
+
test.info().annotations.push({
|
|
224
|
+
type: 'positions from the block on',
|
|
225
|
+
description: xs.map(x => Math.round(x)).join(' '),
|
|
226
|
+
});
|
|
227
|
+
const landed = xs.findIndex(x => x >= TRAVEL - 1);
|
|
228
|
+
expect(landed).toBeGreaterThanOrEqual(0);
|
|
229
|
+
// WebKit's compositor falls back to the main thread's last committed value
|
|
230
|
+
// when an animation ends during a block; the keyframes' hold of the end
|
|
231
|
+
// state past the curve keeps the end on screen until script runs again.
|
|
232
|
+
for (const x of xs.slice(landed)) {
|
|
233
|
+
expect(x).toBeGreaterThanOrEqual(TRAVEL - 1);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
test('a frame painted before the compositor has the curve shows the element where it is', async ({
|
|
238
|
+
page,
|
|
239
|
+
}) => {
|
|
240
|
+
await open(page);
|
|
241
|
+
// What a frame shows without the curve is the element's own style: drop the
|
|
242
|
+
// curves right after they are created and read it. A present from rest,
|
|
243
|
+
// then a retarget mid-flight.
|
|
244
|
+
const result = await page.evaluate(
|
|
245
|
+
async ({travel}) => {
|
|
246
|
+
const fresh = (now?: () => number) => {
|
|
247
|
+
const element = document.createElement('div');
|
|
248
|
+
element.style.cssText =
|
|
249
|
+
'position:absolute;top:120px;left:0;width:48px;height:48px;background:#c63';
|
|
250
|
+
document.body.append(element);
|
|
251
|
+
return {
|
|
252
|
+
element,
|
|
253
|
+
animator: Motion.createAnimator(element, now ? {now} : {}),
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
const x = (element: HTMLElement) =>
|
|
257
|
+
Number.parseFloat(getComputedStyle(element).translate.split(' ')[0]) ||
|
|
258
|
+
0;
|
|
259
|
+
const present = fresh();
|
|
260
|
+
present.animator.animate({x: travel}, {spring: Motion.springs.settle});
|
|
261
|
+
for (const animation of present.element.getAnimations()) {
|
|
262
|
+
animation.cancel();
|
|
263
|
+
}
|
|
264
|
+
const presentX = x(present.element);
|
|
265
|
+
|
|
266
|
+
// One instant for the read and the retarget: 150 ms into the settle the
|
|
267
|
+
// curve moves about a pixel a millisecond, so two clock reads would
|
|
268
|
+
// differ by however long a busy page took between them.
|
|
269
|
+
let frozen: number | null = null;
|
|
270
|
+
const retarget = fresh(() => frozen ?? performance.now());
|
|
271
|
+
await retarget.animator.animate(
|
|
272
|
+
{x: travel},
|
|
273
|
+
{spring: Motion.springs.settle},
|
|
274
|
+
).started;
|
|
275
|
+
await new Promise(resolve => setTimeout(resolve, 150));
|
|
276
|
+
frozen = performance.now();
|
|
277
|
+
const onScreen = retarget.animator.get('x');
|
|
278
|
+
retarget.animator.animate({x: 0}, {spring: Motion.springs.settle});
|
|
279
|
+
frozen = null;
|
|
280
|
+
for (const animation of retarget.element.getAnimations()) {
|
|
281
|
+
animation.cancel();
|
|
282
|
+
}
|
|
283
|
+
return {presentX, onScreen, retargetX: x(retarget.element)};
|
|
284
|
+
},
|
|
285
|
+
{travel: TRAVEL},
|
|
286
|
+
);
|
|
287
|
+
test.info().annotations.push({
|
|
288
|
+
type: 'without the curve',
|
|
289
|
+
description: JSON.stringify(result),
|
|
290
|
+
});
|
|
291
|
+
expect(result.presentX).toBeCloseTo(0, 1);
|
|
292
|
+
expect(result.onScreen).toBeGreaterThan(20);
|
|
293
|
+
// The inline value is written to a thousandth of a pixel.
|
|
294
|
+
expect(result.retargetX).toBeCloseTo(result.onScreen, 2);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test('under Reduce Motion, a dip a busy main thread lands late still ends within its 200 ms cross-fade', async ({
|
|
298
|
+
page,
|
|
299
|
+
}) => {
|
|
300
|
+
// design:reduced-motion DR2 on a touch screen: the move dips (fades out,
|
|
301
|
+
// lands while transparent, fades back in) in 200 ms or less, opacity only.
|
|
302
|
+
await page.emulateMedia({reducedMotion: 'reduce'});
|
|
303
|
+
await open(page);
|
|
304
|
+
const read = await page.evaluate(async travel => {
|
|
305
|
+
const box = document.getElementById('box') as HTMLElement;
|
|
306
|
+
const handle = window.animator.animate(
|
|
307
|
+
{x: travel},
|
|
308
|
+
{spring: Motion.springs.navigationPush},
|
|
309
|
+
);
|
|
310
|
+
const start = await handle.started;
|
|
311
|
+
// What the dip animates, read while it runs.
|
|
312
|
+
const animated = box
|
|
313
|
+
.getAnimations()
|
|
314
|
+
.flatMap(animation =>
|
|
315
|
+
(animation.effect as KeyframeEffect)
|
|
316
|
+
.getKeyframes()
|
|
317
|
+
.flatMap(frame =>
|
|
318
|
+
Object.keys(frame).filter(
|
|
319
|
+
key =>
|
|
320
|
+
!['offset', 'easing', 'composite', 'computedOffset'].includes(
|
|
321
|
+
key,
|
|
322
|
+
),
|
|
323
|
+
),
|
|
324
|
+
),
|
|
325
|
+
);
|
|
326
|
+
// The main thread is busy from 60 to 180 ms into the dip, so the task
|
|
327
|
+
// that lands it (due at 100 ms) runs 80 ms late.
|
|
328
|
+
await new Promise(resolve =>
|
|
329
|
+
setTimeout(resolve, Math.max(0, start + 60 - performance.now())),
|
|
330
|
+
);
|
|
331
|
+
while (performance.now() < start + 180) {
|
|
332
|
+
// the main thread is busy
|
|
333
|
+
}
|
|
334
|
+
await new Promise(resolve =>
|
|
335
|
+
setTimeout(resolve, Math.max(0, start + 230 - performance.now())),
|
|
336
|
+
);
|
|
337
|
+
const style = getComputedStyle(box);
|
|
338
|
+
return {
|
|
339
|
+
at: performance.now() - start,
|
|
340
|
+
opacity: Number(style.opacity),
|
|
341
|
+
translate: style.translate,
|
|
342
|
+
animated,
|
|
343
|
+
};
|
|
344
|
+
}, TRAVEL);
|
|
345
|
+
test.info().annotations.push({
|
|
346
|
+
type: '30 ms after the cross-fade was due to end',
|
|
347
|
+
description: JSON.stringify(read),
|
|
348
|
+
});
|
|
349
|
+
// Landed, and fully back in by then: the late landing did not stretch it.
|
|
350
|
+
expect(read.translate).toBe(`${TRAVEL}px`);
|
|
351
|
+
expect(read.opacity).toBeCloseTo(1, 2);
|
|
352
|
+
// Opacity only, read while the dip ran: the travel is never animated.
|
|
353
|
+
expect(read.animated).toContain('opacity');
|
|
354
|
+
expect(read.animated.every(key => key === 'opacity')).toBe(true);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test('under Reduce Motion, a dip held before its first frame lands once the hold is finished', async ({
|
|
358
|
+
page,
|
|
359
|
+
}) => {
|
|
360
|
+
// A sampler can pause a call's animations before the browser starts them
|
|
361
|
+
// (the interaction harness's hold landing ahead of the call's first frame
|
|
362
|
+
// under load, or a page pausing every animation). Its release with finish
|
|
363
|
+
// ends the held fade out; with no animator call after it, the dip still
|
|
364
|
+
// lands and fades back in.
|
|
365
|
+
await page.emulateMedia({reducedMotion: 'reduce'});
|
|
366
|
+
await open(page);
|
|
367
|
+
await page.evaluate(travel => {
|
|
368
|
+
(window as unknown as {dip: MotionHandle}).dip = window.animator.animate(
|
|
369
|
+
{x: travel},
|
|
370
|
+
{spring: Motion.springs.navigationPush},
|
|
371
|
+
);
|
|
372
|
+
// In the call's own task, ahead of its first frame.
|
|
373
|
+
const held = document.getAnimations();
|
|
374
|
+
for (const animation of held) {
|
|
375
|
+
animation.pause();
|
|
376
|
+
}
|
|
377
|
+
(window as unknown as {held: Animation[]}).held = held;
|
|
378
|
+
}, TRAVEL);
|
|
379
|
+
await page.evaluate(
|
|
380
|
+
async () =>
|
|
381
|
+
new Promise<void>(resolve =>
|
|
382
|
+
requestAnimationFrame(() =>
|
|
383
|
+
requestAnimationFrame(() => setTimeout(resolve, 40)),
|
|
384
|
+
),
|
|
385
|
+
),
|
|
386
|
+
);
|
|
387
|
+
await page.evaluate(() => {
|
|
388
|
+
for (const animation of (window as unknown as {held: Animation[]}).held) {
|
|
389
|
+
animation.finish();
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
// Read from the page only: an animator call would look for the start again.
|
|
393
|
+
const read = async () =>
|
|
394
|
+
page.evaluate(() => {
|
|
395
|
+
const box = document.getElementById('box') as HTMLElement;
|
|
396
|
+
const style = getComputedStyle(box);
|
|
397
|
+
return {opacity: Number(style.opacity), translate: style.translate};
|
|
398
|
+
});
|
|
399
|
+
await dipDone(page);
|
|
400
|
+
expect(await read()).toEqual({opacity: 1, translate: `${TRAVEL}px`});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test('under Reduce Motion, a dip held before its first frame lands once the hold is resumed', async ({
|
|
404
|
+
page,
|
|
405
|
+
}) => {
|
|
406
|
+
// The hold's release without finish plays the held fade out again: the
|
|
407
|
+
// browser starts it then, and the dip lands and fades back in on the clock
|
|
408
|
+
// it resumed on, with no animator call after the release.
|
|
409
|
+
await page.emulateMedia({reducedMotion: 'reduce'});
|
|
410
|
+
await open(page);
|
|
411
|
+
await page.evaluate(travel => {
|
|
412
|
+
(window as unknown as {dip: MotionHandle}).dip = window.animator.animate(
|
|
413
|
+
{x: travel},
|
|
414
|
+
{spring: Motion.springs.navigationPush},
|
|
415
|
+
);
|
|
416
|
+
const held = document.getAnimations();
|
|
417
|
+
for (const animation of held) {
|
|
418
|
+
animation.pause();
|
|
419
|
+
}
|
|
420
|
+
(window as unknown as {held: Animation[]}).held = held;
|
|
421
|
+
}, TRAVEL);
|
|
422
|
+
await page.evaluate(
|
|
423
|
+
async () =>
|
|
424
|
+
new Promise<void>(resolve =>
|
|
425
|
+
requestAnimationFrame(() =>
|
|
426
|
+
requestAnimationFrame(() => setTimeout(resolve, 40)),
|
|
427
|
+
),
|
|
428
|
+
),
|
|
429
|
+
);
|
|
430
|
+
await page.evaluate(() => {
|
|
431
|
+
for (const animation of (window as unknown as {held: Animation[]}).held) {
|
|
432
|
+
animation.play();
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
const read = async () =>
|
|
436
|
+
page.evaluate(() => {
|
|
437
|
+
const box = document.getElementById('box') as HTMLElement;
|
|
438
|
+
const style = getComputedStyle(box);
|
|
439
|
+
return {opacity: Number(style.opacity), translate: style.translate};
|
|
440
|
+
});
|
|
441
|
+
await dipDone(page);
|
|
442
|
+
expect(await read()).toEqual({opacity: 1, translate: `${TRAVEL}px`});
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
test('a spring started right before a block plays in full after it', async ({
|
|
446
|
+
page,
|
|
447
|
+
}) => {
|
|
448
|
+
await open(page);
|
|
449
|
+
const box = page.locator('#box');
|
|
450
|
+
await markElement(box, {inset: MARKER_INSET});
|
|
451
|
+
const cast = await startScreencast(page);
|
|
452
|
+
// Started and blocked in one task: the browser has not committed it yet.
|
|
453
|
+
// It starts when the first frame after the block commits it, as Core
|
|
454
|
+
// Animation starts an animation at its transaction's commit, instead of
|
|
455
|
+
// landing 400 ms into its curve.
|
|
456
|
+
const busy = await page.evaluate(
|
|
457
|
+
({spring, travel}) => {
|
|
458
|
+
(window as unknown as {blocked: MotionHandle}).blocked =
|
|
459
|
+
window.animator.animate({x: travel}, {spring});
|
|
460
|
+
const from = performance.timeOrigin + performance.now();
|
|
461
|
+
const end = performance.now() + 400;
|
|
462
|
+
while (performance.now() < end) {
|
|
463
|
+
// the main thread is busy
|
|
464
|
+
}
|
|
465
|
+
return {from, to: performance.timeOrigin + performance.now()};
|
|
466
|
+
},
|
|
467
|
+
{spring: SLOW, travel: TRAVEL},
|
|
468
|
+
);
|
|
469
|
+
// Wait for the motion, not a wall clock: on a loaded machine the frames
|
|
470
|
+
// after the block reach the screencast later than any fixed wait. The page
|
|
471
|
+
// shows the box a quarter of the way along, then three more frames arrive.
|
|
472
|
+
await page.waitForFunction(
|
|
473
|
+
min =>
|
|
474
|
+
(document.getElementById('box')?.getBoundingClientRect().left ?? 0) > min,
|
|
475
|
+
TRAVEL / 4,
|
|
476
|
+
{polling: 'raf', timeout: 0},
|
|
477
|
+
);
|
|
478
|
+
const seen = cast.frameCount();
|
|
479
|
+
await expect
|
|
480
|
+
.poll(() => cast.frameCount(), {timeout: 0})
|
|
481
|
+
.toBeGreaterThan(seen + 2);
|
|
482
|
+
const startedAt = await page.evaluate(
|
|
483
|
+
async () =>
|
|
484
|
+
performance.timeOrigin +
|
|
485
|
+
(await (window as unknown as {blocked: MotionHandle}).blocked.started),
|
|
486
|
+
);
|
|
487
|
+
const tracked = await trackMarker(page, await cast.stop());
|
|
488
|
+
const xs = tracked
|
|
489
|
+
.filter(f => f.box != null)
|
|
490
|
+
.map(f => ({t: f.t, x: (f.box?.x ?? NaN) - MARKER_INSET}));
|
|
491
|
+
// Judged on the first frame after the block, whatever the frames before
|
|
492
|
+
// it showed: it is at the start of the curve, and the frames after it
|
|
493
|
+
// move on from there.
|
|
494
|
+
const first = xs.find(f => f.t >= busy.to);
|
|
495
|
+
const later = xs.filter(f => f.t >= busy.to + 100);
|
|
496
|
+
test.info().annotations.push({
|
|
497
|
+
type: 'first frame after the block',
|
|
498
|
+
description: JSON.stringify({
|
|
499
|
+
x: first?.x,
|
|
500
|
+
after: first == null ? null : first.t - busy.to,
|
|
501
|
+
}),
|
|
502
|
+
});
|
|
503
|
+
expect(first).toBeDefined();
|
|
504
|
+
// The curve starts after the block, as Core Animation commits it.
|
|
505
|
+
expect(startedAt).toBeGreaterThan(busy.to - FRAME_MS);
|
|
506
|
+
// The first frame after the block shows that curve: no further along than
|
|
507
|
+
// one that started a frame before the block ended, at that frame's own
|
|
508
|
+
// time, however sparse the frames a loaded machine sends. A curve dated at
|
|
509
|
+
// the call is 107 px in by then.
|
|
510
|
+
const atMost = await page.evaluate(
|
|
511
|
+
({spring, travel, ms}) =>
|
|
512
|
+
Motion.solveSpring(Motion.toSpring(spring), {from: 0, to: travel}).value(
|
|
513
|
+
Math.max(0, ms) / 1000,
|
|
514
|
+
),
|
|
515
|
+
{
|
|
516
|
+
spring: SLOW,
|
|
517
|
+
travel: TRAVEL,
|
|
518
|
+
ms: (first?.t ?? Infinity) - (busy.to - FRAME_MS),
|
|
519
|
+
},
|
|
520
|
+
);
|
|
521
|
+
expect(first?.x ?? Infinity).toBeLessThanOrEqual(atMost + 1);
|
|
522
|
+
expect(later.length).toBeGreaterThan(0);
|
|
523
|
+
expect(Math.max(...later.map(f => f.x))).toBeGreaterThan((first?.x ?? 0) + 1);
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
test('no Layout or Paint runs while it animates', async ({
|
|
527
|
+
page,
|
|
528
|
+
browserName,
|
|
529
|
+
}) => {
|
|
530
|
+
test.skip(browserName !== 'chromium', 'tracing is a Chromium protocol');
|
|
531
|
+
await open(page);
|
|
532
|
+
let start = 0;
|
|
533
|
+
const trace = await traceRendering(page, async () => {
|
|
534
|
+
start = await page.evaluate(
|
|
535
|
+
({spring, travel}) => {
|
|
536
|
+
window.animator.animate({x: travel, opacity: 0.5}, {spring});
|
|
537
|
+
return performance.timeOrigin + performance.now();
|
|
538
|
+
},
|
|
539
|
+
{spring: SLOW, travel: TRAVEL},
|
|
540
|
+
);
|
|
541
|
+
await page.waitForTimeout(1900);
|
|
542
|
+
});
|
|
543
|
+
// After the frame that starts the animation.
|
|
544
|
+
const counts = countBetween(trace, start + 50, trace.window.to);
|
|
545
|
+
test.info().annotations.push({
|
|
546
|
+
type: 'rendering work while animating',
|
|
547
|
+
description: JSON.stringify(counts),
|
|
548
|
+
});
|
|
549
|
+
expect(counts.Layout ?? 0).toBe(0);
|
|
550
|
+
expect(counts.Paint ?? 0).toBe(0);
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
test('the engine plays the analytic curve, all channels on one clock', async ({
|
|
554
|
+
page,
|
|
555
|
+
}) => {
|
|
556
|
+
await open(page);
|
|
557
|
+
const result = await page.evaluate(async () => {
|
|
558
|
+
const spring = Motion.springs.quickChange;
|
|
559
|
+
const handle = window.animator.animate({x: 300, opacity: 0.4}, {spring});
|
|
560
|
+
// From rest, the animations start in the frame after the call.
|
|
561
|
+
await handle.started;
|
|
562
|
+
const animations = document.getAnimations();
|
|
563
|
+
const starts = animations.map(a => Number(a.startTime));
|
|
564
|
+
const start = starts[0];
|
|
565
|
+
const box = document.getElementById('box') as HTMLElement;
|
|
566
|
+
let worstX = 0;
|
|
567
|
+
let worstOpacity = 0;
|
|
568
|
+
const duration = Math.max(
|
|
569
|
+
...animations.map(a => Number(a.effect?.getComputedTiming().endTime)),
|
|
570
|
+
);
|
|
571
|
+
for (const a of animations) {
|
|
572
|
+
a.pause();
|
|
573
|
+
}
|
|
574
|
+
for (let t = 0; t <= duration; t += 4) {
|
|
575
|
+
for (const a of animations) {
|
|
576
|
+
a.currentTime = t;
|
|
577
|
+
}
|
|
578
|
+
const style = getComputedStyle(box);
|
|
579
|
+
const x = Number.parseFloat(style.translate || '0');
|
|
580
|
+
const opacity = Number.parseFloat(style.opacity);
|
|
581
|
+
worstX = Math.max(
|
|
582
|
+
worstX,
|
|
583
|
+
Math.abs(x - window.animator.get('x', start + t)),
|
|
584
|
+
);
|
|
585
|
+
worstOpacity = Math.max(
|
|
586
|
+
worstOpacity,
|
|
587
|
+
Math.abs(opacity - window.animator.get('opacity', start + t)),
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
return {count: animations.length, starts, worstX, worstOpacity};
|
|
591
|
+
});
|
|
592
|
+
test.info().annotations.push({
|
|
593
|
+
type: 'seeked curve',
|
|
594
|
+
description: JSON.stringify(result),
|
|
595
|
+
});
|
|
596
|
+
expect(result.count).toBe(2);
|
|
597
|
+
expect(new Set(result.starts).size).toBe(1);
|
|
598
|
+
expect(result.worstX).toBeLessThan(0.26);
|
|
599
|
+
expect(result.worstOpacity).toBeLessThan(0.0045);
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
test('a role variable set on a scope changes nothing while touch motion stays internal', async ({
|
|
603
|
+
page,
|
|
604
|
+
}) => {
|
|
605
|
+
// A page's own style sets the role's variable on a scope; the per-role
|
|
606
|
+
// tables stay internal (spec:AST-094 DEC-15), so both boxes play the
|
|
607
|
+
// table's spring.
|
|
608
|
+
const html = `<!doctype html><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
609
|
+
<style>
|
|
610
|
+
html, body { margin: 0; background: #fff; }
|
|
611
|
+
.box { position: absolute; top: 40px; width: 48px; height: 48px; background: #36c; }
|
|
612
|
+
@scope ([data-astryx-theme="soft"]) { :scope { --motion-springs-settle: 0.8s 0.3; } }
|
|
613
|
+
</style>
|
|
614
|
+
<div class="box" id="plain" style="left: 0"></div>
|
|
615
|
+
<div data-astryx-theme="soft"><div class="box" id="themed" style="left: 80px"></div></div>
|
|
616
|
+
<script>${script}</script>`;
|
|
617
|
+
await page.route('http://motion.test/', async route =>
|
|
618
|
+
route.fulfill({contentType: 'text/html', body: html}),
|
|
619
|
+
);
|
|
620
|
+
await page.goto('http://motion.test/');
|
|
621
|
+
const result = await page.evaluate(async () => {
|
|
622
|
+
// Only a registered table's roles resolve: register it as a touch
|
|
623
|
+
// module would, and fail loudly if the role is not there.
|
|
624
|
+
Motion.registerSpringsTable();
|
|
625
|
+
if (Motion.motionRoleOf(Motion.springs.settle)?.id !== 'springs.settle') {
|
|
626
|
+
throw new Error(
|
|
627
|
+
'springs.settle is not a registered role: call registerSpringsTable() first',
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
const curves = {
|
|
631
|
+
plain: Motion.solveSpring(Motion.toSpring(Motion.springs.settle), {
|
|
632
|
+
from: 300,
|
|
633
|
+
to: 0,
|
|
634
|
+
}),
|
|
635
|
+
themed: Motion.solveSpring(Motion.toSpring(Motion.springs.settle), {
|
|
636
|
+
from: 300,
|
|
637
|
+
to: 0,
|
|
638
|
+
}),
|
|
639
|
+
};
|
|
640
|
+
const report: Record<string, {worst: number; lowest: number}> = {};
|
|
641
|
+
for (const id of ['plain', 'themed'] as const) {
|
|
642
|
+
const element = document.getElementById(id) as HTMLElement;
|
|
643
|
+
const animator = Motion.createAnimator(element);
|
|
644
|
+
animator.set({y: 300});
|
|
645
|
+
const handle = animator.animate({y: 0}, {spring: Motion.springs.settle});
|
|
646
|
+
await handle.started;
|
|
647
|
+
const animations = element.getAnimations();
|
|
648
|
+
for (const a of animations) {
|
|
649
|
+
a.pause();
|
|
650
|
+
}
|
|
651
|
+
let worst = 0;
|
|
652
|
+
let lowest = Infinity;
|
|
653
|
+
for (let t = 0; t <= 1200; t += 8) {
|
|
654
|
+
for (const a of animations) {
|
|
655
|
+
a.currentTime = t;
|
|
656
|
+
}
|
|
657
|
+
const [, y = '0'] = getComputedStyle(element).translate.split(' ');
|
|
658
|
+
const value = Number.parseFloat(y) || 0;
|
|
659
|
+
lowest = Math.min(lowest, value);
|
|
660
|
+
worst = Math.max(worst, Math.abs(value - curves[id].value(t / 1000)));
|
|
661
|
+
}
|
|
662
|
+
report[id] = {worst, lowest};
|
|
663
|
+
}
|
|
664
|
+
return report;
|
|
665
|
+
});
|
|
666
|
+
test.info().annotations.push({
|
|
667
|
+
type: 'themed spring',
|
|
668
|
+
description: JSON.stringify(result),
|
|
669
|
+
});
|
|
670
|
+
// Both boxes play the table's (critically damped) spring: neither
|
|
671
|
+
// overshoots.
|
|
672
|
+
expect(result.plain.worst).toBeLessThan(0.26);
|
|
673
|
+
expect(result.themed.worst).toBeLessThan(0.26);
|
|
674
|
+
expect(result.plain.lowest).toBeGreaterThan(-0.5);
|
|
675
|
+
expect(result.themed.lowest).toBeGreaterThan(-0.5);
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
test('a finished animation leaves the element once the curve ends', async ({
|
|
679
|
+
page,
|
|
680
|
+
}) => {
|
|
681
|
+
await open(page);
|
|
682
|
+
const result = await page.evaluate(
|
|
683
|
+
async spring =>
|
|
684
|
+
new Promise<{curveEnd: number; leftAt: number}>(resolve => {
|
|
685
|
+
const start = performance.now();
|
|
686
|
+
window.animator.animate({x: 120}, {spring});
|
|
687
|
+
const box = document.getElementById('box') as HTMLElement;
|
|
688
|
+
const solved = Motion.solveSpring(Motion.toSpring(spring), {
|
|
689
|
+
from: 0,
|
|
690
|
+
to: 120,
|
|
691
|
+
});
|
|
692
|
+
const curveEnd = solved.settleTime(0.05) * 1000;
|
|
693
|
+
const tick = () => {
|
|
694
|
+
if (box.getAnimations().length === 0) {
|
|
695
|
+
resolve({curveEnd, leftAt: performance.now() - start});
|
|
696
|
+
} else {
|
|
697
|
+
requestAnimationFrame(tick);
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
requestAnimationFrame(tick);
|
|
701
|
+
}),
|
|
702
|
+
{response: 0.3, dampingRatio: 1},
|
|
703
|
+
);
|
|
704
|
+
test.info().annotations.push({
|
|
705
|
+
type: 'animation lifetime',
|
|
706
|
+
description: JSON.stringify(result),
|
|
707
|
+
});
|
|
708
|
+
// Gone within a couple of frames of the curve's end, not after the hold.
|
|
709
|
+
expect(result.leftAt).toBeGreaterThanOrEqual(result.curveEnd - 1);
|
|
710
|
+
expect(result.leftAt).toBeLessThan(result.curveEnd + 100);
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
test('a fade-in on an element its stylesheet hides stays visible once it retires', async ({
|
|
714
|
+
page,
|
|
715
|
+
}) => {
|
|
716
|
+
await open(page);
|
|
717
|
+
const result = await page.evaluate(
|
|
718
|
+
async spring => {
|
|
719
|
+
const sheet = document.createElement('style');
|
|
720
|
+
sheet.textContent = '.hidden { opacity: 0; }';
|
|
721
|
+
document.head.append(sheet);
|
|
722
|
+
const element = document.createElement('div');
|
|
723
|
+
element.className = 'hidden';
|
|
724
|
+
element.style.cssText =
|
|
725
|
+
'position:absolute;top:120px;left:0;width:48px;height:48px;background:#c63';
|
|
726
|
+
document.body.append(element);
|
|
727
|
+
const animator = Motion.createAnimator(element);
|
|
728
|
+
animator.set({opacity: 0});
|
|
729
|
+
animator.animate({opacity: 1}, {spring});
|
|
730
|
+
await new Promise<void>(resolve => {
|
|
731
|
+
const tick = () => {
|
|
732
|
+
if (element.getAnimations().length === 0) {
|
|
733
|
+
resolve();
|
|
734
|
+
} else {
|
|
735
|
+
requestAnimationFrame(tick);
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
requestAnimationFrame(tick);
|
|
739
|
+
});
|
|
740
|
+
// A frame after the retire.
|
|
741
|
+
await new Promise(resolve =>
|
|
742
|
+
requestAnimationFrame(() => requestAnimationFrame(resolve)),
|
|
743
|
+
);
|
|
744
|
+
return {
|
|
745
|
+
inline: element.style.opacity,
|
|
746
|
+
computed: getComputedStyle(element).opacity,
|
|
747
|
+
};
|
|
748
|
+
},
|
|
749
|
+
{response: 0.3, dampingRatio: 1},
|
|
750
|
+
);
|
|
751
|
+
test.info().annotations.push({
|
|
752
|
+
type: 'after retire',
|
|
753
|
+
description: JSON.stringify(result),
|
|
754
|
+
});
|
|
755
|
+
// The end stays inline over the stylesheet's opacity 0.
|
|
756
|
+
expect(result.computed).toBe('1');
|
|
757
|
+
expect(result.inline).toBe('1');
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
test('a fixed child stays fixed after a motion back to identity', async ({
|
|
761
|
+
page,
|
|
762
|
+
}) => {
|
|
763
|
+
await open(page);
|
|
764
|
+
const result = await page.evaluate(async () => {
|
|
765
|
+
const box = document.getElementById('box') as HTMLElement;
|
|
766
|
+
const child = document.createElement('div');
|
|
767
|
+
child.style.cssText =
|
|
768
|
+
'position: fixed; top: 10px; left: 10px; width: 4px; height: 4px;';
|
|
769
|
+
box.appendChild(child);
|
|
770
|
+
const quick = {response: 0.1, dampingRatio: 1};
|
|
771
|
+
await window.animator.animate({x: 120}, {spring: quick}).finished;
|
|
772
|
+
await window.animator.animate({x: 0}, {spring: quick}).finished;
|
|
773
|
+
// At rest: the animation retired and the layer promotion lingered out.
|
|
774
|
+
await new Promise<void>(resolve => {
|
|
775
|
+
const tick = () =>
|
|
776
|
+
box.getAnimations().length === 0 && box.style.willChange === ''
|
|
777
|
+
? resolve()
|
|
778
|
+
: requestAnimationFrame(tick);
|
|
779
|
+
requestAnimationFrame(tick);
|
|
780
|
+
});
|
|
781
|
+
const rect = child.getBoundingClientRect();
|
|
782
|
+
return {top: rect.top, left: rect.left, translate: box.style.translate};
|
|
783
|
+
});
|
|
784
|
+
// The identity left the element: any translate but none would keep the box
|
|
785
|
+
// (40 px down) its containing block for good.
|
|
786
|
+
expect(result.translate).toBe('');
|
|
787
|
+
expect(result.top).toBe(10);
|
|
788
|
+
expect(result.left).toBe(10);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
test('a dialog\u2019s ::backdrop plays the curve and holds its end state', async ({
|
|
792
|
+
page,
|
|
793
|
+
}) => {
|
|
794
|
+
await open(page);
|
|
795
|
+
const result = await page.evaluate(async () => {
|
|
796
|
+
const dialog = document.createElement('dialog');
|
|
797
|
+
document.body.append(dialog);
|
|
798
|
+
dialog.showModal();
|
|
799
|
+
const backdrop = Motion.createAnimator(dialog, {
|
|
800
|
+
pseudoElement: '::backdrop',
|
|
801
|
+
});
|
|
802
|
+
backdrop.set({opacity: 0});
|
|
803
|
+
await backdrop.animate({opacity: 1}, {spring: Motion.springs.alertPresent})
|
|
804
|
+
.started;
|
|
805
|
+
const animations = document
|
|
806
|
+
.getAnimations()
|
|
807
|
+
.filter(a => (a.effect as KeyframeEffect).target === dialog);
|
|
808
|
+
const start = Number(animations[0].startTime);
|
|
809
|
+
let worst = 0;
|
|
810
|
+
const read = () =>
|
|
811
|
+
Number.parseFloat(getComputedStyle(dialog, '::backdrop').opacity);
|
|
812
|
+
for (const a of animations) {
|
|
813
|
+
a.pause();
|
|
814
|
+
}
|
|
815
|
+
for (let t = 0; t <= 400; t += 5) {
|
|
816
|
+
for (const a of animations) {
|
|
817
|
+
a.currentTime = t;
|
|
818
|
+
}
|
|
819
|
+
worst = Math.max(
|
|
820
|
+
worst,
|
|
821
|
+
Math.abs(read() - backdrop.get('opacity', start + t)),
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
for (const a of animations) {
|
|
825
|
+
a.currentTime = 20_000; // long after the curve and the hold
|
|
826
|
+
}
|
|
827
|
+
return {count: animations.length, worst, held: read()};
|
|
828
|
+
});
|
|
829
|
+
test.info().annotations.push({
|
|
830
|
+
type: 'backdrop curve',
|
|
831
|
+
description: JSON.stringify(result),
|
|
832
|
+
});
|
|
833
|
+
expect(result.count).toBe(1);
|
|
834
|
+
expect(result.worst).toBeLessThan(0.0045);
|
|
835
|
+
expect(result.held).toBeCloseTo(1, 6);
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
declare global {
|
|
839
|
+
interface Window {
|
|
840
|
+
animator: Animator;
|
|
841
|
+
}
|
|
842
|
+
const Motion: typeof MotionBundle;
|
|
843
|
+
}
|