@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,1801 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file animatedLayout.ts
5
+ * @input The DOM (layout rectangles, computed style), Web Animations, the
6
+ * internal `springs.settle` motion role (motion/roles.ts) and the Reduce Motion
7
+ * cross-fade clock (uikit/timing.ts)
8
+ * @output Exports `createAnimatedLayout` and the opaque `AnimatedLayout`
9
+ * handle, `reportLayoutChange`, `playLayoutChange`, `holdLayoutExit` /
10
+ * `releaseLayoutExit`, the in-place swap (`holdLayoutSwap` /
11
+ * `playLayoutSwap`), `playLayoutFrames` and `applyLayoutChangeTransition`:
12
+ * the one module
13
+ * that produces the
14
+ * size-change glide `spec:AST-105` defines
15
+ * (`architecture:react-component-runtime` INV12)
16
+ * @position Motion foundation, internal to core. A handle comes from the
17
+ * public `useAnimatedLayout` hook; a component that takes it reports its
18
+ * size changes through this module.
19
+ *
20
+ * How it works:
21
+ * - `measureBefore()` runs before the change commits: from the changed
22
+ * element it walks up to the handle's container and, at each level,
23
+ * records the rectangles of the element siblings after it and before it (a
24
+ * centered, end-aligned or space-between row, or `order`, moves those too),
25
+ * through `parentElement`, `nextElementSibling` and
26
+ * `previousElementSibling`, descending only into an element with
27
+ * `display: contents` (it has no box). Each level's walk stops at the first
28
+ * sibling outside the band a change can move content into view from: the
29
+ * area's visible part plus one viewport, or the changed element's size if
30
+ * larger, above and below. So its cost grows with depth plus the siblings
31
+ * near the visible part, never with a list's length.
32
+ * - `animate()` runs after the commit (a layout effect). Every change in the
33
+ * same area reported in one frame is measured together after the commit,
34
+ * once, in a microtask, so each element moves once, by its total change.
35
+ * - An element moves only when its rectangle changed and it is in the area's
36
+ * visible part, before or after. Absolute, fixed, top-layer, hidden and
37
+ * zero-size elements are skipped (an absolute child rides with its moving
38
+ * parent); a stuck sticky element does not change rectangle, so it stays.
39
+ * - The move is a compositor-only `translate` (replace composition) from the
40
+ * old place to the new one, sampled from `springs.settle` into linear
41
+ * keyframes and corrected for a scaled ancestor. An element already gliding
42
+ * keeps that motion and adds the new move: the rest of its curve and the
43
+ * new move are summed into one new glide, velocity included. Nothing
44
+ * animates height, and nothing scrolls the area.
45
+ * - A measurement no commit claims by the next frame is dropped.
46
+ * - The changed element plays its own entrance on the same spring, started in
47
+ * the same frame (`playLayoutChange`), or its exit: kept where it is while
48
+ * it gives up its space and conceals (`holdLayoutExit`). A disclosure's
49
+ * indicator turns on the same motion (`applyLayoutChangeTransition`).
50
+ * - A swap holds old content as one transient copy, inert and hidden from
51
+ * assistive technology, while new content enters in its place, on the same
52
+ * motion, and removes it when the swap ends (`holdLayoutSwap`,
53
+ * `playLayoutSwap`; `spec:AST-105` FR8). The caller shapes the frames over
54
+ * the swap's progress and, riding a gliding element, how far it has moved,
55
+ * so every part keeps to that glide; under Reduce Motion with a coarse
56
+ * pointer only opacity changes.
57
+ * - Frames on elements the page renders can play on the same motion with no
58
+ * copy (`playLayoutFrames`), such as a surface reaching over a gap a glide
59
+ * opens, and are released when the motion ends.
60
+ * - Every pointer (`spec:AST-105` FR5). Under Reduce Motion nothing travels
61
+ * (`design:reduced-motion` DR1–DR3): a cross-fade under a coarse primary
62
+ * pointer, an immediate change otherwise.
63
+ * - Without a handle nothing happens: the component keeps its jump
64
+ * (`spec:AST-105` FR2).
65
+ */
66
+
67
+ import {motionRole} from './roles';
68
+ import {
69
+ inertCopy,
70
+ isCopyable,
71
+ paintedBackground,
72
+ placeOver,
73
+ visiblePartCopy,
74
+ wrapText,
75
+ } from './transientCopy';
76
+ import {isSpring} from './roleValue';
77
+ import {solveSpring, toSpring, type SpringDescription} from './spring';
78
+ import {registerSpringsTable, SETTLE_SPRING} from './uikit/springs';
79
+ import {reducedMotionCrossFade} from './uikit/timing';
80
+
81
+ /** The shared motion role (`spec:AST-105` FR4). */
82
+ const ROLE_ID = 'springs.settle';
83
+ /** Below this many pixels a shift is not worth a move. */
84
+ const MIN_SHIFT_PX = 0.5;
85
+ /** The touch cross-fade's cap (`design:reduced-motion` DR2). */
86
+ const CROSS_FADE_CAP_MS = 200;
87
+ /** Keyframes per second the spring is sampled at. */
88
+ const SAMPLES_PER_SECOND = 60;
89
+
90
+ // ---------------------------------------------------------------------------
91
+ // Motion
92
+ // ---------------------------------------------------------------------------
93
+
94
+ /** How a change plays under the reader's settings. */
95
+ type LayoutMotion =
96
+ | {readonly kind: 'spring'; readonly progress: SpringProgress}
97
+ | {
98
+ readonly kind: 'fade';
99
+ readonly durationMs: number;
100
+ readonly easing: string;
101
+ }
102
+ | {readonly kind: 'instant'};
103
+
104
+ /** The settle spring as remaining distance (1 → 0) over its duration. */
105
+ interface SpringProgress {
106
+ readonly durationMs: number;
107
+ /** Remaining fraction of the move at `t` ms. */
108
+ remaining(t: number): number;
109
+ }
110
+
111
+ function matches(element: Element, query: string): boolean {
112
+ const view = element.ownerDocument.defaultView;
113
+ return (
114
+ typeof view?.matchMedia === 'function' && view.matchMedia(query).matches
115
+ );
116
+ }
117
+
118
+ /**
119
+ * `springs.settle` from the internal role registry: one shared value for the
120
+ * glide, the changed element and the indicator. Motion roles are internal
121
+ * (`spec:AST-094` DEC-11): no theme, scope or custom property changes it.
122
+ */
123
+ function settleSpring(): SpringDescription {
124
+ registerSpringsTable();
125
+ const value = motionRole(ROLE_ID)?.value;
126
+ return isSpring(value) ? value : SETTLE_SPRING;
127
+ }
128
+
129
+ function springProgress(description: SpringDescription): SpringProgress {
130
+ const curve = solveSpring(toSpring(description), {from: 1, to: 0});
131
+ const durationMs = Math.max(1, curve.settleTime(0.001) * 1000);
132
+ return {
133
+ durationMs,
134
+ remaining: t => (t >= durationMs ? 0 : curve.value(t / 1000)),
135
+ };
136
+ }
137
+
138
+ /** The motion a change in `area` plays now. */
139
+ function layoutMotion(area: Element): LayoutMotion {
140
+ if (matches(area, '(prefers-reduced-motion: reduce)')) {
141
+ if (!matches(area, '(pointer: coarse)')) {
142
+ return {kind: 'instant'};
143
+ }
144
+ const [x1, y1, x2, y2] = reducedMotionCrossFade.curve;
145
+ return {
146
+ kind: 'fade',
147
+ durationMs: Math.min(
148
+ CROSS_FADE_CAP_MS,
149
+ reducedMotionCrossFade.durationMs,
150
+ ),
151
+ easing: `cubic-bezier(${x1}, ${y1}, ${x2}, ${y2})`,
152
+ };
153
+ }
154
+ return {kind: 'spring', progress: springProgress(settleSpring())};
155
+ }
156
+
157
+ /** Linear keyframes over `durationMs`, one per frame, from `frame(t ms)`. */
158
+ function sampleOver(
159
+ durationMs: number,
160
+ frame: (t: number) => Keyframe,
161
+ ): Keyframe[] {
162
+ const count = Math.max(
163
+ 2,
164
+ Math.ceil((durationMs / 1000) * SAMPLES_PER_SECOND) + 1,
165
+ );
166
+ const keyframes: Keyframe[] = [];
167
+ for (let i = 0; i < count; i++) {
168
+ const offset = i / (count - 1);
169
+ keyframes.push({...frame(offset * durationMs), offset});
170
+ }
171
+ return keyframes;
172
+ }
173
+
174
+ /** Linear keyframes sampled from the spring, one per frame. */
175
+ function sampleKeyframes(
176
+ progress: SpringProgress,
177
+ frame: (remaining: number) => Keyframe,
178
+ ): Keyframe[] {
179
+ return sampleOver(progress.durationMs, t => frame(progress.remaining(t)));
180
+ }
181
+
182
+ /** The spring as a CSS `linear()` easing, for a CSS transition. */
183
+ function linearEasing(progress: SpringProgress): string {
184
+ const stops: string[] = [];
185
+ const count = 24;
186
+ for (let i = 0; i <= count; i++) {
187
+ const fraction = i / count;
188
+ const value = 1 - progress.remaining(fraction * progress.durationMs);
189
+ stops.push(`${round(value)} ${round(fraction * 100)}%`);
190
+ }
191
+ return `linear(${stops.join(', ')})`;
192
+ }
193
+
194
+ function round(value: number): number {
195
+ return Math.round(value * 1000) / 1000;
196
+ }
197
+
198
+ // ---------------------------------------------------------------------------
199
+ // Playing
200
+ // ---------------------------------------------------------------------------
201
+
202
+ /**
203
+ * Play `keyframes` on `element`. Every option here (linear easing over sampled
204
+ * keyframes, replace composition) is one any Web Animations engine takes, so
205
+ * a failure means no Web Animations at all: the change then lands at once.
206
+ */
207
+ function safeAnimate(
208
+ element: Element,
209
+ keyframes: Keyframe[],
210
+ options: KeyframeAnimationOptions,
211
+ ): Animation | null {
212
+ if (typeof (element as HTMLElement).animate !== 'function') {
213
+ return null;
214
+ }
215
+ let animation: Animation;
216
+ try {
217
+ animation = (element as HTMLElement).animate(keyframes, options);
218
+ } catch {
219
+ return null;
220
+ }
221
+ ours.add(animation);
222
+ // Started on the document timeline's current time, not on the next frame:
223
+ // a retargeted glide keeps moving through the frame it is replaced in, and
224
+ // every animation of one change shares the same start.
225
+ const now = element.ownerDocument.timeline?.currentTime;
226
+ if (now != null) {
227
+ animation.startTime = now;
228
+ }
229
+ return animation;
230
+ }
231
+
232
+ /** Every animation this module started, so it can tell the app's apart. */
233
+ const ours = new WeakSet<Animation>();
234
+
235
+ const TRANSFORM_PROPERTIES = ['transform', 'translate', 'rotate', 'scale'];
236
+
237
+ /** The numbers in a CSS value, units dropped. */
238
+ function numbersIn(value: string): number[] {
239
+ return (value.match(/-?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?/gi) ?? []).map(
240
+ Number,
241
+ );
242
+ }
243
+
244
+ /**
245
+ * Whether a transform value leaves the element where it is: nothing at all
246
+ * (a swipe's `translate3d(0, 0, 0)` at rest, a button's `scale(1)`, computed
247
+ * as `matrix(1, 0, 0, 1, 0, 0)`), or a scale in place (a pressed button's
248
+ * `scale(0.98)`). A glide's `translate` composes with either; a translation,
249
+ * rotation or skew of its own is the app moving the element.
250
+ */
251
+ function staysInPlace(property: string, value: string): boolean {
252
+ if (value === 'none') {
253
+ // No transform at all (a keyframe a press's own transition starts from).
254
+ return true;
255
+ }
256
+ if (property === 'scale') {
257
+ return true;
258
+ }
259
+ if (value.includes('var(')) {
260
+ // An unresolved custom property in an app's own keyframes: its value is
261
+ // unknown here, so the app moves the element.
262
+ return false;
263
+ }
264
+ if (property === 'translate') {
265
+ return numbersIn(value).every(n => n === 0);
266
+ }
267
+ if (property === 'rotate') {
268
+ // An angle, after an optional axis: only the angle matters.
269
+ const numbers = numbersIn(value);
270
+ return numbers.length > 0 && numbers[numbers.length - 1] === 0;
271
+ }
272
+ // A list of transform functions, as computed (`matrix()`, `matrix3d()`)
273
+ // or as written.
274
+ const functions = [...value.matchAll(/([a-z0-9]+)\(([^)]*)\)/gi)];
275
+ return (
276
+ functions.length > 0 &&
277
+ functions.every(([, name, args]) => {
278
+ const numbers = numbersIn(args);
279
+ const fn = name.toLowerCase();
280
+ if (fn === 'matrix') {
281
+ // a b c d e f: no skew, rotation or translation.
282
+ return (
283
+ numbers.length === 6 &&
284
+ [1, 2, 4, 5].every(index => numbers[index] === 0)
285
+ );
286
+ }
287
+ if (fn === 'matrix3d') {
288
+ // Only the diagonal: a scale, nothing else.
289
+ return (
290
+ numbers.length === 16 &&
291
+ numbers.every((n, index) => index % 5 === 0 || n === 0)
292
+ );
293
+ }
294
+ if (fn === 'rotate3d') {
295
+ return numbers[3] === 0;
296
+ }
297
+ if (fn.startsWith('scale')) {
298
+ return true;
299
+ }
300
+ if (
301
+ fn.startsWith('translate') ||
302
+ fn.startsWith('rotate') ||
303
+ fn.startsWith('skew')
304
+ ) {
305
+ return numbers.every(n => n === 0);
306
+ }
307
+ return false;
308
+ })
309
+ );
310
+ }
311
+
312
+ /**
313
+ * Whether the app moves `element` itself: its own `transform`, `translate`
314
+ * or `rotate`, or a running animation of one this module did not start. A
315
+ * value that leaves it in place (nothing, or a scale) is not a move.
316
+ */
317
+ function movedByApp(element: Element): boolean {
318
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
319
+ if (
320
+ style != null &&
321
+ TRANSFORM_PROPERTIES.some(property => {
322
+ const value = style.getPropertyValue(property);
323
+ return value !== '' && value !== 'none' && !staysInPlace(property, value);
324
+ })
325
+ ) {
326
+ return true;
327
+ }
328
+ if (typeof element.getAnimations !== 'function') {
329
+ return false;
330
+ }
331
+ return element.getAnimations().some(animation => {
332
+ if (ours.has(animation)) {
333
+ return false;
334
+ }
335
+ const effect = animation.effect;
336
+ if (!(effect instanceof KeyframeEffect)) {
337
+ return false;
338
+ }
339
+ return effect
340
+ .getKeyframes()
341
+ .some(frame =>
342
+ TRANSFORM_PROPERTIES.some(
343
+ property =>
344
+ property in frame &&
345
+ !staysInPlace(property, String(frame[property])),
346
+ ),
347
+ );
348
+ });
349
+ }
350
+
351
+ /** An offset in the element's own px, as a function of ms into a glide. */
352
+ type OffsetCurve = (t: number) => {readonly x: number; readonly y: number};
353
+
354
+ const AT_REST: OffsetCurve = () => ({x: 0, y: 0});
355
+
356
+ /** A glide an element is playing, so a new change can retarget it. */
357
+ interface Glide {
358
+ readonly animation: Animation;
359
+ readonly offsetAt: OffsetCurve;
360
+ readonly durationMs: number;
361
+ }
362
+
363
+ const glides = new WeakMap<Element, Glide>();
364
+
365
+ /**
366
+ * The glide `element` is playing now, if any. For an adopter that draws
367
+ * something with each moving element (a table row's divider): it finds what
368
+ * moves without reading the DOM.
369
+ */
370
+ export function glideOf(element: Element): Animation | null {
371
+ return glides.get(element)?.animation ?? null;
372
+ }
373
+
374
+ // ---------------------------------------------------------------------------
375
+ // Handles
376
+ // ---------------------------------------------------------------------------
377
+
378
+ const AREA = Symbol('astryx.animatedLayout.area');
379
+
380
+ /**
381
+ * The opaque handle `useAnimatedLayout` returns (`spec:AST-105` FR1): no
382
+ * public members. A component that receives it reports its size changes to
383
+ * the handle's container, the area the glide stays inside.
384
+ */
385
+ export interface AnimatedLayout {
386
+ readonly [AREA]: () => Element | null;
387
+ }
388
+
389
+ /** A handle over `area` (the container element, read when a change runs). */
390
+ export function createAnimatedLayout(
391
+ area: () => Element | null,
392
+ ): AnimatedLayout {
393
+ // Not enumerable and frozen: the handle shows no fields to a caller.
394
+ return Object.freeze(
395
+ Object.defineProperty({}, AREA, {value: area}),
396
+ ) as AnimatedLayout;
397
+ }
398
+
399
+ function areaOf(handle: AnimatedLayout, element: Element): Element | null {
400
+ const area = handle[AREA]();
401
+ return area != null && area !== element && area.contains(element)
402
+ ? area
403
+ : null;
404
+ }
405
+
406
+ // ---------------------------------------------------------------------------
407
+ // The walk
408
+ // ---------------------------------------------------------------------------
409
+
410
+ /**
411
+ * Whether `element` takes part: in flow, rendered, not in the top layer.
412
+ * `display: contents` is handled by the caller.
413
+ */
414
+ function takesPart(element: Element, style: CSSStyleDeclaration): boolean {
415
+ if (
416
+ style.display === 'none' ||
417
+ style.visibility === 'hidden' ||
418
+ style.position === 'absolute' ||
419
+ style.position === 'fixed'
420
+ ) {
421
+ return false;
422
+ }
423
+ try {
424
+ if (element.matches(':popover-open, :modal')) {
425
+ return false;
426
+ }
427
+ } catch {
428
+ // An engine without these pseudo-classes has no top layer to skip.
429
+ }
430
+ return true;
431
+ }
432
+
433
+ /**
434
+ * The band of the page a change can move content into or out of view: the
435
+ * area's visible part, extended above and below by one viewport or by the
436
+ * size of every element changing in the frame, whichever is larger (a
437
+ * collapse pulls content up by at most its size, and changes in one frame
438
+ * add up). Content outside it before the change stays outside it, so the
439
+ * walk stops there.
440
+ */
441
+ interface Band {
442
+ /** Its top edge, in client px. */
443
+ readonly start: number;
444
+ /** Its bottom edge, in client px. */
445
+ readonly end: number;
446
+ }
447
+
448
+ function bandFor(visible: DOMRect, reach: number): Band {
449
+ return {start: visible.top - reach, end: visible.bottom + reach};
450
+ }
451
+
452
+ /**
453
+ * What one frame's walks read, kept so a level two changes share, or a walk
454
+ * repeated when the band grows, reads each element once.
455
+ */
456
+ interface WalkCache {
457
+ readonly rects: Map<Element, DOMRect>;
458
+ /** Whether the element takes part, or `contents` for a boxless element. */
459
+ readonly parts: Map<Element, boolean | 'contents'>;
460
+ }
461
+
462
+ function partOf(element: Element, cache: WalkCache): boolean | 'contents' {
463
+ let part = cache.parts.get(element);
464
+ if (part === undefined) {
465
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
466
+ part =
467
+ style == null
468
+ ? false
469
+ : style.display === 'contents'
470
+ ? 'contents'
471
+ : takesPart(element, style);
472
+ cache.parts.set(element, part);
473
+ }
474
+ return part;
475
+ }
476
+
477
+ /**
478
+ * Whether a container lays its children out across the block direction, so
479
+ * DOM order does not run down the page: multi-column, a wrapping column flex
480
+ * box, or a grid that flows by column. The band says nothing about where its
481
+ * later children sit, so a walk there runs through the level.
482
+ */
483
+ function flowsAcross(container: Element | null): boolean {
484
+ if (container == null) {
485
+ return false;
486
+ }
487
+ const style =
488
+ container.ownerDocument.defaultView?.getComputedStyle(container);
489
+ if (style == null) {
490
+ return false;
491
+ }
492
+ const count = style.getPropertyValue('column-count');
493
+ const width = style.getPropertyValue('column-width');
494
+ return (
495
+ (count !== '' && count !== 'auto') ||
496
+ (width !== '' && width !== 'auto') ||
497
+ (style.display.includes('flex') &&
498
+ style.flexDirection.startsWith('column') &&
499
+ style.flexWrap.startsWith('wrap')) ||
500
+ (style.display.includes('grid') &&
501
+ style.getPropertyValue('grid-auto-flow').startsWith('column'))
502
+ );
503
+ }
504
+
505
+ /**
506
+ * The box a sticky element sticks to: its nearest scrolling ancestor's, or
507
+ * the viewport.
508
+ */
509
+ function scrollportOf(element: Element): {start: number; end: number} {
510
+ const view = element.ownerDocument.defaultView;
511
+ for (
512
+ let node = element.parentElement;
513
+ node != null && node !== element.ownerDocument.documentElement;
514
+ node = node.parentElement
515
+ ) {
516
+ const overflow = view?.getComputedStyle(node).overflowY ?? 'visible';
517
+ if (
518
+ node === element.ownerDocument.body &&
519
+ view?.getComputedStyle(element.ownerDocument.documentElement)
520
+ .overflowY === 'visible'
521
+ ) {
522
+ // The body's overflow applies to the viewport while the root's is
523
+ // visible: the body is no scroller of its own.
524
+ continue;
525
+ }
526
+ if (overflow !== 'visible' && overflow !== 'clip') {
527
+ const box = node.getBoundingClientRect();
528
+ return {
529
+ start: box.top + node.clientTop,
530
+ end: box.top + node.clientTop + node.clientHeight,
531
+ };
532
+ }
533
+ }
534
+ return {start: 0, end: view?.innerHeight ?? 0};
535
+ }
536
+
537
+ /**
538
+ * Whether a sticky element is stuck: resting against its scrollport's edge
539
+ * at its inset. A stuck element takes its final place; an unstuck one is in
540
+ * flow.
541
+ */
542
+ function isStuck(element: Element, cache: WalkCache): boolean {
543
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
544
+ if (style?.position !== 'sticky') {
545
+ return false;
546
+ }
547
+ const rect = rectOf(element, cache);
548
+ const edge = scrollportOf(element);
549
+ const top = Number.parseFloat(style.top);
550
+ const bottom = Number.parseFloat(style.bottom);
551
+ return (
552
+ (Number.isFinite(top) && Math.abs(rect.top - (edge.start + top)) < 1) ||
553
+ (Number.isFinite(bottom) && Math.abs(rect.bottom - (edge.end - bottom)) < 1)
554
+ );
555
+ }
556
+
557
+ function rectOf(element: Element, cache: WalkCache): DOMRect {
558
+ let rect = cache.rects.get(element);
559
+ if (rect === undefined) {
560
+ rect = element.getBoundingClientRect();
561
+ cache.rects.set(element, rect);
562
+ }
563
+ return rect;
564
+ }
565
+
566
+ /**
567
+ * The elements a change can move, each with its rectangle before the change:
568
+ * the changed element's ancestors up to the area (a centered column moves
569
+ * the card around the change), and at each of their levels the siblings
570
+ * after and before (a centered, end-aligned or space-between row, or
571
+ * `order`, moves those too). A `display: contents` element has no box: its
572
+ * children stand in its place, walked in the same direction. At each level
573
+ * the walk stops at the first sibling outside `band`, so its cost grows with
574
+ * depth plus the siblings near the visible part, never with the length of a
575
+ * list; where the area opts out of scroll anchoring (`walksToBand`), the walk
576
+ * after a change above the band goes on to the band, a cost that grows with
577
+ * that distance. Inside a positioned, stuck sticky or top-layer ancestor only the
578
+ * content after the change is taken.
579
+ */
580
+ function collectCandidates(
581
+ changed: Element,
582
+ area: Element,
583
+ band: Band,
584
+ cache: WalkCache,
585
+ walksToBand: boolean,
586
+ ancestors: Set<Element>,
587
+ befores: Set<Element>,
588
+ ): Map<Element, DOMRect> {
589
+ const out = new Map<Element, DOMRect>();
590
+ /** Takes `element`; returns false once it lies outside the band. */
591
+ /** The current level runs through its siblings, ignoring the band. */
592
+ let runsThrough = false;
593
+ const take = (element: Element, isAfter: boolean): boolean => {
594
+ const part = partOf(element, cache);
595
+ if (part === 'contents') {
596
+ for (
597
+ let child = isAfter
598
+ ? element.firstElementChild
599
+ : element.lastElementChild;
600
+ child != null;
601
+ child = isAfter
602
+ ? child.nextElementSibling
603
+ : child.previousElementSibling
604
+ ) {
605
+ if (!take(child, isAfter)) {
606
+ return false;
607
+ }
608
+ }
609
+ return true;
610
+ }
611
+ if (!part) {
612
+ return true;
613
+ }
614
+ const rect = rectOf(element, cache);
615
+ if (runsThrough) {
616
+ out.set(element, rect);
617
+ return true;
618
+ }
619
+ if (rect.top > band.end) {
620
+ return false;
621
+ }
622
+ if (rect.bottom < band.start) {
623
+ // Above the band. Where the scroller opts out of scroll anchoring, the
624
+ // content after a change above the band shifts the rows in view, so
625
+ // the walk after it goes on to the band; with anchoring, it stops.
626
+ return isAfter && walksToBand;
627
+ }
628
+ out.set(element, rect);
629
+ if (!isAfter) {
630
+ befores.add(element);
631
+ }
632
+ return true;
633
+ };
634
+ // The change's chain up to the area, and from where it is inside a
635
+ // positioned, stuck sticky or top-layer ancestor: that ancestor takes its final
636
+ // place, so inside it only the content after the change moves; the
637
+ // ancestors and the siblings before the change stay with it.
638
+ const chain: Element[] = [];
639
+ for (
640
+ let node: Element | null = changed;
641
+ node != null && node !== area;
642
+ node = node.parentElement
643
+ ) {
644
+ chain.push(node);
645
+ }
646
+ // The levels below this index are inside a positioned ancestor.
647
+ let positionedFrom = 0;
648
+ for (let index = chain.length - 1; index > 0; index -= 1) {
649
+ if (partOf(chain[index], cache) === false || isStuck(chain[index], cache)) {
650
+ positionedFrom = index;
651
+ break;
652
+ }
653
+ }
654
+ for (const [level, node] of chain.entries()) {
655
+ runsThrough = flowsAcross(node.parentElement);
656
+ if (
657
+ node !== changed &&
658
+ level > positionedFrom &&
659
+ partOf(node, cache) === true
660
+ ) {
661
+ // An ancestor of the change in flow: where its layout moves it (a
662
+ // centered column), it glides, and what is inside moves only by its own
663
+ // change. A positioned, stuck sticky or top-layer ancestor, and every
664
+ // ancestor inside it, takes its final place.
665
+ out.set(node, rectOf(node, cache));
666
+ ancestors.add(node);
667
+ }
668
+ for (
669
+ let sibling = node.nextElementSibling;
670
+ sibling != null && take(sibling, true);
671
+ sibling = sibling.nextElementSibling
672
+ ) {
673
+ // The siblings after it, until one lies past the band.
674
+ }
675
+ if (level < positionedFrom) {
676
+ continue;
677
+ }
678
+ for (
679
+ let sibling = node.previousElementSibling;
680
+ sibling != null && take(sibling, false);
681
+ sibling = sibling.previousElementSibling
682
+ ) {
683
+ // The siblings before it, until one lies before the band.
684
+ }
685
+ }
686
+ return out;
687
+ }
688
+
689
+ // ---------------------------------------------------------------------------
690
+ // Batches: every change in one area in one frame moves together
691
+ // ---------------------------------------------------------------------------
692
+
693
+ interface Batch {
694
+ readonly area: Element;
695
+ readonly changed: Set<Element>;
696
+ readonly before: Map<Element, DOMRect>;
697
+ /** What each changed element's walk found, so a dropped change moves none. */
698
+ readonly candidates: Map<Element, Element[]>;
699
+ /** The changed elements' sizes before the change, added up. */
700
+ changedSize: number;
701
+ /** How far past the visible part the walks reach (0 before the first). */
702
+ reach: number;
703
+ /** The area's visible part, read once per frame. */
704
+ visible: DOMRect | null;
705
+ /** Whether the area opts out of scroll anchoring, read once per frame. */
706
+ walksToBand: boolean | null;
707
+ /** The change's ancestors among the candidates. */
708
+ readonly ancestors: Set<Element>;
709
+ /** The siblings before the change among the candidates. */
710
+ readonly befores: Set<Element>;
711
+ /**
712
+ * Where the area's content sat before the change, read once per frame: the
713
+ * area's place in view less its scroll offset, so a scroll of the area, an
714
+ * outer scroller or the page shows up as a change of it.
715
+ */
716
+ originBefore: {readonly x: number; readonly y: number} | null;
717
+ readonly cache: WalkCache;
718
+ scheduled: boolean;
719
+ /** Called after every reading and before any glide starts. */
720
+ readonly beforeMove: ((candidates: ReadonlyArray<Element>) => void)[];
721
+ }
722
+
723
+ const batches = new Map<Element, Batch>();
724
+
725
+ function batchFor(area: Element): Batch {
726
+ let batch = batches.get(area);
727
+ if (batch == null) {
728
+ const created: Batch = {
729
+ area,
730
+ changed: new Set(),
731
+ before: new Map(),
732
+ candidates: new Map(),
733
+ changedSize: 0,
734
+ reach: 0,
735
+ visible: null,
736
+ walksToBand: null,
737
+ ancestors: new Set(),
738
+ befores: new Set(),
739
+ originBefore: null,
740
+ cache: {rects: new Map(), parts: new Map()},
741
+ scheduled: false,
742
+ beforeMove: [],
743
+ };
744
+ batches.set(area, created);
745
+ // A measurement no commit claims by the next frame (a controlled owner
746
+ // refused the change) is dropped, so it never moves rows later and holds
747
+ // no elements.
748
+ const view = area.ownerDocument.defaultView;
749
+ const drop = () => {
750
+ if (batches.get(area) === created && !created.scheduled) {
751
+ batches.delete(area);
752
+ }
753
+ };
754
+ if (typeof view?.requestAnimationFrame === 'function') {
755
+ view.requestAnimationFrame(drop);
756
+ } else {
757
+ setTimeout(drop, 16);
758
+ }
759
+ batch = created;
760
+ }
761
+ return batch;
762
+ }
763
+
764
+ function intersects(a: DOMRect, b: DOMRect): boolean {
765
+ return (
766
+ a.width > 0 &&
767
+ a.height > 0 &&
768
+ a.right > b.left &&
769
+ a.left < b.right &&
770
+ a.bottom > b.top &&
771
+ a.top < b.bottom
772
+ );
773
+ }
774
+
775
+ /** The part of the area the person can see: its box within the viewport. */
776
+ /** Where the area's scrolled content starts, in client px. */
777
+ function originOf(area: Element): {x: number; y: number} {
778
+ const box = area.getBoundingClientRect();
779
+ return {x: box.left - area.scrollLeft, y: box.top - area.scrollTop};
780
+ }
781
+
782
+ function visibleRect(area: Element): DOMRect {
783
+ const box = area.getBoundingClientRect();
784
+ const view = area.ownerDocument.defaultView;
785
+ const width = view?.innerWidth ?? box.right;
786
+ const height = view?.innerHeight ?? box.bottom;
787
+ const left = Math.max(box.left, 0);
788
+ const top = Math.max(box.top, 0);
789
+ return new DOMRect(
790
+ left,
791
+ top,
792
+ Math.max(0, Math.min(box.right, width) - left),
793
+ Math.max(0, Math.min(box.bottom, height) - top),
794
+ );
795
+ }
796
+
797
+ /** The element's rendered scale against its layout size (a scaled ancestor). */
798
+ function scaleOf(
799
+ element: Element,
800
+ rect: DOMRect,
801
+ own: {readonly x: number; readonly y: number} = {x: 1, y: 1},
802
+ ): {x: number; y: number} {
803
+ const html = element as HTMLElement;
804
+ const x =
805
+ html.offsetWidth > 0 && rect.width > 0
806
+ ? rect.width / html.offsetWidth / own.x
807
+ : 1;
808
+ const y =
809
+ html.offsetHeight > 0 && rect.height > 0
810
+ ? rect.height / html.offsetHeight / own.y
811
+ : 1;
812
+ // Subpixel rounding makes an unscaled element read a hair off 1; only a
813
+ // real scale is corrected.
814
+ return {
815
+ x: Math.abs(x - 1) < 0.01 ? 1 : x || 1,
816
+ y: Math.abs(y - 1) < 0.01 ? 1 : y || 1,
817
+ };
818
+ }
819
+
820
+ /**
821
+ * The scale an element's own `scale` and `transform` give it, on each axis
822
+ * (a follower that keeps one in place, `staysInPlace`). A glide's `translate`
823
+ * does not go through them: the individual transform properties apply
824
+ * `translate` first, in the parent's space.
825
+ */
826
+ function ownScaleOf(element: Element): {x: number; y: number} {
827
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
828
+ if (style == null) {
829
+ return {x: 1, y: 1};
830
+ }
831
+ let x = 1;
832
+ let y = 1;
833
+ const scale = style.getPropertyValue('scale');
834
+ if (scale !== '' && scale !== 'none') {
835
+ const [sx = 1, sy = sx] = numbersIn(scale);
836
+ // Its size, not its direction: a negative scale flips the element in
837
+ // place, and its measured box stays positive.
838
+ x *= Math.abs(sx);
839
+ y *= Math.abs(sy);
840
+ }
841
+ // The computed transform is a matrix: its first column's length is the
842
+ // scale on x, its second's on y.
843
+ const matrix = /^matrix(3d)?\(([^)]*)\)/.exec(
844
+ style.getPropertyValue('transform'),
845
+ );
846
+ if (matrix != null) {
847
+ const m = numbersIn(matrix[2]);
848
+ const [a = 1, b = 0, c = 0, d = 1] =
849
+ matrix[1] == null ? m : [m[0], m[1], m[4], m[5]];
850
+ x *= Math.hypot(a, b);
851
+ y *= Math.hypot(c, d);
852
+ }
853
+ return {x: x || 1, y: y || 1};
854
+ }
855
+
856
+ function flush(batch: Batch): void {
857
+ batches.delete(batch.area);
858
+ const notify = (candidates: ReadonlyArray<Element>) => {
859
+ for (const callback of batch.beforeMove) {
860
+ callback(candidates);
861
+ }
862
+ };
863
+ // What each change's walk measured before it: an element added by the
864
+ // change has no old place, and one it removed is gone.
865
+ const followers = new Set<Element>();
866
+ for (const changed of batch.changed) {
867
+ for (const element of batch.candidates.get(changed) ?? []) {
868
+ if (element.isConnected) {
869
+ followers.add(element);
870
+ }
871
+ }
872
+ }
873
+ if (followers.size === 0) {
874
+ notify([]);
875
+ return;
876
+ }
877
+ const motion = layoutMotion(batch.area);
878
+ if (motion.kind === 'instant') {
879
+ notify([]);
880
+ return;
881
+ }
882
+ const visible = visibleRect(batch.area);
883
+ // Every running glide stops first and every new place is read before any
884
+ // glide starts, so no reading includes another's new motion.
885
+ const entries: {
886
+ readonly element: Element;
887
+ readonly before: DOMRect;
888
+ readonly carried: OffsetCurve;
889
+ readonly carriedMs: number;
890
+ after?: DOMRect;
891
+ rawX?: number;
892
+ rawY?: number;
893
+ isMovedByApp?: boolean;
894
+ scale?: {x: number; y: number};
895
+ }[] = [];
896
+ for (const element of followers) {
897
+ const before = batch.before.get(element);
898
+ if (before == null || (before.width === 0 && before.height === 0)) {
899
+ // Added by the change, or not rendered before it: it has no old place.
900
+ // A changed element an earlier change displaced does have one, and
901
+ // moves with its row while it plays its own entrance or exit.
902
+ continue;
903
+ }
904
+ // An element already gliding keeps that motion and adds the new move: the
905
+ // running glide stops (so its rectangle is its new layout place) and the
906
+ // rest of its curve carries into the one new glide, velocity included,
907
+ // summed with the new move.
908
+ const running = glides.get(element);
909
+ let carried = AT_REST;
910
+ let carriedMs = 0;
911
+ if (running != null) {
912
+ const time = Number(running.animation.currentTime);
913
+ const elapsed = Number.isFinite(time) ? Math.max(0, time) : 0;
914
+ if (elapsed < running.durationMs) {
915
+ carried = t => running.offsetAt(elapsed + t);
916
+ carriedMs = running.durationMs - elapsed;
917
+ }
918
+ running.animation.cancel();
919
+ glides.delete(element);
920
+ }
921
+ entries.push({element, before, carried, carriedMs});
922
+ }
923
+ // Every reading (places, transforms, scales) before any glide starts: a
924
+ // glide started between two readings would make the next one lay the page
925
+ // out again, once per element (on a long page, the whole cost).
926
+ const byElement = new Map<Element, (typeof entries)[number]>();
927
+ // An ancestor of the change, and a sibling before it, move by their layout
928
+ // change alone: when scroll anchoring re-scrolls the area, an outer
929
+ // scroller or the page (a change above the visible part), or the area
930
+ // itself moves as its content grows (a dialog re-centered), their place in
931
+ // view shifts by that while their place in the area stays.
932
+ const origin = originOf(batch.area);
933
+ const scrolledX = origin.x - (batch.originBefore?.x ?? origin.x);
934
+ const scrolledY = origin.y - (batch.originBefore?.y ?? origin.y);
935
+ // Netted only where that makes the move smaller: an element the browser
936
+ // kept in place (scroll anchoring for another change in the same frame)
937
+ // stays where it is.
938
+ const nearer = (raw: number, shift: number) =>
939
+ Math.abs(raw + shift) < Math.abs(raw) ? raw + shift : raw;
940
+ for (const entry of entries) {
941
+ entry.after = entry.element.getBoundingClientRect();
942
+ // The move is the inline-start edge's, by the container's direction (it
943
+ // decides where the element sits): in a right-to-left container an
944
+ // element that narrows keeps its left edge and moves its right one.
945
+ const container = entry.element.parentElement ?? entry.element;
946
+ const isRtl =
947
+ container.ownerDocument.defaultView?.getComputedStyle(container)
948
+ .direction === 'rtl';
949
+ const rawX = isRtl
950
+ ? entry.before.right - entry.after.right
951
+ : entry.before.left - entry.after.left;
952
+ const rawY = entry.before.top - entry.after.top;
953
+ // The siblings before the change stay with the ancestors around them.
954
+ const isAncestor =
955
+ batch.ancestors.has(entry.element) || batch.befores.has(entry.element);
956
+ entry.rawX = isAncestor ? nearer(rawX, scrolledX) : rawX;
957
+ entry.rawY = isAncestor ? nearer(rawY, scrolledY) : rawY;
958
+ byElement.set(entry.element, entry);
959
+ }
960
+ for (const entry of entries) {
961
+ const after = entry.after as DOMRect;
962
+ if (intersects(entry.before, visible) || intersects(after, visible)) {
963
+ entry.isMovedByApp = movedByApp(entry.element);
964
+ // Only its ancestors' scale is corrected: its own scale or transform
965
+ // (a press's scale) does not apply to the glide's `translate`.
966
+ entry.scale = scaleOf(entry.element, after, ownScaleOf(entry.element));
967
+ }
968
+ }
969
+ // An adopter's own readings join them here, before any glide starts.
970
+ notify(entries.map(entry => entry.element));
971
+ for (const entry of entries) {
972
+ const {element, before, carried, carriedMs} = entry;
973
+ const after = entry.after as DOMRect;
974
+ // Nested changes compose: an element inside another moving element moves
975
+ // only by its own change, whatever order the changes were reported in.
976
+ let dx = entry.rawX ?? 0;
977
+ let dy = entry.rawY ?? 0;
978
+ for (
979
+ let ancestor = element.parentElement;
980
+ ancestor != null && ancestor !== batch.area;
981
+ ancestor = ancestor.parentElement
982
+ ) {
983
+ const moving = byElement.get(ancestor);
984
+ if (moving != null) {
985
+ dx -= moving.rawX ?? 0;
986
+ dy -= moving.rawY ?? 0;
987
+ break;
988
+ }
989
+ }
990
+ if (Math.abs(dx) < MIN_SHIFT_PX && Math.abs(dy) < MIN_SHIFT_PX) {
991
+ continue;
992
+ }
993
+ if (!intersects(before, visible) && !intersects(after, visible)) {
994
+ // Outside the visible part before and after: it lands silently.
995
+ continue;
996
+ }
997
+ if (motion.kind === 'fade') {
998
+ safeAnimate(element, [{opacity: 0}, {opacity: 1}], {
999
+ duration: motion.durationMs,
1000
+ easing: motion.easing,
1001
+ });
1002
+ continue;
1003
+ }
1004
+ if (entry.isMovedByApp === true) {
1005
+ // The app moves it itself: it takes its final place at once
1006
+ // (`spec:AST-105` Coverage).
1007
+ continue;
1008
+ }
1009
+ // Where it shows now, against its new place, in its own px; the part the
1010
+ // carried glide does not cover is the new move.
1011
+ const scale = entry.scale ?? {x: 1, y: 1};
1012
+ const now = carried(0);
1013
+ const moveX = dx / scale.x - now.x;
1014
+ const moveY = dy / scale.y - now.y;
1015
+ const {progress} = motion;
1016
+ const offsetAt: OffsetCurve = t => {
1017
+ const remaining = progress.remaining(t);
1018
+ const carry = carried(t);
1019
+ return {x: carry.x + moveX * remaining, y: carry.y + moveY * remaining};
1020
+ };
1021
+ const durationMs = Math.max(progress.durationMs, carriedMs);
1022
+ // One replace-composited `translate`: the compositor runs it (INV12).
1023
+ const animation = safeAnimate(
1024
+ element,
1025
+ sampleOver(durationMs, t => {
1026
+ const offset = offsetAt(t);
1027
+ return {translate: `${offset.x}px ${offset.y}px`};
1028
+ }),
1029
+ {duration: durationMs, easing: 'linear'},
1030
+ );
1031
+ if (animation != null) {
1032
+ const glide: Glide = {animation, offsetAt, durationMs};
1033
+ glides.set(element, glide);
1034
+ animation.addEventListener?.('finish', () => {
1035
+ if (glides.get(element) === glide) {
1036
+ glides.delete(element);
1037
+ }
1038
+ });
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ type Target = {readonly current: Element | null} | (() => Element | null);
1044
+
1045
+ function resolve(target: Target): Element | null {
1046
+ return typeof target === 'function' ? target() : target.current;
1047
+ }
1048
+
1049
+ export interface LayoutChange {
1050
+ /** Before the change commits (in the event handler that causes it). */
1051
+ measureBefore(): void;
1052
+ /**
1053
+ * After it commits (a layout effect). Returns whether the change was
1054
+ * measured: an unmeasured change (an owner set the state directly) moves
1055
+ * nothing, and the component plays no entrance for it either.
1056
+ *
1057
+ * `beforeMove`, when given, runs once the new places are read and before
1058
+ * any glide starts, with the elements the glide may move: whatever the
1059
+ * component reads from the layout for the glide, it reads there, so the page
1060
+ * is not laid out again (`playLayoutChange` included).
1061
+ */
1062
+ animate(beforeMove?: (candidates: ReadonlyArray<Element>) => void): boolean;
1063
+ }
1064
+
1065
+ /**
1066
+ * Report a size change of `target` to the handle's area. Call
1067
+ * `measureBefore()` before the change commits and `animate()` after it; the
1068
+ * content after `target`, up to the area, glides from its old place.
1069
+ * Changes in one area in one frame move together. Without a handle, or
1070
+ * outside its container, nothing moves.
1071
+ */
1072
+ export function reportLayoutChange(
1073
+ handle: AnimatedLayout | null | undefined,
1074
+ target: Target,
1075
+ ): LayoutChange {
1076
+ return {
1077
+ measureBefore() {
1078
+ const element = resolve(target);
1079
+ if (element == null || handle == null) {
1080
+ return;
1081
+ }
1082
+ const area = areaOf(handle, element);
1083
+ if (area == null) {
1084
+ return;
1085
+ }
1086
+ const batch = batchFor(area);
1087
+ if (batch.changed.has(element)) {
1088
+ return;
1089
+ }
1090
+ batch.changed.add(element);
1091
+ batch.changedSize += rectOf(element, batch.cache).height;
1092
+ batch.visible ??= visibleRect(area);
1093
+ batch.originBefore ??= originOf(area);
1094
+ batch.walksToBand ??=
1095
+ area.ownerDocument.defaultView
1096
+ ?.getComputedStyle(area)
1097
+ .getPropertyValue('overflow-anchor') === 'none';
1098
+ // Changes in one frame add up: every change's walk reaches the band
1099
+ // their summed size can pull into view. When that outgrows the band
1100
+ // walked so far, the band at least doubles and every change is walked
1101
+ // again (from the cache), so a frame of many changes re-walks a few
1102
+ // times, not once per change.
1103
+ const needed = Math.max(batch.visible.height, batch.changedSize);
1104
+ const walks = needed > batch.reach ? [...batch.changed] : [element];
1105
+ if (needed > batch.reach) {
1106
+ batch.reach = Math.max(needed, batch.reach * 2);
1107
+ }
1108
+ const band = bandFor(batch.visible, batch.reach);
1109
+ for (const changed of walks) {
1110
+ const candidates = collectCandidates(
1111
+ changed,
1112
+ area,
1113
+ band,
1114
+ batch.cache,
1115
+ batch.walksToBand,
1116
+ batch.ancestors,
1117
+ batch.befores,
1118
+ );
1119
+ for (const [candidate, rect] of candidates) {
1120
+ if (!batch.before.has(candidate)) {
1121
+ batch.before.set(candidate, rect);
1122
+ }
1123
+ }
1124
+ batch.candidates.set(changed, [...candidates.keys()]);
1125
+ }
1126
+ },
1127
+ animate(beforeMove) {
1128
+ const element = resolve(target);
1129
+ if (element == null || handle == null) {
1130
+ return false;
1131
+ }
1132
+ const area = areaOf(handle, element);
1133
+ const batch = area == null ? undefined : batches.get(area);
1134
+ if (batch == null || !batch.changed.has(element)) {
1135
+ return false;
1136
+ }
1137
+ if (beforeMove != null) {
1138
+ batch.beforeMove.push(beforeMove);
1139
+ }
1140
+ if (!batch.scheduled) {
1141
+ batch.scheduled = true;
1142
+ // After every layout effect of this commit, before paint.
1143
+ queueMicrotask(() => flush(batch));
1144
+ }
1145
+ return true;
1146
+ },
1147
+ };
1148
+ }
1149
+
1150
+ /**
1151
+ * The changed element's own animation, on the same motion as the content
1152
+ * after it: content that appears reveals downward from its top edge. Plays
1153
+ * only with a handle, inside its area and in the area's visible part.
1154
+ * Returns the entrance it started, or null when it played none.
1155
+ */
1156
+ export function playLayoutChange(
1157
+ handle: AnimatedLayout | null | undefined,
1158
+ element: Element,
1159
+ ): Animation | null {
1160
+ if (handle == null) {
1161
+ return null;
1162
+ }
1163
+ const area = areaOf(handle, element);
1164
+ if (area == null) {
1165
+ return null;
1166
+ }
1167
+ if (!intersects(element.getBoundingClientRect(), visibleRect(area))) {
1168
+ return null;
1169
+ }
1170
+ const motion = layoutMotion(area);
1171
+ if (motion.kind === 'instant') {
1172
+ return null;
1173
+ }
1174
+ if (motion.kind === 'fade') {
1175
+ return safeAnimate(element, [{opacity: 0}, {opacity: 1}], {
1176
+ duration: motion.durationMs,
1177
+ easing: motion.easing,
1178
+ });
1179
+ }
1180
+ return safeAnimate(
1181
+ element,
1182
+ sampleKeyframes(motion.progress, remaining => ({
1183
+ opacity: 1 - remaining,
1184
+ clipPath: `inset(0 0 ${round(remaining * 100)}% 0)`,
1185
+ })),
1186
+ {duration: motion.progress.durationMs, easing: 'linear'},
1187
+ );
1188
+ }
1189
+
1190
+ /** The inline properties an exit sets, so a release removes exactly them. */
1191
+ const EXIT_PROPERTIES = [
1192
+ 'margin-block-end',
1193
+ 'margin-inline-end',
1194
+ 'pointer-events',
1195
+ ] as const;
1196
+
1197
+ /**
1198
+ * The first element after `element` in the area that takes part in layout:
1199
+ * its next sibling, or its nearest ancestor's below the area. A wrapper's
1200
+ * edge is not used: a negative end margin can collapse through it.
1201
+ */
1202
+ function nextInFlow(element: Element, area: Element): Element | null {
1203
+ const view = element.ownerDocument.defaultView;
1204
+ // The first box at or inside `from` (a `display: contents` element has
1205
+ // none of its own: its children stand in its place).
1206
+ const firstBox = (from: Element): Element | null => {
1207
+ const style = view?.getComputedStyle(from);
1208
+ if (style == null) {
1209
+ return from;
1210
+ }
1211
+ if (style.display === 'contents') {
1212
+ for (
1213
+ let child = from.firstElementChild;
1214
+ child != null;
1215
+ child = child.nextElementSibling
1216
+ ) {
1217
+ const box = firstBox(child);
1218
+ if (box != null) {
1219
+ return box;
1220
+ }
1221
+ }
1222
+ return null;
1223
+ }
1224
+ return takesPart(from, style) ? from : null;
1225
+ };
1226
+ let node: Element | null = element;
1227
+ while (node != null && node !== area) {
1228
+ for (
1229
+ let sibling = node.nextElementSibling;
1230
+ sibling != null;
1231
+ sibling = sibling.nextElementSibling
1232
+ ) {
1233
+ const box = firstBox(sibling);
1234
+ if (box != null) {
1235
+ return box;
1236
+ }
1237
+ }
1238
+ node = node.parentElement;
1239
+ }
1240
+ return null;
1241
+ }
1242
+
1243
+ /**
1244
+ * An element's place: its block start, and its inline start (RTL read right
1245
+ * to left).
1246
+ */
1247
+ function placeOf(
1248
+ element: Element,
1249
+ rtl: boolean,
1250
+ ): {block: number; inline: number} {
1251
+ const rect = element.getBoundingClientRect();
1252
+ return {block: rect.top, inline: rtl ? -rect.right : rect.left};
1253
+ }
1254
+
1255
+ /**
1256
+ * Keeps `element` where it is, in flow (so it scrolls and clips with its
1257
+ * container), while the content after it takes the place it takes once the
1258
+ * element is hidden: a negative end margin measured against that content,
1259
+ * so a gap or collapsing margins come out exact. Returns false, setting
1260
+ * nothing, when no margin reaches that place.
1261
+ */
1262
+ function giveUpSpace(element: HTMLElement, area: Element): boolean {
1263
+ const view = element.ownerDocument.defaultView;
1264
+ const parent =
1265
+ element.parentElement == null
1266
+ ? undefined
1267
+ : view?.getComputedStyle(element.parentElement);
1268
+ const isRow =
1269
+ parent != null &&
1270
+ parent.display.includes('flex') &&
1271
+ parent.flexDirection.startsWith('row');
1272
+ const rtl = view?.getComputedStyle(element).direction === 'rtl';
1273
+ const property = isRow ? 'margin-inline-end' : 'margin-block-end';
1274
+ const size = isRow ? element.offsetWidth : element.offsetHeight;
1275
+ const next = nextInFlow(element, area);
1276
+ if (next == null) {
1277
+ // Nothing after it in the area to land anywhere.
1278
+ element.style.setProperty(property, `${-size}px`);
1279
+ return true;
1280
+ }
1281
+ const own = element.style.getPropertyValue(property);
1282
+ const ownPriority = element.style.getPropertyPriority(property);
1283
+ const axis = isRow ? 'inline' : 'block';
1284
+ // The content after its container must land too: a flex-row item that
1285
+ // sets its row's height moves what follows the row.
1286
+ const afterParent =
1287
+ element.parentElement == null || element.parentElement === area
1288
+ ? null
1289
+ : nextInFlow(element.parentElement, area);
1290
+ const checked = afterParent == null ? [next] : [next, afterParent];
1291
+ // The element's scale, read in the layout the caller's visibility check
1292
+ // already laid out.
1293
+ const scale = scaleOf(element, element.getBoundingClientRect());
1294
+ // Where the content after it goes once it is hidden, read with it taken
1295
+ // out of flow (not `display: none`, which would restart the CSS animations
1296
+ // inside it).
1297
+ const position = element.style.getPropertyValue('position');
1298
+ const positionPriority = element.style.getPropertyPriority('position');
1299
+ element.style.setProperty('position', 'absolute', 'important');
1300
+ const targets = checked.map(box => placeOf(box, rtl));
1301
+ const target = targets[0];
1302
+ if (position === '') {
1303
+ element.style.removeProperty('position');
1304
+ } else {
1305
+ element.style.setProperty('position', position, positionPriority);
1306
+ }
1307
+ // The reading is in screen px, the margin in the element's own: under a
1308
+ // scaled ancestor a distance is divided by the scale on this axis.
1309
+ const perPx = isRow ? scale.x : scale.y;
1310
+ // A first guess (its box), then one correction from the measured result:
1311
+ // a gap, a collapsed margin or the element's own margins.
1312
+ element.style.setProperty(property, `${-size}px`);
1313
+ const guess = placeOf(next, rtl)[axis];
1314
+ const correction = (target[axis] - guess) / perPx;
1315
+ element.style.setProperty(property, `${-size + correction}px`);
1316
+ // Everything checked must land on both axes: a flex-row item that sets
1317
+ // its row's height frees no block space with an inline margin.
1318
+ const missed = checked.some((box, index) => {
1319
+ const landed = placeOf(box, rtl);
1320
+ return (
1321
+ Math.abs(landed.block - targets[index].block) > 1 ||
1322
+ Math.abs(landed.inline - targets[index].inline) > 1
1323
+ );
1324
+ });
1325
+ if (missed) {
1326
+ if (own === '') {
1327
+ element.style.removeProperty(property);
1328
+ } else {
1329
+ element.style.setProperty(property, own, ownPriority);
1330
+ }
1331
+ return false;
1332
+ }
1333
+ return true;
1334
+ }
1335
+
1336
+ /** Exits holding an element back, so a release can stop one. */
1337
+ const exits = new WeakMap<Element, Animation | null>();
1338
+
1339
+ /** What an exit replaced on its element, so a release puts back exactly it. */
1340
+ interface Replaced {
1341
+ readonly inert: boolean;
1342
+ readonly styles: ReadonlyArray<readonly [string, string, string]>;
1343
+ }
1344
+ const replaced = new WeakMap<Element, Replaced>();
1345
+
1346
+ /**
1347
+ * The changed element's exit (`spec:AST-105` FR4): content that disappears
1348
+ * keeps its place on screen but gives up its space (a negative end margin
1349
+ * measured against the layout without it, so the content after it glides up
1350
+ * at once to exactly where it ends, and it still scrolls and clips with its
1351
+ * container), is inert (no focus, no pointer, nothing read), conceals upward
1352
+ * from its bottom edge on the same motion, and then `done` runs, when the
1353
+ * component hides or unmounts it. Under Reduce Motion with a coarse primary pointer it
1354
+ * fades instead. Call it in the layout effect of the commit that closes the
1355
+ * element, after the change's `animate()` reported it measured, in the same
1356
+ * task: the glide reads the layout once the element has given up its space.
1357
+ *
1358
+ * Returns false, holding nothing, when the exit lands at once: no handle, a
1359
+ * close no change in the area measured, outside the area or its visible part,
1360
+ * Reduce Motion with a fine pointer, or a layout no end margin can free (a
1361
+ * grid track and its gap, a flex-row item that sets its row's height); in
1362
+ * that last case the content after it takes its final place at once too.
1363
+ * The component then hides the element itself.
1364
+ */
1365
+ export function holdLayoutExit(
1366
+ handle: AnimatedLayout | null | undefined,
1367
+ element: HTMLElement,
1368
+ done: () => void,
1369
+ ): boolean {
1370
+ if (handle == null) {
1371
+ return false;
1372
+ }
1373
+ const area = areaOf(handle, element);
1374
+ if (
1375
+ area == null ||
1376
+ !intersects(element.getBoundingClientRect(), visibleRect(area))
1377
+ ) {
1378
+ return false;
1379
+ }
1380
+ // Only a measured close exits: the content after it glides into its place.
1381
+ const batch = batches.get(area);
1382
+ if (
1383
+ batch == null ||
1384
+ ![...batch.changed].some(
1385
+ changed => changed === element || changed.contains(element),
1386
+ )
1387
+ ) {
1388
+ return false;
1389
+ }
1390
+ const motion = layoutMotion(area);
1391
+ if (motion.kind === 'instant') {
1392
+ return false;
1393
+ }
1394
+ releaseLayoutExit(element);
1395
+ const prior: Replaced = {
1396
+ inert: element.hasAttribute('inert'),
1397
+ styles: EXIT_PROPERTIES.map(
1398
+ property =>
1399
+ [
1400
+ property,
1401
+ element.style.getPropertyValue(property),
1402
+ element.style.getPropertyPriority(property),
1403
+ ] as const,
1404
+ ),
1405
+ };
1406
+ if (!giveUpSpace(element, area)) {
1407
+ // A layout no end margin can free (a grid track and its gap, a flex-row
1408
+ // item that sets its row's height): it hides at once, and the content
1409
+ // after it takes its final place at once (`spec:AST-105` out of
1410
+ // coverage).
1411
+ for (const changed of [...batch.changed]) {
1412
+ if (changed === element || changed.contains(element)) {
1413
+ batch.changed.delete(changed);
1414
+ }
1415
+ }
1416
+ return false;
1417
+ }
1418
+ replaced.set(element, prior);
1419
+ // Out of reach while it conceals: no focus, no pointer, nothing read.
1420
+ element.setAttribute('inert', '');
1421
+ element.style.setProperty('pointer-events', 'none');
1422
+ const animation =
1423
+ motion.kind === 'fade'
1424
+ ? safeAnimate(element, [{opacity: 1}, {opacity: 0}], {
1425
+ duration: motion.durationMs,
1426
+ easing: motion.easing,
1427
+ fill: 'forwards',
1428
+ })
1429
+ : safeAnimate(
1430
+ element,
1431
+ sampleKeyframes(motion.progress, remaining => ({
1432
+ opacity: remaining,
1433
+ clipPath: `inset(0 0 ${round((1 - remaining) * 100)}% 0)`,
1434
+ })),
1435
+ {
1436
+ duration: motion.progress.durationMs,
1437
+ easing: 'linear',
1438
+ fill: 'forwards',
1439
+ },
1440
+ );
1441
+ exits.set(element, animation);
1442
+ if (animation == null) {
1443
+ // No Web Animations: nothing to wait for.
1444
+ done();
1445
+ return true;
1446
+ }
1447
+ animation.addEventListener?.('finish', () => {
1448
+ if (exits.get(element) === animation) {
1449
+ done();
1450
+ }
1451
+ });
1452
+ return true;
1453
+ }
1454
+
1455
+ /**
1456
+ * Puts an element `holdLayoutExit` held back: stops its exit and puts back
1457
+ * what the exit replaced (its `inert` and inline values as they were). Called
1458
+ * once the component has hidden the element, or when the element opens again
1459
+ * mid-exit.
1460
+ */
1461
+ export function releaseLayoutExit(element: HTMLElement): void {
1462
+ if (!exits.has(element)) {
1463
+ return;
1464
+ }
1465
+ exits.get(element)?.cancel();
1466
+ exits.delete(element);
1467
+ const prior = replaced.get(element);
1468
+ replaced.delete(element);
1469
+ if (prior?.inert !== true) {
1470
+ element.removeAttribute('inert');
1471
+ }
1472
+ for (const [property, value, priority] of prior?.styles ?? []) {
1473
+ if (value === '') {
1474
+ element.style.removeProperty(property);
1475
+ } else {
1476
+ element.style.setProperty(property, value, priority);
1477
+ }
1478
+ }
1479
+ }
1480
+
1481
+ // ---------------------------------------------------------------------------
1482
+ // The in-place swap
1483
+ // ---------------------------------------------------------------------------
1484
+
1485
+ /**
1486
+ * Old content held as one transient copy while new content enters in its
1487
+ * place (`spec:AST-105` FR8): inert, hidden from assistive technology, and
1488
+ * removed when the swap ends (`architecture:component-style-authoring` INV7).
1489
+ */
1490
+ export interface LayoutSwap {
1491
+ readonly area: Element;
1492
+ readonly copy: HTMLElement;
1493
+ /** Where the old content showed, in viewport coordinates. */
1494
+ readonly rect: DOMRect;
1495
+ }
1496
+
1497
+ /** How far a ridden element has moved since the swap began. */
1498
+ export interface LayoutRide {
1499
+ readonly x: number;
1500
+ readonly y: number;
1501
+ }
1502
+
1503
+ /**
1504
+ * How a swap plays, as frames over its progress (0 → 1) and, with
1505
+ * `rideWith`, the ridden element's travel so far.
1506
+ */
1507
+ export interface LayoutSwapMotion {
1508
+ /** The box the copy is laid out in, over the old content's place. */
1509
+ readonly host: Element;
1510
+ /** The copy's frames while it travels. */
1511
+ readonly copy: (p: number, ride: LayoutRide) => Keyframe;
1512
+ /** Its text's opacity, on its own curve, when that differs from the copy's. */
1513
+ readonly copyText?: (p: number) => number;
1514
+ /** The copy paints above its neighbours, in the background it shows. */
1515
+ readonly isOpaque?: boolean;
1516
+ /**
1517
+ * An element the glide moves, such as the column the old content sat in.
1518
+ * Every part plays over its glide, frame by frame, and is told how far it
1519
+ * has moved; the copy rides it unless `isCopyMoved` is false. Without a
1520
+ * glide (it lands silently) the ride is the whole `travel` at once (its
1521
+ * old place less its new).
1522
+ */
1523
+ readonly rideWith?: {
1524
+ readonly element: Element;
1525
+ readonly travel: LayoutRide;
1526
+ readonly isCopyMoved?: boolean;
1527
+ };
1528
+ /** Called once when the swap ends, however it ends. */
1529
+ readonly onEnd?: () => void;
1530
+ /** Elements the page already renders, entering with the swap. */
1531
+ readonly incoming: ReadonlyArray<{
1532
+ readonly element: Element;
1533
+ readonly frames: (p: number, ride: LayoutRide) => Keyframe;
1534
+ }>;
1535
+ }
1536
+
1537
+ const NO_RIDE: LayoutRide = {x: 0, y: 0};
1538
+
1539
+ /**
1540
+ * Before a change commits: hold `element`'s old content as one transient copy
1541
+ * (`spec:AST-105` FR8). With `isVisiblePart`, the copy is the element's
1542
+ * visible part, its content scrolled as it was (a scroll container). Returns
1543
+ * null without a handle, outside its area, under an immediate change, or for
1544
+ * content too large to copy.
1545
+ */
1546
+ export function holdLayoutSwap(
1547
+ handle: AnimatedLayout | null | undefined,
1548
+ element: HTMLElement,
1549
+ {isVisiblePart = false}: {isVisiblePart?: boolean} = {},
1550
+ ): LayoutSwap | null {
1551
+ if (handle == null || typeof element.animate !== 'function') {
1552
+ return null;
1553
+ }
1554
+ const area = areaOf(handle, element);
1555
+ if (
1556
+ area == null ||
1557
+ layoutMotion(area).kind === 'instant' ||
1558
+ !isCopyable(element)
1559
+ ) {
1560
+ return null;
1561
+ }
1562
+ const box = element.getBoundingClientRect();
1563
+ if (!isVisiblePart) {
1564
+ const copy = inertCopy(element);
1565
+ return copy == null ? null : {area, copy, rect: box};
1566
+ }
1567
+ const part = visiblePartCopy(element);
1568
+ return part == null ? null : {area, ...part};
1569
+ }
1570
+
1571
+ /**
1572
+ * After the change commits, before paint: the copy leaves while the incoming
1573
+ * elements enter, on FR4's one motion, every part started on the same
1574
+ * timeline time. Under Reduce Motion with a coarse pointer, only opacity
1575
+ * changes (`design:reduced-motion` DR2). Returns what ends the swap at once;
1576
+ * it also ends when its motion does, and the copy is removed.
1577
+ */
1578
+ export function playLayoutSwap(
1579
+ swap: LayoutSwap,
1580
+ how: LayoutSwapMotion,
1581
+ ): () => void {
1582
+ const motion = layoutMotion(swap.area);
1583
+ if (motion.kind === 'instant') {
1584
+ return () => {};
1585
+ }
1586
+ const {copy} = swap;
1587
+ placeOver(copy, how.host, swap.rect);
1588
+ if (how.isOpaque === true) {
1589
+ copy.style.zIndex = '1';
1590
+ copy.style.backgroundColor = paintedBackground(copy);
1591
+ }
1592
+ const animations: Animation[] = [];
1593
+ let isDone = false;
1594
+ const end = () => {
1595
+ if (isDone) {
1596
+ return;
1597
+ }
1598
+ isDone = true;
1599
+ animations.forEach(animation => animation.cancel());
1600
+ copy.remove();
1601
+ how.onEnd?.();
1602
+ };
1603
+ const {copyText, rideWith} = how;
1604
+ const fadedText =
1605
+ copyText != null && motion.kind === 'spring' ? wrapText(copy) : [];
1606
+ // Each part as a function of time: its frame, or the copy's with its ride.
1607
+ const parts: [Element, (p: number, ride: LayoutRide) => Keyframe][] = [];
1608
+ if (motion.kind === 'spring') {
1609
+ const moves = rideWith != null && rideWith.isCopyMoved !== false;
1610
+ parts.push([
1611
+ copy,
1612
+ (p, ride) => ({
1613
+ ...how.copy(p, ride),
1614
+ ...(moves ? {translate: `${ride.x}px ${ride.y}px`} : null),
1615
+ }),
1616
+ ]);
1617
+ for (const span of fadedText) {
1618
+ parts.push([span, p => ({opacity: copyText?.(p) ?? 1})]);
1619
+ }
1620
+ for (const {element, frames} of how.incoming) {
1621
+ parts.push([element, frames]);
1622
+ }
1623
+ } else {
1624
+ // Reduce Motion with a coarse pointer: only opacity changes.
1625
+ parts.push([copy, p => ({opacity: 1 - p})]);
1626
+ for (const {element} of how.incoming) {
1627
+ parts.push([element, p => ({opacity: p})]);
1628
+ }
1629
+ }
1630
+ const playAll = (
1631
+ durationMs: number,
1632
+ progressAt: (t: number) => number,
1633
+ rideAt: (t: number) => LayoutRide,
1634
+ options: KeyframeAnimationOptions,
1635
+ sample: (shape: (t: number) => Keyframe) => Keyframe[],
1636
+ ) => {
1637
+ for (const [element, shape] of parts) {
1638
+ const animation = safeAnimate(
1639
+ element,
1640
+ sample(t => shape(progressAt(t), rideAt(t))),
1641
+ {duration: durationMs, fill: 'both', ...options},
1642
+ );
1643
+ if (animation != null) {
1644
+ animations.push(animation);
1645
+ }
1646
+ }
1647
+ if (animations.length === 0) {
1648
+ end();
1649
+ } else {
1650
+ // Every part runs on one clock, so the first to finish ends them all.
1651
+ animations[0].addEventListener?.('finish', end);
1652
+ }
1653
+ };
1654
+ if (motion.kind === 'fade') {
1655
+ playAll(
1656
+ motion.durationMs,
1657
+ t => (t <= 0 ? 0 : 1),
1658
+ () => NO_RIDE,
1659
+ {easing: motion.easing},
1660
+ shape => [shape(0), shape(motion.durationMs)],
1661
+ );
1662
+ return end;
1663
+ }
1664
+ const {progress} = motion;
1665
+ const progressAt = (t: number) => 1 - progress.remaining(t);
1666
+ if (rideWith == null) {
1667
+ playAll(
1668
+ progress.durationMs,
1669
+ progressAt,
1670
+ () => NO_RIDE,
1671
+ {easing: 'linear'},
1672
+ shape => sampleOver(progress.durationMs, shape),
1673
+ );
1674
+ return end;
1675
+ }
1676
+ // After this commit's glides start (the batch flushes in a microtask queued
1677
+ // before this one), before the frame paints: every part plays over the
1678
+ // ridden element's glide, told how far it has moved from where it showed.
1679
+ queueMicrotask(() => {
1680
+ if (isDone) {
1681
+ return;
1682
+ }
1683
+ const glide = glides.get(rideWith.element);
1684
+ const durationMs = glide?.durationMs ?? progress.durationMs;
1685
+ const rideAt = (t: number): LayoutRide => {
1686
+ if (glide == null) {
1687
+ return {x: -rideWith.travel.x, y: -rideWith.travel.y};
1688
+ }
1689
+ const now = glide.offsetAt(t);
1690
+ const start = glide.offsetAt(0);
1691
+ return {x: now.x - start.x, y: now.y - start.y};
1692
+ };
1693
+ playAll(durationMs, progressAt, rideAt, {easing: 'linear'}, shape =>
1694
+ sampleOver(durationMs, shape),
1695
+ );
1696
+ });
1697
+ return end;
1698
+ }
1699
+
1700
+ /**
1701
+ * After a change commits, before paint: elements the page already renders
1702
+ * play frames over the change's progress on FR4's one motion, with no copy,
1703
+ * such as a surface reaching over a gap a glide opens. Under Reduce Motion
1704
+ * with a coarse pointer, only opacity changes; under an immediate change,
1705
+ * nothing plays. Returns what ends them at once.
1706
+ */
1707
+ export function playLayoutFrames(
1708
+ handle: AnimatedLayout | null | undefined,
1709
+ parts: LayoutSwapMotion['incoming'],
1710
+ ): () => void {
1711
+ const area = handle?.[AREA]() ?? null;
1712
+ const motion = area == null ? null : layoutMotion(area);
1713
+ if (motion == null || motion.kind === 'instant') {
1714
+ return () => {};
1715
+ }
1716
+ const animations: Animation[] = [];
1717
+ for (const {element, frames: shape} of parts) {
1718
+ const animation =
1719
+ motion.kind === 'spring'
1720
+ ? safeAnimate(
1721
+ element,
1722
+ sampleKeyframes(motion.progress, remaining =>
1723
+ shape(1 - remaining, NO_RIDE),
1724
+ ),
1725
+ {
1726
+ duration: motion.progress.durationMs,
1727
+ easing: 'linear',
1728
+ fill: 'both',
1729
+ },
1730
+ )
1731
+ : safeAnimate(element, [{opacity: 0}, {opacity: 1}], {
1732
+ duration: motion.durationMs,
1733
+ easing: motion.easing,
1734
+ });
1735
+ if (animation != null) {
1736
+ animations.push(animation);
1737
+ }
1738
+ }
1739
+ // Held through the motion, then released: every part shares one clock, so
1740
+ // the first to finish ends them all and each element shows its own styles.
1741
+ const end = () => animations.forEach(animation => animation.cancel());
1742
+ animations[0]?.addEventListener?.('finish', end);
1743
+ return end;
1744
+ }
1745
+
1746
+ /**
1747
+ * A disclosure's indicator (its chevron) turns on the same motion as the
1748
+ * glide: its CSS transition takes the spring as a `linear()` easing, and an
1749
+ * immediate change under Reduce Motion. Without a handle the inline values are
1750
+ * cleared, so the component's own transition applies. An engine without
1751
+ * `linear()` drops that value and keeps the component's easing.
1752
+ */
1753
+ export function applyLayoutChangeTransition(
1754
+ handle: AnimatedLayout | null | undefined,
1755
+ element: HTMLElement | SVGElement | null,
1756
+ ): void {
1757
+ if (element == null) {
1758
+ return;
1759
+ }
1760
+ const area = handle == null ? null : areaOf(handle, element);
1761
+ if (area == null) {
1762
+ element.style.removeProperty('transition-duration');
1763
+ element.style.removeProperty('transition-timing-function');
1764
+ return;
1765
+ }
1766
+ const motion = layoutMotion(area);
1767
+ if (motion.kind !== 'spring') {
1768
+ element.style.setProperty('transition-duration', '0s');
1769
+ element.style.removeProperty('transition-timing-function');
1770
+ return;
1771
+ }
1772
+ element.style.setProperty(
1773
+ 'transition-duration',
1774
+ `${Math.round(motion.progress.durationMs)}ms`,
1775
+ );
1776
+ element.style.setProperty(
1777
+ 'transition-timing-function',
1778
+ linearEasing(motion.progress),
1779
+ );
1780
+ }
1781
+
1782
+ /**
1783
+ * Lands `element`'s running glide at once: it takes its layout place, and a
1784
+ * later change starts from there (a change its caller lands rather than
1785
+ * animates, such as a rail that snaps).
1786
+ */
1787
+ export function landLayoutGlide(element: Element): void {
1788
+ const glide = glides.get(element);
1789
+ if (glide != null) {
1790
+ glides.delete(element);
1791
+ glide.animation.cancel();
1792
+ }
1793
+ }
1794
+
1795
+ /**
1796
+ * @internal The motion a change in `area` plays, for tests and for SideNav's
1797
+ * rail motion, which plays on the same clock (`component:SideNav` FR6).
1798
+ */
1799
+ export function layoutMotionFor(area: Element): LayoutMotion {
1800
+ return layoutMotion(area);
1801
+ }