@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.
Files changed (912) hide show
  1. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  2. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  3. package/dist/AlertDialog/AlertDialog.js +5 -5
  4. package/dist/AppShell/AppShell.d.ts.map +1 -1
  5. package/dist/AppShell/AppShell.js +183 -5
  6. package/dist/AppShell/observeMainOverflow.d.ts +9 -0
  7. package/dist/AppShell/observeMainOverflow.d.ts.map +1 -0
  8. package/dist/AppShell/observeMainOverflow.js +125 -0
  9. package/dist/Avatar/Avatar.d.ts.map +1 -1
  10. package/dist/Avatar/Avatar.js +12 -3
  11. package/dist/Badge/Badge.d.ts.map +1 -1
  12. package/dist/Badge/Badge.js +7 -1
  13. package/dist/BottomSheet/BottomSheet.js +1 -1
  14. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  15. package/dist/BottomSheet/BottomSheetPanel.js +2 -1
  16. package/dist/BottomSheet/useSheetGestures.d.ts +12 -0
  17. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  18. package/dist/BottomSheet/useSheetGestures.js +30 -3
  19. package/dist/Button/Button.js +4 -4
  20. package/dist/Carousel/Carousel.d.ts +3 -1
  21. package/dist/Carousel/Carousel.d.ts.map +1 -1
  22. package/dist/Carousel/Carousel.js +12 -3
  23. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  24. package/dist/CheckboxInput/CheckboxInput.js +6 -5
  25. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  26. package/dist/ClickableCard/ClickableCard.js +37 -4
  27. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  28. package/dist/ComplexSelector/ComplexSelector.js +41 -4
  29. package/dist/DateInput/DateInput.d.ts.map +1 -1
  30. package/dist/DateInput/DateInput.js +12 -4
  31. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  32. package/dist/DateInput/MonthScroller.js +101 -15
  33. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  34. package/dist/DateInput/TouchDateField.js +8 -3
  35. package/dist/DateInput/Wheel.d.ts.map +1 -1
  36. package/dist/DateInput/Wheel.js +11 -7
  37. package/dist/DateInput/usePointerDragScroll.d.ts +10 -1
  38. package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -1
  39. package/dist/DateInput/usePointerDragScroll.js +25 -9
  40. package/dist/DateInput/useScrollSettle.d.ts +3 -1
  41. package/dist/DateInput/useScrollSettle.d.ts.map +1 -1
  42. package/dist/DateInput/useScrollSettle.js +37 -8
  43. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  44. package/dist/DateRangeInput/DateRangeInput.js +1 -1
  45. package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
  46. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  47. package/dist/DateTimeInput/DateTimeInput.js +23 -12
  48. package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
  49. package/dist/DateTimeInput/NativeTimeSegment.js +5 -4
  50. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  51. package/dist/DateTimeInput/TouchDateTimeField.js +4 -3
  52. package/dist/Dialog/Dialog.d.ts.map +1 -1
  53. package/dist/Dialog/Dialog.js +34 -9
  54. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  55. package/dist/Dialog/DialogHeader.js +5 -4
  56. package/dist/Divider/Divider.d.ts.map +1 -1
  57. package/dist/Divider/Divider.js +2 -1
  58. package/dist/Drawer/Drawer.d.ts +1 -0
  59. package/dist/Drawer/Drawer.d.ts.map +1 -1
  60. package/dist/Drawer/Drawer.js +7 -2
  61. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  62. package/dist/DropdownMenu/DropdownMenu.js +35 -22
  63. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
  64. package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
  65. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +20 -2
  66. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
  67. package/dist/DropdownMenu/lazyMenuBottomSheet.js +31 -3
  68. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  69. package/dist/DropdownMenu/renderDropdownItems.js +21 -16
  70. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  71. package/dist/EmptyState/EmptyState.js +2 -1
  72. package/dist/Field/FieldLabel.d.ts +1 -1
  73. package/dist/Field/FieldLabel.d.ts.map +1 -1
  74. package/dist/Field/FieldLabel.js +4 -4
  75. package/dist/Field/InputClearButton.js +3 -3
  76. package/dist/Field/PanelSearchInput.js +2 -2
  77. package/dist/FieldStatus/FieldStatus.d.ts +3 -0
  78. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  79. package/dist/FieldStatus/FieldStatus.js +3 -2
  80. package/dist/FileInput/FileInput.d.ts +3 -0
  81. package/dist/FileInput/FileInput.d.ts.map +1 -1
  82. package/dist/FileInput/FileInput.js +34 -13
  83. package/dist/Heading/Heading.js +1 -1
  84. package/dist/Icon/Icon.js +1 -1
  85. package/dist/Indicator/CheckIndicator.d.ts.map +1 -1
  86. package/dist/Indicator/CheckIndicator.js +2 -1
  87. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  88. package/dist/Indicator/CheckboxIndicator.js +3 -1
  89. package/dist/Indicator/RadioIndicator.d.ts.map +1 -1
  90. package/dist/Indicator/RadioIndicator.js +3 -1
  91. package/dist/Item/Item.d.ts.map +1 -1
  92. package/dist/Item/Item.js +21 -7
  93. package/dist/Item/ItemSwipeLayer.js +1 -1
  94. package/dist/Layer/popoverOperations.d.ts +27 -0
  95. package/dist/Layer/popoverOperations.d.ts.map +1 -0
  96. package/dist/Layer/popoverOperations.js +159 -0
  97. package/dist/Layer/useLayer.d.ts +1 -1
  98. package/dist/Layer/useLayer.d.ts.map +1 -1
  99. package/dist/Layer/useLayer.js +120 -65
  100. package/dist/Layout/Layout.js +1 -1
  101. package/dist/Layout/LayoutContent.js +1 -1
  102. package/dist/Layout/LayoutFooter.js +1 -1
  103. package/dist/Layout/LayoutHeader.js +1 -1
  104. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  105. package/dist/Lightbox/Lightbox.js +5 -0
  106. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +5 -4
  107. package/dist/Link/Link.d.ts.map +1 -1
  108. package/dist/Link/Link.js +8 -3
  109. package/dist/List/List.js +1 -1
  110. package/dist/List/ListItem.js +3 -3
  111. package/dist/Markdown/plugins/headingLinks.a11y.chromium.spec.js +1 -1
  112. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  113. package/dist/MobileNav/MobileNav.js +7 -2
  114. package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +7 -6
  115. package/dist/MultiSelector/MultiSelector.d.ts +1 -1
  116. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  117. package/dist/MultiSelector/MultiSelector.js +26 -10
  118. package/dist/NavMenu/NavHeadingMenuItem.d.ts.map +1 -1
  119. package/dist/NavMenu/NavHeadingMenuItem.js +5 -29
  120. package/dist/NumberInput/NumberInput.d.ts +3 -1
  121. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  122. package/dist/NumberInput/NumberInput.js +26 -5
  123. package/dist/NumberInput/numberParser.d.ts +3 -0
  124. package/dist/NumberInput/numberParser.d.ts.map +1 -1
  125. package/dist/NumberInput/numberParser.js +7 -44
  126. package/dist/Outline/Outline.d.ts.map +1 -1
  127. package/dist/Outline/Outline.js +27 -0
  128. package/dist/Popover/Popover.d.ts.map +1 -1
  129. package/dist/Popover/Popover.js +32 -12
  130. package/dist/Popover/usePopover.d.ts.map +1 -1
  131. package/dist/Popover/usePopover.js +10 -3
  132. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  133. package/dist/PowerSearch/PowerSearch.js +37 -30
  134. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  135. package/dist/ProgressBar/ProgressBar.js +16 -12
  136. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  137. package/dist/RadioList/RadioListItem.js +11 -3
  138. package/dist/Resizable/useResizable.d.ts.map +1 -1
  139. package/dist/Resizable/useResizable.js +28 -2
  140. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  141. package/dist/SegmentedControl/SegmentedControlItem.js +4 -1
  142. package/dist/Selector/useSelectorPresentation.d.ts +8 -1
  143. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
  144. package/dist/Selector/useSelectorPresentation.js +20 -4
  145. package/dist/SideNav/SideNavItem.d.ts +2 -2
  146. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  147. package/dist/SideNav/SideNavItem.js +18 -7
  148. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  149. package/dist/Skeleton/Skeleton.js +1 -1
  150. package/dist/Slider/Slider.d.ts.map +1 -1
  151. package/dist/Slider/Slider.js +10 -2
  152. package/dist/Spinner/Spinner.d.ts.map +1 -1
  153. package/dist/Spinner/Spinner.js +3 -3
  154. package/dist/Stack/Stack.js +1 -1
  155. package/dist/Stack/StackItem.js +1 -1
  156. package/dist/Stepper/Step.d.ts.map +1 -1
  157. package/dist/Stepper/Step.js +26 -6
  158. package/dist/Switch/Switch.d.ts.map +1 -1
  159. package/dist/Switch/Switch.js +10 -3
  160. package/dist/TabList/TabList.d.ts.map +1 -1
  161. package/dist/TabList/TabList.js +16 -1
  162. package/dist/Table/Table.d.ts.map +1 -1
  163. package/dist/Table/Table.js +36 -10
  164. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  165. package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
  166. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  167. package/dist/Table/plugins/sortable/useTableSortable.js +46 -58
  168. package/dist/Text/Text.js +1 -1
  169. package/dist/Text/useTruncation.d.ts.map +1 -1
  170. package/dist/Text/useTruncation.js +23 -5
  171. package/dist/TextArea/TextArea.d.ts +1 -1
  172. package/dist/TextArea/TextArea.d.ts.map +1 -1
  173. package/dist/TextArea/TextArea.js +13 -2
  174. package/dist/TextInput/TextInput.d.ts.map +1 -1
  175. package/dist/TextInput/TextInput.js +3 -3
  176. package/dist/TimeInput/TimeInput.d.ts +6 -2
  177. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  178. package/dist/TimeInput/TimeInput.js +21 -14
  179. package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
  180. package/dist/TimeInput/TouchTimeField.js +5 -4
  181. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  182. package/dist/Timestamp/Timestamp.js +2 -2
  183. package/dist/Timestamp/TimestampHoverCard.js +4 -4
  184. package/dist/Toast/Toast.d.ts.map +1 -1
  185. package/dist/Toast/Toast.js +60 -20
  186. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  187. package/dist/Toast/ToastViewport.js +101 -54
  188. package/dist/ToggleButton/ToggleButtonGroup.d.ts +7 -1
  189. package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
  190. package/dist/ToggleButton/ToggleButtonGroup.js +16 -2
  191. package/dist/Token/Token.d.ts +1 -1
  192. package/dist/Token/Token.d.ts.map +1 -1
  193. package/dist/Token/Token.js +52 -5
  194. package/dist/Token/TokenLink.d.ts.map +1 -1
  195. package/dist/Token/TokenLink.js +14 -2
  196. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  197. package/dist/Tokenizer/Tokenizer.js +44 -7
  198. package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
  199. package/dist/Tokenizer/TokenizerClearAllMessageContext.d.ts +2 -0
  200. package/dist/Tokenizer/TokenizerClearAllMessageContext.d.ts.map +1 -0
  201. package/dist/Tokenizer/TokenizerClearAllMessageContext.js +17 -0
  202. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  203. package/dist/Toolbar/Toolbar.js +2 -1
  204. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  205. package/dist/TopNav/TopNavMegaMenu.js +3 -0
  206. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  207. package/dist/TopNav/TopNavMenu.js +1 -0
  208. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  209. package/dist/TreeList/TreeListItem.js +27 -4
  210. package/dist/Typeahead/BaseTypeahead.d.ts +4 -4
  211. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  212. package/dist/Typeahead/BaseTypeahead.js +43 -7
  213. package/dist/Typeahead/Typeahead.d.ts +1 -1
  214. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  215. package/dist/Typeahead/Typeahead.js +43 -9
  216. package/dist/astryx.css +25 -4
  217. package/dist/gestures/GestureArena.d.ts +32 -1
  218. package/dist/gestures/GestureArena.d.ts.map +1 -1
  219. package/dist/gestures/GestureArena.js +110 -9
  220. package/dist/gestures/GestureHost.d.ts +351 -0
  221. package/dist/gestures/GestureHost.d.ts.map +1 -0
  222. package/dist/gestures/GestureHost.js +1773 -0
  223. package/dist/gestures/GestureRecognizer.d.ts +13 -1
  224. package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
  225. package/dist/gestures/GestureRecognizer.js +19 -1
  226. package/dist/gestures/LongPressGestureRecognizer.d.ts +1 -0
  227. package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -1
  228. package/dist/gestures/LongPressGestureRecognizer.js +3 -0
  229. package/dist/gestures/PanGestureRecognizer.d.ts +1 -0
  230. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  231. package/dist/gestures/PanGestureRecognizer.js +3 -0
  232. package/dist/gestures/PinchGestureRecognizer.d.ts +31 -0
  233. package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -0
  234. package/dist/gestures/PinchGestureRecognizer.js +128 -0
  235. package/dist/gestures/PressTracker.d.ts +112 -0
  236. package/dist/gestures/PressTracker.d.ts.map +1 -0
  237. package/dist/gestures/PressTracker.js +267 -0
  238. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +71 -0
  239. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -0
  240. package/dist/gestures/ScreenEdgePanGestureRecognizer.js +223 -0
  241. package/dist/gestures/SwipeGestureRecognizer.d.ts +37 -0
  242. package/dist/gestures/SwipeGestureRecognizer.d.ts.map +1 -0
  243. package/dist/gestures/SwipeGestureRecognizer.js +148 -0
  244. package/dist/gestures/TapGestureRecognizer.d.ts +1 -0
  245. package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -1
  246. package/dist/gestures/TapGestureRecognizer.js +3 -0
  247. package/dist/gestures/VelocityTracker.d.ts +6 -2
  248. package/dist/gestures/VelocityTracker.d.ts.map +1 -1
  249. package/dist/gestures/VelocityTracker.js +7 -3
  250. package/dist/gestures/haptics.d.ts +65 -0
  251. package/dist/gestures/haptics.d.ts.map +1 -0
  252. package/dist/gestures/haptics.js +182 -0
  253. package/dist/gestures/index.d.ts +37 -0
  254. package/dist/gestures/index.d.ts.map +1 -0
  255. package/dist/gestures/index.js +25 -0
  256. package/dist/gestures/nativeScroll.d.ts +42 -0
  257. package/dist/gestures/nativeScroll.d.ts.map +1 -0
  258. package/dist/gestures/nativeScroll.js +228 -0
  259. package/dist/gestures/touchAction.d.ts +60 -0
  260. package/dist/gestures/touchAction.d.ts.map +1 -0
  261. package/dist/gestures/touchAction.js +157 -0
  262. package/dist/gestures/touchActionRule.d.ts +34 -0
  263. package/dist/gestures/touchActionRule.d.ts.map +1 -0
  264. package/dist/gestures/touchActionRule.js +140 -0
  265. package/dist/gestures/types.d.ts +18 -7
  266. package/dist/gestures/types.d.ts.map +1 -1
  267. package/dist/gestures/types.js +22 -2
  268. package/dist/gestures/useGestureRecognizer.d.ts +56 -0
  269. package/dist/gestures/useGestureRecognizer.d.ts.map +1 -0
  270. package/dist/gestures/useGestureRecognizer.js +226 -0
  271. package/dist/hooks/index.d.ts +1 -1
  272. package/dist/hooks/index.d.ts.map +1 -1
  273. package/dist/hooks/modalAnnounce.d.ts.map +1 -1
  274. package/dist/hooks/modalAnnounce.js +107 -61
  275. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -1
  276. package/dist/hooks/scrollKeyboardDelegation.js +7 -3
  277. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
  278. package/dist/hooks/useAdaptivePresentation.js +4 -1
  279. package/dist/hooks/useAnnounce.d.ts +101 -42
  280. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  281. package/dist/hooks/useAnnounce.js +161 -75
  282. package/dist/hooks/useAnnounceRenderedText.d.ts +11 -3
  283. package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
  284. package/dist/hooks/useAnnounceRenderedText.js +5 -3
  285. package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
  286. package/dist/hooks/useBusyAnnouncement.js +6 -12
  287. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  288. package/dist/hooks/useMenuHover.js +12 -1
  289. package/dist/hooks/useScrollOverflow.d.ts +2 -1
  290. package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
  291. package/dist/hooks/useScrollOverflow.js +56 -10
  292. package/dist/i18n/generated-locales/af-ZA.generated.d.ts.map +1 -1
  293. package/dist/i18n/generated-locales/af-ZA.generated.js +0 -5
  294. package/dist/i18n/generated-locales/ar-SA.generated.d.ts.map +1 -1
  295. package/dist/i18n/generated-locales/ar-SA.generated.js +0 -5
  296. package/dist/i18n/generated-locales/ca-ES.generated.d.ts.map +1 -1
  297. package/dist/i18n/generated-locales/ca-ES.generated.js +0 -5
  298. package/dist/i18n/generated-locales/cs-CZ.generated.d.ts.map +1 -1
  299. package/dist/i18n/generated-locales/cs-CZ.generated.js +0 -5
  300. package/dist/i18n/generated-locales/da-DK.generated.d.ts.map +1 -1
  301. package/dist/i18n/generated-locales/da-DK.generated.js +0 -5
  302. package/dist/i18n/generated-locales/de-DE.generated.d.ts.map +1 -1
  303. package/dist/i18n/generated-locales/de-DE.generated.js +0 -5
  304. package/dist/i18n/generated-locales/el-GR.generated.d.ts.map +1 -1
  305. package/dist/i18n/generated-locales/el-GR.generated.js +0 -5
  306. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  307. package/dist/i18n/generated-locales/en.generated.js +8 -5
  308. package/dist/i18n/generated-locales/es-ES.generated.d.ts.map +1 -1
  309. package/dist/i18n/generated-locales/es-ES.generated.js +0 -5
  310. package/dist/i18n/generated-locales/fi-FI.generated.d.ts.map +1 -1
  311. package/dist/i18n/generated-locales/fi-FI.generated.js +0 -5
  312. package/dist/i18n/generated-locales/fr-FR.generated.d.ts.map +1 -1
  313. package/dist/i18n/generated-locales/fr-FR.generated.js +0 -5
  314. package/dist/i18n/generated-locales/he-IL.generated.d.ts.map +1 -1
  315. package/dist/i18n/generated-locales/he-IL.generated.js +0 -5
  316. package/dist/i18n/generated-locales/hu-HU.generated.d.ts.map +1 -1
  317. package/dist/i18n/generated-locales/hu-HU.generated.js +0 -5
  318. package/dist/i18n/generated-locales/it-IT.generated.d.ts.map +1 -1
  319. package/dist/i18n/generated-locales/it-IT.generated.js +0 -5
  320. package/dist/i18n/generated-locales/ja-JP.generated.d.ts.map +1 -1
  321. package/dist/i18n/generated-locales/ja-JP.generated.js +0 -5
  322. package/dist/i18n/generated-locales/ko-KR.generated.d.ts.map +1 -1
  323. package/dist/i18n/generated-locales/ko-KR.generated.js +0 -5
  324. package/dist/i18n/generated-locales/nl-NL.generated.d.ts.map +1 -1
  325. package/dist/i18n/generated-locales/nl-NL.generated.js +0 -5
  326. package/dist/i18n/generated-locales/no-NO.generated.d.ts.map +1 -1
  327. package/dist/i18n/generated-locales/no-NO.generated.js +0 -5
  328. package/dist/i18n/generated-locales/pl-PL.generated.d.ts.map +1 -1
  329. package/dist/i18n/generated-locales/pl-PL.generated.js +0 -5
  330. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  331. package/dist/i18n/generated-locales/pseudo.generated.js +8 -5
  332. package/dist/i18n/generated-locales/pt-BR.generated.d.ts.map +1 -1
  333. package/dist/i18n/generated-locales/pt-BR.generated.js +0 -5
  334. package/dist/i18n/generated-locales/pt-PT.generated.d.ts.map +1 -1
  335. package/dist/i18n/generated-locales/pt-PT.generated.js +0 -5
  336. package/dist/i18n/generated-locales/ro-RO.generated.d.ts.map +1 -1
  337. package/dist/i18n/generated-locales/ro-RO.generated.js +0 -5
  338. package/dist/i18n/generated-locales/ru-RU.generated.d.ts.map +1 -1
  339. package/dist/i18n/generated-locales/ru-RU.generated.js +0 -5
  340. package/dist/i18n/generated-locales/sr-SP.generated.d.ts.map +1 -1
  341. package/dist/i18n/generated-locales/sr-SP.generated.js +0 -5
  342. package/dist/i18n/generated-locales/sv-SE.generated.d.ts.map +1 -1
  343. package/dist/i18n/generated-locales/sv-SE.generated.js +0 -5
  344. package/dist/i18n/generated-locales/tr-TR.generated.d.ts.map +1 -1
  345. package/dist/i18n/generated-locales/tr-TR.generated.js +0 -5
  346. package/dist/i18n/generated-locales/uk-UA.generated.d.ts.map +1 -1
  347. package/dist/i18n/generated-locales/uk-UA.generated.js +0 -5
  348. package/dist/i18n/generated-locales/vi-VN.generated.d.ts.map +1 -1
  349. package/dist/i18n/generated-locales/vi-VN.generated.js +0 -5
  350. package/dist/i18n/generated-locales/zh-CN.generated.d.ts.map +1 -1
  351. package/dist/i18n/generated-locales/zh-CN.generated.js +0 -5
  352. package/dist/i18n/generated-locales/zh-TW.generated.d.ts.map +1 -1
  353. package/dist/i18n/generated-locales/zh-TW.generated.js +0 -5
  354. package/dist/i18n/useListFormatter.d.ts +9 -0
  355. package/dist/i18n/useListFormatter.d.ts.map +1 -0
  356. package/dist/i18n/useListFormatter.js +41 -0
  357. package/dist/motion/animator.d.ts +83 -8
  358. package/dist/motion/animator.d.ts.map +1 -1
  359. package/dist/motion/animator.js +701 -119
  360. package/dist/motion/coast.d.ts +4 -1
  361. package/dist/motion/coast.d.ts.map +1 -1
  362. package/dist/motion/coast.js +4 -2
  363. package/dist/motion/reducedMotion.d.ts.map +1 -1
  364. package/dist/motion/reducedMotion.js +6 -2
  365. package/dist/motion/reducedMotionPlan.d.ts +7 -0
  366. package/dist/motion/reducedMotionPlan.d.ts.map +1 -1
  367. package/dist/motion/reducedMotionPlan.js +14 -1
  368. package/dist/motion/resolveMotion.d.ts +42 -0
  369. package/dist/motion/resolveMotion.d.ts.map +1 -0
  370. package/dist/motion/resolveMotion.js +43 -0
  371. package/dist/motion/roleValue.d.ts +2 -1
  372. package/dist/motion/roleValue.d.ts.map +1 -1
  373. package/dist/motion/roleValue.js +2 -1
  374. package/dist/motion/uikit/timing.d.ts +7 -1
  375. package/dist/motion/uikit/timing.d.ts.map +1 -1
  376. package/dist/motion/uikit/timing.js +19 -1
  377. package/dist/theme/defineTheme.d.ts +19 -5
  378. package/dist/theme/defineTheme.d.ts.map +1 -1
  379. package/dist/theme/defineTheme.js +64 -4
  380. package/dist/theme/domainTokens/domainTokenDefaults.d.ts +3 -0
  381. package/dist/theme/domainTokens/domainTokenDefaults.d.ts.map +1 -0
  382. package/dist/theme/domainTokens/domainTokenDefaults.js +19 -0
  383. package/dist/theme/domainTokens/index.d.ts +5 -4
  384. package/dist/theme/domainTokens/index.d.ts.map +1 -1
  385. package/dist/theme/domainTokens/index.js +5 -9
  386. package/dist/theme/index.d.ts +1 -0
  387. package/dist/theme/index.d.ts.map +1 -1
  388. package/dist/theme/motionKnobs.d.ts +56 -0
  389. package/dist/theme/motionKnobs.d.ts.map +1 -0
  390. package/dist/theme/motionKnobs.js +48 -0
  391. package/dist/theme/resolveThemeValues.d.ts +11 -4
  392. package/dist/theme/resolveThemeValues.d.ts.map +1 -1
  393. package/dist/theme/resolveThemeValues.js +40 -4
  394. package/dist/theme/themeAdaptations.d.ts +7 -3
  395. package/dist/theme/themeAdaptations.d.ts.map +1 -1
  396. package/dist/theme/themeAdaptations.js +36 -7
  397. package/dist/theme/themeMotion.d.ts +96 -0
  398. package/dist/theme/themeMotion.d.ts.map +1 -0
  399. package/dist/theme/themeMotion.js +177 -0
  400. package/dist/theme/tokenReferences.d.ts +31 -0
  401. package/dist/theme/tokenReferences.d.ts.map +1 -0
  402. package/dist/theme/tokenReferences.js +132 -0
  403. package/dist/theme/tokens.d.ts +1 -0
  404. package/dist/theme/tokens.d.ts.map +1 -1
  405. package/dist/theme/tokens.js +9 -129
  406. package/dist/theme/tokens.stylex.d.ts +12 -0
  407. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  408. package/dist/theme/tokens.stylex.js +12 -0
  409. package/dist/utils/focusOutline.stylex.d.ts +6 -0
  410. package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
  411. package/dist/utils/focusOutline.stylex.js +7 -0
  412. package/dist/utils/focusReturn.d.ts +17 -1
  413. package/dist/utils/focusReturn.d.ts.map +1 -1
  414. package/dist/utils/focusReturn.js +11 -4
  415. package/dist/utils/getNodeText.d.ts +8 -0
  416. package/dist/utils/getNodeText.d.ts.map +1 -0
  417. package/dist/utils/getNodeText.js +37 -0
  418. package/dist/utils/interactionModality.d.ts +11 -2
  419. package/dist/utils/interactionModality.d.ts.map +1 -1
  420. package/dist/utils/interactionModality.js +58 -5
  421. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  422. package/dist/utils/interactionOverlay.stylex.js +17 -8
  423. package/dist/utils/plainDate.d.ts +2 -0
  424. package/dist/utils/plainDate.d.ts.map +1 -1
  425. package/dist/utils/plainDate.js +46 -3
  426. package/dist/utils/presentation.d.ts +50 -0
  427. package/dist/utils/presentation.d.ts.map +1 -0
  428. package/dist/utils/presentation.js +125 -0
  429. package/dist/utils/pressFeedback.d.ts.map +1 -1
  430. package/dist/utils/pressFeedback.js +20 -1
  431. package/dist/utils/primaryClick.d.ts +11 -0
  432. package/dist/utils/primaryClick.d.ts.map +1 -0
  433. package/dist/utils/primaryClick.js +25 -0
  434. package/dist/utils/sharedMutationObserver.d.ts +19 -11
  435. package/dist/utils/sharedMutationObserver.d.ts.map +1 -1
  436. package/dist/utils/sharedMutationObserver.js +66 -26
  437. package/dist/utils/timeFormat.d.ts +47 -0
  438. package/dist/utils/timeFormat.d.ts.map +1 -0
  439. package/dist/utils/timeFormat.js +240 -0
  440. package/dist/utils/touchPresentation.d.ts +2 -2
  441. package/dist/utils/touchPresentation.d.ts.map +1 -1
  442. package/dist/utils/touchPresentation.js +13 -8
  443. package/dist/utils/touchPresentation.stylex.d.ts +15 -0
  444. package/dist/utils/touchPresentation.stylex.d.ts.map +1 -0
  445. package/dist/utils/touchPresentation.stylex.js +33 -0
  446. package/dist/utils/touchQueries.d.ts +13 -0
  447. package/dist/utils/touchQueries.d.ts.map +1 -0
  448. package/dist/utils/touchQueries.js +15 -0
  449. package/dist/utils/unicodeDigits.d.ts +20 -0
  450. package/dist/utils/unicodeDigits.d.ts.map +1 -0
  451. package/dist/utils/unicodeDigits.js +70 -0
  452. package/dist/utils/useFocusAcrossSwap.d.ts +19 -0
  453. package/dist/utils/useFocusAcrossSwap.d.ts.map +1 -0
  454. package/dist/utils/useFocusAcrossSwap.js +41 -0
  455. package/locales/af-ZA.json +0 -21
  456. package/locales/ar-SA.json +0 -21
  457. package/locales/ca-ES.json +0 -21
  458. package/locales/cs-CZ.json +0 -21
  459. package/locales/da-DK.json +0 -21
  460. package/locales/de-DE.json +0 -21
  461. package/locales/el-GR.json +0 -21
  462. package/locales/en.json +35 -23
  463. package/locales/es-ES.json +0 -21
  464. package/locales/fi-FI.json +0 -21
  465. package/locales/fr-FR.json +0 -21
  466. package/locales/he-IL.json +0 -21
  467. package/locales/hu-HU.json +0 -21
  468. package/locales/it-IT.json +0 -21
  469. package/locales/ja-JP.json +0 -21
  470. package/locales/ko-KR.json +0 -21
  471. package/locales/nl-NL.json +0 -21
  472. package/locales/no-NO.json +0 -21
  473. package/locales/pl-PL.json +0 -21
  474. package/locales/pseudo.json +23 -14
  475. package/locales/pt-BR.json +0 -21
  476. package/locales/pt-PT.json +0 -21
  477. package/locales/ro-RO.json +0 -21
  478. package/locales/ru-RU.json +0 -21
  479. package/locales/sr-SP.json +0 -21
  480. package/locales/sv-SE.json +0 -21
  481. package/locales/tr-TR.json +0 -21
  482. package/locales/uk-UA.json +0 -21
  483. package/locales/vi-VN.json +0 -21
  484. package/locales/zh-CN.json +0 -21
  485. package/locales/zh-TW.json +0 -21
  486. package/package.json +5 -4
  487. package/src/AlertDialog/AlertDialog.tsx +6 -5
  488. package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +18 -6
  489. package/src/AppShell/AppShell.doc.mjs +1 -1
  490. package/src/AppShell/AppShell.spec.md +9 -12
  491. package/src/AppShell/AppShell.test.tsx +164 -2
  492. package/src/AppShell/AppShell.tsx +225 -5
  493. package/src/AppShell/__tests__/AppShellMainKeyboard.a11y.browser.spec.ts +534 -0
  494. package/src/AppShell/observeMainOverflow.test.ts +173 -0
  495. package/src/AppShell/observeMainOverflow.ts +143 -0
  496. package/src/Avatar/Avatar.spec.md +22 -22
  497. package/src/Avatar/Avatar.tsx +18 -1
  498. package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +126 -0
  499. package/src/Badge/Badge.doc.mjs +1 -1
  500. package/src/Badge/Badge.tsx +19 -2
  501. package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +260 -0
  502. package/src/BottomSheet/BottomSheet.test.tsx +46 -0
  503. package/src/BottomSheet/BottomSheet.tsx +1 -1
  504. package/src/BottomSheet/BottomSheetPanel.tsx +2 -1
  505. package/src/BottomSheet/useSheetGestures.test.ts +52 -0
  506. package/src/BottomSheet/useSheetGestures.ts +37 -6
  507. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +18 -6
  508. package/src/Button/Button.tsx +4 -4
  509. package/src/Calendar/Calendar.spec.md +87 -48
  510. package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +21 -7
  511. package/src/Carousel/Carousel.doc.mjs +1 -1
  512. package/src/Carousel/Carousel.spec.md +9 -9
  513. package/src/Carousel/Carousel.test.tsx +124 -3
  514. package/src/Carousel/Carousel.tsx +10 -2
  515. package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
  516. package/src/Carousel/__tests__/Carousel.a11y.known-failures.ts +1 -16
  517. package/src/Chat/ChatComposer.spec.md +75 -59
  518. package/src/Chat/ChatComposerTokenElement.spec.md +45 -33
  519. package/src/Chat/ChatDictationButton.spec.md +126 -81
  520. package/src/Chat/ChatLayout.spec.md +41 -36
  521. package/src/Chat/ChatLayoutScrollButton.spec.md +87 -103
  522. package/src/Chat/ChatMessage.spec.md +64 -65
  523. package/src/Chat/ChatSendButton.spec.md +78 -67
  524. package/src/CheckboxInput/CheckboxInput.tsx +6 -5
  525. package/src/Citation/Citation.spec.md +60 -47
  526. package/src/ClickableCard/ClickableCard.test.tsx +96 -0
  527. package/src/ClickableCard/ClickableCard.tsx +48 -4
  528. package/src/CodeBlock/__tests__/CodeBlockCopyClearance.a11y.chromium.spec.ts +38 -3
  529. package/src/Collapsible/Collapsible.spec.md +2 -0
  530. package/src/Collapsible/CollapsibleGroup.spec.md +57 -29
  531. package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +18 -7
  532. package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +18 -6
  533. package/src/ComplexSelector/ComplexSelector.test.tsx +148 -0
  534. package/src/ComplexSelector/ComplexSelector.tsx +41 -4
  535. package/src/ContextMenu/ContextMenu.spec.md +84 -56
  536. package/src/ContextMenu/ContextMenu.test.tsx +35 -0
  537. package/src/ContextMenu/ContextMenuItem.spec.md +132 -0
  538. package/src/DateInput/DateInput.spec.md +74 -57
  539. package/src/DateInput/DateInput.test.tsx +115 -3
  540. package/src/DateInput/DateInput.tsx +29 -14
  541. package/src/DateInput/DateInputTouch.test.tsx +120 -0
  542. package/src/DateInput/MonthScroller.tsx +106 -20
  543. package/src/DateInput/MonthScrollerSettle.test.tsx +165 -0
  544. package/src/DateInput/TouchDateField.tsx +14 -3
  545. package/src/DateInput/Wheel.tsx +9 -6
  546. package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
  547. package/src/DateInput/usePointerDragScroll.ts +34 -10
  548. package/src/DateInput/useScrollSettle.ts +38 -7
  549. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -3
  550. package/src/DateRangeInput/DateRangeInput.tsx +16 -12
  551. package/src/DateTimeInput/DateTimeInput.doc.mjs +10 -8
  552. package/src/DateTimeInput/DateTimeInput.spec.md +75 -51
  553. package/src/DateTimeInput/DateTimeInput.test.tsx +81 -0
  554. package/src/DateTimeInput/DateTimeInput.tsx +46 -24
  555. package/src/DateTimeInput/NativeTimeSegment.tsx +4 -6
  556. package/src/DateTimeInput/TouchDateTimeField.tsx +3 -7
  557. package/src/Dialog/Dialog.test.tsx +216 -2
  558. package/src/Dialog/Dialog.tsx +42 -9
  559. package/src/Dialog/DialogHeader.tsx +5 -4
  560. package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +202 -0
  561. package/src/Divider/Divider.tsx +2 -1
  562. package/src/Drawer/Drawer.spec.md +111 -80
  563. package/src/Drawer/Drawer.test.tsx +35 -0
  564. package/src/Drawer/Drawer.tsx +13 -2
  565. package/src/Drawer/DrawerHeader.spec.md +181 -0
  566. package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +267 -0
  567. package/src/DropdownMenu/DropdownMenu.spec.md +198 -218
  568. package/src/DropdownMenu/DropdownMenu.test.tsx +158 -0
  569. package/src/DropdownMenu/DropdownMenu.tsx +43 -21
  570. package/src/DropdownMenu/DropdownMenuCheckboxItem.spec.md +192 -0
  571. package/src/DropdownMenu/DropdownMenuDivider.spec.md +25 -31
  572. package/src/DropdownMenu/DropdownMenuGroup.spec.md +145 -0
  573. package/src/DropdownMenu/DropdownMenuItem.spec.md +48 -42
  574. package/src/DropdownMenu/DropdownMenuRadioGroup.spec.md +34 -37
  575. package/src/DropdownMenu/DropdownMenuRadioItem.spec.md +54 -53
  576. package/src/DropdownMenu/DropdownMenuSubMenu.spec.md +47 -41
  577. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +34 -0
  578. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -5
  579. package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +19 -7
  580. package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +21 -9
  581. package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +60 -0
  582. package/src/DropdownMenu/lazyMenuBottomSheet.ts +36 -7
  583. package/src/DropdownMenu/renderDropdownItems.tsx +24 -19
  584. package/src/EmptyState/EmptyState.spec.md +35 -29
  585. package/src/EmptyState/EmptyState.tsx +2 -1
  586. package/src/Field/FieldLabel.tsx +5 -4
  587. package/src/Field/InputClearButton.tsx +3 -3
  588. package/src/Field/PanelSearchInput.tsx +2 -2
  589. package/src/FieldStatus/FieldStatus.tsx +9 -2
  590. package/src/FieldStatus/__tests__/FieldStatusAudit.a11y.chromium.spec.ts +477 -0
  591. package/src/FileInput/FileInput.test.tsx +159 -0
  592. package/src/FileInput/FileInput.tsx +34 -6
  593. package/src/FileInput/__tests__/FileInputAudit.a11y.chromium.spec.ts +796 -0
  594. package/src/FormLayout/FormLayout.spec.md +11 -20
  595. package/src/Heading/Heading.tsx +1 -1
  596. package/src/Icon/Icon.tsx +1 -1
  597. package/src/Indicator/CheckIndicator.spec.md +47 -42
  598. package/src/Indicator/CheckIndicator.tsx +2 -1
  599. package/src/Indicator/CheckboxIndicator.spec.md +40 -37
  600. package/src/Indicator/CheckboxIndicator.tsx +3 -1
  601. package/src/Indicator/Indicator.spec.md +188 -0
  602. package/src/Indicator/RadioIndicator.tsx +3 -1
  603. package/src/Item/Item.test.tsx +60 -0
  604. package/src/Item/Item.tsx +16 -8
  605. package/src/Item/ItemSwipeLayer.tsx +1 -1
  606. package/src/Kbd/Kbd.spec.md +81 -38
  607. package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +126 -0
  608. package/src/Layer/popoverOperations.test.ts +205 -0
  609. package/src/Layer/popoverOperations.ts +172 -0
  610. package/src/Layer/useLayer.test.tsx +426 -4
  611. package/src/Layer/useLayer.tsx +145 -77
  612. package/src/Layout/Layout.spec.md +127 -131
  613. package/src/Layout/Layout.tsx +1 -1
  614. package/src/Layout/LayoutContent.spec.md +205 -0
  615. package/src/Layout/LayoutContent.tsx +1 -1
  616. package/src/Layout/LayoutFooter.spec.md +190 -0
  617. package/src/Layout/LayoutFooter.tsx +1 -1
  618. package/src/Layout/LayoutHeader.spec.md +193 -0
  619. package/src/Layout/LayoutHeader.tsx +1 -1
  620. package/src/Layout/LayoutPanel.spec.md +194 -0
  621. package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +18 -6
  622. package/src/Lightbox/Lightbox.test.tsx +18 -0
  623. package/src/Lightbox/Lightbox.tsx +5 -0
  624. package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +8 -4
  625. package/src/Link/Link.spec.md +3 -2
  626. package/src/Link/Link.tsx +11 -0
  627. package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
  628. package/src/Link/__tests__/Link.truncation.a11y.chromium.spec.ts +58 -0
  629. package/src/List/List.tsx +1 -1
  630. package/src/List/ListItem.spec.md +205 -0
  631. package/src/List/ListItem.tsx +3 -3
  632. package/src/Markdown/plugins/headingLinks.a11y.chromium.spec.ts +1 -1
  633. package/src/MetadataList/MetadataList.spec.md +187 -0
  634. package/src/MetadataList/MetadataListItem.spec.md +165 -0
  635. package/src/MobileNav/MobileNav.test.tsx +15 -0
  636. package/src/MobileNav/MobileNav.tsx +9 -1
  637. package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +89 -0
  638. package/src/MoreMenu/MoreMenu.test.tsx +11 -0
  639. package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +7 -8
  640. package/src/MultiSelector/MultiSelector.spec.md +7 -4
  641. package/src/MultiSelector/MultiSelector.test.tsx +270 -1
  642. package/src/MultiSelector/MultiSelector.tsx +25 -10
  643. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +8 -1
  644. package/src/NavMenu/NavHeadingMenu.spec.md +1 -5
  645. package/src/NavMenu/NavHeadingMenuItem.tsx +5 -39
  646. package/src/NumberInput/NumberInput.doc.mjs +13 -7
  647. package/src/NumberInput/NumberInput.spec.md +59 -37
  648. package/src/NumberInput/NumberInput.test.tsx +68 -7
  649. package/src/NumberInput/NumberInput.tsx +44 -4
  650. package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
  651. package/src/NumberInput/numberParser.ts +7 -45
  652. package/src/Outline/Outline.spec.md +165 -69
  653. package/src/Outline/Outline.test.tsx +67 -2
  654. package/src/Outline/Outline.tsx +23 -0
  655. package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +3 -4
  656. package/src/OverflowList/OverflowList.spec.md +102 -55
  657. package/src/Pagination/Pagination.spec.md +158 -84
  658. package/src/Popover/Popover.test.tsx +84 -0
  659. package/src/Popover/Popover.tsx +34 -14
  660. package/src/Popover/__tests__/PopoverSecondDocument.a11y.chromium.spec.ts +70 -8
  661. package/src/Popover/usePopover.tsx +10 -3
  662. package/src/PowerSearch/PowerSearch.test.tsx +24 -0
  663. package/src/PowerSearch/PowerSearch.tsx +42 -31
  664. package/src/ProgressBar/ProgressBar.spec.md +143 -119
  665. package/src/ProgressBar/ProgressBar.test.tsx +108 -32
  666. package/src/ProgressBar/ProgressBar.tsx +58 -10
  667. package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +21 -9
  668. package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +831 -0
  669. package/src/RadioList/RadioList.spec.md +1 -1
  670. package/src/RadioList/RadioList.test.tsx +84 -0
  671. package/src/RadioList/RadioListItem.tsx +11 -2
  672. package/src/Resizable/Resizable.spec.md +144 -124
  673. package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +21 -14
  674. package/src/Resizable/useResizable.test.ts +43 -0
  675. package/src/Resizable/useResizable.ts +32 -9
  676. package/src/SegmentedControl/SegmentedControl.test.tsx +84 -0
  677. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -5
  678. package/src/Selector/Selector.test.tsx +90 -1
  679. package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +8 -1
  680. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +8 -1
  681. package/src/Selector/useSelectorPresentation.ts +31 -3
  682. package/src/SideNav/SideNav.test.tsx +151 -4
  683. package/src/SideNav/SideNavItem.spec.md +14 -24
  684. package/src/SideNav/SideNavItem.tsx +27 -10
  685. package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +176 -51
  686. package/src/Skeleton/Skeleton.tsx +3 -1
  687. package/src/Slider/Slider.test.tsx +31 -0
  688. package/src/Slider/Slider.tsx +8 -3
  689. package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
  690. package/src/Spinner/Spinner.tsx +5 -3
  691. package/src/Stack/Stack.tsx +1 -1
  692. package/src/Stack/StackItem.tsx +1 -1
  693. package/src/Stepper/Step.spec.md +36 -42
  694. package/src/Stepper/Step.tsx +33 -6
  695. package/src/Stepper/Stepper.doc.mjs +1 -1
  696. package/src/Stepper/Stepper.test.tsx +69 -7
  697. package/src/Switch/Switch.spec.md +1 -1
  698. package/src/Switch/Switch.test.tsx +66 -1
  699. package/src/Switch/Switch.tsx +11 -3
  700. package/src/TabList/TabList.test.tsx +58 -4
  701. package/src/TabList/TabList.tsx +16 -1
  702. package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +163 -0
  703. package/src/Table/Table.spec.md +1 -1
  704. package/src/Table/Table.test.tsx +32 -0
  705. package/src/Table/Table.tsx +43 -11
  706. package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
  707. package/src/Table/__tests__/Table.a11y.states.ts +1 -5
  708. package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
  709. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
  710. package/src/Table/plugins/sortable/useTableSortable.test.tsx +73 -144
  711. package/src/Table/plugins/sortable/useTableSortable.tsx +44 -73
  712. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +9 -21
  713. package/src/Text/Text.tsx +1 -1
  714. package/src/Text/useTruncation.test.tsx +128 -1
  715. package/src/Text/useTruncation.ts +23 -5
  716. package/src/TextArea/TextArea.spec.md +10 -13
  717. package/src/TextArea/TextArea.test.tsx +60 -0
  718. package/src/TextArea/TextArea.tsx +15 -1
  719. package/src/TextInput/TextInput.test.tsx +21 -0
  720. package/src/TextInput/TextInput.tsx +3 -1
  721. package/src/TimeInput/NativeTimeInput.test.tsx +17 -0
  722. package/src/TimeInput/Presentation.test.tsx +21 -0
  723. package/src/TimeInput/TimeInput.doc.mjs +8 -8
  724. package/src/TimeInput/TimeInput.spec.md +58 -61
  725. package/src/TimeInput/TimeInput.test.tsx +76 -0
  726. package/src/TimeInput/TimeInput.tsx +36 -18
  727. package/src/TimeInput/TouchTimeField.tsx +4 -6
  728. package/src/Timestamp/Timestamp.spec.md +6 -12
  729. package/src/Timestamp/Timestamp.test.tsx +30 -5
  730. package/src/Timestamp/Timestamp.tsx +6 -2
  731. package/src/Timestamp/TimestampHoverCard.tsx +4 -4
  732. package/src/Toast/Toast.spec.md +15 -24
  733. package/src/Toast/Toast.tsx +104 -36
  734. package/src/Toast/ToastViewport.test.tsx +798 -1
  735. package/src/Toast/ToastViewport.tsx +121 -53
  736. package/src/ToggleButton/ToggleButton.test.tsx +27 -0
  737. package/src/ToggleButton/ToggleButtonGroup.tsx +20 -1
  738. package/src/Token/Token.doc.mjs +2 -2
  739. package/src/Token/Token.spec.md +52 -61
  740. package/src/Token/Token.test.tsx +104 -0
  741. package/src/Token/Token.tsx +75 -5
  742. package/src/Token/TokenLink.tsx +21 -7
  743. package/src/Tokenizer/Tokenizer.spec.md +18 -4
  744. package/src/Tokenizer/Tokenizer.test.tsx +176 -0
  745. package/src/Tokenizer/Tokenizer.tsx +48 -12
  746. package/src/Tokenizer/TokenizerBottomSheet.test.tsx +23 -4
  747. package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
  748. package/src/Tokenizer/TokenizerClearAllMessageContext.ts +21 -0
  749. package/src/Toolbar/Toolbar.spec.md +5 -6
  750. package/src/Toolbar/Toolbar.test.tsx +30 -0
  751. package/src/Toolbar/Toolbar.tsx +2 -1
  752. package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +18 -6
  753. package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +18 -7
  754. package/src/TopNav/TopNav.test.tsx +27 -0
  755. package/src/TopNav/TopNavMegaMenu.test.tsx +21 -0
  756. package/src/TopNav/TopNavMegaMenu.tsx +4 -1
  757. package/src/TopNav/TopNavMenu.test.tsx +17 -0
  758. package/src/TopNav/TopNavMenu.tsx +1 -0
  759. package/src/TreeList/TreeList.test.tsx +26 -0
  760. package/src/TreeList/TreeListItem.tsx +26 -4
  761. package/src/Typeahead/BaseTypeahead.doc.mjs +3 -3
  762. package/src/Typeahead/BaseTypeahead.spec.md +45 -45
  763. package/src/Typeahead/BaseTypeahead.tsx +48 -9
  764. package/src/Typeahead/Typeahead.test.tsx +294 -11
  765. package/src/Typeahead/Typeahead.tsx +51 -9
  766. package/src/__tests__/internalModulesNotExperimental.test.ts +88 -0
  767. package/src/__tests__/pressState.ts +8 -4
  768. package/src/gestures/GestureArena.ts +111 -11
  769. package/src/gestures/GestureHost.ts +2064 -0
  770. package/src/gestures/GestureRecognizer.ts +21 -1
  771. package/src/gestures/LongPressGestureRecognizer.ts +4 -0
  772. package/src/gestures/PanGestureRecognizer.ts +4 -0
  773. package/src/gestures/PinchGestureRecognizer.ts +148 -0
  774. package/src/gestures/PressTracker.ts +386 -0
  775. package/src/gestures/README.md +420 -0
  776. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +256 -0
  777. package/src/gestures/SwipeGestureRecognizer.ts +197 -0
  778. package/src/gestures/TapGestureRecognizer.ts +4 -0
  779. package/src/gestures/VelocityTracker.ts +10 -3
  780. package/src/gestures/__tests__/GestureHost.test.ts +2136 -0
  781. package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
  782. package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
  783. package/src/gestures/__tests__/PressTracker.test.ts +275 -0
  784. package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +498 -0
  785. package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +108 -0
  786. package/src/gestures/__tests__/arena.test.ts +40 -0
  787. package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +193 -0
  788. package/src/gestures/__tests__/browser/build-fixture.mjs +46 -0
  789. package/src/gestures/__tests__/browser/fixture.ts +307 -0
  790. package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +1137 -0
  791. package/src/gestures/__tests__/browserNegotiation.test.ts +293 -0
  792. package/src/gestures/__tests__/haptics.test.ts +187 -0
  793. package/src/gestures/__tests__/harness.ts +52 -4
  794. package/src/gestures/__tests__/pressTrackerFactory.test.ts +59 -0
  795. package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
  796. package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
  797. package/src/gestures/__tests__/useGestureRecognizer.test.tsx +570 -0
  798. package/src/gestures/haptics.ts +203 -0
  799. package/src/gestures/index.ts +79 -0
  800. package/src/gestures/nativeScroll.ts +277 -0
  801. package/src/gestures/touchAction.ts +191 -0
  802. package/src/gestures/touchActionRule.ts +157 -0
  803. package/src/gestures/types.ts +30 -9
  804. package/src/gestures/useGestureRecognizer.ts +305 -0
  805. package/src/hooks/index.ts +5 -1
  806. package/src/hooks/modalAnnounce.ts +129 -72
  807. package/src/hooks/scrollKeyboardDelegation.test.ts +33 -0
  808. package/src/hooks/scrollKeyboardDelegation.ts +9 -3
  809. package/src/hooks/useAdaptivePresentation.ts +4 -1
  810. package/src/hooks/useAnnounce.doc.mjs +35 -3
  811. package/src/hooks/useAnnounce.replace.test.tsx +516 -0
  812. package/src/hooks/useAnnounce.ts +209 -102
  813. package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +10 -1
  814. package/src/hooks/useAnnounceRenderedText.ts +17 -3
  815. package/src/hooks/useBusyAnnouncement.ts +7 -10
  816. package/src/hooks/useMenuHover.ts +15 -1
  817. package/src/hooks/useScrollOverflow.doc.mjs +1 -1
  818. package/src/hooks/useScrollOverflow.test.tsx +102 -1
  819. package/src/hooks/useScrollOverflow.ts +59 -10
  820. package/src/i18n/__tests__/useListFormatter.test.tsx +58 -0
  821. package/src/i18n/generated-locales/af-ZA.generated.ts +0 -7
  822. package/src/i18n/generated-locales/ar-SA.generated.ts +0 -6
  823. package/src/i18n/generated-locales/ca-ES.generated.ts +0 -7
  824. package/src/i18n/generated-locales/cs-CZ.generated.ts +0 -6
  825. package/src/i18n/generated-locales/da-DK.generated.ts +0 -6
  826. package/src/i18n/generated-locales/de-DE.generated.ts +0 -6
  827. package/src/i18n/generated-locales/el-GR.generated.ts +0 -7
  828. package/src/i18n/generated-locales/en.generated.ts +9 -6
  829. package/src/i18n/generated-locales/es-ES.generated.ts +0 -7
  830. package/src/i18n/generated-locales/fi-FI.generated.ts +0 -6
  831. package/src/i18n/generated-locales/fr-FR.generated.ts +0 -7
  832. package/src/i18n/generated-locales/he-IL.generated.ts +0 -6
  833. package/src/i18n/generated-locales/hu-HU.generated.ts +0 -6
  834. package/src/i18n/generated-locales/it-IT.generated.ts +0 -7
  835. package/src/i18n/generated-locales/ja-JP.generated.ts +0 -6
  836. package/src/i18n/generated-locales/ko-KR.generated.ts +0 -6
  837. package/src/i18n/generated-locales/nl-NL.generated.ts +0 -6
  838. package/src/i18n/generated-locales/no-NO.generated.ts +0 -6
  839. package/src/i18n/generated-locales/pl-PL.generated.ts +0 -7
  840. package/src/i18n/generated-locales/pseudo.generated.ts +9 -6
  841. package/src/i18n/generated-locales/pt-BR.generated.ts +0 -7
  842. package/src/i18n/generated-locales/pt-PT.generated.ts +0 -7
  843. package/src/i18n/generated-locales/ro-RO.generated.ts +0 -6
  844. package/src/i18n/generated-locales/ru-RU.generated.ts +0 -7
  845. package/src/i18n/generated-locales/sr-SP.generated.ts +0 -6
  846. package/src/i18n/generated-locales/sv-SE.generated.ts +0 -6
  847. package/src/i18n/generated-locales/tr-TR.generated.ts +0 -7
  848. package/src/i18n/generated-locales/uk-UA.generated.ts +0 -7
  849. package/src/i18n/generated-locales/vi-VN.generated.ts +0 -6
  850. package/src/i18n/generated-locales/zh-CN.generated.ts +0 -6
  851. package/src/i18n/generated-locales/zh-TW.generated.ts +0 -6
  852. package/src/i18n/useListFormatter.ts +42 -0
  853. package/src/motion/MEASUREMENTS.md +2 -1
  854. package/src/motion/README.md +113 -33
  855. package/src/motion/__tests__/animator.interaction.browser.spec.ts +843 -0
  856. package/src/motion/__tests__/motionBundle.ts +14 -0
  857. package/src/motion/animator.test.ts +1125 -32
  858. package/src/motion/animator.ts +932 -130
  859. package/src/motion/coast.ts +10 -3
  860. package/src/motion/reducedMotion.ts +12 -2
  861. package/src/motion/reducedMotionPlan.test.ts +26 -0
  862. package/src/motion/reducedMotionPlan.ts +20 -1
  863. package/src/motion/resolveMotion.test.ts +123 -0
  864. package/src/motion/resolveMotion.ts +68 -0
  865. package/src/motion/roleValue.ts +2 -1
  866. package/src/motion/roles.test.ts +21 -4
  867. package/src/motion/uikit/tableImports.test.ts +293 -0
  868. package/src/motion/uikit/timing.ts +15 -1
  869. package/src/motion/uikit/values.test.ts +23 -12
  870. package/src/theme/Theme.doc.mjs +1 -1
  871. package/src/theme/defineTheme.ts +117 -8
  872. package/src/theme/derivedVarRegistry.test.ts +4 -0
  873. package/src/theme/domainTokens/domainTokenDefaults.ts +19 -0
  874. package/src/theme/domainTokens/index.ts +6 -10
  875. package/src/theme/expandMotionScale.test.ts +1 -1
  876. package/src/theme/index.ts +5 -0
  877. package/src/theme/motionKnobs.ts +82 -0
  878. package/src/theme/resolveThemeValues.ts +68 -6
  879. package/src/theme/themeAdaptations.ts +52 -12
  880. package/src/theme/themeMotion.test.ts +620 -0
  881. package/src/theme/themeMotion.ts +221 -0
  882. package/src/theme/tokenReferences.ts +149 -0
  883. package/src/theme/tokens.stylex.ts +10 -0
  884. package/src/theme/tokens.ts +15 -158
  885. package/src/utils/focusOutline.stylex.ts +28 -0
  886. package/src/utils/focusReturn.ts +17 -6
  887. package/src/utils/getNodeText.test.ts +24 -0
  888. package/src/utils/getNodeText.ts +37 -0
  889. package/src/utils/interactionModality.test.ts +45 -1
  890. package/src/utils/interactionModality.ts +64 -5
  891. package/src/utils/interactionOverlay.stylex.ts +12 -3
  892. package/src/utils/plainDate.test.ts +90 -0
  893. package/src/utils/plainDate.ts +58 -3
  894. package/src/utils/presentation.test.ts +380 -0
  895. package/src/utils/presentation.ts +180 -0
  896. package/src/utils/pressFeedback.test.ts +138 -0
  897. package/src/utils/pressFeedback.ts +34 -11
  898. package/src/utils/pressGesture.test.ts +9 -0
  899. package/src/utils/pressPaintPriority.test.ts +80 -0
  900. package/src/utils/primaryClick.test.ts +38 -0
  901. package/src/utils/primaryClick.ts +28 -0
  902. package/src/utils/sharedMutationObserver.test.ts +54 -1
  903. package/src/utils/sharedMutationObserver.ts +87 -29
  904. package/src/utils/timeFormat.test.ts +204 -0
  905. package/src/utils/timeFormat.ts +314 -0
  906. package/src/utils/touchPresentation.stylex.ts +43 -0
  907. package/src/utils/touchPresentation.test.ts +140 -1
  908. package/src/utils/touchPresentation.ts +13 -8
  909. package/src/utils/touchQueries.ts +15 -0
  910. package/src/utils/unicodeDigits.test.ts +44 -0
  911. package/src/utils/unicodeDigits.ts +71 -0
  912. 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
+ }