@astryxdesign/core 0.7.5-canary.fccd771 → 0.7.5

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 (1346) hide show
  1. package/CHANGELOG.md +211 -10
  2. package/README.md +15 -12
  3. package/dist/AlertDialog/AlertDialog.js +1 -1
  4. package/dist/AppShell/AppShell.d.ts +0 -22
  5. package/dist/AppShell/AppShell.d.ts.map +1 -1
  6. package/dist/AppShell/AppShell.js +155 -1
  7. package/dist/Avatar/AvatarStatusDot.js +2 -2
  8. package/dist/Badge/Badge.d.ts.map +1 -1
  9. package/dist/Badge/Badge.js +18 -2
  10. package/dist/Banner/Banner.d.ts +1 -0
  11. package/dist/Banner/Banner.d.ts.map +1 -1
  12. package/dist/Banner/Banner.js +64 -9
  13. package/dist/BottomSheet/BottomSheet.d.ts +53 -5
  14. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  15. package/dist/BottomSheet/BottomSheet.js +435 -198
  16. package/dist/BottomSheet/BottomSheetHostContext.d.ts +8 -0
  17. package/dist/BottomSheet/BottomSheetHostContext.d.ts.map +1 -0
  18. package/dist/BottomSheet/BottomSheetHostContext.js +35 -0
  19. package/dist/BottomSheet/BottomSheetPanel.d.ts +9 -1
  20. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  21. package/dist/BottomSheet/BottomSheetPanel.js +77 -23
  22. package/dist/BottomSheet/BottomSheetSwitcher.d.ts +53 -14
  23. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  24. package/dist/BottomSheet/BottomSheetSwitcher.js +229 -27
  25. package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts +6 -0
  26. package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts.map +1 -1
  27. package/dist/BottomSheet/bottomSheetEscape.d.ts +3 -0
  28. package/dist/BottomSheet/bottomSheetEscape.d.ts.map +1 -0
  29. package/dist/BottomSheet/bottomSheetEscape.js +20 -0
  30. package/dist/BottomSheet/bottomSheetStack.d.ts +262 -0
  31. package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -0
  32. package/dist/BottomSheet/bottomSheetStack.js +1675 -0
  33. package/dist/BottomSheet/useSheetGestures.d.ts +19 -3
  34. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  35. package/dist/BottomSheet/useSheetGestures.js +43 -14
  36. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  37. package/dist/Breadcrumbs/BreadcrumbItem.js +36 -3
  38. package/dist/Button/Button.d.ts.map +1 -1
  39. package/dist/Button/Button.js +18 -7
  40. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  41. package/dist/Chat/ChatComposer.js +25 -32
  42. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  43. package/dist/Chat/ChatComposerInput.js +55 -16
  44. package/dist/Chat/ChatMessageMetadata.js +2 -2
  45. package/dist/Chat/ChatPastedTextToken.d.ts.map +1 -1
  46. package/dist/Chat/ChatPastedTextToken.js +7 -6
  47. package/dist/Chat/ChatToolCalls.js +4 -4
  48. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  49. package/dist/ClickableCard/ClickableCard.js +10 -6
  50. package/dist/CodeBlock/CodeBlock.d.ts +25 -2
  51. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  52. package/dist/CodeBlock/CodeBlock.js +58 -19
  53. package/dist/CodeBlock/grammar.d.ts +134 -0
  54. package/dist/CodeBlock/grammar.d.ts.map +1 -0
  55. package/dist/CodeBlock/grammar.js +219 -0
  56. package/dist/CodeBlock/index.d.ts +2 -0
  57. package/dist/CodeBlock/index.d.ts.map +1 -1
  58. package/dist/CodeBlock/index.js +1 -0
  59. package/dist/CodeBlock/languages/dockerfile.d.ts +3 -0
  60. package/dist/CodeBlock/languages/dockerfile.d.ts.map +1 -0
  61. package/dist/CodeBlock/languages/dockerfile.js +45 -0
  62. package/dist/CodeBlock/languages/graphql.d.ts +3 -0
  63. package/dist/CodeBlock/languages/graphql.d.ts.map +1 -0
  64. package/dist/CodeBlock/languages/graphql.js +27 -0
  65. package/dist/CodeBlock/languages/java.d.ts +3 -0
  66. package/dist/CodeBlock/languages/java.d.ts.map +1 -0
  67. package/dist/CodeBlock/languages/java.js +24 -0
  68. package/dist/CodeBlock/languages/lua.d.ts +3 -0
  69. package/dist/CodeBlock/languages/lua.d.ts.map +1 -0
  70. package/dist/CodeBlock/languages/lua.js +21 -0
  71. package/dist/CodeBlock/languages/objective-c.d.ts +3 -0
  72. package/dist/CodeBlock/languages/objective-c.d.ts.map +1 -0
  73. package/dist/CodeBlock/languages/objective-c.js +27 -0
  74. package/dist/CodeBlock/languages/powershell.d.ts +3 -0
  75. package/dist/CodeBlock/languages/powershell.d.ts.map +1 -0
  76. package/dist/CodeBlock/languages/powershell.js +30 -0
  77. package/dist/CodeBlock/languages/ruby.d.ts +3 -0
  78. package/dist/CodeBlock/languages/ruby.d.ts.map +1 -0
  79. package/dist/CodeBlock/languages/ruby.js +24 -0
  80. package/dist/CodeBlock/languages/thrift.d.ts +3 -0
  81. package/dist/CodeBlock/languages/thrift.d.ts.map +1 -0
  82. package/dist/CodeBlock/languages/thrift.js +18 -0
  83. package/dist/CodeBlock/languages/toml.d.ts +3 -0
  84. package/dist/CodeBlock/languages/toml.d.ts.map +1 -0
  85. package/dist/CodeBlock/languages/toml.js +53 -0
  86. package/dist/CodeBlock/tokenizer.d.ts +8 -4
  87. package/dist/CodeBlock/tokenizer.d.ts.map +1 -1
  88. package/dist/CodeBlock/tokenizer.js +158 -8
  89. package/dist/Collapsible/Collapsible.d.ts +8 -1
  90. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  91. package/dist/Collapsible/Collapsible.js +84 -2
  92. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  93. package/dist/CommandPalette/CommandPalette.js +15 -1
  94. package/dist/CommandPalette/CommandPaletteEmpty.d.ts.map +1 -1
  95. package/dist/CommandPalette/CommandPaletteEmpty.js +1 -0
  96. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  97. package/dist/CommandPalette/CommandPaletteInput.js +14 -2
  98. package/dist/CommandPalette/busyStartSettle.d.ts +4 -0
  99. package/dist/CommandPalette/busyStartSettle.d.ts.map +1 -0
  100. package/dist/CommandPalette/busyStartSettle.js +23 -0
  101. package/dist/ComplexSelector/ComplexSelector.d.ts +20 -2
  102. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  103. package/dist/ComplexSelector/ComplexSelector.js +42 -7
  104. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  105. package/dist/ContextMenu/ContextMenu.js +48 -13
  106. package/dist/DateInput/DateInput.d.ts.map +1 -1
  107. package/dist/DateInput/DateInput.js +12 -5
  108. package/dist/DateInput/NativeDateField.d.ts.map +1 -1
  109. package/dist/DateInput/NativeDateField.js +2 -1
  110. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  111. package/dist/DateInput/TouchDateField.js +2 -1
  112. package/dist/DateInput/Wheel.d.ts.map +1 -1
  113. package/dist/DateInput/Wheel.js +1 -1
  114. package/dist/Dialog/Dialog.d.ts +4 -0
  115. package/dist/Dialog/Dialog.d.ts.map +1 -1
  116. package/dist/Dialog/Dialog.js +20 -8
  117. package/dist/Drawer/Drawer.d.ts.map +1 -1
  118. package/dist/Drawer/Drawer.js +18 -13
  119. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  120. package/dist/DropdownMenu/DropdownMenu.js +34 -30
  121. package/dist/DropdownMenu/DropdownMenuGroup.d.ts +7 -4
  122. package/dist/DropdownMenu/DropdownMenuGroup.d.ts.map +1 -1
  123. package/dist/DropdownMenu/DropdownMenuGroup.js +10 -4
  124. package/dist/DropdownMenu/DropdownMenuItem.js +3 -3
  125. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +10 -5
  126. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  127. package/dist/DropdownMenu/DropdownMenuRadioItem.js +13 -5
  128. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +6 -6
  129. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  130. package/dist/DropdownMenu/DropdownMenuSubMenu.js +0 -3
  131. package/dist/DropdownMenu/MenuBottomSheet.d.ts +11 -4
  132. package/dist/DropdownMenu/MenuBottomSheet.d.ts.map +1 -1
  133. package/dist/DropdownMenu/MenuBottomSheet.js +35 -9
  134. package/dist/DropdownMenu/MenuBottomSheetActionList.js +3 -3
  135. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +2 -0
  136. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
  137. package/dist/DropdownMenu/lazyMenuBottomSheet.js +25 -3
  138. package/dist/DropdownMenu/menuBottomSheet.stylex.d.ts +23 -0
  139. package/dist/DropdownMenu/menuBottomSheet.stylex.d.ts.map +1 -0
  140. package/dist/DropdownMenu/menuBottomSheet.stylex.js +29 -0
  141. package/dist/DropdownMenu/menuItemHover.d.ts +3 -0
  142. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -1
  143. package/dist/DropdownMenu/menuItemHover.js +14 -1
  144. package/dist/DropdownMenu/menuTouchAction.stylex.d.ts +25 -0
  145. package/dist/DropdownMenu/menuTouchAction.stylex.d.ts.map +1 -0
  146. package/dist/DropdownMenu/menuTouchAction.stylex.js +29 -0
  147. package/dist/DropdownMenu/useMenuDrillIn.d.ts.map +1 -1
  148. package/dist/DropdownMenu/useMenuDrillIn.js +7 -5
  149. package/dist/EmptyState/EmptyState.d.ts +4 -2
  150. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  151. package/dist/EmptyState/EmptyState.js +6 -4
  152. package/dist/Field/Field.js +1 -1
  153. package/dist/Field/FieldLabel.js +1 -1
  154. package/dist/Field/PanelSearchInput.d.ts +9 -1
  155. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  156. package/dist/Field/PanelSearchInput.js +31 -22
  157. package/dist/Field/inputDisabledFocus.d.ts +14 -0
  158. package/dist/Field/inputDisabledFocus.d.ts.map +1 -0
  159. package/dist/Field/inputDisabledFocus.js +19 -0
  160. package/dist/Field/inputStyles.stylex.d.ts +9 -9
  161. package/dist/Field/inputStyles.stylex.js +9 -9
  162. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  163. package/dist/FieldStatus/FieldStatus.js +7 -3
  164. package/dist/FileInput/FileInput.d.ts.map +1 -1
  165. package/dist/FileInput/FileInput.js +22 -12
  166. package/dist/Icon/Icon.d.ts +37 -5
  167. package/dist/Icon/Icon.d.ts.map +1 -1
  168. package/dist/Icon/Icon.js +65 -11
  169. package/dist/Icon/IconSize.stylex.d.ts +16 -11
  170. package/dist/Icon/IconSize.stylex.d.ts.map +1 -1
  171. package/dist/Icon/IconSize.stylex.js +27 -11
  172. package/dist/Icon/globalIconRegistry.d.ts +71 -4
  173. package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
  174. package/dist/Icon/globalIconRegistry.js +163 -23
  175. package/dist/Icon/index.d.ts +26 -2
  176. package/dist/Icon/index.d.ts.map +1 -1
  177. package/dist/Icon/index.js +24 -1
  178. package/dist/Icon/useIcon.d.ts +5 -1
  179. package/dist/Icon/useIcon.d.ts.map +1 -1
  180. package/dist/Icon/useIcon.js +5 -1
  181. package/dist/InputGroup/InputGroup.d.ts +1 -1
  182. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  183. package/dist/InputGroup/InputGroup.js +46 -36
  184. package/dist/InputGroup/InputGroupInternalContext.d.ts +4 -0
  185. package/dist/InputGroup/InputGroupInternalContext.d.ts.map +1 -0
  186. package/dist/InputGroup/InputGroupInternalContext.js +15 -0
  187. package/dist/InputGroup/InputGroupText.d.ts.map +1 -1
  188. package/dist/InputGroup/InputGroupText.js +2 -0
  189. package/dist/InputGroup/groupStyles.d.ts +9 -0
  190. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  191. package/dist/InputGroup/groupStyles.js +28 -14
  192. package/dist/Item/Item.d.ts +5 -1
  193. package/dist/Item/Item.d.ts.map +1 -1
  194. package/dist/Item/Item.js +23 -7
  195. package/dist/Item/ItemMarkerColumns.a11y.chromium.spec.d.ts +2 -0
  196. package/dist/Item/ItemMarkerColumns.a11y.chromium.spec.d.ts.map +1 -0
  197. package/dist/Item/ItemMarkerColumns.a11y.chromium.spec.js +132 -0
  198. package/dist/Item/ItemMarkerColumnsContext.d.ts +14 -0
  199. package/dist/Item/ItemMarkerColumnsContext.d.ts.map +1 -0
  200. package/dist/Item/ItemMarkerColumnsContext.js +18 -0
  201. package/dist/Item/ItemSwipeLayer.d.ts.map +1 -1
  202. package/dist/Item/ItemSwipeLayer.js +3 -0
  203. package/dist/Item/useSwipeAction.d.ts.map +1 -1
  204. package/dist/Item/useSwipeAction.js +60 -5
  205. package/dist/Kbd/Kbd.d.ts +2 -2
  206. package/dist/Kbd/Kbd.d.ts.map +1 -1
  207. package/dist/Kbd/Kbd.js +18 -11
  208. package/dist/Layer/layerAnimations.stylex.d.ts +9 -5
  209. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  210. package/dist/Layer/layerAnimations.stylex.js +23 -10
  211. package/dist/Layer/layerSlideRules.d.ts +62 -2
  212. package/dist/Layer/layerSlideRules.d.ts.map +1 -1
  213. package/dist/Layer/layerSlideRules.js +124 -3
  214. package/dist/Layer/layerStack.d.ts +12 -9
  215. package/dist/Layer/layerStack.d.ts.map +1 -1
  216. package/dist/Layer/layerStack.js +116 -53
  217. package/dist/Layer/modalOutlet.d.ts +44 -6
  218. package/dist/Layer/modalOutlet.d.ts.map +1 -1
  219. package/dist/Layer/modalOutlet.js +150 -14
  220. package/dist/Layer/preserveAnimations.d.ts +11 -0
  221. package/dist/Layer/preserveAnimations.d.ts.map +1 -0
  222. package/dist/Layer/preserveAnimations.js +245 -0
  223. package/dist/Layer/useLayer.d.ts +19 -2
  224. package/dist/Layer/useLayer.d.ts.map +1 -1
  225. package/dist/Layer/useLayer.js +531 -44
  226. package/dist/Layer/useLayerDismissal.d.ts +10 -7
  227. package/dist/Layer/useLayerDismissal.d.ts.map +1 -1
  228. package/dist/Layer/useLayerDismissal.js +8 -8
  229. package/dist/Layer/useTouchTrigger.d.ts +14 -1
  230. package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
  231. package/dist/Layer/useTouchTrigger.js +72 -17
  232. package/dist/Layout/Layout.d.ts.map +1 -1
  233. package/dist/Layout/Layout.js +4 -0
  234. package/dist/Layout/LayoutContent.d.ts.map +1 -1
  235. package/dist/Layout/LayoutContent.js +2 -2
  236. package/dist/Layout/LayoutFooter.d.ts.map +1 -1
  237. package/dist/Layout/LayoutFooter.js +2 -1
  238. package/dist/Layout/LayoutHeader.d.ts.map +1 -1
  239. package/dist/Layout/LayoutHeader.js +2 -1
  240. package/dist/Layout/layoutEdges.stylex.d.ts +20 -0
  241. package/dist/Layout/layoutEdges.stylex.d.ts.map +1 -0
  242. package/dist/Layout/layoutEdges.stylex.js +28 -0
  243. package/dist/Lightbox/Lightbox.d.ts +5 -2
  244. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  245. package/dist/Lightbox/Lightbox.js +111 -89
  246. package/dist/Lightbox/LightboxKeyboard.a11y.browser.spec.d.ts +2 -0
  247. package/dist/Lightbox/LightboxKeyboard.a11y.browser.spec.d.ts.map +1 -0
  248. package/dist/Lightbox/LightboxKeyboard.a11y.browser.spec.js +78 -0
  249. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.d.ts +2 -0
  250. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.d.ts.map +1 -0
  251. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +65 -0
  252. package/dist/List/List.d.ts +2 -1
  253. package/dist/List/List.d.ts.map +1 -1
  254. package/dist/List/List.js +9 -2
  255. package/dist/List/ListContext.d.ts +16 -4
  256. package/dist/List/ListContext.d.ts.map +1 -1
  257. package/dist/List/ListContext.js +10 -5
  258. package/dist/List/ListItem.d.ts +7 -1
  259. package/dist/List/ListItem.d.ts.map +1 -1
  260. package/dist/List/ListItem.js +52 -8
  261. package/dist/List/ListMarkers.a11y.chromium.spec.d.ts +2 -0
  262. package/dist/List/ListMarkers.a11y.chromium.spec.d.ts.map +1 -0
  263. package/dist/List/ListMarkers.a11y.chromium.spec.js +677 -0
  264. package/dist/Markdown/Markdown.d.ts +11 -1
  265. package/dist/Markdown/Markdown.d.ts.map +1 -1
  266. package/dist/Markdown/Markdown.fr23.bench.js +3 -1
  267. package/dist/Markdown/Markdown.fr23.sampling.d.ts +16 -0
  268. package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -1
  269. package/dist/Markdown/Markdown.fr23.sampling.js +13 -4
  270. package/dist/Markdown/Markdown.js +41 -14
  271. package/dist/Markdown/MarkdownTable.a11y.chromium.spec.js +1 -0
  272. package/dist/MobileNav/MobileNav.d.ts +2 -1
  273. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  274. package/dist/MobileNav/MobileNav.js +46 -37
  275. package/dist/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.js +1 -0
  276. package/dist/MobileNav/MobileNavToggle.d.ts +7 -3
  277. package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
  278. package/dist/MobileNav/MobileNavToggle.js +11 -3
  279. package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +53 -6
  280. package/dist/MultiSelector/MultiSelector.d.ts +1 -1
  281. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  282. package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.js +1 -0
  283. package/dist/MultiSelector/MultiSelector.js +21 -5
  284. package/dist/MultiSelector/OptionActions.a11y.chromium.spec.js +1 -0
  285. package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
  286. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  287. package/dist/NavMenu/NavHeadingMenu.js +29 -5
  288. package/dist/NavMenu/NavHeadingMenuItem.d.ts.map +1 -1
  289. package/dist/NavMenu/NavHeadingMenuItem.js +51 -7
  290. package/dist/NavMenu/NavMenuContext.d.ts +9 -0
  291. package/dist/NavMenu/NavMenuContext.d.ts.map +1 -1
  292. package/dist/NavMenu/NavMenuContext.js +9 -0
  293. package/dist/NumberInput/NumberInput.d.ts +4 -4
  294. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  295. package/dist/NumberInput/NumberInput.js +61 -24
  296. package/dist/Overlay/Overlay.d.ts +3 -3
  297. package/dist/Overlay/Overlay.d.ts.map +1 -1
  298. package/dist/Overlay/Overlay.js +12 -5
  299. package/dist/Popover/Popover.d.ts +41 -2
  300. package/dist/Popover/Popover.d.ts.map +1 -1
  301. package/dist/Popover/Popover.js +276 -44
  302. package/dist/Popover/index.d.ts +1 -1
  303. package/dist/Popover/index.d.ts.map +1 -1
  304. package/dist/Popover/lazyPopoverBottomSheet.d.ts +23 -0
  305. package/dist/Popover/lazyPopoverBottomSheet.d.ts.map +1 -0
  306. package/dist/Popover/lazyPopoverBottomSheet.js +40 -0
  307. package/dist/Popover/usePopover.d.ts.map +1 -1
  308. package/dist/Popover/usePopover.js +11 -5
  309. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  310. package/dist/PowerSearch/PowerSearch.js +7 -5
  311. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  312. package/dist/ProgressBar/ProgressBar.js +8 -0
  313. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  314. package/dist/RadioList/RadioListItem.js +10 -2
  315. package/dist/ScrollableArea/ScrollableArea.d.ts.map +1 -1
  316. package/dist/ScrollableArea/ScrollableArea.js +1 -1
  317. package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
  318. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  319. package/dist/SegmentedControl/SegmentedControl.js +6 -2
  320. package/dist/SelectableCard/SelectableCard.d.ts +5 -5
  321. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  322. package/dist/SelectableCard/SelectableCard.js +15 -11
  323. package/dist/Selector/Selector.d.ts.map +1 -1
  324. package/dist/Selector/Selector.js +27 -8
  325. package/dist/Selector/hooks.d.ts +52 -6
  326. package/dist/Selector/hooks.d.ts.map +1 -1
  327. package/dist/Selector/hooks.js +145 -2
  328. package/dist/SideNav/SideNav.d.ts.map +1 -1
  329. package/dist/SideNav/SideNav.js +58 -2
  330. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  331. package/dist/SideNav/SideNavHeading.js +79 -3
  332. package/dist/SideNav/SideNavItem.d.ts +5 -1
  333. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  334. package/dist/SideNav/SideNavItem.js +36 -13
  335. package/dist/SideNav/railMotion.d.ts +54 -0
  336. package/dist/SideNav/railMotion.d.ts.map +1 -0
  337. package/dist/SideNav/railMotion.js +253 -0
  338. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  339. package/dist/Skeleton/Skeleton.js +12 -3
  340. package/dist/Slider/Slider.d.ts.map +1 -1
  341. package/dist/Slider/Slider.js +52 -15
  342. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  343. package/dist/StatusDot/StatusDot.js +12 -0
  344. package/dist/Stepper/Step.d.ts.map +1 -1
  345. package/dist/Stepper/Step.js +10 -6
  346. package/dist/Switch/Switch.d.ts.map +1 -1
  347. package/dist/Switch/Switch.js +5 -5
  348. package/dist/Switch/switch.markers.stylex.d.ts +7 -2
  349. package/dist/Switch/switch.markers.stylex.d.ts.map +1 -1
  350. package/dist/Switch/switch.markers.stylex.js +8 -3
  351. package/dist/TabList/Tab.d.ts.map +1 -1
  352. package/dist/TabList/Tab.js +5 -1
  353. package/dist/TabList/TabMenu.d.ts.map +1 -1
  354. package/dist/TabList/TabMenu.js +25 -3
  355. package/dist/Table/TableCell.d.ts.map +1 -1
  356. package/dist/Table/TableCell.js +5 -1
  357. package/dist/Table/TableHeaderCell.d.ts.map +1 -1
  358. package/dist/Table/TableHeaderCell.js +1 -0
  359. package/dist/Table/TableRow.d.ts.map +1 -1
  360. package/dist/Table/TableRow.js +3 -0
  361. package/dist/Table/glidingDivider.d.ts +96 -0
  362. package/dist/Table/glidingDivider.d.ts.map +1 -0
  363. package/dist/Table/glidingDivider.js +275 -0
  364. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  365. package/dist/Table/plugins/columnResize/useTableColumnResize.js +11 -2
  366. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +8 -0
  367. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  368. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +374 -13
  369. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  370. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +244 -6
  371. package/dist/Table/rowDivider.d.ts +34 -0
  372. package/dist/Table/rowDivider.d.ts.map +1 -0
  373. package/dist/Table/rowDivider.js +118 -0
  374. package/dist/TextArea/TextArea.d.ts +6 -4
  375. package/dist/TextArea/TextArea.d.ts.map +1 -1
  376. package/dist/TextArea/TextArea.js +15 -12
  377. package/dist/TextInput/TextInput.d.ts +7 -5
  378. package/dist/TextInput/TextInput.d.ts.map +1 -1
  379. package/dist/TextInput/TextInput.js +43 -22
  380. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  381. package/dist/Thumbnail/Thumbnail.js +45 -11
  382. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  383. package/dist/TimeInput/TimeInput.js +12 -4
  384. package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
  385. package/dist/TimeInput/TouchTimeField.js +2 -1
  386. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  387. package/dist/Toast/ToastViewport.js +62 -6
  388. package/dist/Tokenizer/Tokenizer.d.ts +71 -4
  389. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  390. package/dist/Tokenizer/Tokenizer.js +430 -45
  391. package/dist/Tokenizer/TokenizerBottomSheet.d.ts +98 -0
  392. package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -0
  393. package/dist/Tokenizer/TokenizerBottomSheet.js +721 -0
  394. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  395. package/dist/Tooltip/useTooltip.js +9 -3
  396. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  397. package/dist/TopNav/TopNavHeading.js +26 -0
  398. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  399. package/dist/TopNav/TopNavMegaMenu.js +4 -4
  400. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  401. package/dist/TopNav/TopNavMenu.js +32 -4
  402. package/dist/TreeList/TreeList.d.ts +8 -23
  403. package/dist/TreeList/TreeList.d.ts.map +1 -1
  404. package/dist/TreeList/TreeList.js +175 -3
  405. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  406. package/dist/TreeList/TreeListBranches.js +7 -5
  407. package/dist/TreeList/TreeListItem.d.ts +7 -1
  408. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  409. package/dist/TreeList/TreeListItem.js +5 -3
  410. package/dist/Typeahead/BaseTypeahead.d.ts +1 -1
  411. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  412. package/dist/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.d.ts +2 -0
  413. package/dist/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.d.ts.map +1 -0
  414. package/dist/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.js +118 -0
  415. package/dist/Typeahead/BaseTypeahead.js +27 -11
  416. package/dist/Typeahead/Typeahead.d.ts +1 -1
  417. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  418. package/dist/Typeahead/Typeahead.js +31 -14
  419. package/dist/astryx.css +164 -41
  420. package/dist/gestures/GestureArena.d.ts +175 -0
  421. package/dist/gestures/GestureArena.d.ts.map +1 -0
  422. package/dist/gestures/GestureArena.js +816 -0
  423. package/dist/gestures/GestureRecognizer.d.ts +239 -0
  424. package/dist/gestures/GestureRecognizer.d.ts.map +1 -0
  425. package/dist/gestures/GestureRecognizer.js +487 -0
  426. package/dist/gestures/LongPressGestureRecognizer.d.ts +32 -0
  427. package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -0
  428. package/dist/gestures/LongPressGestureRecognizer.js +135 -0
  429. package/dist/gestures/PanGestureRecognizer.d.ts +117 -0
  430. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -0
  431. package/dist/gestures/PanGestureRecognizer.js +349 -0
  432. package/dist/gestures/TapGestureRecognizer.d.ts +39 -0
  433. package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -0
  434. package/dist/gestures/TapGestureRecognizer.js +151 -0
  435. package/dist/gestures/VelocityTracker.d.ts +51 -0
  436. package/dist/gestures/VelocityTracker.d.ts.map +1 -0
  437. package/dist/gestures/VelocityTracker.js +186 -0
  438. package/dist/gestures/geometry.d.ts +17 -0
  439. package/dist/gestures/geometry.d.ts.map +1 -0
  440. package/dist/gestures/geometry.js +55 -0
  441. package/dist/gestures/types.d.ts +139 -0
  442. package/dist/gestures/types.d.ts.map +1 -0
  443. package/dist/gestures/types.js +67 -0
  444. package/dist/hooks/AnnounceRenderedText.d.ts +17 -0
  445. package/dist/hooks/AnnounceRenderedText.d.ts.map +1 -0
  446. package/dist/hooks/AnnounceRenderedText.js +32 -0
  447. package/dist/hooks/ModalAnnounceProvider.d.ts +41 -0
  448. package/dist/hooks/ModalAnnounceProvider.d.ts.map +1 -0
  449. package/dist/hooks/ModalAnnounceProvider.js +133 -0
  450. package/dist/hooks/actionGroupTracker.d.ts +98 -0
  451. package/dist/hooks/actionGroupTracker.d.ts.map +1 -0
  452. package/dist/hooks/actionGroupTracker.js +338 -0
  453. package/dist/hooks/index.d.ts +2 -0
  454. package/dist/hooks/index.d.ts.map +1 -1
  455. package/dist/hooks/index.js +1 -0
  456. package/dist/hooks/menuPressOnItems.d.ts +19 -0
  457. package/dist/hooks/menuPressOnItems.d.ts.map +1 -0
  458. package/dist/hooks/menuPressOnItems.js +32 -0
  459. package/dist/hooks/modalAnnounce.d.ts +18 -0
  460. package/dist/hooks/modalAnnounce.d.ts.map +1 -0
  461. package/dist/hooks/modalAnnounce.js +382 -0
  462. package/dist/hooks/scrollGeometry.d.ts +28 -0
  463. package/dist/hooks/scrollGeometry.d.ts.map +1 -1
  464. package/dist/hooks/scrollGeometry.js +36 -2
  465. package/dist/hooks/useAdaptivePresentation.d.ts +9 -1
  466. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
  467. package/dist/hooks/useAdaptivePresentation.js +33 -8
  468. package/dist/hooks/useAnimatedLayout.d.ts +42 -0
  469. package/dist/hooks/useAnimatedLayout.d.ts.map +1 -0
  470. package/dist/hooks/useAnimatedLayout.js +46 -0
  471. package/dist/hooks/useAnnounce.d.ts +132 -1
  472. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  473. package/dist/hooks/useAnnounce.js +356 -27
  474. package/dist/hooks/useAnnounceRenderedText.d.ts +19 -2
  475. package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
  476. package/dist/hooks/useAnnounceRenderedText.js +52 -11
  477. package/dist/hooks/useBusyAnnouncement.d.ts +9 -5
  478. package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
  479. package/dist/hooks/useBusyAnnouncement.js +58 -46
  480. package/dist/hooks/useFocusTrap.d.ts +1 -1
  481. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  482. package/dist/hooks/useFocusTrap.js +57 -26
  483. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  484. package/dist/hooks/useMenuHover.js +6 -2
  485. package/dist/hooks/useMenuPress.d.ts +4 -2
  486. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  487. package/dist/hooks/useMenuPress.js +58 -33
  488. package/dist/hooks/usePressFeedback.d.ts +5 -2
  489. package/dist/hooks/usePressFeedback.d.ts.map +1 -1
  490. package/dist/hooks/usePressFeedback.js +5 -2
  491. package/dist/hooks/useScrollableArea.d.ts +5 -0
  492. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  493. package/dist/hooks/useScrollableArea.js +104 -11
  494. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  495. package/dist/i18n/generated-locales/en.generated.js +33 -0
  496. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  497. package/dist/i18n/generated-locales/pseudo.generated.js +33 -0
  498. package/dist/internal/tokenizer-presentation.d.ts +21 -0
  499. package/dist/internal/tokenizer-presentation.d.ts.map +1 -0
  500. package/dist/internal/tokenizer-presentation.js +21 -0
  501. package/dist/internal/touch.d.ts +26 -0
  502. package/dist/internal/touch.d.ts.map +1 -0
  503. package/dist/internal/touch.js +28 -0
  504. package/dist/motion/LayoutChangeSnapshot.d.ts +33 -0
  505. package/dist/motion/LayoutChangeSnapshot.d.ts.map +1 -0
  506. package/dist/motion/LayoutChangeSnapshot.js +37 -0
  507. package/dist/motion/animatedLayout.d.ts +190 -0
  508. package/dist/motion/animatedLayout.d.ts.map +1 -0
  509. package/dist/motion/animatedLayout.js +1502 -0
  510. package/dist/motion/animator.d.ts +240 -0
  511. package/dist/motion/animator.d.ts.map +1 -0
  512. package/dist/motion/animator.js +2203 -0
  513. package/dist/motion/bezier.d.ts +18 -0
  514. package/dist/motion/bezier.d.ts.map +1 -0
  515. package/dist/motion/bezier.js +60 -0
  516. package/dist/motion/coast.d.ts +61 -0
  517. package/dist/motion/coast.d.ts.map +1 -0
  518. package/dist/motion/coast.js +107 -0
  519. package/dist/motion/decay.d.ts +41 -0
  520. package/dist/motion/decay.d.ts.map +1 -0
  521. package/dist/motion/decay.js +90 -0
  522. package/dist/motion/projection.d.ts +36 -0
  523. package/dist/motion/projection.d.ts.map +1 -0
  524. package/dist/motion/projection.js +92 -0
  525. package/dist/motion/reducedMotion.d.ts +25 -0
  526. package/dist/motion/reducedMotion.d.ts.map +1 -0
  527. package/dist/motion/reducedMotion.js +85 -0
  528. package/dist/motion/reducedMotion.stylex.d.ts +19 -0
  529. package/dist/motion/reducedMotion.stylex.d.ts.map +1 -0
  530. package/dist/motion/reducedMotion.stylex.js +37 -0
  531. package/dist/motion/reducedMotionPlan.d.ts +89 -0
  532. package/dist/motion/reducedMotionPlan.d.ts.map +1 -0
  533. package/dist/motion/reducedMotionPlan.js +194 -0
  534. package/dist/motion/resolveSnapPoint.d.ts +52 -0
  535. package/dist/motion/resolveSnapPoint.d.ts.map +1 -0
  536. package/dist/motion/resolveSnapPoint.js +135 -0
  537. package/dist/motion/roleValue.d.ts +33 -0
  538. package/dist/motion/roleValue.d.ts.map +1 -0
  539. package/dist/motion/roleValue.js +84 -0
  540. package/dist/motion/roles.d.ts +79 -0
  541. package/dist/motion/roles.d.ts.map +1 -0
  542. package/dist/motion/roles.js +199 -0
  543. package/dist/motion/rubberBand.d.ts +20 -0
  544. package/dist/motion/rubberBand.d.ts.map +1 -0
  545. package/dist/motion/rubberBand.js +91 -0
  546. package/dist/motion/selectPage.d.ts +26 -0
  547. package/dist/motion/selectPage.d.ts.map +1 -0
  548. package/dist/motion/selectPage.js +55 -0
  549. package/dist/motion/spring.d.ts +193 -0
  550. package/dist/motion/spring.d.ts.map +1 -0
  551. package/dist/motion/spring.js +442 -0
  552. package/dist/motion/transientCopy.d.ts +33 -0
  553. package/dist/motion/transientCopy.d.ts.map +1 -0
  554. package/dist/motion/transientCopy.js +314 -0
  555. package/dist/motion/uikit/gestures.d.ts +642 -0
  556. package/dist/motion/uikit/gestures.d.ts.map +1 -0
  557. package/dist/motion/uikit/gestures.js +428 -0
  558. package/dist/motion/uikit/index.d.ts +24 -0
  559. package/dist/motion/uikit/index.d.ts.map +1 -0
  560. package/dist/motion/uikit/index.js +26 -0
  561. package/dist/motion/uikit/navigation.d.ts +54 -0
  562. package/dist/motion/uikit/navigation.d.ts.map +1 -0
  563. package/dist/motion/uikit/navigation.js +83 -0
  564. package/dist/motion/uikit/scroll.d.ts +116 -0
  565. package/dist/motion/uikit/scroll.d.ts.map +1 -0
  566. package/dist/motion/uikit/scroll.js +146 -0
  567. package/dist/motion/uikit/springs.d.ts +545 -0
  568. package/dist/motion/uikit/springs.d.ts.map +1 -0
  569. package/dist/motion/uikit/springs.js +548 -0
  570. package/dist/motion/uikit/timing.d.ts +202 -0
  571. package/dist/motion/uikit/timing.d.ts.map +1 -0
  572. package/dist/motion/uikit/timing.js +201 -0
  573. package/dist/reset.a11y.chromium.spec.js +1 -0
  574. package/dist/reset.until-found.a11y.browser.spec.js +1 -0
  575. package/dist/theme/declarationBoundary.d.ts +13 -0
  576. package/dist/theme/declarationBoundary.d.ts.map +1 -1
  577. package/dist/theme/declarationBoundary.js +264 -1
  578. package/dist/theme/defineTheme.d.ts +111 -11
  579. package/dist/theme/defineTheme.d.ts.map +1 -1
  580. package/dist/theme/defineTheme.js +97 -7
  581. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  582. package/dist/theme/derivedVarRegistry.js +9 -0
  583. package/dist/theme/generateThemeRules.d.ts +6 -2
  584. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  585. package/dist/theme/generateThemeRules.js +468 -24
  586. package/dist/theme/index.d.ts +2 -2
  587. package/dist/theme/index.d.ts.map +1 -1
  588. package/dist/theme/index.js +1 -1
  589. package/dist/theme/statusColor.d.ts +48 -0
  590. package/dist/theme/statusColor.d.ts.map +1 -0
  591. package/dist/theme/statusColor.js +203 -0
  592. package/dist/theme/statusRoleDerivation.d.ts +11 -0
  593. package/dist/theme/statusRoleDerivation.d.ts.map +1 -0
  594. package/dist/theme/statusRoleDerivation.js +236 -0
  595. package/dist/theme/syntax/SyntaxTheme.d.ts +1 -1
  596. package/dist/theme/syntax/SyntaxTheme.js +1 -1
  597. package/dist/theme/syntax/defineSyntaxTheme.js +1 -1
  598. package/dist/theme/syntax/presets.d.ts +1 -1
  599. package/dist/theme/syntax/presets.js +1 -1
  600. package/dist/theme/syntax/tokens.d.ts +1 -1
  601. package/dist/theme/syntax/tokens.js +1 -1
  602. package/dist/theme/themeAdaptations.d.ts +25 -1
  603. package/dist/theme/themeAdaptations.d.ts.map +1 -1
  604. package/dist/theme/themeAdaptations.js +30 -1
  605. package/dist/theme/tokens.d.ts.map +1 -1
  606. package/dist/theme/tokens.js +16 -1
  607. package/dist/theme/tokens.stylex.d.ts +42 -2
  608. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  609. package/dist/theme/tokens.stylex.js +54 -3
  610. package/dist/theme/useTheme.d.ts +4 -2
  611. package/dist/theme/useTheme.d.ts.map +1 -1
  612. package/dist/theme/useTheme.js +10 -4
  613. package/dist/utils/edgeAutoscroll.d.ts +53 -0
  614. package/dist/utils/edgeAutoscroll.d.ts.map +1 -0
  615. package/dist/utils/edgeAutoscroll.js +81 -0
  616. package/dist/utils/hitArea.d.ts +72 -0
  617. package/dist/utils/hitArea.d.ts.map +1 -0
  618. package/dist/utils/hitArea.js +681 -0
  619. package/dist/utils/interactionOverlay.stylex.d.ts +4 -1
  620. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  621. package/dist/utils/interactionOverlay.stylex.js +4 -1
  622. package/dist/utils/pressFeedback.d.ts +5 -1
  623. package/dist/utils/pressFeedback.d.ts.map +1 -1
  624. package/dist/utils/pressFeedback.js +285 -54
  625. package/dist/utils/pressGesture.d.ts +13 -1
  626. package/dist/utils/pressGesture.d.ts.map +1 -1
  627. package/dist/utils/pressGesture.js +40 -1
  628. package/dist/utils/touchPresentation.d.ts +48 -0
  629. package/dist/utils/touchPresentation.d.ts.map +1 -0
  630. package/dist/utils/touchPresentation.js +133 -0
  631. package/locales/af-ZA.json +1 -1
  632. package/locales/ar-SA.json +1 -1
  633. package/locales/ca-ES.json +1 -1
  634. package/locales/cs-CZ.json +1 -1
  635. package/locales/da-DK.json +1 -1
  636. package/locales/de-DE.json +1 -1
  637. package/locales/el-GR.json +1 -1
  638. package/locales/en.json +132 -0
  639. package/locales/es-ES.json +1 -1
  640. package/locales/fi-FI.json +1 -1
  641. package/locales/fr-FR.json +1 -1
  642. package/locales/he-IL.json +1 -1
  643. package/locales/hu-HU.json +1 -1
  644. package/locales/it-IT.json +1 -1
  645. package/locales/ja-JP.json +1 -1
  646. package/locales/ko-KR.json +1 -1
  647. package/locales/nl-NL.json +1 -1
  648. package/locales/no-NO.json +1 -1
  649. package/locales/pl-PL.json +1 -1
  650. package/locales/pseudo.json +99 -0
  651. package/locales/pt-BR.json +1 -1
  652. package/locales/pt-PT.json +1 -1
  653. package/locales/ro-RO.json +1 -1
  654. package/locales/ru-RU.json +1 -1
  655. package/locales/sr-SP.json +1 -1
  656. package/locales/sv-SE.json +1 -1
  657. package/locales/tr-TR.json +1 -1
  658. package/locales/uk-UA.json +1 -1
  659. package/locales/vi-VN.json +1 -1
  660. package/locales/zh-CN.json +1 -1
  661. package/locales/zh-TW.json +1 -1
  662. package/package.json +63 -8
  663. package/src/AlertDialog/AlertDialog.spec.md +85 -31
  664. package/src/AlertDialog/AlertDialog.tsx +1 -1
  665. package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +1 -0
  666. package/src/AppShell/AppShell.spec.md +334 -0
  667. package/src/AppShell/AppShell.tsx +170 -2
  668. package/src/AspectRatio/AspectRatio.spec.md +179 -0
  669. package/src/AspectRatio/__tests__/AspectRatioFitLayers.a11y.browser.spec.ts +1 -0
  670. package/src/Avatar/Avatar.spec.md +253 -0
  671. package/src/Avatar/AvatarStatusDot.spec.md +93 -79
  672. package/src/Avatar/AvatarStatusDot.test.tsx +22 -0
  673. package/src/Avatar/AvatarStatusDot.tsx +2 -2
  674. package/src/AvatarGroup/AvatarGroup.spec.md +205 -0
  675. package/src/AvatarGroup/AvatarGroupOverflow.spec.md +123 -120
  676. package/src/Badge/Badge.spec.md +207 -0
  677. package/src/Badge/Badge.test.tsx +13 -0
  678. package/src/Badge/Badge.tsx +38 -2
  679. package/src/Banner/Banner.spec.md +41 -28
  680. package/src/Banner/Banner.test.tsx +118 -16
  681. package/src/Banner/Banner.tsx +94 -7
  682. package/src/Blockquote/Blockquote.spec.md +171 -0
  683. package/src/BottomSheet/BottomSheet.doc.mjs +106 -24
  684. package/src/BottomSheet/BottomSheet.spec.md +271 -40
  685. package/src/BottomSheet/BottomSheet.test.tsx +491 -5
  686. package/src/BottomSheet/BottomSheet.tsx +544 -145
  687. package/src/BottomSheet/BottomSheetHostContext.ts +44 -0
  688. package/src/BottomSheet/BottomSheetPanel.test.tsx +73 -19
  689. package/src/BottomSheet/BottomSheetPanel.tsx +178 -63
  690. package/src/BottomSheet/BottomSheetReplace.test.tsx +1638 -0
  691. package/src/BottomSheet/BottomSheetStacking.announce.test.tsx +246 -0
  692. package/src/BottomSheet/BottomSheetStacking.test.tsx +3184 -0
  693. package/src/BottomSheet/BottomSheetSwitcher.doc.mjs +27 -31
  694. package/src/BottomSheet/BottomSheetSwitcher.spec.md +138 -43
  695. package/src/BottomSheet/BottomSheetSwitcher.tsx +275 -26
  696. package/src/BottomSheet/BottomSheetSwitcherContext.ts +6 -0
  697. package/src/BottomSheet/__tests__/BottomSheetDrag.a11y.chromium.spec.ts +1 -0
  698. package/src/BottomSheet/__tests__/BottomSheetFocusReturn.a11y.browser.spec.ts +1 -0
  699. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +4 -1
  700. package/src/BottomSheet/__tests__/BottomSheetNativeModal.a11y.browser.spec.ts +1 -0
  701. package/src/BottomSheet/__tests__/BottomSheetPinchZoom.a11y.chromium.spec.ts +1 -0
  702. package/src/BottomSheet/__tests__/BottomSheetToastOutlet.a11y.chromium.spec.ts +83 -0
  703. package/src/BottomSheet/bottomSheetEscape.ts +21 -0
  704. package/src/BottomSheet/bottomSheetStack.ts +2054 -0
  705. package/src/BottomSheet/useSheetGestures.ts +68 -12
  706. package/src/Breadcrumbs/BreadcrumbItem.spec.md +104 -60
  707. package/src/Breadcrumbs/BreadcrumbItem.tsx +30 -1
  708. package/src/Breadcrumbs/Breadcrumbs.spec.md +165 -0
  709. package/src/Breadcrumbs/Breadcrumbs.test.tsx +90 -0
  710. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +1 -0
  711. package/src/Button/Button.spec.md +322 -0
  712. package/src/Button/Button.test.tsx +8 -1
  713. package/src/Button/Button.tsx +36 -7
  714. package/src/Button/__tests__/Button.a11y.chromium.spec.ts +1 -0
  715. package/src/ButtonGroup/ButtonGroup.spec.md +220 -0
  716. package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +1 -0
  717. package/src/Card/Card.spec.md +205 -0
  718. package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +1 -0
  719. package/src/Center/Center.spec.md +104 -124
  720. package/src/Chat/ChatComposer.test.tsx +54 -0
  721. package/src/Chat/ChatComposer.tsx +41 -27
  722. package/src/Chat/ChatComposerInput.test.tsx +165 -21
  723. package/src/Chat/ChatComposerInput.tsx +73 -16
  724. package/src/Chat/ChatMessageMetadata.tsx +1 -1
  725. package/src/Chat/ChatPastedTextToken.test.tsx +71 -0
  726. package/src/Chat/ChatPastedTextToken.tsx +8 -7
  727. package/src/Chat/ChatToolCalls.tsx +5 -5
  728. package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +22 -4
  729. package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +1 -0
  730. package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +1 -0
  731. package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +1 -0
  732. package/src/Chat/__tests__/ChatSendButton.a11y.chromium.spec.ts +1 -0
  733. package/src/Chat/__tests__/ChatSystemMessage.a11y.chromium.spec.ts +1 -0
  734. package/src/Chat/__tests__/ChatTokenizedText.a11y.chromium.spec.ts +1 -0
  735. package/src/Chat/__tests__/useChatStreamScroll.a11y.chromium.spec.ts +1 -0
  736. package/src/CheckboxInput/CheckboxInput.spec.md +97 -66
  737. package/src/CheckboxInput/__tests__/Checkbox.a11y.chromium.spec.ts +1 -0
  738. package/src/CheckboxList/CheckboxList.spec.md +92 -78
  739. package/src/CheckboxList/CheckboxListItem.spec.md +86 -60
  740. package/src/CheckboxList/__tests__/CheckboxList.a11y.chromium.spec.ts +1 -0
  741. package/src/ClickableCard/ClickableCard.doc.mjs +1 -2
  742. package/src/ClickableCard/ClickableCard.spec.md +124 -128
  743. package/src/ClickableCard/ClickableCard.test.tsx +14 -3
  744. package/src/ClickableCard/ClickableCard.tsx +44 -28
  745. package/src/Code/Code.spec.md +30 -32
  746. package/src/CodeBlock/CodeBlock.doc.mjs +21 -4
  747. package/src/CodeBlock/CodeBlock.spec.md +96 -61
  748. package/src/CodeBlock/CodeBlock.test.tsx +97 -1
  749. package/src/CodeBlock/CodeBlock.tsx +132 -22
  750. package/src/CodeBlock/CodeLanguage.test.tsx +173 -0
  751. package/src/CodeBlock/__tests__/CodeBlockCopyClearance.a11y.chromium.spec.ts +290 -0
  752. package/src/CodeBlock/__tests__/CodeBlockLanguages.a11y.chromium.spec.ts +64 -0
  753. package/src/CodeBlock/__tests__/CodeBlockOverflowStop.a11y.chromium.spec.ts +1 -0
  754. package/src/CodeBlock/__tests__/DiffRowPaint.a11y.chromium.spec.ts +1 -0
  755. package/src/CodeBlock/grammar.ts +291 -0
  756. package/src/CodeBlock/index.ts +7 -0
  757. package/src/CodeBlock/languages/dockerfile.ts +43 -0
  758. package/src/CodeBlock/languages/graphql.ts +30 -0
  759. package/src/CodeBlock/languages/java.ts +28 -0
  760. package/src/CodeBlock/languages/lua.ts +21 -0
  761. package/src/CodeBlock/languages/objective-c.ts +26 -0
  762. package/src/CodeBlock/languages/powershell.ts +31 -0
  763. package/src/CodeBlock/languages/ruby.ts +29 -0
  764. package/src/CodeBlock/languages/thrift.ts +32 -0
  765. package/src/CodeBlock/languages/toml.ts +36 -0
  766. package/src/CodeBlock/languages.test.ts +402 -0
  767. package/src/CodeBlock/tokenizer.ts +176 -16
  768. package/src/CodeBlock/tokenizerBudget.test.ts +112 -0
  769. package/src/Collapsible/Collapsible.doc.mjs +6 -0
  770. package/src/Collapsible/Collapsible.spec.md +26 -23
  771. package/src/Collapsible/Collapsible.tsx +121 -2
  772. package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +1 -0
  773. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.chromium.spec.ts +1 -0
  774. package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +1 -0
  775. package/src/CommandPalette/CommandPalette.perf.test.ts +8 -4
  776. package/src/CommandPalette/CommandPalette.tsx +17 -1
  777. package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +6 -3
  778. package/src/CommandPalette/CommandPaletteEmpty.spec.md +190 -0
  779. package/src/CommandPalette/CommandPaletteEmpty.tsx +4 -0
  780. package/src/CommandPalette/CommandPaletteInput.tsx +21 -2
  781. package/src/CommandPalette/__tests__/CommandPalette.a11y.chromium.spec.ts +1 -0
  782. package/src/CommandPalette/__tests__/CommandPaletteEmptyAudit.a11y.chromium.spec.ts +715 -0
  783. package/src/CommandPalette/__tests__/CommandPaletteFooter.a11y.chromium.spec.ts +3 -2
  784. package/src/CommandPalette/__tests__/CommandPaletteInputAudit.a11y.chromium.spec.ts +1 -0
  785. package/src/CommandPalette/__tests__/CommandPaletteItemAudit.a11y.chromium.spec.ts +1 -0
  786. package/src/CommandPalette/busyStartSettle.ts +26 -0
  787. package/src/ComplexSelector/ComplexSelector.doc.mjs +1 -1
  788. package/src/ComplexSelector/ComplexSelector.focusableDisabled.test.tsx +1 -1
  789. package/src/ComplexSelector/ComplexSelector.fr10.test.tsx +9 -9
  790. package/src/ComplexSelector/ComplexSelector.spec.md +161 -107
  791. package/src/ComplexSelector/ComplexSelector.test.tsx +236 -17
  792. package/src/ComplexSelector/ComplexSelector.tsx +69 -4
  793. package/src/ComplexSelector/__tests__/ComplexSelector.a11y.chromium.spec.ts +965 -0
  794. package/src/ContextMenu/ContextMenu.doc.mjs +1 -1
  795. package/src/ContextMenu/ContextMenu.spec.md +38 -30
  796. package/src/ContextMenu/ContextMenu.test.tsx +189 -11
  797. package/src/ContextMenu/ContextMenu.tsx +75 -17
  798. package/src/ContextMenu/__tests__/ContextMenuAudit.a11y.chromium.spec.ts +1 -0
  799. package/src/ContextMenu/__tests__/ContextMenuCursorAnchor.a11y.browser.spec.ts +1 -0
  800. package/src/ContextMenu/__tests__/ContextMenuLongPress.a11y.chromium.spec.ts +117 -0
  801. package/src/DateInput/DateInput.tsx +9 -4
  802. package/src/DateInput/DateInputTouch.test.tsx +10 -1
  803. package/src/DateInput/NativeDateField.tsx +2 -1
  804. package/src/DateInput/TouchDateField.tsx +2 -1
  805. package/src/DateInput/Wheel.tsx +4 -1
  806. package/src/DateInput/__tests__/DateInputAudit.a11y.chromium.spec.ts +1 -0
  807. package/src/DateInput/__tests__/WheelPinchZoom.a11y.chromium.spec.ts +171 -0
  808. package/src/Dialog/Dialog.doc.mjs +201 -47
  809. package/src/Dialog/Dialog.spec.md +20 -4
  810. package/src/Dialog/Dialog.tsx +37 -10
  811. package/src/Dialog/__tests__/Dialog.a11y.browser.spec.ts +1 -0
  812. package/src/Dialog/__tests__/Dialog.a11y.chromium.spec.ts +1 -0
  813. package/src/Dialog/__tests__/Dialog.reduced-motion.a11y.browser.spec.ts +252 -0
  814. package/src/Divider/Divider.spec.md +79 -70
  815. package/src/Drawer/Drawer.tsx +38 -35
  816. package/src/Drawer/__tests__/DrawerAudit.a11y.chromium.spec.ts +1 -0
  817. package/src/Drawer/__tests__/DrawerHeaderAudit.a11y.chromium.spec.ts +1 -0
  818. package/src/DropdownMenu/DropdownMenu.spec.md +14 -6
  819. package/src/DropdownMenu/DropdownMenu.ssr.test.tsx +44 -8
  820. package/src/DropdownMenu/DropdownMenu.test.tsx +107 -5
  821. package/src/DropdownMenu/DropdownMenu.tsx +51 -34
  822. package/src/DropdownMenu/DropdownMenuGroup.doc.mjs +2 -2
  823. package/src/DropdownMenu/DropdownMenuGroup.tsx +12 -6
  824. package/src/DropdownMenu/DropdownMenuItem.tsx +5 -5
  825. package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +5 -2
  826. package/src/DropdownMenu/DropdownMenuRadioItem.spec.md +226 -0
  827. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +32 -16
  828. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +158 -0
  829. package/src/DropdownMenu/DropdownMenuSheetFirstOpen.test.tsx +72 -0
  830. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +9 -0
  831. package/src/DropdownMenu/DropdownMenuSubMenu.spec.md +225 -0
  832. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +105 -0
  833. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +6 -6
  834. package/src/DropdownMenu/MenuBottomSheet.tsx +42 -7
  835. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +3 -3
  836. package/src/DropdownMenu/__tests__/DropdownMenuDividerAudit.a11y.chromium.spec.ts +1 -0
  837. package/src/DropdownMenu/__tests__/DropdownMenuDrillIn.a11y.chromium.spec.ts +1 -0
  838. package/src/DropdownMenu/__tests__/DropdownMenuFocusReturn.a11y.browser.spec.ts +1 -0
  839. package/src/DropdownMenu/__tests__/DropdownMenuGroupAudit.a11y.chromium.spec.ts +1 -0
  840. package/src/DropdownMenu/__tests__/DropdownMenuItemAudit.a11y.chromium.spec.ts +1 -0
  841. package/src/DropdownMenu/__tests__/DropdownMenuRadioGroupAudit.a11y.chromium.spec.ts +1 -0
  842. package/src/DropdownMenu/__tests__/DropdownMenuRadioItemAudit.a11y.chromium.spec.ts +540 -0
  843. package/src/DropdownMenu/__tests__/DropdownMenuSubMenuAudit.a11y.chromium.spec.ts +671 -0
  844. package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +1 -0
  845. package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +1 -0
  846. package/src/DropdownMenu/__tests__/MenuHeaderFooter.a11y.chromium.spec.ts +1 -0
  847. package/src/DropdownMenu/__tests__/MenuHoverFocus.a11y.chromium.spec.ts +238 -0
  848. package/src/DropdownMenu/__tests__/MenuPinchZoom.a11y.chromium.spec.ts +1 -0
  849. package/src/DropdownMenu/__tests__/MenuPress.a11y.chromium.spec.ts +1 -0
  850. package/src/DropdownMenu/__tests__/SubMenuHeaderFooter.a11y.chromium.spec.ts +1 -0
  851. package/src/DropdownMenu/lazyMenuBottomSheet.ts +28 -2
  852. package/src/DropdownMenu/menuBottomSheet.stylex.ts +33 -0
  853. package/src/DropdownMenu/menuItemHover.ts +13 -1
  854. package/src/DropdownMenu/menuTouchAction.stylex.ts +28 -0
  855. package/src/DropdownMenu/modules/useMenuPress.spec.md +90 -62
  856. package/src/DropdownMenu/useMenuDrillIn.tsx +7 -5
  857. package/src/EmptyState/EmptyState.announce.test.tsx +227 -0
  858. package/src/EmptyState/EmptyState.doc.mjs +1 -1
  859. package/src/EmptyState/EmptyState.spec.md +22 -14
  860. package/src/EmptyState/EmptyState.test.tsx +8 -8
  861. package/src/EmptyState/EmptyState.tsx +7 -5
  862. package/src/Field/Field.spec.md +57 -48
  863. package/src/Field/Field.tsx +1 -1
  864. package/src/Field/FieldLabel.spec.md +70 -59
  865. package/src/Field/FieldLabel.tsx +1 -1
  866. package/src/Field/PanelSearchInput.tsx +23 -13
  867. package/src/Field/__tests__/FieldLabelAudit.a11y.chromium.spec.ts +1 -0
  868. package/src/Field/inputDisabledFocus.ts +28 -0
  869. package/src/Field/inputStyles.stylex.ts +15 -15
  870. package/src/FieldStatus/FieldStatus.test.tsx +12 -0
  871. package/src/FieldStatus/FieldStatus.tsx +12 -3
  872. package/src/FieldStatus/__tests__/StatusMessage.a11y.chromium.spec.ts +1 -0
  873. package/src/FileInput/FileInput.doc.mjs +1 -1
  874. package/src/FileInput/FileInput.test.tsx +102 -0
  875. package/src/FileInput/FileInput.tsx +18 -12
  876. package/src/FormLayout/FormLayout.spec.md +69 -51
  877. package/src/Grid/Grid.spec.md +72 -69
  878. package/src/Grid/GridSpan.spec.md +158 -0
  879. package/src/Heading/Heading.spec.md +198 -0
  880. package/src/HoverCard/HoverCard.spec.md +244 -0
  881. package/src/HoverCard/HoverCard.test.tsx +93 -3
  882. package/src/Icon/Icon.doc.mjs +67 -5
  883. package/src/Icon/Icon.test.tsx +548 -9
  884. package/src/Icon/Icon.tsx +79 -15
  885. package/src/Icon/IconSize.stylex.ts +27 -11
  886. package/src/Icon/globalIconRegistry.test.tsx +395 -3
  887. package/src/Icon/globalIconRegistry.tsx +184 -36
  888. package/src/Icon/index.ts +29 -1
  889. package/src/Icon/useIcon.ts +5 -1
  890. package/src/IconButton/IconButton.spec.md +197 -0
  891. package/src/IconButton/IconButton.test.tsx +5 -2
  892. package/src/InputGroup/InputGroup.spec.md +199 -0
  893. package/src/InputGroup/InputGroup.test.tsx +120 -0
  894. package/src/InputGroup/InputGroup.tsx +59 -52
  895. package/src/InputGroup/InputGroupInternalContext.ts +15 -0
  896. package/src/InputGroup/InputGroupText.spec.md +139 -0
  897. package/src/InputGroup/InputGroupText.tsx +2 -0
  898. package/src/InputGroup/groupStyles.ts +22 -11
  899. package/src/Item/Item.test.tsx +158 -1
  900. package/src/Item/Item.tsx +42 -7
  901. package/src/Item/ItemMarkerColumns.a11y.chromium.spec.ts +211 -0
  902. package/src/Item/ItemMarkerColumnsContext.tsx +20 -0
  903. package/src/Item/ItemSwipeLayer.tsx +9 -0
  904. package/src/Item/__tests__/ItemSwipeActions.a11y.chromium.spec.ts +1 -0
  905. package/src/Item/__tests__/ItemSwipePinchZoom.a11y.chromium.spec.ts +186 -0
  906. package/src/Item/useSwipeAction.ts +71 -5
  907. package/src/Kbd/Kbd.test.tsx +95 -0
  908. package/src/Kbd/Kbd.tsx +30 -23
  909. package/src/Layer/LayerProvider.spec.md +149 -0
  910. package/src/Layer/__tests__/LayerReducedMotion.a11y.chromium.spec.ts +176 -0
  911. package/src/Layer/__tests__/TouchTrigger.a11y.chromium.spec.ts +200 -0
  912. package/src/Layer/layerAnimations.stylex.ts +22 -2
  913. package/src/Layer/layerDismissalInvariants.test.tsx +9 -0
  914. package/src/Layer/layerSlideRules.ts +141 -8
  915. package/src/Layer/layerStack.ts +129 -62
  916. package/src/Layer/modalOutlet.ts +156 -15
  917. package/src/Layer/preserveAnimations.ts +304 -0
  918. package/src/Layer/useLayer.doc.mjs +1 -1
  919. package/src/Layer/useLayer.test.tsx +850 -0
  920. package/src/Layer/useLayer.tsx +644 -58
  921. package/src/Layer/useLayerDismissal.test.tsx +85 -2
  922. package/src/Layer/useLayerDismissal.ts +12 -9
  923. package/src/Layer/useTouchTrigger.ts +95 -41
  924. package/src/Layout/Layout.tsx +18 -0
  925. package/src/Layout/LayoutContent.tsx +5 -14
  926. package/src/Layout/LayoutFooter.tsx +2 -0
  927. package/src/Layout/LayoutHeader.tsx +2 -0
  928. package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +1 -0
  929. package/src/Layout/layoutEdges.stylex.ts +25 -0
  930. package/src/Lightbox/Lightbox.spec.md +9 -8
  931. package/src/Lightbox/Lightbox.test.tsx +83 -0
  932. package/src/Lightbox/Lightbox.tsx +149 -125
  933. package/src/Lightbox/LightboxKeyboard.a11y.browser.spec.ts +78 -0
  934. package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +70 -0
  935. package/src/Link/Link.spec.md +229 -0
  936. package/src/Link/LinkProvider.spec.md +167 -0
  937. package/src/Link/__tests__/Link.a11y.chromium.spec.ts +1 -0
  938. package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +1 -0
  939. package/src/List/List.spec.md +113 -34
  940. package/src/List/List.tsx +13 -1
  941. package/src/List/ListContext.tsx +19 -5
  942. package/src/List/ListItem.doc.mjs +3 -3
  943. package/src/List/ListItem.tsx +97 -28
  944. package/src/List/ListMarkers.a11y.chromium.spec.ts +904 -0
  945. package/src/Markdown/Markdown.codeLanguages.test.tsx +137 -0
  946. package/src/Markdown/Markdown.doc.mjs +12 -0
  947. package/src/Markdown/Markdown.fr23.bench.ts +3 -1
  948. package/src/Markdown/Markdown.fr23.perf.test.ts +45 -3
  949. package/src/Markdown/Markdown.fr23.sampling.ts +13 -4
  950. package/src/Markdown/Markdown.spec.md +71 -59
  951. package/src/Markdown/Markdown.test.tsx +50 -0
  952. package/src/Markdown/Markdown.tsx +61 -8
  953. package/src/Markdown/MarkdownTable.a11y.chromium.spec.ts +1 -0
  954. package/src/Markdown/__tests__/MarkdownNesting.a11y.chromium.spec.ts +1 -0
  955. package/src/MobileNav/MobileNav.doc.mjs +2 -2
  956. package/src/MobileNav/MobileNav.spec.md +161 -64
  957. package/src/MobileNav/MobileNav.test.tsx +27 -10
  958. package/src/MobileNav/MobileNav.tsx +51 -38
  959. package/src/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.ts +1 -0
  960. package/src/MobileNav/MobileNavToggle.test.tsx +63 -0
  961. package/src/MobileNav/MobileNavToggle.tsx +13 -5
  962. package/src/MobileNav/__tests__/MobileNavWidth.a11y.chromium.spec.ts +103 -0
  963. package/src/MoreMenu/MoreMenu.doc.mjs +2 -2
  964. package/src/MoreMenu/MoreMenu.spec.md +88 -53
  965. package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +67 -9
  966. package/src/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.ts +1 -0
  967. package/src/MultiSelector/MultiSelector.test.tsx +122 -10
  968. package/src/MultiSelector/MultiSelector.tsx +24 -4
  969. package/src/MultiSelector/OptionActions.a11y.chromium.spec.ts +1 -0
  970. package/src/MultiSelector/__tests__/MultiSelector.a11y.chromium.spec.ts +1 -0
  971. package/src/NavIcon/NavIcon.spec.md +66 -38
  972. package/src/NavMenu/NavHeadingMenu.spec.md +104 -46
  973. package/src/NavMenu/NavHeadingMenu.test.tsx +276 -2
  974. package/src/NavMenu/NavHeadingMenu.tsx +42 -4
  975. package/src/NavMenu/NavHeadingMenuItem.tsx +60 -6
  976. package/src/NavMenu/NavMenuContext.tsx +11 -0
  977. package/src/NavMenu/__tests__/NavMenusSlideSelection.a11y.chromium.spec.ts +137 -0
  978. package/src/NumberInput/NumberInput.doc.mjs +6 -6
  979. package/src/NumberInput/NumberInput.spec.md +248 -0
  980. package/src/NumberInput/NumberInput.test.tsx +187 -14
  981. package/src/NumberInput/NumberInput.tsx +86 -24
  982. package/src/NumberInput/__tests__/NumberInput.a11y.chromium.spec.ts +1 -0
  983. package/src/Overlay/Overlay.doc.mjs +2 -2
  984. package/src/Overlay/Overlay.test.tsx +72 -4
  985. package/src/Overlay/Overlay.tsx +18 -8
  986. package/src/Pagination/Pagination.test.tsx +2 -2
  987. package/src/Popover/Popover.doc.mjs +38 -2
  988. package/src/Popover/Popover.spec.md +90 -11
  989. package/src/Popover/Popover.test.tsx +340 -2
  990. package/src/Popover/Popover.tsx +401 -35
  991. package/src/Popover/PopoverPresentation.test.tsx +952 -0
  992. package/src/Popover/__tests__/PopoverSecondDocument.a11y.chromium.spec.ts +205 -0
  993. package/src/Popover/index.ts +5 -1
  994. package/src/Popover/lazyPopoverBottomSheet.ts +57 -0
  995. package/src/Popover/usePopover.tsx +11 -5
  996. package/src/PowerSearch/PowerSearch.spec.md +423 -53
  997. package/src/PowerSearch/PowerSearch.test.tsx +77 -1
  998. package/src/PowerSearch/PowerSearch.tsx +7 -5
  999. package/src/ProgressBar/ProgressBar.test.tsx +12 -0
  1000. package/src/ProgressBar/ProgressBar.tsx +18 -0
  1001. package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +1 -0
  1002. package/src/RadioList/RadioList.spec.md +227 -0
  1003. package/src/RadioList/RadioList.test.tsx +34 -7
  1004. package/src/RadioList/RadioListItem.press.source-build.test.mjs +80 -0
  1005. package/src/RadioList/RadioListItem.spec.md +223 -0
  1006. package/src/RadioList/RadioListItem.tsx +26 -12
  1007. package/src/RadioList/__tests__/RadioGroup.a11y.chromium.spec.ts +1 -0
  1008. package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +1 -0
  1009. package/src/ScrollableArea/ScrollableArea.spec.md +6 -5
  1010. package/src/ScrollableArea/ScrollableArea.test.tsx +5 -0
  1011. package/src/ScrollableArea/ScrollableArea.tsx +4 -0
  1012. package/src/Section/Section.spec.md +102 -44
  1013. package/src/SegmentedControl/SegmentedControl.spec.md +162 -53
  1014. package/src/SegmentedControl/SegmentedControl.test.tsx +46 -0
  1015. package/src/SegmentedControl/SegmentedControl.tsx +7 -3
  1016. package/src/SegmentedControl/SegmentedControlItem.spec.md +206 -0
  1017. package/src/SelectableCard/SelectableCard.doc.mjs +7 -6
  1018. package/src/SelectableCard/SelectableCard.spec.md +230 -0
  1019. package/src/SelectableCard/SelectableCard.test.tsx +11 -1
  1020. package/src/SelectableCard/SelectableCard.tsx +49 -33
  1021. package/src/Selector/Selector.sheetActiveDescendant.test.tsx +95 -0
  1022. package/src/Selector/Selector.spec.md +12 -4
  1023. package/src/Selector/Selector.test.tsx +114 -8
  1024. package/src/Selector/Selector.tsx +30 -6
  1025. package/src/Selector/__tests__/ComboboxField.a11y.chromium.spec.ts +458 -0
  1026. package/src/Selector/__tests__/EmptyStateAnnouncement.a11y.chromium.spec.ts +1 -0
  1027. package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +1 -0
  1028. package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +1 -0
  1029. package/src/Selector/__tests__/Selector.combobox.a11y.chromium.spec.ts +1 -0
  1030. package/src/Selector/hooks.ts +234 -10
  1031. package/src/Selector/useCombobox.doc.mjs +156 -9
  1032. package/src/Selector/useCombobox.public.test.tsx +89 -0
  1033. package/src/Selector/useCombobox.test.tsx +444 -0
  1034. package/src/SideNav/SideNav.spec.md +50 -30
  1035. package/src/SideNav/SideNav.test.tsx +425 -25
  1036. package/src/SideNav/SideNav.tsx +85 -1
  1037. package/src/SideNav/SideNavCollapseButton.spec.md +161 -0
  1038. package/src/SideNav/SideNavHeading.spec.md +226 -0
  1039. package/src/SideNav/SideNavHeading.tsx +102 -6
  1040. package/src/SideNav/SideNavItem.spec.md +246 -0
  1041. package/src/SideNav/SideNavItem.tsx +40 -9
  1042. package/src/SideNav/SideNavRailMotion.test.tsx +620 -0
  1043. package/src/SideNav/SideNavSection.spec.md +153 -0
  1044. package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +417 -0
  1045. package/src/SideNav/railMotion.ts +315 -0
  1046. package/src/Skeleton/Skeleton.spec.md +99 -42
  1047. package/src/Skeleton/Skeleton.test.tsx +108 -1
  1048. package/src/Skeleton/Skeleton.tsx +30 -2
  1049. package/src/Slider/Slider.fr10.test.tsx +34 -0
  1050. package/src/Slider/Slider.test.tsx +172 -0
  1051. package/src/Slider/Slider.tsx +70 -14
  1052. package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +1 -0
  1053. package/src/Spinner/Spinner.spec.md +231 -0
  1054. package/src/Stack/Stack.spec.md +104 -56
  1055. package/src/StatusDot/StatusDot.spec.md +139 -51
  1056. package/src/StatusDot/StatusDot.test.tsx +13 -0
  1057. package/src/StatusDot/StatusDot.tsx +27 -0
  1058. package/src/Stepper/Step.spec.md +206 -0
  1059. package/src/Stepper/Step.tsx +19 -3
  1060. package/src/Stepper/Stepper.test.tsx +50 -0
  1061. package/src/Switch/Switch.focusRing.source-build.test.mjs +81 -0
  1062. package/src/Switch/Switch.spec.md +150 -66
  1063. package/src/Switch/Switch.tsx +11 -9
  1064. package/src/Switch/__tests__/Switch.a11y.chromium.spec.ts +1 -0
  1065. package/src/Switch/switch.markers.stylex.ts +7 -2
  1066. package/src/TabList/Tab.spec.md +201 -0
  1067. package/src/TabList/Tab.tsx +7 -1
  1068. package/src/TabList/TabList.doc.mjs +3 -3
  1069. package/src/TabList/TabList.test.tsx +27 -0
  1070. package/src/TabList/TabMenu.spec.md +198 -0
  1071. package/src/TabList/TabMenu.tsx +24 -1
  1072. package/src/TabList/__tests__/TabListOverflow.interaction.browser.spec.ts +99 -0
  1073. package/src/TabList/__tests__/Tabs.a11y.chromium.spec.ts +1 -0
  1074. package/src/Table/Table.spec.md +54 -30
  1075. package/src/Table/TableCell.tsx +9 -0
  1076. package/src/Table/TableHeaderCell.tsx +2 -0
  1077. package/src/Table/TableRow.tsx +3 -0
  1078. package/src/Table/__tests__/Table.a11y.chromium.spec.ts +129 -0
  1079. package/src/Table/__tests__/Table.a11y.contracts.ts +35 -0
  1080. package/src/Table/__tests__/Table.a11y.renders.tsx +112 -0
  1081. package/src/Table/__tests__/Table.a11y.states.ts +140 -0
  1082. package/src/Table/__tests__/Table.a11y.test.tsx +198 -0
  1083. package/src/Table/__tests__/TableMinWidth.a11y.chromium.spec.ts +1 -0
  1084. package/src/Table/__tests__/TableRowGlide.a11y.browser.spec.ts +382 -0
  1085. package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +1 -0
  1086. package/src/Table/__tests__/TableStickyDividers.a11y.browser.spec.ts +560 -0
  1087. package/src/Table/glidingDivider.ts +336 -0
  1088. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +23 -8
  1089. package/src/Table/plugins/rowExpansion/useTableRowExpansion.glide.test.tsx +280 -0
  1090. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +91 -9
  1091. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +471 -10
  1092. package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +4 -4
  1093. package/src/Table/plugins/sortable/__tests__/useTableSortable.a11y.test.tsx +174 -0
  1094. package/src/Table/plugins/sortable/__tests__/useTableSortable.a11y.ts +86 -0
  1095. package/src/Table/plugins/sortable/useTableSortable.test.tsx +0 -12
  1096. package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +51 -1
  1097. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +312 -12
  1098. package/src/Table/rowDivider.ts +154 -0
  1099. package/src/Table/useTableRowExpansion.doc.mjs +8 -0
  1100. package/src/Text/Text.spec.md +114 -127
  1101. package/src/TextArea/TextArea.doc.mjs +6 -6
  1102. package/src/TextArea/TextArea.spec.md +164 -64
  1103. package/src/TextArea/TextArea.test.tsx +65 -6
  1104. package/src/TextArea/TextArea.tsx +27 -15
  1105. package/src/TextInput/TextInput.doc.mjs +8 -8
  1106. package/src/TextInput/TextInput.spec.md +260 -0
  1107. package/src/TextInput/TextInput.test.tsx +126 -10
  1108. package/src/TextInput/TextInput.tsx +57 -23
  1109. package/src/TextInput/__tests__/TextInput.a11y.chromium.spec.ts +1 -0
  1110. package/src/Thumbnail/Thumbnail.doc.mjs +1 -2
  1111. package/src/Thumbnail/Thumbnail.spec.md +244 -0
  1112. package/src/Thumbnail/Thumbnail.test.tsx +120 -7
  1113. package/src/Thumbnail/Thumbnail.tsx +77 -31
  1114. package/src/TimeInput/TimeInput.spec.md +273 -0
  1115. package/src/TimeInput/TimeInput.tsx +12 -4
  1116. package/src/TimeInput/TouchTimeField.tsx +2 -1
  1117. package/src/Timestamp/Timestamp.spec.md +252 -0
  1118. package/src/Toast/Toast.spec.md +300 -0
  1119. package/src/Toast/ToastViewport.modalHost.test.tsx +630 -5
  1120. package/src/Toast/ToastViewport.test.tsx +137 -0
  1121. package/src/Toast/ToastViewport.tsx +63 -6
  1122. package/src/ToggleButton/ToggleButton.spec.md +256 -0
  1123. package/src/ToggleButton/ToggleButtonGroup.spec.md +195 -0
  1124. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +1 -0
  1125. package/src/Token/Token.spec.md +271 -0
  1126. package/src/Token/__tests__/TokenRemoveTarget.a11y.chromium.spec.ts +1 -0
  1127. package/src/Tokenizer/Tokenizer.props-type.test.tsx +126 -0
  1128. package/src/Tokenizer/Tokenizer.spec.md +313 -72
  1129. package/src/Tokenizer/Tokenizer.ssr.test.tsx +196 -0
  1130. package/src/Tokenizer/Tokenizer.test.tsx +44 -8
  1131. package/src/Tokenizer/Tokenizer.tsx +586 -41
  1132. package/src/Tokenizer/TokenizerBottomSheet.test.tsx +2719 -0
  1133. package/src/Tokenizer/TokenizerBottomSheet.tsx +957 -0
  1134. package/src/Tokenizer/__tests__/TokenizerEndLane.a11y.chromium.spec.ts +61 -27
  1135. package/src/Toolbar/Toolbar.spec.md +103 -49
  1136. package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +1 -0
  1137. package/src/Tooltip/Tooltip.spec.md +161 -36
  1138. package/src/Tooltip/Tooltip.test.tsx +171 -3
  1139. package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +1 -0
  1140. package/src/Tooltip/__tests__/Tooltip.a11y.states.ts +2 -2
  1141. package/src/Tooltip/__tests__/TooltipFocusReturn.a11y.chromium.spec.ts +1 -0
  1142. package/src/Tooltip/__tests__/TooltipHoverBridge.a11y.chromium.spec.ts +1 -0
  1143. package/src/Tooltip/__tests__/TooltipTallContent.a11y.browser.spec.ts +673 -0
  1144. package/src/Tooltip/__tests__/TooltipTallContentTracking.a11y.browser.spec.ts +1162 -0
  1145. package/src/Tooltip/useTooltip.tsx +7 -2
  1146. package/src/TopNav/TopNav.spec.md +190 -0
  1147. package/src/TopNav/TopNav.test.tsx +89 -0
  1148. package/src/TopNav/TopNavHeading.spec.md +211 -0
  1149. package/src/TopNav/TopNavHeading.tsx +35 -2
  1150. package/src/TopNav/TopNavItem.spec.md +189 -0
  1151. package/src/TopNav/TopNavMegaMenu.reduced-motion.source-build.test.mjs +83 -0
  1152. package/src/TopNav/TopNavMegaMenu.spec.md +190 -0
  1153. package/src/TopNav/TopNavMegaMenu.tsx +21 -4
  1154. package/src/TopNav/TopNavMegaMenuFeaturedCard.spec.md +150 -0
  1155. package/src/TopNav/TopNavMegaMenuItem.spec.md +155 -0
  1156. package/src/TopNav/TopNavMenu.spec.md +202 -0
  1157. package/src/TopNav/TopNavMenu.test.tsx +65 -1
  1158. package/src/TopNav/TopNavMenu.tsx +30 -1
  1159. package/src/TopNav/__tests__/TopNavMobileLongHeading.a11y.chromium.spec.ts +1 -0
  1160. package/src/TreeList/TreeList.doc.mjs +13 -0
  1161. package/src/TreeList/TreeList.spec.md +54 -35
  1162. package/src/TreeList/TreeList.tsx +234 -2
  1163. package/src/TreeList/TreeListBranches.tsx +8 -6
  1164. package/src/TreeList/TreeListItem.tsx +12 -6
  1165. package/src/TreeList/__tests__/TreeList.a11y.chromium.spec.ts +19 -6
  1166. package/src/TreeList/__tests__/TreeListGuideAlignment.interaction.browser.spec.ts +127 -0
  1167. package/src/TreeList/__tests__/TreeListRowNames.a11y.chromium.spec.ts +1 -0
  1168. package/src/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.ts +138 -0
  1169. package/src/Typeahead/BaseTypeahead.test.tsx +201 -4
  1170. package/src/Typeahead/BaseTypeahead.tsx +26 -10
  1171. package/src/Typeahead/Typeahead.test.tsx +114 -1
  1172. package/src/Typeahead/Typeahead.tsx +34 -16
  1173. package/src/VisuallyHidden/VisuallyHidden.spec.md +170 -0
  1174. package/src/__tests__/BusyOwnerAnnouncement.test.tsx +66 -5
  1175. package/src/__tests__/CardPress.a11y.chromium.spec.ts +353 -0
  1176. package/src/__tests__/DisabledTriggerFocus.a11y.chromium.spec.ts +2 -1
  1177. package/src/__tests__/PressModality.a11y.chromium.spec.ts +392 -0
  1178. package/src/__tests__/PressedState.a11y.chromium.spec.ts +1 -0
  1179. package/src/__tests__/pressState.ts +43 -1
  1180. package/src/__tests__/unthemedLength.ts +34 -0
  1181. package/src/gestures/GestureArena.ts +966 -0
  1182. package/src/gestures/GestureRecognizer.ts +626 -0
  1183. package/src/gestures/LongPressGestureRecognizer.ts +186 -0
  1184. package/src/gestures/PanGestureRecognizer.ts +410 -0
  1185. package/src/gestures/TapGestureRecognizer.ts +192 -0
  1186. package/src/gestures/VelocityTracker.ts +194 -0
  1187. package/src/gestures/__tests__/LongPressGestureRecognizer.test.ts +141 -0
  1188. package/src/gestures/__tests__/PanGestureRecognizer.test.ts +327 -0
  1189. package/src/gestures/__tests__/TapGestureRecognizer.test.ts +154 -0
  1190. package/src/gestures/__tests__/VelocityTracker.streams.test.ts +243 -0
  1191. package/src/gestures/__tests__/VelocityTracker.test.ts +261 -0
  1192. package/src/gestures/__tests__/arena.test.ts +824 -0
  1193. package/src/gestures/__tests__/arenaContinuous.test.ts +207 -0
  1194. package/src/gestures/__tests__/arenaTapLongPress.test.ts +211 -0
  1195. package/src/gestures/__tests__/fixtures/pointer-streams/README.md +82 -0
  1196. package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-fling.json +130 -0
  1197. package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-slow.json +860 -0
  1198. package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-stop-release.json +357 -0
  1199. package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-fling.json +66 -0
  1200. package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-slow.json +268 -0
  1201. package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-stop-release.json +128 -0
  1202. package/src/gestures/__tests__/fixtures/pointer-streams/capture.html +123 -0
  1203. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-fling.json +64 -0
  1204. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-slow.json +268 -0
  1205. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-stop-release.json +124 -0
  1206. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-fling.json +64 -0
  1207. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-slow.json +268 -0
  1208. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-stop-release.json +124 -0
  1209. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-fling.json +84 -0
  1210. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-slow.json +381 -0
  1211. package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-stop-release.json +171 -0
  1212. package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-fling.json +45 -0
  1213. package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-slow.json +101 -0
  1214. package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-stop-release.json +130 -0
  1215. package/src/gestures/__tests__/harness.ts +204 -0
  1216. package/src/gestures/geometry.ts +55 -0
  1217. package/src/gestures/types.ts +161 -0
  1218. package/src/hooks/AnnounceRenderedText.tsx +27 -0
  1219. package/src/hooks/ModalAnnounceProvider.tsx +155 -0
  1220. package/src/hooks/__tests__/MenuPressShadowRoot.a11y.chromium.spec.ts +98 -4
  1221. package/src/hooks/__tests__/menuLinkClicks.ts +71 -0
  1222. package/src/hooks/actionGroupTracker.exports.test.ts +28 -0
  1223. package/src/hooks/actionGroupTracker.test.ts +510 -0
  1224. package/src/hooks/actionGroupTracker.ts +449 -0
  1225. package/src/hooks/index.ts +6 -0
  1226. package/src/hooks/menuPressOnItems.ts +40 -0
  1227. package/src/hooks/modalAnnounce.ts +439 -0
  1228. package/src/hooks/scrollGeometry.ts +71 -4
  1229. package/src/hooks/useAdaptivePresentation.ts +46 -9
  1230. package/src/hooks/useAnimatedLayout.doc.mjs +101 -0
  1231. package/src/hooks/useAnimatedLayout.ts +61 -0
  1232. package/src/hooks/useAnnounce.doc.mjs +4 -4
  1233. package/src/hooks/useAnnounce.modal.test.tsx +1291 -0
  1234. package/src/hooks/useAnnounce.test.tsx +64 -4
  1235. package/src/hooks/useAnnounce.ts +452 -28
  1236. package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +226 -0
  1237. package/src/hooks/useAnnounceRenderedText.ts +81 -11
  1238. package/src/hooks/useBusyAnnouncement.adopters.test.tsx +69 -0
  1239. package/src/hooks/useBusyAnnouncement.test.tsx +112 -0
  1240. package/src/hooks/useBusyAnnouncement.ts +64 -54
  1241. package/src/hooks/useFocusTrap.doc.mjs +3 -3
  1242. package/src/hooks/useFocusTrap.test.tsx +135 -2
  1243. package/src/hooks/useFocusTrap.ts +59 -27
  1244. package/src/hooks/useMenuHover.ts +6 -2
  1245. package/src/hooks/useMenuPress.doc.mjs +2 -2
  1246. package/src/hooks/useMenuPress.test.tsx +5 -2
  1247. package/src/hooks/useMenuPress.ts +72 -37
  1248. package/src/hooks/usePressFeedback.doc.mjs +4 -4
  1249. package/src/hooks/usePressFeedback.ts +5 -2
  1250. package/src/hooks/useScrollableArea.test.tsx +344 -3
  1251. package/src/hooks/useScrollableArea.ts +120 -12
  1252. package/src/i18n/generated-locales/en.generated.ts +35 -0
  1253. package/src/i18n/generated-locales/pseudo.generated.ts +37 -0
  1254. package/src/internal/tokenizer-presentation.test.ts +29 -0
  1255. package/src/internal/tokenizer-presentation.ts +25 -0
  1256. package/src/internal/touch.test.ts +44 -0
  1257. package/src/internal/touch.ts +41 -0
  1258. package/src/motion/LayoutChangeSnapshot.tsx +50 -0
  1259. package/src/motion/MEASUREMENTS.md +271 -0
  1260. package/src/motion/README.md +218 -0
  1261. package/src/motion/__tests__/animatedLayout.interaction.browser.spec.ts +1613 -0
  1262. package/src/motion/__tests__/animatedLayoutAdopters.interaction.browser.spec.ts +217 -0
  1263. package/src/motion/__tests__/animatedLayoutBundle.ts +17 -0
  1264. package/src/motion/animatedLayout.boundary.test.ts +155 -0
  1265. package/src/motion/animatedLayout.swap.test.ts +827 -0
  1266. package/src/motion/animatedLayout.test.ts +1154 -0
  1267. package/src/motion/animatedLayout.ts +1801 -0
  1268. package/src/motion/animatedLayoutAdopters.test.tsx +500 -0
  1269. package/src/motion/animator.test.ts +2653 -0
  1270. package/src/motion/animator.ts +2794 -0
  1271. package/src/motion/bezier.test.ts +52 -0
  1272. package/src/motion/bezier.ts +64 -0
  1273. package/src/motion/coast.test.ts +99 -0
  1274. package/src/motion/coast.ts +150 -0
  1275. package/src/motion/decay.test.ts +120 -0
  1276. package/src/motion/decay.ts +126 -0
  1277. package/src/motion/projection.test.ts +107 -0
  1278. package/src/motion/projection.ts +116 -0
  1279. package/src/motion/reducedMotion.stylex.ts +41 -0
  1280. package/src/motion/reducedMotion.test.ts +129 -0
  1281. package/src/motion/reducedMotion.ts +94 -0
  1282. package/src/motion/reducedMotionPlan.test.ts +182 -0
  1283. package/src/motion/reducedMotionPlan.ts +263 -0
  1284. package/src/motion/resolveSnapPoint.test.ts +189 -0
  1285. package/src/motion/resolveSnapPoint.ts +169 -0
  1286. package/src/motion/roleValue.ts +105 -0
  1287. package/src/motion/roles.test.ts +256 -0
  1288. package/src/motion/roles.ts +262 -0
  1289. package/src/motion/rubberBand.test.ts +88 -0
  1290. package/src/motion/rubberBand.ts +115 -0
  1291. package/src/motion/selectPage.test.ts +31 -0
  1292. package/src/motion/selectPage.ts +55 -0
  1293. package/src/motion/spring.test.ts +650 -0
  1294. package/src/motion/spring.ts +551 -0
  1295. package/src/motion/transientCopy.ts +374 -0
  1296. package/src/motion/uikit/gestures.test.ts +89 -0
  1297. package/src/motion/uikit/gestures.ts +359 -0
  1298. package/src/motion/uikit/index.ts +80 -0
  1299. package/src/motion/uikit/navigation.ts +83 -0
  1300. package/src/motion/uikit/scroll.ts +141 -0
  1301. package/src/motion/uikit/springRows.test.ts +71 -0
  1302. package/src/motion/uikit/springs.ts +514 -0
  1303. package/src/motion/uikit/timing.ts +210 -0
  1304. package/src/motion/uikit/uikit.test.ts +364 -0
  1305. package/src/motion/uikit/values.test.ts +110 -0
  1306. package/src/reset.a11y.chromium.spec.ts +1 -0
  1307. package/src/reset.until-found.a11y.browser.spec.ts +1 -0
  1308. package/src/serverSafeComponents.test.ts +10 -0
  1309. package/src/tailwind-theme.css +51 -1
  1310. package/src/tailwind-theme.test.ts +51 -0
  1311. package/src/theme/Theme.test.tsx +28 -0
  1312. package/src/theme/__tests__/SpacingRootFontSize.a11y.chromium.spec.ts +1 -0
  1313. package/src/theme/declarationBoundary.ts +282 -1
  1314. package/src/theme/defineTheme.test.ts +529 -12
  1315. package/src/theme/defineTheme.ts +231 -19
  1316. package/src/theme/derivedVarRegistry.test.ts +34 -5
  1317. package/src/theme/derivedVarRegistry.ts +4 -0
  1318. package/src/theme/expandMotionScale.test.ts +17 -0
  1319. package/src/theme/extensibleAxes.test.ts +74 -29
  1320. package/src/theme/generateThemeRules.ts +772 -35
  1321. package/src/theme/index.ts +3 -0
  1322. package/src/theme/onMediaTokens.test.ts +186 -0
  1323. package/src/theme/statusColor.ts +189 -0
  1324. package/src/theme/statusRoleDerivation.ts +289 -0
  1325. package/src/theme/syntax/SyntaxTheme.tsx +1 -1
  1326. package/src/theme/syntax/defineSyntaxTheme.ts +1 -1
  1327. package/src/theme/syntax/presets.ts +1 -1
  1328. package/src/theme/syntax/tokens.ts +1 -1
  1329. package/src/theme/themeAdaptations.test.ts +412 -0
  1330. package/src/theme/themeAdaptations.ts +43 -1
  1331. package/src/theme/tokens.stylex.ts +36 -2
  1332. package/src/theme/tokens.test.ts +111 -1
  1333. package/src/theme/tokens.ts +23 -1
  1334. package/src/theme/useTheme.ts +10 -4
  1335. package/src/utils/customPropertyArmLayering.test.ts +131 -0
  1336. package/src/utils/edgeAutoscroll.test.ts +192 -0
  1337. package/src/utils/edgeAutoscroll.ts +111 -0
  1338. package/src/utils/hitArea.test.ts +628 -0
  1339. package/src/utils/hitArea.ts +770 -0
  1340. package/src/utils/interactionOverlay.stylex.ts +4 -1
  1341. package/src/utils/pressFeedback.test.ts +310 -2
  1342. package/src/utils/pressFeedback.ts +306 -54
  1343. package/src/utils/pressGesture.test.ts +50 -0
  1344. package/src/utils/pressGesture.ts +40 -2
  1345. package/src/utils/touchPresentation.test.ts +323 -0
  1346. package/src/utils/touchPresentation.ts +153 -0
@@ -0,0 +1,1613 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file animatedLayout.interaction.browser.spec.ts
5
+ * @input The animated-layout module bundled with esbuild onto fixture pages
6
+ * written inline, real Chromium and WebKit (the interaction projects: a
7
+ * phone with a coarse pointer) plus a fine-pointer describe
8
+ * @output One proof per `spec:AST-105` Coverage row, and FR2–FR4: which
9
+ * elements glide after a reported size change, by how much, on one shared
10
+ * start and spring, never past the area and never scrolling it; nothing
11
+ * without a handle; Reduce Motion by pointer
12
+ * @position Real-browser verification of `spec:AST-105` and
13
+ * `architecture:react-component-runtime` INV12
14
+ */
15
+
16
+ import {fileURLToPath} from 'node:url';
17
+ import {expect, test, type Page} from '@playwright/test';
18
+ import {build} from 'esbuild';
19
+ import type * as Bundle from './animatedLayoutBundle';
20
+
21
+ /** One animation on an element: its first frame and its timing. */
22
+ interface MotionRead {
23
+ first: string | null;
24
+ opacity: string | null;
25
+ composite: string;
26
+ duration: number;
27
+ startTime: number | null;
28
+ }
29
+
30
+ declare global {
31
+ interface Window {
32
+ AnimatedLayout: typeof Bundle;
33
+ /** Runs one reported change; resolves after the glide is set up. */
34
+ change: (options: {
35
+ changed: string;
36
+ mutate: string;
37
+ area?: string;
38
+ handle?: boolean;
39
+ }) => Promise<void>;
40
+ /** Animations on an element: their first transform and timing. */
41
+ motionOf: (selector: string) => MotionRead[];
42
+ }
43
+ }
44
+
45
+ let script = '';
46
+
47
+ test.beforeAll(async () => {
48
+ const result = await build({
49
+ entryPoints: [
50
+ fileURLToPath(new URL('./animatedLayoutBundle.ts', import.meta.url)),
51
+ ],
52
+ bundle: true,
53
+ write: false,
54
+ format: 'iife',
55
+ globalName: 'AnimatedLayout',
56
+ target: 'es2022',
57
+ });
58
+ script = result.outputFiles[0].text;
59
+ });
60
+
61
+ const BASE_STYLE = `
62
+ html, body { margin: 0; font: 14px sans-serif; background: #fff; }
63
+ .area { position: relative; height: 560px; overflow: auto; }
64
+ .row { height: 40px; margin: 0 0 4px; background: #eef; }
65
+ .grow { height: 0; overflow: hidden; background: #fd9; }
66
+ .grow.open { height: 80px; }
67
+ `;
68
+
69
+ const HELPERS = `
70
+ window.change = async ({changed, mutate, area = '#area', handle = true}) => {
71
+ const container = document.querySelector(area);
72
+ const target = document.querySelector(changed);
73
+ const layout = handle
74
+ ? AnimatedLayout.createAnimatedLayout(() => container)
75
+ : null;
76
+ const report = AnimatedLayout.reportLayoutChange(layout, () => target);
77
+ report.measureBefore();
78
+ new Function(mutate)();
79
+ report.animate();
80
+ AnimatedLayout.playLayoutChange(layout, target);
81
+ await new Promise(resolve => queueMicrotask(resolve));
82
+ };
83
+ window.motionOf = selector => {
84
+ const element = document.querySelector(selector);
85
+ return element.getAnimations({subtree: false}).map(animation => {
86
+ const effect = animation.effect;
87
+ const frames = effect.getKeyframes();
88
+ const timing = effect.getTiming();
89
+ return {
90
+ first: frames[0].translate ?? frames[0].transform ?? null,
91
+ opacity: frames[0].opacity == null ? null : String(frames[0].opacity),
92
+ composite: effect.composite,
93
+ duration: Number(timing.duration),
94
+ startTime: animation.startTime == null ? null : Number(animation.startTime),
95
+ };
96
+ });
97
+ };
98
+ `;
99
+
100
+ async function open(page: Page, body: string, style = '') {
101
+ const html = `<!doctype html><meta name="viewport" content="width=device-width,initial-scale=1">
102
+ <style>${BASE_STYLE}${style}</style>
103
+ ${body}
104
+ <script>${script}</script>
105
+ <script>${HELPERS}</script>`;
106
+ await page.route('http://layout.test/', async route =>
107
+ route.fulfill({contentType: 'text/html', body: html}),
108
+ );
109
+ await page.goto('http://layout.test/');
110
+ }
111
+
112
+ const OPEN_GROW = `document.querySelector('#grow').classList.add('open')`;
113
+
114
+ /** Reports one change from the test (its options cross into the page). */
115
+ async function change(
116
+ page: Page,
117
+ options: {
118
+ changed?: string;
119
+ mutate?: string;
120
+ area?: string;
121
+ handle?: boolean;
122
+ } = {},
123
+ ) {
124
+ await page.evaluate(async o => window.change(o), {
125
+ changed: '#grow',
126
+ mutate: OPEN_GROW,
127
+ ...options,
128
+ });
129
+ }
130
+
131
+ /** Until every animation on the page has finished. */
132
+ async function settle(page: Page) {
133
+ await expect
134
+ .poll(async () => page.evaluate(() => document.getAnimations().length), {
135
+ timeout: 5000,
136
+ })
137
+ .toBe(0);
138
+ }
139
+
140
+ /** The translate an animation starts from, in px. */
141
+ function startOffset(first: string | null): {x: number; y: number} {
142
+ // The browser shortens `-80px 0px` to `-80px`.
143
+ const match = /^(-?[\d.e+-]+)px(?:\s+(-?[\d.e+-]+)px)?/.exec(first ?? '');
144
+ return match == null
145
+ ? {x: 0, y: 0}
146
+ : {x: Number(match[1]), y: match[2] == null ? 0 : Number(match[2])};
147
+ }
148
+
149
+ test.describe('spec:AST-105 Coverage', () => {
150
+ test('normal-flow siblings at each ancestor level glide, and nothing past the area moves', async ({
151
+ page,
152
+ }) => {
153
+ await open(
154
+ page,
155
+ `<div id="area" class="area">
156
+ <section id="l1">
157
+ <div id="l2">
158
+ <div id="l3"><div id="grow" class="grow"></div><div id="s3" class="row"></div></div>
159
+ <div id="s2" class="row"></div>
160
+ </div>
161
+ <div id="s1" class="row"></div>
162
+ </section>
163
+ <div id="s0" class="row"></div>
164
+ </div>
165
+ <div id="outside" class="row"></div>`,
166
+ );
167
+ await change(page);
168
+ for (const id of ['#s3', '#s2', '#s1', '#s0']) {
169
+ const [motion] = await page.evaluate(s => window.motionOf(s), id);
170
+ expect(motion, id).toBeDefined();
171
+ expect(startOffset(motion.first).y, id).toBeCloseTo(-80, 0);
172
+ expect(motion.composite, id).toBe('replace');
173
+ }
174
+ expect(await page.evaluate(() => window.motionOf('#outside'))).toEqual([]);
175
+ });
176
+
177
+ test('a display: contents wrapper has no box: its children glide in its place', async ({
178
+ page,
179
+ }) => {
180
+ await open(
181
+ page,
182
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
183
+ <div id="wrap" style="display: contents"><div id="c1" class="row"></div><div id="c2" class="row"></div></div></div>`,
184
+ );
185
+ await change(page);
186
+ expect(await page.evaluate(() => window.motionOf('#wrap'))).toEqual([]);
187
+ for (const id of ['#c1', '#c2']) {
188
+ expect(await page.evaluate(s => window.motionOf(s), id)).toHaveLength(1);
189
+ }
190
+ });
191
+
192
+ test('absolute and fixed elements take their final place; an absolute badge rides with its row', async ({
193
+ page,
194
+ }) => {
195
+ await open(
196
+ page,
197
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
198
+ <div id="row" class="row" style="position: relative"><span id="badge" style="position: absolute; top: 4px; right: 4px; width: 16px; height: 16px; background: #c00"></span></div>
199
+ <div id="abs" style="position: absolute; top: 200px; left: 0; width: 40px; height: 40px; background: #0c0"></div>
200
+ <div id="fixed" style="position: fixed; bottom: 0; right: 0; width: 40px; height: 40px; background: #00c"></div></div>`,
201
+ );
202
+ const before = await page.locator('#badge').boundingBox();
203
+ await change(page);
204
+ expect(await page.evaluate(() => window.motionOf('#abs'))).toEqual([]);
205
+ expect(await page.evaluate(() => window.motionOf('#fixed'))).toEqual([]);
206
+ expect(await page.evaluate(() => window.motionOf('#badge'))).toEqual([]);
207
+ // Halfway through, the row and its badge are between the two places.
208
+ await page.evaluate(() => {
209
+ for (const animation of document
210
+ .querySelector<HTMLElement>('#row')
211
+ ?.getAnimations() ?? []) {
212
+ animation.pause();
213
+ animation.currentTime = 60;
214
+ }
215
+ });
216
+ const mid = await page.locator('#badge').boundingBox();
217
+ expect(mid?.y ?? 0).toBeGreaterThan(before?.y ?? 0);
218
+ expect(mid?.y ?? 0).toBeLessThan((before?.y ?? 0) + 80);
219
+ });
220
+
221
+ test('a sticky element glides while unstuck and stays put while stuck', async ({
222
+ page,
223
+ }) => {
224
+ // Both headers come after the change; the first is stuck at the area's
225
+ // top, the second is still in flow below. No scroll anchoring, so content
226
+ // after a change above the fold moves.
227
+ await open(
228
+ page,
229
+ `<div id="area" class="area" style="overflow-anchor: none">
230
+ <div id="grow" class="grow"></div>
231
+ ${'<div class="row"></div>'.repeat(2)}
232
+ <div id="stuck" style="position: sticky; top: 0; height: 30px; background: #ccf"></div>
233
+ ${'<div class="row"></div>'.repeat(10)}
234
+ <div id="unstuck" style="position: sticky; top: 0; height: 30px; background: #fcc"></div>
235
+ ${'<div class="row"></div>'.repeat(20)}
236
+ </div>`,
237
+ );
238
+ const stuckTop = await page.evaluate(() => {
239
+ const area = document.querySelector('#area') as HTMLElement;
240
+ area.scrollTop = 300;
241
+ const top = area.getBoundingClientRect().top;
242
+ return (
243
+ (document.querySelector('#stuck')?.getBoundingClientRect().top ?? 0) -
244
+ top
245
+ );
246
+ });
247
+ // Precondition: the first header is stuck at the top.
248
+ expect(stuckTop).toBeCloseTo(0, 0);
249
+ await change(page);
250
+ expect(await page.evaluate(() => window.motionOf('#stuck'))).toEqual([]);
251
+ const [unstuck] = await page.evaluate(() => window.motionOf('#unstuck'));
252
+ expect(startOffset(unstuck.first).y).toBeCloseTo(-80, 0);
253
+ });
254
+
255
+ test('a float after the change glides', async ({page}) => {
256
+ await open(
257
+ page,
258
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
259
+ <div id="float" style="float: left; width: 60px; height: 60px; background: #9c9"></div></div>`,
260
+ );
261
+ await change(page);
262
+ expect(await page.evaluate(() => window.motionOf('#float'))).toHaveLength(
263
+ 1,
264
+ );
265
+ });
266
+
267
+ test('flex items: an item that wraps glides, a row-direction neighbor whose rectangle does not change stays', async ({
268
+ page,
269
+ }) => {
270
+ await open(
271
+ page,
272
+ `<div id="area" class="area">
273
+ <div style="display: flex; flex-wrap: wrap; gap: 4px; width: 200px">
274
+ <div id="chip" style="width: 40px; height: 24px; background: #fd9"></div>
275
+ <div id="t1" style="width: 60px; height: 24px; background: #ddd"></div>
276
+ <div id="t2" style="width: 60px; height: 24px; background: #ddd"></div>
277
+ </div>
278
+ <div style="display: flex; align-items: flex-start; gap: 8px">
279
+ <div id="tall" style="width: 40px; height: 30px; background: #fd9"></div>
280
+ <div id="neighbor" style="width: 40px; height: 30px; background: #9cf"></div>
281
+ </div>
282
+ <div id="below" class="row"></div>
283
+ </div>`,
284
+ );
285
+ // The first chip widens: the last item wraps to a new line and glides.
286
+ const t2Before = await page.evaluate(
287
+ () => document.querySelector('#t2')?.getBoundingClientRect().top ?? 0,
288
+ );
289
+ await change(page, {
290
+ changed: '#chip',
291
+ mutate: `document.querySelector('#chip').style.width = '120px'`,
292
+ });
293
+ const t2After = await page.evaluate(
294
+ () => document.querySelector('#t2')?.getBoundingClientRect().top ?? 0,
295
+ );
296
+ const [wrapped] = await page.evaluate(() => window.motionOf('#t2'));
297
+ expect(wrapped).toBeDefined();
298
+ // It wrapped: its layout moved down a line, and it starts where it was.
299
+ expect(startOffset(wrapped.first).y).toBeLessThan(-20);
300
+ // A round trip after the change: it has barely left its old place.
301
+ expect(Math.abs(t2After - t2Before)).toBeLessThan(4);
302
+ await settle(page);
303
+ // An item grows taller: its row-direction neighbor keeps its rectangle and
304
+ // stays; the content after the row glides.
305
+ await change(page, {
306
+ changed: '#tall',
307
+ mutate: `document.querySelector('#tall').style.height = '110px'`,
308
+ });
309
+ expect(await page.evaluate(() => window.motionOf('#neighbor'))).toEqual([]);
310
+ const [below] = await page.evaluate(() => window.motionOf('#below'));
311
+ expect(startOffset(below.first).y).toBeCloseTo(-80, 0);
312
+ });
313
+
314
+ test('hidden, display: none and zero-size elements are skipped', async ({
315
+ page,
316
+ }) => {
317
+ await open(
318
+ page,
319
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
320
+ <div id="hidden" class="row" style="visibility: hidden"></div>
321
+ <div id="none" class="row" style="display: none"></div>
322
+ <div id="empty" style="height: 0"></div>
323
+ <div id="after" class="row"></div></div>`,
324
+ );
325
+ await change(page);
326
+ for (const id of ['#hidden', '#none', '#empty']) {
327
+ expect(await page.evaluate(s => window.motionOf(s), id), id).toEqual([]);
328
+ }
329
+ expect(await page.evaluate(() => window.motionOf('#after'))).toHaveLength(
330
+ 1,
331
+ );
332
+ });
333
+
334
+ test('elements outside the visible part land without animation', async ({
335
+ page,
336
+ }) => {
337
+ await open(
338
+ page,
339
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
340
+ ${Array.from({length: 40}, (_, i) => `<div id="r${i}" class="row"></div>`).join('')}</div>`,
341
+ );
342
+ await change(page);
343
+ expect(await page.evaluate(() => window.motionOf('#r0'))).toHaveLength(1);
344
+ // Far below the fold before and after.
345
+ expect(await page.evaluate(() => window.motionOf('#r39'))).toEqual([]);
346
+ // A change above the fold, out of sight: the changed element plays nothing.
347
+ await settle(page);
348
+ await page.evaluate(() => {
349
+ (document.querySelector('#area') as HTMLElement).scrollTop = 1200;
350
+ });
351
+ await change(page, {
352
+ changed: '#r2',
353
+ mutate: `document.querySelector('#r2').style.height = '120px'`,
354
+ });
355
+ expect(await page.evaluate(() => window.motionOf('#r2'))).toEqual([]);
356
+ });
357
+
358
+ test('a row under a scaled panel moves by its layout change, corrected for the scale', async ({
359
+ page,
360
+ }) => {
361
+ await open(
362
+ page,
363
+ `<div id="area" class="area"><div style="transform: scale(0.5); transform-origin: 0 0">
364
+ <div id="grow" class="grow"></div><div id="scaled" class="row"></div></div></div>`,
365
+ );
366
+ await change(page);
367
+ const [motion] = await page.evaluate(() => window.motionOf('#scaled'));
368
+ // 80 px of layout: 40 px on screen, translated in the panel's own space.
369
+ expect(startOffset(motion.first).y).toBeCloseTo(-80, 0);
370
+ });
371
+
372
+ test("a follower with its own scale glides from its old place: its own scale is no ancestor's", async ({
373
+ page,
374
+ }) => {
375
+ await open(
376
+ page,
377
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
378
+ <div id="pressed" class="row" style="transform: scale(0.98)"></div>
379
+ <div id="half" class="row" style="scale: 0.5"></div>
380
+ <div id="flipped" class="row" style="scale: -1"></div>
381
+ <div id="mirrored" class="row" style="scale: 1 -1"></div>
382
+ <div id="pressing" class="row" style="transition: transform 2s linear"></div></div>`,
383
+ );
384
+ // A press starting on #pressing: its own transition runs from
385
+ // \`transform: none\` toward a scale while the change happens.
386
+ await page.evaluate(() => {
387
+ const pressing = document.querySelector<HTMLElement>('#pressing');
388
+ if (pressing != null) {
389
+ void pressing.offsetHeight;
390
+ pressing.style.transform = 'scale(0.98)';
391
+ }
392
+ });
393
+ await change(page);
394
+ // A negative scale flips the element in place: it glides the same way.
395
+ for (const id of [
396
+ '#pressed',
397
+ '#half',
398
+ '#flipped',
399
+ '#mirrored',
400
+ '#pressing',
401
+ ]) {
402
+ const motions = await page.evaluate(s => window.motionOf(s), id);
403
+ const glide = motions.find(motion => (motion.first ?? '').includes('px'));
404
+ expect(glide, `${id} ${JSON.stringify(motions)}`).toBeDefined();
405
+ // 80 px of layout, translated in its parent's space: a \`translate\`
406
+ // does not go through the element's own scale.
407
+ expect(startOffset(glide?.first ?? null).y, id).toBeCloseTo(-80, 0);
408
+ }
409
+ });
410
+
411
+ test('top-layer content is never moved', async ({page}) => {
412
+ await open(
413
+ page,
414
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
415
+ <div class="row"></div><div id="pop" popover>menu</div></div>`,
416
+ );
417
+ await page.evaluate(() =>
418
+ (document.querySelector('#pop') as HTMLElement).showPopover(),
419
+ );
420
+ await change(page);
421
+ expect(await page.evaluate(() => window.motionOf('#pop'))).toEqual([]);
422
+ });
423
+
424
+ test('an element already moving keeps its motion and adds the new move: no jump, no lost speed', async ({
425
+ page,
426
+ }) => {
427
+ await open(
428
+ page,
429
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
430
+ <div id="second" class="grow"></div><div id="after" class="row"></div></div>`,
431
+ );
432
+ await change(page);
433
+ await page.waitForTimeout(100);
434
+ const [first] = await page.evaluate(() => window.motionOf('#after'));
435
+ // The row's on-screen speed over the frame before the second change and
436
+ // the frame after it, and its place either side of the change.
437
+ const run = await page.evaluate(async mutate => {
438
+ const row = document.querySelector('#after') as HTMLElement;
439
+ const frame = async () =>
440
+ new Promise<number>(resolve => requestAnimationFrame(resolve));
441
+ const t0 = await frame();
442
+ const y0 = row.getBoundingClientRect().top;
443
+ const t1 = await frame();
444
+ const y1 = row.getBoundingClientRect().top;
445
+ await window.change({changed: '#second', mutate});
446
+ const y1After = row.getBoundingClientRect().top;
447
+ const t2 = await frame();
448
+ const y2 = row.getBoundingClientRect().top;
449
+ return {
450
+ before: (y1 - y0) / (t1 - t0),
451
+ after: (y2 - y1After) / (t2 - t1),
452
+ y1,
453
+ y1After,
454
+ };
455
+ }, `document.querySelector('#second').classList.add('open')`);
456
+ const motions = await page.evaluate(() => window.motionOf('#after'));
457
+ expect(motions).toHaveLength(1);
458
+ expect(motions[0].composite).toBe('replace');
459
+ expect(motions[0].startTime).not.toBe(first.startTime);
460
+ expect(run.y1After).toBeCloseTo(run.y1, 0);
461
+ // Still gliding down at least as fast: the new move adds to the motion.
462
+ expect(run.before).toBeGreaterThan(0);
463
+ expect(run.after).toBeGreaterThan(run.before * 0.9);
464
+ // It still lands where layout put it: 160 px below where it began.
465
+ await settle(page);
466
+ const landed = await page.evaluate(() => {
467
+ const area = document.querySelector('#area')?.getBoundingClientRect();
468
+ const row = document.querySelector('#after')?.getBoundingClientRect();
469
+ return (row?.top ?? 0) - (area?.top ?? 0);
470
+ });
471
+ expect(landed).toBeCloseTo(160, 0);
472
+ });
473
+
474
+ test('nested areas: motion stops at the inner area; an inner area moves as one unit', async ({
475
+ page,
476
+ }) => {
477
+ await open(
478
+ page,
479
+ `<div id="area" class="area"><div id="outerGrow" class="grow"></div>
480
+ <div id="inner" style="height: 200px; overflow: auto"><div id="grow" class="grow"></div><div id="innerAfter" class="row"></div></div>
481
+ <div id="outerAfter" class="row"></div></div>`,
482
+ );
483
+ await change(page, {area: '#inner'});
484
+ expect(
485
+ await page.evaluate(() => window.motionOf('#innerAfter')),
486
+ ).toHaveLength(1);
487
+ expect(await page.evaluate(() => window.motionOf('#outerAfter'))).toEqual(
488
+ [],
489
+ );
490
+ await settle(page);
491
+ await change(page, {
492
+ changed: '#outerGrow',
493
+ mutate: `document.querySelector('#outerGrow').classList.add('open')`,
494
+ });
495
+ expect(await page.evaluate(() => window.motionOf('#inner'))).toHaveLength(
496
+ 1,
497
+ );
498
+ expect(
499
+ (await page.evaluate(() => window.motionOf('#innerAfter'))).length,
500
+ ).toBe(0);
501
+ });
502
+ });
503
+
504
+ test.describe('architecture:react-component-runtime INV12', () => {
505
+ test('a 10-level by 50-sibling tree on a throttled phone: one move per follower, none inside a subtree, none past the area, no height', async ({
506
+ page,
507
+ browserName,
508
+ }) => {
509
+ if (browserName === 'chromium') {
510
+ const cdp = await page.context().newCDPSession(page);
511
+ await cdp.send('Emulation.setCPUThrottlingRate', {rate: 4});
512
+ }
513
+ // Level k holds the path to the changed element plus 49 rows, each with
514
+ // a child of its own (a subtree the walk must not enter).
515
+ const level = (depth: number): string => {
516
+ const rows = Array.from(
517
+ {length: 49},
518
+ () =>
519
+ `<div class="sib" data-depth="${depth}" style="height: 2px"><i class="inner" style="display: block; height: 1px"></i></div>`,
520
+ ).join('');
521
+ const inner =
522
+ depth === 9
523
+ ? '<div id="g1" class="grow"></div><div id="g2" class="grow"></div>'
524
+ : level(depth + 1);
525
+ return `<div class="lvl">${inner}</div>${rows}`;
526
+ };
527
+ await open(
528
+ page,
529
+ `<div id="area" class="area" style="height: 700px">${level(0)}</div>
530
+ <div id="outside" class="row"></div>`,
531
+ );
532
+ // Two changes in one frame, read in the same task: on a throttled page a
533
+ // second round trip can outlast the glide.
534
+ const report = await page.evaluate(async () => {
535
+ const area = document.querySelector('#area');
536
+ const layout = window.AnimatedLayout.createAnimatedLayout(() => area);
537
+ const one = window.AnimatedLayout.reportLayoutChange(layout, () =>
538
+ document.querySelector('#g1'),
539
+ );
540
+ const two = window.AnimatedLayout.reportLayoutChange(layout, () =>
541
+ document.querySelector('#g2'),
542
+ );
543
+ one.measureBefore();
544
+ two.measureBefore();
545
+ document.querySelector('#g1')?.classList.add('open');
546
+ document.querySelector('#g2')?.classList.add('open');
547
+ one.animate();
548
+ two.animate();
549
+ await new Promise<void>(resolve => {
550
+ queueMicrotask(resolve);
551
+ });
552
+ const animations = document.getAnimations();
553
+ const targets = animations.map(
554
+ a => (a.effect as KeyframeEffect).target as Element,
555
+ );
556
+ return {
557
+ total: animations.length,
558
+ distinct: new Set(targets).size,
559
+ intoSubtree: targets.filter(t => t.classList.contains('inner')).length,
560
+ pastArea: targets.filter(t => t.id === 'outside').length,
561
+ animatesHeight: animations.some(a =>
562
+ (a.effect as KeyframeEffect)
563
+ .getKeyframes()
564
+ .some(f => 'height' in f || 'top' in f),
565
+ ),
566
+ followers: targets.filter(t => t.classList.contains('sib')).length,
567
+ };
568
+ });
569
+ expect(report.followers).toBeGreaterThan(0);
570
+ expect(report.distinct).toBe(report.total);
571
+ expect(report.intoSubtree).toBe(0);
572
+ expect(report.pastArea).toBe(0);
573
+ expect(report.animatesHeight).toBe(false);
574
+ });
575
+ });
576
+
577
+ test.describe('spec:AST-105 FR2–FR4', () => {
578
+ const PAGE = `<div id="area" class="area"><div id="grow" class="grow"></div>
579
+ <div id="a" class="row"></div><div id="b" class="row"></div>
580
+ ${'<div class="row"></div>'.repeat(30)}</div>`;
581
+
582
+ test('without a handle nothing animates (FR2)', async ({page}) => {
583
+ await open(page, PAGE);
584
+ await change(page, {handle: false});
585
+ for (const id of ['#grow', '#a', '#b']) {
586
+ expect(await page.evaluate(s => window.motionOf(s), id), id).toEqual([]);
587
+ }
588
+ });
589
+
590
+ test('two changes in one frame move each element once, by its total change (FR3)', async ({
591
+ page,
592
+ }) => {
593
+ await open(
594
+ page,
595
+ `<div id="area" class="area"><div id="g1" class="grow"></div><div id="g2" class="grow"></div><div id="after" class="row"></div></div>`,
596
+ );
597
+ await page.evaluate(async () => {
598
+ const area = document.querySelector('#area');
599
+ const layout = window.AnimatedLayout.createAnimatedLayout(() => area);
600
+ const one = window.AnimatedLayout.reportLayoutChange(layout, () =>
601
+ document.querySelector('#g1'),
602
+ );
603
+ const two = window.AnimatedLayout.reportLayoutChange(layout, () =>
604
+ document.querySelector('#g2'),
605
+ );
606
+ one.measureBefore();
607
+ two.measureBefore();
608
+ document.querySelector<HTMLElement>('#g1')?.classList.add('open');
609
+ document.querySelector<HTMLElement>('#g2')?.classList.add('open');
610
+ one.animate();
611
+ two.animate();
612
+ await new Promise<void>(resolve => {
613
+ queueMicrotask(resolve);
614
+ });
615
+ });
616
+ const motions = await page.evaluate(() => window.motionOf('#after'));
617
+ expect(motions).toHaveLength(1);
618
+ expect(startOffset(motions[0].first).y).toBeCloseTo(-160, 0);
619
+ // The second changed element, pushed down by the first, moves with its
620
+ // row from its old place.
621
+ const [second] = await page.evaluate(() => window.motionOf('#g2'));
622
+ expect(startOffset(second.first).y).toBeCloseTo(-80, 0);
623
+ });
624
+
625
+ test('nested changes compose whichever is reported first: a row inside a moving folder moves only by its own change (FR3)', async ({
626
+ page,
627
+ }) => {
628
+ await open(
629
+ page,
630
+ `<div id="area" class="area"><div id="a" class="grow"></div>
631
+ <div id="folder"><div id="inner" class="grow"></div><div id="row" class="row"></div></div>
632
+ <div id="after" class="row"></div></div>`,
633
+ );
634
+ await page.evaluate(async () => {
635
+ const area = document.querySelector('#area');
636
+ const layout = window.AnimatedLayout.createAnimatedLayout(() => area);
637
+ // The inner change is reported first.
638
+ const inner = window.AnimatedLayout.reportLayoutChange(layout, () =>
639
+ document.querySelector('#inner'),
640
+ );
641
+ const outer = window.AnimatedLayout.reportLayoutChange(layout, () =>
642
+ document.querySelector('#a'),
643
+ );
644
+ inner.measureBefore();
645
+ outer.measureBefore();
646
+ document.querySelector<HTMLElement>('#inner')?.classList.add('open');
647
+ document.querySelector<HTMLElement>('#a')?.classList.add('open');
648
+ inner.animate();
649
+ outer.animate();
650
+ await new Promise<void>(resolve => {
651
+ queueMicrotask(resolve);
652
+ });
653
+ });
654
+ const [folder] = await page.evaluate(() => window.motionOf('#folder'));
655
+ const [row] = await page.evaluate(() => window.motionOf('#row'));
656
+ const [after] = await page.evaluate(() => window.motionOf('#after'));
657
+ // The folder moves by the first change; the row inside it by the inner
658
+ // one alone; what follows by both.
659
+ expect(startOffset(folder.first).y).toBeCloseTo(-80, 0);
660
+ expect(startOffset(row.first).y).toBeCloseTo(-80, 0);
661
+ expect(startOffset(after.first).y).toBeCloseTo(-160, 0);
662
+ });
663
+
664
+ for (const row of [
665
+ {
666
+ name: 'a centered row',
667
+ justify: 'center',
668
+ items: ['before', 'changed', 'after'],
669
+ // The row grows by 80 px: an item before moves left by half of it.
670
+ expectX: 40,
671
+ },
672
+ {
673
+ name: 'a space-between row',
674
+ justify: 'space-between',
675
+ items: ['first', 'before', 'changed', 'last'],
676
+ // Four items: the gaps shrink by a third of the growth each.
677
+ expectX: 80 / 3,
678
+ },
679
+ {
680
+ name: 'an end-aligned row',
681
+ justify: 'flex-end',
682
+ items: ['before', 'changed'],
683
+ expectX: 80,
684
+ },
685
+ ]) {
686
+ test(`an earlier sibling ${row.name} moves glides from its old place (spec:AST-105 Coverage)`, async ({
687
+ page,
688
+ }) => {
689
+ await open(
690
+ page,
691
+ `<div id="area" class="area"><div style="display: flex; justify-content: ${row.justify}; gap: 8px">
692
+ ${row.items
693
+ .map(
694
+ id =>
695
+ `<div id="${id}" style="width: 60px; height: 24px; flex: none; background: #ddd"></div>`,
696
+ )
697
+ .join('')}
698
+ </div></div>`,
699
+ );
700
+ await change(page, {
701
+ changed: '#changed',
702
+ mutate: `document.querySelector('#changed').style.width = '140px'`,
703
+ });
704
+ const [motion] = await page.evaluate(() => window.motionOf('#before'));
705
+ expect(motion).toBeDefined();
706
+ expect(startOffset(motion.first).x).toBeCloseTo(row.expectX, 0);
707
+ });
708
+ }
709
+
710
+ test('an earlier sibling that order places after the change glides from its old place (spec:AST-105 Coverage)', async ({
711
+ page,
712
+ }) => {
713
+ await open(
714
+ page,
715
+ `<div id="area" class="area"><div style="display: flex; gap: 8px">
716
+ <div id="ordered" style="order: 1; width: 60px; height: 24px; flex: none; background: #ddd"></div>
717
+ <div id="changed" style="width: 60px; height: 24px; flex: none; background: #ddd"></div>
718
+ </div></div>`,
719
+ );
720
+ await change(page, {
721
+ changed: '#changed',
722
+ mutate: `document.querySelector('#changed').style.width = '140px'`,
723
+ });
724
+ const [motion] = await page.evaluate(() => window.motionOf('#ordered'));
725
+ expect(motion).toBeDefined();
726
+ // First in the DOM, laid out after the change: it starts 80 px back.
727
+ expect(startOffset(motion.first).x).toBeCloseTo(-80, 0);
728
+ });
729
+
730
+ for (const position of ['absolute', 'fixed']) {
731
+ test(`a ${position} ancestor of the change takes its final place (spec:AST-105 Coverage)`, async ({
732
+ page,
733
+ }) => {
734
+ await open(
735
+ page,
736
+ `<div id="area" class="area">
737
+ <div id="anchored" style="position: ${position}; left: 0; bottom: 0; width: 300px">
738
+ <div id="grow" class="grow"></div><div class="row"></div>
739
+ </div>
740
+ </div>`,
741
+ );
742
+ await change(page);
743
+ // Anchored at its bottom, it grows upward: its top moves, yet it never
744
+ // glides.
745
+ expect(await page.evaluate(() => window.motionOf('#anchored'))).toEqual(
746
+ [],
747
+ );
748
+ });
749
+ }
750
+
751
+ test('inside a positioned ancestor only the content after the change moves: the header before it and the card around it take their final place (spec:AST-105 Coverage)', async ({
752
+ page,
753
+ }) => {
754
+ await open(
755
+ page,
756
+ `<div id="area" class="area">
757
+ <div style="position: absolute; left: 0; right: 0; bottom: 0">
758
+ <div id="header" class="row"></div>
759
+ <div id="card" style="padding: 8px; background: #eee"><div id="trigger" class="row"></div><div id="grow" class="grow"></div></div>
760
+ <div id="footer" class="row"></div>
761
+ </div>
762
+ </div>`,
763
+ );
764
+ await change(page);
765
+ // Docked at the bottom, the panel rises as the content opens, and
766
+ // everything around the change takes its place at once with it, so no
767
+ // gap opens and the revealing content never covers what is above it.
768
+ for (const id of ['#header', '#card', '#trigger']) {
769
+ expect(await page.evaluate(s => window.motionOf(s), id), id).toEqual([]);
770
+ }
771
+ });
772
+
773
+ test('a stuck sticky footer around the change stays at the area edge (spec:AST-105 Coverage, FR7)', async ({
774
+ page,
775
+ }) => {
776
+ await open(
777
+ page,
778
+ `<div id="area" class="area">${Array.from(
779
+ {length: 30},
780
+ () => '<div class="row"></div>',
781
+ ).join(
782
+ '',
783
+ )}<div id="footer" style="position: sticky; bottom: 0; background: #ccc"><div id="grow" class="grow"></div><div class="row"></div></div></div>`,
784
+ );
785
+ await change(page);
786
+ expect(await page.evaluate(() => window.motionOf('#footer'))).toEqual([]);
787
+ });
788
+
789
+ for (const reduce of [false, true]) {
790
+ test(`a change above the visible part inside a wrapper: with scroll anchoring the rows in view and their wrapper stay put${reduce ? ' under Reduce Motion' : ''} (FR3)`, async ({
791
+ page,
792
+ }) => {
793
+ if (reduce) {
794
+ await page.emulateMedia({reducedMotion: 'reduce'});
795
+ }
796
+ await open(
797
+ page,
798
+ `<div id="area" class="area"><div id="wrapper"><div id="grow" class="grow"></div>${Array.from(
799
+ {length: 1000},
800
+ (_, i) => `<div id="r${i}" class="row"></div>`,
801
+ ).join('')}</div></div>`,
802
+ );
803
+ const result = await page.evaluate(async () => {
804
+ const area = document.querySelector('#area') as HTMLElement;
805
+ area.scrollTop = 4200;
806
+ const inView = document.querySelector('#r95') as HTMLElement;
807
+ const before = inView.getBoundingClientRect().top;
808
+ await window.change({
809
+ changed: '#grow',
810
+ mutate: `document.querySelector('#grow').classList.add('open')`,
811
+ });
812
+ const wrapper = document.querySelector('#wrapper') as HTMLElement;
813
+ const moving = [wrapper, ...wrapper.children].filter(
814
+ element => element.getAnimations().length > 0,
815
+ ).length;
816
+ const shown = inView.getBoundingClientRect().top;
817
+ document.getAnimations().forEach(animation => animation.finish());
818
+ return {moving, before, shown};
819
+ });
820
+ // The browser keeps the rows in view where they were; nothing glides
821
+ // or fades, the wrapper around them included.
822
+ expect(result.moving).toBe(0);
823
+ expect(Math.abs(result.shown - result.before)).toBeLessThan(1);
824
+ });
825
+ }
826
+
827
+ test('a change above the view in a panel the page scrolls: with the page anchoring its scroll, the rows in view and their wrapper stay put (FR3)', async ({
828
+ page,
829
+ }) => {
830
+ await open(
831
+ page,
832
+ `<div id="area"><div id="wrapper"><div id="grow" class="grow"></div>${Array.from(
833
+ {length: 1000},
834
+ (_, i) => `<div id="r${i}" class="row"></div>`,
835
+ ).join('')}</div></div>`,
836
+ );
837
+ const result = await page.evaluate(async () => {
838
+ window.scrollTo(0, 4200);
839
+ const inView = document.querySelector('#r95') as HTMLElement;
840
+ const before = inView.getBoundingClientRect().top;
841
+ await window.change({
842
+ changed: '#grow',
843
+ mutate: `document.querySelector('#grow').classList.add('open')`,
844
+ });
845
+ const wrapper = document.querySelector('#wrapper') as HTMLElement;
846
+ const moving = [wrapper, ...wrapper.children].filter(
847
+ element => element.getAnimations().length > 0,
848
+ ).length;
849
+ const shown = inView.getBoundingClientRect().top;
850
+ document.getAnimations().forEach(animation => animation.finish());
851
+ return {moving, before, shown};
852
+ });
853
+ expect(result.moving).toBe(0);
854
+ expect(Math.abs(result.shown - result.before)).toBeLessThan(1);
855
+ });
856
+
857
+ test('a sticky footer stuck to the viewport in a panel the page scrolls stays at the edge (FR7)', async ({
858
+ page,
859
+ }) => {
860
+ await open(
861
+ page,
862
+ `<div id="area">${Array.from(
863
+ {length: 60},
864
+ () => '<div class="row"></div>',
865
+ ).join(
866
+ '',
867
+ )}<div id="footer" style="position: sticky; bottom: 0; background: #ccc"><div id="grow" class="grow"></div><div class="row"></div></div>${Array.from(
868
+ {length: 60},
869
+ () => '<div class="row"></div>',
870
+ ).join('')}</div>`,
871
+ );
872
+ await page.evaluate(() => window.scrollTo(0, 200));
873
+ await change(page);
874
+ expect(await page.evaluate(() => window.motionOf('#footer'))).toEqual([]);
875
+ });
876
+
877
+ test('in a multi-column list the rows of a later column glide too (spec:AST-105 Coverage)', async ({
878
+ page,
879
+ }) => {
880
+ await open(
881
+ page,
882
+ `<div id="area" class="area"><div id="list" style="columns: 2; column-gap: 8px">${[
883
+ '<div id="grow" class="grow"></div>',
884
+ ...Array.from(
885
+ {length: 120},
886
+ (_, i) =>
887
+ `<div id="c${i}" class="row" style="break-inside: avoid"></div>`,
888
+ ),
889
+ ].join('')}</div></div>`,
890
+ );
891
+ await change(page);
892
+ const moving = await page.evaluate(
893
+ () =>
894
+ [...document.querySelectorAll('#list > .row')].filter(
895
+ row => row.getAnimations().length > 0,
896
+ ).length,
897
+ );
898
+ // Every row shifts one slot along the columns; the rows in view glide,
899
+ // the second column's included, though they come past the band in DOM
900
+ // order.
901
+ expect(moving).toBeGreaterThanOrEqual(20);
902
+ });
903
+
904
+ test('in a dialog re-centered as it grows, the header and trigger before the change stay with their card (FR3)', async ({
905
+ page,
906
+ }) => {
907
+ await open(
908
+ page,
909
+ `<div style="position: fixed; inset: 0; display: flex; align-items: center; justify-content: center">
910
+ <div id="area" style="width: 320px; background: #fff; border: 1px solid #999">
911
+ <div id="header" class="row"></div>
912
+ <div id="card" style="padding: 8px; background: #eee"><div id="trigger" class="row"></div><div id="grow" class="grow"></div></div>
913
+ </div>
914
+ </div>`,
915
+ );
916
+ await change(page);
917
+ // The dialog rises by half the opening at once; what is before the
918
+ // change in it rises with it, never over the opening content.
919
+ for (const id of ['#header', '#card', '#trigger']) {
920
+ expect(await page.evaluate(s => window.motionOf(s), id), id).toEqual([]);
921
+ }
922
+ });
923
+
924
+ test('a sticky footer stuck to the viewport stays at the edge when the body sets an overflow (FR7)', async ({
925
+ page,
926
+ }) => {
927
+ await open(
928
+ page,
929
+ `<div id="area">${Array.from(
930
+ {length: 60},
931
+ () => '<div class="row"></div>',
932
+ ).join(
933
+ '',
934
+ )}<div id="footer" style="position: sticky; bottom: 0; background: #ccc"><div id="grow" class="grow"></div><div class="row"></div></div>${Array.from(
935
+ {length: 60},
936
+ () => '<div class="row"></div>',
937
+ ).join('')}</div>`,
938
+ 'body { overflow-x: hidden; }',
939
+ );
940
+ await page.evaluate(() => window.scrollTo(0, 200));
941
+ await change(page);
942
+ expect(await page.evaluate(() => window.motionOf('#footer'))).toEqual([]);
943
+ });
944
+
945
+ test('closing an item above the view while opening one in view, in one frame: the rows the browser keeps in place stay put (FR3)', async ({
946
+ page,
947
+ }) => {
948
+ await open(
949
+ page,
950
+ `<div id="area" class="area"><div id="shut" style="height: 344px; overflow: hidden; background: #fd9"></div>${Array.from(
951
+ {length: 30},
952
+ (_, i) =>
953
+ i === 14
954
+ ? '<div id="grow" class="grow"></div>'
955
+ : `<div id="q${i}" class="row"></div>`,
956
+ ).join('')}</div>`,
957
+ );
958
+ const result = await page.evaluate(async () => {
959
+ const area = document.querySelector('#area') as HTMLElement;
960
+ area.scrollTop = 395;
961
+ const layout = window.AnimatedLayout.createAnimatedLayout(() => area);
962
+ const shut = window.AnimatedLayout.reportLayoutChange(layout, () =>
963
+ document.querySelector('#shut'),
964
+ );
965
+ const grow = window.AnimatedLayout.reportLayoutChange(layout, () =>
966
+ document.querySelector('#grow'),
967
+ );
968
+ shut.measureBefore();
969
+ grow.measureBefore();
970
+ (document.querySelector('#shut') as HTMLElement).style.height = '0px';
971
+ document.querySelector('#grow')?.classList.add('open');
972
+ shut.animate();
973
+ grow.animate();
974
+ await new Promise<void>(resolve => {
975
+ queueMicrotask(resolve);
976
+ });
977
+ // The rows in view before the opening one: anchoring keeps them still.
978
+ return [5, 6, 7, 8, 9].map(
979
+ i => document.querySelector(`#q${i}`)?.getAnimations().length ?? -1,
980
+ );
981
+ });
982
+ expect(result).toEqual([0, 0, 0, 0, 0]);
983
+ });
984
+
985
+ for (const anchoring of ['auto', 'none']) {
986
+ test(`a change above the band with scroll anchoring ${anchoring === 'auto' ? 'on' : 'off'}: ${anchoring === 'auto' ? 'the rows in view stay put and the walk stops' : 'the rows in view glide'} (FR3)`, async ({
987
+ page,
988
+ }) => {
989
+ await open(
990
+ page,
991
+ `<div id="area" class="area" style="overflow-anchor: ${anchoring}"><div id="grow" class="grow"></div>${Array.from(
992
+ {length: 1000},
993
+ (_, i) => `<div id="r${i}" class="row"></div>`,
994
+ ).join('')}</div>`,
995
+ );
996
+ const result = await page.evaluate(async () => {
997
+ const area = document.querySelector('#area') as HTMLElement;
998
+ area.scrollTop = 3600 + 600;
999
+ const firstInView = document.querySelector('#r95') as HTMLElement;
1000
+ const before = firstInView.getBoundingClientRect().top;
1001
+ await window.change({
1002
+ changed: '#grow',
1003
+ mutate: `document.querySelector('#grow').classList.add('open')`,
1004
+ });
1005
+ const moving = [...area.children].filter(
1006
+ row => row.getAnimations().length > 0,
1007
+ ).length;
1008
+ document.getAnimations().forEach(animation => animation.finish());
1009
+ return {moving, before, after: firstInView.getBoundingClientRect().top};
1010
+ });
1011
+ if (anchoring === 'auto') {
1012
+ // The browser keeps the rows in view where they were: nothing moves.
1013
+ expect(result.moving).toBe(0);
1014
+ expect(Math.abs(result.after - result.before)).toBeLessThan(1);
1015
+ } else {
1016
+ // They shift down 80 px, and glide there.
1017
+ expect(result.moving).toBeGreaterThanOrEqual(12);
1018
+ }
1019
+ });
1020
+ }
1021
+
1022
+ test('in a centered column an unstuck sticky card around the change glides with the content before it (spec:AST-105 Coverage)', async ({
1023
+ page,
1024
+ }) => {
1025
+ await open(
1026
+ page,
1027
+ `<div id="area" class="area"><div style="display: flex; flex-direction: column; justify-content: center; min-height: 400px">
1028
+ <div id="above" class="row"></div>
1029
+ <div id="card" style="position: sticky; top: 0; background: #eee"><div id="grow" class="grow"></div><div class="row"></div></div>
1030
+ <div class="row"></div>
1031
+ </div></div>`,
1032
+ );
1033
+ await change(page);
1034
+ const [above] = await page.evaluate(() => window.motionOf('#above'));
1035
+ const [card] = await page.evaluate(() => window.motionOf('#card'));
1036
+ // Not stuck, the card is in flow: it rises with the row above it, so
1037
+ // that row never crosses it.
1038
+ expect(above).toBeDefined();
1039
+ expect(card).toBeDefined();
1040
+ expect(startOffset(card.first).y).toBeCloseTo(
1041
+ startOffset(above.first).y,
1042
+ 0,
1043
+ );
1044
+ });
1045
+
1046
+ test('in a centered column the card around the change glides with the content before it, so nothing slides over the opening content (spec:AST-105 Coverage)', async ({
1047
+ page,
1048
+ }) => {
1049
+ await open(
1050
+ page,
1051
+ `<div id="area" class="area"><div style="display: flex; flex-direction: column; justify-content: center; min-height: 400px">
1052
+ <div id="before" class="row" style="margin: 0"></div>
1053
+ <div id="card" style="padding: 8px; background: #eef"><div id="title" style="height: 24px">Title</div><div id="changed" style="height: 0"></div></div>
1054
+ <div id="after" class="row" style="margin: 0"></div></div></div>`,
1055
+ );
1056
+ await change(page, {
1057
+ changed: '#changed',
1058
+ mutate: `document.querySelector('#changed').style.height = '120px'`,
1059
+ });
1060
+ const card = await page.evaluate(() => window.motionOf('#card'));
1061
+ const before = await page.evaluate(() => window.motionOf('#before'));
1062
+ const title = await page.evaluate(() => window.motionOf('#title'));
1063
+ // The card and the row above it glide up together from their old place;
1064
+ // the title inside the card rides with it.
1065
+ expect(startOffset(card[0].first).y).toBeCloseTo(60, 0);
1066
+ expect(startOffset(before[0].first).y).toBeCloseTo(60, 0);
1067
+ expect(title).toEqual([]);
1068
+ });
1069
+
1070
+ test('in a long list the walk reads only the rows near the visible part, and rows a tall collapse pulls up into view glide in (FR3)', async ({
1071
+ page,
1072
+ }) => {
1073
+ await open(
1074
+ page,
1075
+ `<div id="area" class="area" style="overflow-anchor: none">
1076
+ ${'<div class="row" style="margin: 0"></div>'.repeat(1000)}
1077
+ <div id="tall" style="height: 1200px; background: #fd9"></div>
1078
+ ${Array.from({length: 1000}, (_, i) => `<div id="r${i}" class="row" style="margin: 0"></div>`).join('')}
1079
+ </div>`,
1080
+ );
1081
+ const result = await page.evaluate(async () => {
1082
+ const area = document.querySelector('#area') as HTMLElement;
1083
+ const tall = document.querySelector('#tall') as HTMLElement;
1084
+ // The tall item's bottom part in view.
1085
+ area.scrollTop = tall.offsetTop + 1000 - area.clientHeight / 2;
1086
+ const prototype = Element.prototype;
1087
+ const original = prototype.getBoundingClientRect;
1088
+ let reads = 0;
1089
+ prototype.getBoundingClientRect = function getBoundingClientRect(
1090
+ this: Element,
1091
+ ) {
1092
+ reads += 1;
1093
+ return original.call(this);
1094
+ };
1095
+ const layout = window.AnimatedLayout.createAnimatedLayout(() => area);
1096
+ const report = window.AnimatedLayout.reportLayoutChange(
1097
+ layout,
1098
+ () => tall,
1099
+ );
1100
+ report.measureBefore();
1101
+ tall.style.height = '0px';
1102
+ report.animate();
1103
+ await new Promise<void>(resolve => {
1104
+ queueMicrotask(resolve);
1105
+ });
1106
+ prototype.getBoundingClientRect = original;
1107
+ // Rows now in view that were below the area's visible part plus one
1108
+ // viewport before the collapse: the band reached them because the
1109
+ // collapsing item is taller than a viewport.
1110
+ const areaRect = area.getBoundingClientRect();
1111
+ const inView = [
1112
+ ...area.querySelectorAll<HTMLElement>('[id^="r"]'),
1113
+ ].filter(row => {
1114
+ const rect = row.getBoundingClientRect();
1115
+ return rect.bottom > areaRect.top && rect.top < areaRect.bottom;
1116
+ });
1117
+ const lowest = inView.at(-1);
1118
+ return {
1119
+ reads,
1120
+ rows: inView.length,
1121
+ lowestGlides: lowest?.getAnimations().length ?? 0,
1122
+ };
1123
+ });
1124
+ // Two thousand rows, but only those near the visible part are read.
1125
+ expect(result.reads).toBeLessThan(200);
1126
+ expect(result.rows).toBeGreaterThan(0);
1127
+ expect(result.lowestGlides).toBe(1);
1128
+ });
1129
+
1130
+ test('the glide never scrolls the area (FR3)', async ({page}) => {
1131
+ // The same change with and without a handle, from the same scroll
1132
+ // position: the area's scroll (the browser's own scroll anchoring
1133
+ // included) is identical, frame by frame, so the glide adds none.
1134
+ const scrollsOf = async (handle: boolean) => {
1135
+ await open(page, PAGE);
1136
+ return page.evaluate(
1137
+ async ({mutate, withHandle}) => {
1138
+ const area = document.querySelector('#area') as HTMLElement;
1139
+ area.scrollTop = 40;
1140
+ const frame = async () =>
1141
+ new Promise(resolve => requestAnimationFrame(resolve));
1142
+ await frame();
1143
+ await frame();
1144
+ await window.change({changed: '#grow', mutate, handle: withHandle});
1145
+ const tops: number[] = [];
1146
+ for (let i = 0; i < 40; i++) {
1147
+ tops.push(area.scrollTop);
1148
+ await frame();
1149
+ }
1150
+ return tops;
1151
+ },
1152
+ {mutate: OPEN_GROW, withHandle: handle},
1153
+ );
1154
+ };
1155
+ const without = await scrollsOf(false);
1156
+ const withHandle = await scrollsOf(true);
1157
+ expect(withHandle).toEqual(without);
1158
+ });
1159
+
1160
+ test('the changed element and its followers start on one frame on springs.settle (FR4)', async ({
1161
+ page,
1162
+ }) => {
1163
+ await open(page, PAGE);
1164
+ await change(page);
1165
+ await page.waitForTimeout(50);
1166
+ const grow = await page.evaluate(() => window.motionOf('#grow'));
1167
+ const follower = await page.evaluate(() => window.motionOf('#a'));
1168
+ expect(grow).toHaveLength(1);
1169
+ expect(follower).toHaveLength(1);
1170
+ expect(grow[0].startTime).toBe(follower[0].startTime);
1171
+ expect(grow[0].duration).toBeCloseTo(follower[0].duration, 3);
1172
+ // springs.settle is SwiftUI's smooth spring (duration 0.5 s, no bounce):
1173
+ // it settles within a second.
1174
+ expect(follower[0].duration).toBeGreaterThan(300);
1175
+ expect(follower[0].duration).toBeLessThan(1200);
1176
+ });
1177
+
1178
+ for (const layout of [
1179
+ {
1180
+ name: 'block flow',
1181
+ html: `<div style="display: block"><div id="content" style="height: 80px; background: #fd9">Details</div><div id="a" class="row" style="margin: 0"></div></div>`,
1182
+ },
1183
+ {
1184
+ name: 'a column flex box with a gap',
1185
+ html: `<div style="display: flex; flex-direction: column; gap: 12px"><div id="content" style="height: 80px; background: #fd9">Details</div><div id="a" class="row" style="margin: 0"></div></div>`,
1186
+ },
1187
+ {
1188
+ name: 'a centered column',
1189
+ html: `<div style="display: flex; flex-direction: column; justify-content: center; min-height: 400px"><div class="row"></div><div id="content" style="height: 80px; background: #fd9">Details</div><div id="a" class="row"></div></div>`,
1190
+ },
1191
+ {
1192
+ name: 'a space-between column',
1193
+ html: `<div style="display: flex; flex-direction: column; justify-content: space-between; min-height: 400px"><div class="row"></div><div id="content" style="height: 80px; background: #fd9">Details</div><div id="a" class="row"></div><div class="row"></div></div>`,
1194
+ },
1195
+ {
1196
+ name: 'a column that ends a flex row',
1197
+ html: `<div style="display: flex; gap: 8px"><div style="display: flex; flex-direction: column; flex: 1"><div class="row"></div><div id="content" style="height: 80px; background: #fd9">Details</div></div><div style="width: 60px; height: 40px; background: #ddd"></div></div><div id="a" class="row"></div>`,
1198
+ },
1199
+ ]) {
1200
+ test(`an exit in ${layout.name} lands the content after it exactly where it goes once hidden (FR4)`, async ({
1201
+ page,
1202
+ }) => {
1203
+ await open(
1204
+ page,
1205
+ `<div id="area" class="area">${layout.html}<div class="row"></div></div>`,
1206
+ );
1207
+ const result = await page.evaluate(async () => {
1208
+ const area = document.querySelector('#area');
1209
+ const content = document.querySelector('#content') as HTMLElement;
1210
+ const a = document.querySelector('#a') as HTMLElement;
1211
+ const handle = window.AnimatedLayout.createAnimatedLayout(() => area);
1212
+ const report = window.AnimatedLayout.reportLayoutChange(
1213
+ handle,
1214
+ () => content,
1215
+ );
1216
+ report.measureBefore();
1217
+ report.animate();
1218
+ // Where the content after it lands once the element is gone.
1219
+ content.style.display = 'none';
1220
+ const target = a.getBoundingClientRect().top;
1221
+ content.style.display = '';
1222
+ const held = window.AnimatedLayout.holdLayoutExit(
1223
+ handle,
1224
+ content,
1225
+ () => {},
1226
+ );
1227
+ await new Promise<void>(resolve => {
1228
+ queueMicrotask(resolve);
1229
+ });
1230
+ a.getAnimations().forEach(animation => animation.finish());
1231
+ const landed = a.getBoundingClientRect().top;
1232
+ // When the element hides, nothing after it moves again.
1233
+ content.style.display = 'none';
1234
+ window.AnimatedLayout.releaseLayoutExit(content);
1235
+ const hidden = a.getBoundingClientRect().top;
1236
+ return {held, landed, hidden, target};
1237
+ });
1238
+ if (result.held) {
1239
+ expect(Math.abs(result.landed - result.target)).toBeLessThan(0.5);
1240
+ }
1241
+ expect(Math.abs(result.hidden - result.target)).toBeLessThan(0.5);
1242
+ });
1243
+ }
1244
+
1245
+ test('a closing element exits on the same motion while the content after it glides up at once (FR4)', async ({
1246
+ page,
1247
+ }) => {
1248
+ await open(
1249
+ page,
1250
+ `<div id="area" class="area"><div id="content" style="height: 80px; background: #fd9">Details</div>
1251
+ <div id="a" class="row"></div><div id="b" class="row"></div></div>`,
1252
+ );
1253
+ const result = await page.evaluate(async () => {
1254
+ const area = document.querySelector('#area');
1255
+ const content = document.querySelector('#content') as HTMLElement;
1256
+ const layout = window.AnimatedLayout.createAnimatedLayout(() => area);
1257
+ const report = window.AnimatedLayout.reportLayoutChange(
1258
+ layout,
1259
+ () => content,
1260
+ );
1261
+ report.measureBefore();
1262
+ // The component closes it but keeps it rendered for the exit, holding
1263
+ // it once the change reports it measured.
1264
+ report.animate();
1265
+ let finished = false;
1266
+ const held = window.AnimatedLayout.holdLayoutExit(layout, content, () => {
1267
+ finished = true;
1268
+ });
1269
+ await new Promise<void>(resolve => {
1270
+ queueMicrotask(resolve);
1271
+ });
1272
+ const exit = content.getAnimations()[0];
1273
+ const timing = exit?.effect?.getTiming();
1274
+ const followerStart = window.motionOf('#a')[0]?.first ?? null;
1275
+ const visible = getComputedStyle(content).display !== 'none';
1276
+ await exit?.finished;
1277
+ // The finish event follows the finished promise.
1278
+ await new Promise(resolve => {
1279
+ setTimeout(resolve, 50);
1280
+ });
1281
+ return {
1282
+ held,
1283
+ visible,
1284
+ position: getComputedStyle(content).position,
1285
+ marginEnd: content.style.getPropertyValue('margin-block-end'),
1286
+ followerStart,
1287
+ exitDuration: Number(timing?.duration),
1288
+ followerDuration: window.motionOf('#a')[0]?.duration ?? null,
1289
+ finished,
1290
+ };
1291
+ });
1292
+ expect(result.held).toBe(true);
1293
+ expect(result.visible).toBe(true);
1294
+ // In flow, where it was, giving up its space.
1295
+ expect(result.position).toBe('static');
1296
+ expect(result.marginEnd).toBe('-80px');
1297
+ // The row below starts 80 px lower, where it was, and glides up.
1298
+ expect(startOffset(result.followerStart).y).toBeCloseTo(80, 0);
1299
+ expect(result.finished).toBe(true);
1300
+ });
1301
+
1302
+ test('an exiting element in a scrolled area stays where it is, scrolls with the area and keeps its width (FR4)', async ({
1303
+ page,
1304
+ }) => {
1305
+ await open(
1306
+ page,
1307
+ `<div id="area" class="area" style="overflow-anchor: none">
1308
+ ${'<div class="row"></div>'.repeat(3)}
1309
+ <div id="content" style="box-sizing: content-box; padding: 12px 18px; border: 2px solid #c90; height: 80px">Details</div>
1310
+ ${'<div class="row"></div>'.repeat(30)}
1311
+ </div>`,
1312
+ );
1313
+ const result = await page.evaluate(async () => {
1314
+ const area = document.querySelector('#area') as HTMLElement;
1315
+ const content = document.querySelector('#content') as HTMLElement;
1316
+ area.scrollTop = 60;
1317
+ const before = content.getBoundingClientRect();
1318
+ const layout = window.AnimatedLayout.createAnimatedLayout(() => area);
1319
+ const report = window.AnimatedLayout.reportLayoutChange(
1320
+ layout,
1321
+ () => content,
1322
+ );
1323
+ report.measureBefore();
1324
+ report.animate();
1325
+ window.AnimatedLayout.holdLayoutExit(layout, content, () => {});
1326
+ await new Promise<void>(resolve => {
1327
+ queueMicrotask(resolve);
1328
+ });
1329
+ const held = content.getBoundingClientRect();
1330
+ area.scrollTop = 80;
1331
+ const scrolled = content.getBoundingClientRect();
1332
+ return {before, held, scrolled};
1333
+ });
1334
+ expect(result.held.top).toBeCloseTo(result.before.top, 0);
1335
+ expect(result.held.width).toBeCloseTo(result.before.width, 0);
1336
+ // It scrolls with the area (so the area still clips it).
1337
+ expect(result.scrolled.top).toBeCloseTo(result.before.top - 20, 0);
1338
+ });
1339
+
1340
+ for (const layout of [
1341
+ {
1342
+ name: 'a flex column with a gap',
1343
+ html: `<div style="display: flex; flex-direction: column; gap: 8px">
1344
+ <div class="row" style="margin: 0"></div>
1345
+ <div id="content" style="height: 80px; background: #fd9">Details</div>
1346
+ <div id="after" class="row" style="margin: 0"></div>
1347
+ </div>`,
1348
+ },
1349
+ {
1350
+ name: 'collapsing margins',
1351
+ html: `<div>
1352
+ <div class="row" style="margin: 0"></div>
1353
+ <div id="content" style="height: 80px; margin: 10px 0 20px; background: #fd9">Details</div>
1354
+ <div id="after" class="row" style="margin: 0"></div>
1355
+ </div>`,
1356
+ },
1357
+ {
1358
+ // What follows is inside a `display: contents` wrapper, as Tooltip and
1359
+ // Theme render one.
1360
+ name: 'a flex column whose next item is a display: contents wrapper',
1361
+ html: `<div style="display: flex; flex-direction: column; gap: 8px">
1362
+ <div class="row" style="margin: 0"></div>
1363
+ <div id="content" style="height: 80px; background: #fd9">Details</div>
1364
+ <div style="display: contents"><div id="after" class="row" style="margin: 0"></div></div>
1365
+ </div>`,
1366
+ },
1367
+ {
1368
+ // Under a scaled ancestor: the correction is read in screen px.
1369
+ name: 'a gap stack under a scaled ancestor',
1370
+ html: `<div style="transform: scale(0.5); transform-origin: 0 0">
1371
+ <div style="display: flex; flex-direction: column; gap: 8px">
1372
+ <div class="row" style="margin: 0"></div>
1373
+ <div id="content" style="height: 80px; background: #fd9">Details</div>
1374
+ <div id="after" class="row" style="margin: 0"></div>
1375
+ </div>
1376
+ </div>`,
1377
+ },
1378
+ {
1379
+ // Collapsible's shape: the content is the last child of a plain block
1380
+ // wrapper, and what follows sits after the wrapper.
1381
+ name: 'a plain wrapper, as its last child',
1382
+ html: `<div>
1383
+ <div class="row" style="margin: 0"></div>
1384
+ <div id="content" style="height: 80px; background: #fd9">Details</div>
1385
+ </div>
1386
+ <p id="after" style="margin: 0; height: 40px">Next</p>`,
1387
+ },
1388
+ ]) {
1389
+ test(`an exiting element frees exactly its space in ${layout.name}: the content after it does not jump when it hides (FR3, FR4)`, async ({
1390
+ page,
1391
+ }) => {
1392
+ await open(page, `<div id="area" class="area">${layout.html}</div>`);
1393
+ const result = await page.evaluate(async () => {
1394
+ const area = document.querySelector('#area');
1395
+ const content = document.querySelector('#content') as HTMLElement;
1396
+ const after = document.querySelector('#after') as HTMLElement;
1397
+ const layoutHandle = window.AnimatedLayout.createAnimatedLayout(
1398
+ () => area,
1399
+ );
1400
+ const report = window.AnimatedLayout.reportLayoutChange(
1401
+ layoutHandle,
1402
+ () => content,
1403
+ );
1404
+ report.measureBefore();
1405
+ const measured = report.animate();
1406
+ const held = window.AnimatedLayout.holdLayoutExit(
1407
+ layoutHandle,
1408
+ content,
1409
+ () => {},
1410
+ );
1411
+ const inert = content.hasAttribute('inert');
1412
+ await new Promise<void>(resolve => {
1413
+ queueMicrotask(resolve);
1414
+ });
1415
+ const glides = after.getAnimations().length;
1416
+ for (const animation of document.getAnimations()) {
1417
+ animation.finish();
1418
+ }
1419
+ const settled = after.getBoundingClientRect().top;
1420
+ // The component hides it once its exit ends.
1421
+ content.style.display = 'none';
1422
+ window.AnimatedLayout.releaseLayoutExit(content);
1423
+ const hidden = after.getBoundingClientRect().top;
1424
+ return {measured, held, inert, glides, settled, hidden};
1425
+ });
1426
+ expect(result.measured).toBe(true);
1427
+ expect(result.held).toBe(true);
1428
+ expect(result.inert).toBe(true);
1429
+ expect(result.glides).toBe(1);
1430
+ expect(result.settled).toBeCloseTo(result.hidden, 0);
1431
+ });
1432
+ }
1433
+
1434
+ test("a closing flex-row item that sets its row's height hides at once, and the content after the row takes its final place at once", async ({
1435
+ page,
1436
+ }) => {
1437
+ await open(
1438
+ page,
1439
+ `<div id="area" class="area">
1440
+ <div style="display: flex; align-items: flex-start; gap: 8px">
1441
+ <div id="content" style="width: 80px; height: 120px; background: #fd9"></div>
1442
+ <div style="width: 80px; height: 40px; background: #9cf"></div>
1443
+ </div>
1444
+ <div id="after" class="row" style="margin: 0"></div>
1445
+ </div>`,
1446
+ );
1447
+ const result = await page.evaluate(async () => {
1448
+ const area = document.querySelector('#area');
1449
+ const content = document.querySelector('#content') as HTMLElement;
1450
+ const after = document.querySelector('#after') as HTMLElement;
1451
+ const layoutHandle = window.AnimatedLayout.createAnimatedLayout(
1452
+ () => area,
1453
+ );
1454
+ const report = window.AnimatedLayout.reportLayoutChange(
1455
+ layoutHandle,
1456
+ () => content,
1457
+ );
1458
+ report.measureBefore();
1459
+ report.animate();
1460
+ const held = window.AnimatedLayout.holdLayoutExit(
1461
+ layoutHandle,
1462
+ content,
1463
+ () => {},
1464
+ );
1465
+ // The component hides it in the same commit.
1466
+ content.style.display = 'none';
1467
+ await new Promise<void>(resolve => {
1468
+ queueMicrotask(resolve);
1469
+ });
1470
+ return {
1471
+ held,
1472
+ margin: content.style.getPropertyValue('margin-inline-end'),
1473
+ glides: after.getAnimations().length,
1474
+ };
1475
+ });
1476
+ expect(result).toEqual({held: false, margin: '', glides: 0});
1477
+ });
1478
+
1479
+ test('holding the exit keeps the CSS animations inside the element running (FR4)', async ({
1480
+ page,
1481
+ }) => {
1482
+ await open(
1483
+ page,
1484
+ `<style>@keyframes spin { to { rotate: 360deg; } }</style>
1485
+ <div id="area" class="area">
1486
+ <div id="content" style="height: 80px"><div id="spinner" style="width: 20px; height: 20px; background: #36c; animation: spin 2s linear infinite"></div></div>
1487
+ <div id="after" class="row"></div>
1488
+ </div>`,
1489
+ );
1490
+ const result = await page.evaluate(async () => {
1491
+ const area = document.querySelector('#area');
1492
+ const content = document.querySelector('#content') as HTMLElement;
1493
+ const spinner = document.querySelector('#spinner') as HTMLElement;
1494
+ await new Promise(resolve => {
1495
+ setTimeout(resolve, 300);
1496
+ });
1497
+ let restarts = 0;
1498
+ spinner.addEventListener('animationstart', () => {
1499
+ restarts += 1;
1500
+ });
1501
+ const before = Number(spinner.getAnimations()[0]?.currentTime);
1502
+ const layoutHandle = window.AnimatedLayout.createAnimatedLayout(
1503
+ () => area,
1504
+ );
1505
+ const report = window.AnimatedLayout.reportLayoutChange(
1506
+ layoutHandle,
1507
+ () => content,
1508
+ );
1509
+ report.measureBefore();
1510
+ report.animate();
1511
+ const held = window.AnimatedLayout.holdLayoutExit(
1512
+ layoutHandle,
1513
+ content,
1514
+ () => {},
1515
+ );
1516
+ const after = Number(spinner.getAnimations()[0]?.currentTime);
1517
+ await new Promise(resolve => {
1518
+ setTimeout(resolve, 100);
1519
+ });
1520
+ return {held, before, after, restarts};
1521
+ });
1522
+ expect(result.held).toBe(true);
1523
+ // The spinner kept its time: no restart from 0.
1524
+ expect(result.after).toBeGreaterThanOrEqual(result.before);
1525
+ expect(result.restarts).toBe(0);
1526
+ });
1527
+
1528
+ test('a follower the app moves with its own transform takes its final place at once', async ({
1529
+ page,
1530
+ }) => {
1531
+ await open(
1532
+ page,
1533
+ `<div id="area" class="area"><div id="grow" class="grow"></div>
1534
+ <div id="moved" class="row" style="transform: translateX(4px)"></div>
1535
+ <div id="spun" class="row"></div>
1536
+ <div id="plain" class="row"></div></div>`,
1537
+ );
1538
+ await page.evaluate(() => {
1539
+ document
1540
+ .querySelector('#spun')
1541
+ ?.animate([{rotate: '0deg'}, {rotate: '3deg'}], {
1542
+ duration: 5000,
1543
+ iterations: Infinity,
1544
+ });
1545
+ });
1546
+ await change(page);
1547
+ expect(await page.evaluate(() => window.motionOf('#moved'))).toEqual([]);
1548
+ const spun = await page.evaluate(() => window.motionOf('#spun'));
1549
+ expect(spun.filter(m => m.first?.includes('px') === true)).toEqual([]);
1550
+ expect(await page.evaluate(() => window.motionOf('#plain'))).toHaveLength(
1551
+ 1,
1552
+ );
1553
+ });
1554
+
1555
+ test("a scope's --motion-springs-settle changes nothing: the role is internal (FR4)", async ({
1556
+ page,
1557
+ }) => {
1558
+ await open(page, PAGE);
1559
+ await change(page);
1560
+ const [shared] = await page.evaluate(() => window.motionOf('#a'));
1561
+ await open(page, PAGE, '#area { --motion-springs-settle: 0.2s 0; }');
1562
+ await change(page);
1563
+ const [scoped] = await page.evaluate(() => window.motionOf('#a'));
1564
+ expect(scoped.duration).toBeCloseTo(shared.duration, 3);
1565
+ });
1566
+
1567
+ test('under Reduce Motion with a coarse pointer, both cross-fade with no travel (FR4)', async ({
1568
+ page,
1569
+ }) => {
1570
+ await page.emulateMedia({reducedMotion: 'reduce'});
1571
+ await open(page, PAGE);
1572
+ expect(
1573
+ await page.evaluate(() => matchMedia('(pointer: coarse)').matches),
1574
+ ).toBe(true);
1575
+ await change(page);
1576
+ for (const id of ['#grow', '#a']) {
1577
+ const [motion] = await page.evaluate(s => window.motionOf(s), id);
1578
+ expect(motion.first, id).toBeNull();
1579
+ expect(motion.opacity, id).toBe('0');
1580
+ expect(motion.duration, id).toBeLessThanOrEqual(200);
1581
+ }
1582
+ });
1583
+ });
1584
+
1585
+ test.describe('spec:AST-105 FR5 and FR4 under a fine pointer', () => {
1586
+ test.use({
1587
+ isMobile: false,
1588
+ hasTouch: false,
1589
+ viewport: {width: 1280, height: 800},
1590
+ });
1591
+
1592
+ const PAGE = `<div id="area" class="area"><div id="grow" class="grow"></div>
1593
+ <div id="a" class="row"></div></div>`;
1594
+
1595
+ test('the glide applies under a mouse (FR5)', async ({page}) => {
1596
+ await open(page, PAGE);
1597
+ expect(
1598
+ await page.evaluate(() => matchMedia('(pointer: fine)').matches),
1599
+ ).toBe(true);
1600
+ await change(page);
1601
+ expect(await page.evaluate(() => window.motionOf('#a'))).toHaveLength(1);
1602
+ });
1603
+
1604
+ test('under Reduce Motion with a fine pointer the change is immediate (FR4)', async ({
1605
+ page,
1606
+ }) => {
1607
+ await page.emulateMedia({reducedMotion: 'reduce'});
1608
+ await open(page, PAGE);
1609
+ await change(page);
1610
+ expect(await page.evaluate(() => window.motionOf('#grow'))).toEqual([]);
1611
+ expect(await page.evaluate(() => window.motionOf('#a'))).toEqual([]);
1612
+ });
1613
+ });