@astryxdesign/core 0.7.7-canary.c0929c8 → 0.7.7-canary.c19ca12

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 (472) hide show
  1. package/dist/AlertDialog/AlertDialog.d.ts +4 -1
  2. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  3. package/dist/AlertDialog/AlertDialog.js +36 -6
  4. package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts +13 -0
  5. package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts.map +1 -0
  6. package/dist/AppShell/useCloseMobileDrawerOnActivate.js +45 -0
  7. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheet.js +79 -9
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  10. package/dist/BottomSheet/BottomSheetPanel.js +23 -4
  11. package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
  12. package/dist/BottomSheet/bottomSheetStack.js +5 -4
  13. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  14. package/dist/BottomSheet/useSheetGestures.js +3 -1
  15. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +2 -1
  16. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  17. package/dist/Breadcrumbs/BreadcrumbItem.js +7 -3
  18. package/dist/Button/Button.d.ts.map +1 -1
  19. package/dist/Button/Button.js +47 -3
  20. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  21. package/dist/CheckboxInput/CheckboxInput.js +13 -2
  22. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  23. package/dist/CheckboxList/CheckboxList.js +7 -1
  24. package/dist/CheckboxList/CheckboxListContext.d.ts +6 -0
  25. package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
  26. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  27. package/dist/CheckboxList/CheckboxListItem.js +10 -2
  28. package/dist/ComplexSelector/ComplexSelector.d.ts +4 -1
  29. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  30. package/dist/ComplexSelector/ComplexSelector.js +14 -4
  31. package/dist/ContextMenu/ContextMenu.js +2 -2
  32. package/dist/DateInput/DateInput.d.ts.map +1 -1
  33. package/dist/DateInput/DateInput.js +5 -2
  34. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  35. package/dist/DateInput/MonthScroller.js +13 -27
  36. package/dist/DateInput/Wheel.d.ts.map +1 -1
  37. package/dist/DateInput/Wheel.js +22 -41
  38. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  39. package/dist/DateTimeInput/DateTimeInput.js +5 -2
  40. package/dist/Dialog/Dialog.d.ts.map +1 -1
  41. package/dist/Dialog/Dialog.js +23 -45
  42. package/dist/Drawer/Drawer.d.ts.map +1 -1
  43. package/dist/Drawer/Drawer.js +15 -11
  44. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  45. package/dist/Drawer/useDrawerDialogPresence.js +5 -1
  46. package/dist/Field/Field.js +2 -2
  47. package/dist/Field/PanelSearchInput.d.ts +9 -1
  48. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  49. package/dist/Field/PanelSearchInput.js +3 -1
  50. package/dist/HoverCard/HoverCard.d.ts +4 -3
  51. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  52. package/dist/HoverCard/HoverCard.js +27 -2
  53. package/dist/HoverCard/useHoverCard.d.ts +5 -4
  54. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  55. package/dist/HoverCard/useHoverCard.js +17 -31
  56. package/dist/Icon/Icon.d.ts +5 -1
  57. package/dist/Icon/Icon.d.ts.map +1 -1
  58. package/dist/Icon/Icon.js +5 -2
  59. package/dist/InfoTip/InfoTip.d.ts +63 -0
  60. package/dist/InfoTip/InfoTip.d.ts.map +1 -0
  61. package/dist/InfoTip/InfoTip.js +126 -0
  62. package/dist/InfoTip/index.d.ts +10 -0
  63. package/dist/InfoTip/index.d.ts.map +1 -0
  64. package/dist/InfoTip/index.js +12 -0
  65. package/dist/Layer/layerAnimations.stylex.d.ts +7 -8
  66. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  67. package/dist/Layer/layerAnimations.stylex.js +25 -20
  68. package/dist/Layer/useBackdropPress.d.ts +27 -0
  69. package/dist/Layer/useBackdropPress.d.ts.map +1 -0
  70. package/dist/Layer/useBackdropPress.js +53 -0
  71. package/dist/Layer/usePressPin.d.ts +20 -10
  72. package/dist/Layer/usePressPin.d.ts.map +1 -1
  73. package/dist/Layer/usePressPin.js +66 -18
  74. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  75. package/dist/Lightbox/Lightbox.js +18 -0
  76. package/dist/MobileNav/MobileNav.js +0 -1
  77. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  78. package/dist/MultiSelector/hooks.js +2 -4
  79. package/dist/Outline/Outline.d.ts +2 -4
  80. package/dist/Outline/Outline.d.ts.map +1 -1
  81. package/dist/Outline/Outline.js +4 -52
  82. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  83. package/dist/Outline/useOutlineFromMarkdown.js +1 -0
  84. package/dist/Outline/useScrollSpy.js +3 -3
  85. package/dist/PowerSearch/PowerSearch.d.ts +36 -3
  86. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  87. package/dist/PowerSearch/PowerSearch.js +571 -302
  88. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +100 -0
  89. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -0
  90. package/dist/PowerSearch/PowerSearchBottomSheet.js +1913 -0
  91. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +32 -1
  92. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  93. package/dist/PowerSearch/PowerSearchEditPopover.js +17 -6
  94. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +38 -3
  95. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  96. package/dist/PowerSearch/PowerSearchValueEditor.js +170 -61
  97. package/dist/PowerSearch/formatFilterValue.d.ts +7 -0
  98. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  99. package/dist/PowerSearch/formatFilterValue.js +11 -1
  100. package/dist/PowerSearch/formatTokenValue.d.ts +28 -0
  101. package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -0
  102. package/dist/PowerSearch/formatTokenValue.js +160 -0
  103. package/dist/PowerSearch/powerSearchSheetUtils.d.ts +65 -0
  104. package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +1 -0
  105. package/dist/PowerSearch/powerSearchSheetUtils.js +168 -0
  106. package/dist/RadioList/RadioList.d.ts.map +1 -1
  107. package/dist/RadioList/RadioList.js +8 -2
  108. package/dist/RadioList/RadioListItem.d.ts +1 -1
  109. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  110. package/dist/RadioList/RadioListItem.js +5 -3
  111. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  112. package/dist/Resizable/ResizeHandle.js +118 -260
  113. package/dist/Resizable/resizeGesture.d.ts +91 -0
  114. package/dist/Resizable/resizeGesture.d.ts.map +1 -0
  115. package/dist/Resizable/resizeGesture.js +251 -0
  116. package/dist/SegmentedControl/SegmentedControl.d.ts +3 -1
  117. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  118. package/dist/SegmentedControl/SegmentedControl.js +115 -8
  119. package/dist/SegmentedControl/SegmentedControlContext.d.ts +6 -0
  120. package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
  121. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -0
  122. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  123. package/dist/SegmentedControl/SegmentedControlItem.js +8 -1
  124. package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts +357 -0
  125. package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -0
  126. package/dist/SegmentedControl/useSegmentedSelectionMotion.js +1349 -0
  127. package/dist/SegmentedControl/useSegmentedTouchTracking.d.ts +70 -0
  128. package/dist/SegmentedControl/useSegmentedTouchTracking.d.ts.map +1 -0
  129. package/dist/SegmentedControl/useSegmentedTouchTracking.js +264 -0
  130. package/dist/Selector/Selector.d.ts.map +1 -1
  131. package/dist/Selector/Selector.js +96 -67
  132. package/dist/Selector/optionShape.d.ts +24 -0
  133. package/dist/Selector/optionShape.d.ts.map +1 -0
  134. package/dist/Selector/optionShape.js +48 -0
  135. package/dist/Selector/selectableOptionEntries.d.ts +20 -0
  136. package/dist/Selector/selectableOptionEntries.d.ts.map +1 -0
  137. package/dist/Selector/selectableOptionEntries.js +38 -0
  138. package/dist/Selector/utils.d.ts +2 -17
  139. package/dist/Selector/utils.d.ts.map +1 -1
  140. package/dist/Selector/utils.js +3 -51
  141. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  142. package/dist/SideNav/SideNavItem.js +3 -9
  143. package/dist/Slider/sliderTouchController.js +2 -2
  144. package/dist/Spinner/Spinner.d.ts +1 -1
  145. package/dist/Spinner/Spinner.d.ts.map +1 -1
  146. package/dist/Spinner/Spinner.js +60 -58
  147. package/dist/Switch/switchTouch.d.ts +0 -7
  148. package/dist/Switch/switchTouch.d.ts.map +1 -1
  149. package/dist/Switch/switchTouch.js +2 -10
  150. package/dist/Switch/useSwitchTouch.d.ts +2 -11
  151. package/dist/Switch/useSwitchTouch.d.ts.map +1 -1
  152. package/dist/Switch/useSwitchTouch.js +35 -93
  153. package/dist/Table/BaseTable.d.ts.map +1 -1
  154. package/dist/Table/BaseTable.js +29 -8
  155. package/dist/TextInput/TextInput.d.ts +2 -2
  156. package/dist/TextInput/TextInput.d.ts.map +1 -1
  157. package/dist/TextInput/TextInput.js +10 -7
  158. package/dist/Toast/Toast.d.ts +11 -1
  159. package/dist/Toast/Toast.d.ts.map +1 -1
  160. package/dist/Toast/Toast.js +30 -15
  161. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  162. package/dist/Toast/ToastViewport.js +94 -34
  163. package/dist/Toast/types.d.ts +9 -3
  164. package/dist/Toast/types.d.ts.map +1 -1
  165. package/dist/Token/Token.d.ts +2 -2
  166. package/dist/Token/Token.d.ts.map +1 -1
  167. package/dist/Token/Token.js +13 -4
  168. package/dist/Token/TokenNamingContext.d.ts +14 -0
  169. package/dist/Token/TokenNamingContext.d.ts.map +1 -0
  170. package/dist/Token/TokenNamingContext.js +23 -0
  171. package/dist/Tokenizer/Tokenizer.d.ts +46 -59
  172. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  173. package/dist/Tokenizer/Tokenizer.js +40 -57
  174. package/dist/Tokenizer/TokenizerBottomSheet.d.ts +25 -28
  175. package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -1
  176. package/dist/Tokenizer/TokenizerBottomSheet.js +157 -54
  177. package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts +3 -0
  178. package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts.map +1 -0
  179. package/dist/Tokenizer/TokenizerItemRemovableContext.js +19 -0
  180. package/dist/Tooltip/Tooltip.d.ts +25 -30
  181. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  182. package/dist/Tooltip/Tooltip.js +24 -5
  183. package/dist/Tooltip/index.d.ts +1 -1
  184. package/dist/Tooltip/index.d.ts.map +1 -1
  185. package/dist/Tooltip/useTooltip.d.ts +45 -28
  186. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  187. package/dist/Tooltip/useTooltip.js +52 -59
  188. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  189. package/dist/TopNav/TopNavItem.js +4 -7
  190. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  191. package/dist/TopNav/TopNavMegaMenuItem.js +4 -7
  192. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  193. package/dist/TopNav/TopNavMenu.js +4 -7
  194. package/dist/Typeahead/TypeaheadItem.d.ts +2 -1
  195. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  196. package/dist/animator/createAnimator.d.ts +98 -0
  197. package/dist/animator/createAnimator.d.ts.map +1 -0
  198. package/dist/animator/createAnimator.js +259 -0
  199. package/dist/astryx.css +96 -7
  200. package/dist/gestures/GestureHost.d.ts +27 -1
  201. package/dist/gestures/GestureHost.d.ts.map +1 -1
  202. package/dist/gestures/GestureHost.js +157 -21
  203. package/dist/gestures/PressTracker.d.ts.map +1 -1
  204. package/dist/gestures/PressTracker.js +4 -3
  205. package/dist/hooks/actionGroupTracker.d.ts +7 -4
  206. package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
  207. package/dist/hooks/actionGroupTracker.js +19 -56
  208. package/dist/hooks/index.d.ts +1 -0
  209. package/dist/hooks/index.d.ts.map +1 -1
  210. package/dist/hooks/index.js +1 -0
  211. package/dist/hooks/pressGroupContext.d.ts +6 -0
  212. package/dist/hooks/pressGroupContext.d.ts.map +1 -0
  213. package/dist/hooks/pressGroupContext.js +20 -0
  214. package/dist/hooks/useActionGroupTracking.d.ts +53 -0
  215. package/dist/hooks/useActionGroupTracking.d.ts.map +1 -0
  216. package/dist/hooks/useActionGroupTracking.js +174 -0
  217. package/dist/hooks/useAnimator.d.ts +41 -0
  218. package/dist/hooks/useAnimator.d.ts.map +1 -0
  219. package/dist/hooks/useAnimator.js +70 -0
  220. package/dist/hooks/useAttachment.d.ts +1 -1
  221. package/dist/hooks/useAttachment.js +1 -1
  222. package/dist/hooks/useHighlightedOptionScroll.d.ts +11 -1
  223. package/dist/hooks/useHighlightedOptionScroll.d.ts.map +1 -1
  224. package/dist/hooks/useHighlightedOptionScroll.js +112 -11
  225. package/dist/hooks/useInputStatusIcon.d.ts +1 -1
  226. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  227. package/dist/hooks/useInputStatusIcon.js +2 -2
  228. package/dist/hooks/useLongPress.d.ts +6 -2
  229. package/dist/hooks/useLongPress.d.ts.map +1 -1
  230. package/dist/hooks/useLongPress.js +95 -15
  231. package/dist/hooks/useMediaQuery.d.ts +2 -1
  232. package/dist/hooks/useMediaQuery.d.ts.map +1 -1
  233. package/dist/hooks/useMediaQuery.js +7 -4
  234. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  235. package/dist/hooks/useMenuPress.js +4 -2
  236. package/dist/i18n/generated-english/InfoTip/InfoTip.generated.d.ts +8 -0
  237. package/dist/i18n/generated-english/InfoTip/InfoTip.generated.d.ts.map +1 -0
  238. package/dist/i18n/generated-english/InfoTip/InfoTip.generated.js +12 -0
  239. package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.d.ts.map +1 -1
  240. package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.js +1 -0
  241. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +8 -0
  242. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +1 -0
  243. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +42 -0
  244. package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
  245. package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +6 -0
  246. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +8 -0
  247. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +1 -0
  248. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +14 -0
  249. package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.d.ts.map +1 -1
  250. package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.js +7 -1
  251. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  252. package/dist/i18n/generated-locales/en.generated.js +33 -1
  253. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  254. package/dist/i18n/generated-locales/pseudo.generated.js +33 -1
  255. package/dist/index.d.ts +2 -0
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +5 -0
  258. package/dist/internal/SheetConfirmation.d.ts +11 -0
  259. package/dist/internal/SheetConfirmation.d.ts.map +1 -0
  260. package/dist/internal/SheetConfirmation.js +92 -0
  261. package/dist/internal/indicatorPress.stylex.d.ts +20 -0
  262. package/dist/internal/indicatorPress.stylex.d.ts.map +1 -0
  263. package/dist/internal/indicatorPress.stylex.js +26 -0
  264. package/dist/internal/sheetDraft.d.ts +35 -0
  265. package/dist/internal/sheetDraft.d.ts.map +1 -0
  266. package/dist/internal/sheetDraft.js +65 -0
  267. package/dist/internal/touch-sheet.d.ts +21 -0
  268. package/dist/internal/touch-sheet.d.ts.map +1 -0
  269. package/dist/internal/touch-sheet.js +19 -0
  270. package/dist/internal/useDismissSearchOnTouchDrag.d.ts +24 -0
  271. package/dist/internal/useDismissSearchOnTouchDrag.d.ts.map +1 -0
  272. package/dist/internal/useDismissSearchOnTouchDrag.js +56 -0
  273. package/dist/motion/animator.d.ts +14 -14
  274. package/dist/motion/animator.d.ts.map +1 -1
  275. package/dist/motion/animator.js +41 -18
  276. package/dist/motion/reducedMotion.d.ts +24 -0
  277. package/dist/motion/reducedMotion.d.ts.map +1 -1
  278. package/dist/motion/reducedMotion.js +78 -1
  279. package/dist/motion/roles.d.ts +7 -1
  280. package/dist/motion/roles.d.ts.map +1 -1
  281. package/dist/motion/roles.js +20 -1
  282. package/dist/motion/uikit/alert.d.ts +41 -0
  283. package/dist/motion/uikit/alert.d.ts.map +1 -0
  284. package/dist/motion/uikit/alert.js +43 -0
  285. package/dist/motion/uikit/index.d.ts +6 -5
  286. package/dist/motion/uikit/index.d.ts.map +1 -1
  287. package/dist/motion/uikit/index.js +6 -5
  288. package/dist/motion/uikit/segmented.d.ts +55 -0
  289. package/dist/motion/uikit/segmented.d.ts.map +1 -0
  290. package/dist/motion/uikit/segmented.js +77 -0
  291. package/dist/motion/uikit/springs.d.ts +0 -18
  292. package/dist/motion/uikit/springs.d.ts.map +1 -1
  293. package/dist/motion/uikit/springs.js +5 -21
  294. package/dist/privateAttributes/pressGroupItem.stylex.d.ts +15 -0
  295. package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +1 -0
  296. package/dist/privateAttributes/pressGroupItem.stylex.js +23 -0
  297. package/dist/privateAttributes/segmentTitle.stylex.d.ts +5 -0
  298. package/dist/privateAttributes/segmentTitle.stylex.d.ts.map +1 -0
  299. package/dist/privateAttributes/segmentTitle.stylex.js +22 -0
  300. package/dist/utils/browserClickWait.d.ts +35 -0
  301. package/dist/utils/browserClickWait.d.ts.map +1 -0
  302. package/dist/utils/browserClickWait.js +123 -0
  303. package/dist/utils/clickGuard.d.ts +14 -1
  304. package/dist/utils/clickGuard.d.ts.map +1 -1
  305. package/dist/utils/clickGuard.js +46 -1
  306. package/dist/utils/dateParser.d.ts.map +1 -1
  307. package/dist/utils/dateParser.js +12 -0
  308. package/dist/utils/focusReturn.d.ts +15 -0
  309. package/dist/utils/focusReturn.d.ts.map +1 -1
  310. package/dist/utils/focusReturn.js +28 -0
  311. package/dist/utils/interactionOverlay.stylex.d.ts +3 -2
  312. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  313. package/dist/utils/interactionOverlay.stylex.js +3 -2
  314. package/dist/utils/pressFeedback.d.ts.map +1 -1
  315. package/dist/utils/pressFeedback.js +19 -6
  316. package/dist/utils/triggerFocus.d.ts +36 -0
  317. package/dist/utils/triggerFocus.d.ts.map +1 -0
  318. package/dist/utils/triggerFocus.js +65 -0
  319. package/locales/en.json +128 -0
  320. package/locales/pseudo.json +96 -0
  321. package/package.json +18 -8
  322. package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
  323. package/src/AlertDialog/AlertDialog.tsx +37 -5
  324. package/src/AppShell/useCloseMobileDrawerOnActivate.ts +52 -0
  325. package/src/BottomSheet/BottomSheet.tsx +95 -10
  326. package/src/BottomSheet/BottomSheetPanel.tsx +40 -5
  327. package/src/BottomSheet/bottomSheetStack.ts +8 -4
  328. package/src/BottomSheet/useSheetGestures.ts +3 -1
  329. package/src/Breadcrumbs/BreadcrumbItem.tsx +13 -3
  330. package/src/Button/Button.tsx +63 -5
  331. package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
  332. package/src/CheckboxInput/CheckboxInput.tsx +36 -9
  333. package/src/CheckboxList/CheckboxList.doc.mjs +4 -2
  334. package/src/CheckboxList/CheckboxList.tsx +6 -0
  335. package/src/CheckboxList/CheckboxListContext.tsx +6 -0
  336. package/src/CheckboxList/CheckboxListItem.tsx +11 -2
  337. package/src/ComplexSelector/ComplexSelector.tsx +20 -5
  338. package/src/ContextMenu/ContextMenu.tsx +2 -2
  339. package/src/DateInput/DateInput.tsx +8 -2
  340. package/src/DateInput/MonthScroller.tsx +18 -22
  341. package/src/DateInput/Wheel.tsx +30 -32
  342. package/src/DateTimeInput/DateTimeInput.tsx +8 -2
  343. package/src/Dialog/Dialog.tsx +54 -45
  344. package/src/Drawer/Drawer.tsx +28 -11
  345. package/src/Drawer/useDrawerDialogPresence.ts +5 -1
  346. package/src/Field/Field.tsx +2 -2
  347. package/src/Field/PanelSearchInput.tsx +11 -0
  348. package/src/HoverCard/HoverCard.doc.mjs +4 -2
  349. package/src/HoverCard/HoverCard.tsx +35 -4
  350. package/src/HoverCard/useHoverCard.doc.mjs +178 -36
  351. package/src/HoverCard/useHoverCard.tsx +46 -52
  352. package/src/Icon/Icon.doc.mjs +49 -8
  353. package/src/Icon/Icon.tsx +15 -7
  354. package/src/InfoTip/InfoTip.doc.mjs +192 -0
  355. package/src/InfoTip/InfoTip.tsx +186 -0
  356. package/src/InfoTip/index.ts +14 -0
  357. package/src/Layer/layerAnimations.stylex.ts +24 -16
  358. package/src/Layer/useBackdropPress.ts +81 -0
  359. package/src/Layer/usePressPin.ts +86 -26
  360. package/src/Lightbox/Lightbox.tsx +18 -0
  361. package/src/MobileNav/MobileNav.tsx +1 -1
  362. package/src/MultiSelector/hooks.ts +2 -4
  363. package/src/Outline/Outline.doc.mjs +177 -51
  364. package/src/Outline/Outline.tsx +5 -57
  365. package/src/Outline/useOutlineFromMarkdown.doc.mjs +157 -0
  366. package/src/Outline/useOutlineFromMarkdown.ts +1 -0
  367. package/src/Outline/useScrollSpy.ts +3 -3
  368. package/src/PowerSearch/PowerSearch.doc.mjs +55 -6
  369. package/src/PowerSearch/PowerSearch.tsx +798 -324
  370. package/src/PowerSearch/PowerSearchBottomSheet.tsx +2515 -0
  371. package/src/PowerSearch/PowerSearchEditPopover.tsx +28 -6
  372. package/src/PowerSearch/PowerSearchValueEditor.tsx +203 -38
  373. package/src/PowerSearch/formatFilterValue.ts +18 -1
  374. package/src/PowerSearch/formatTokenValue.ts +215 -0
  375. package/src/PowerSearch/powerSearchSheetUtils.ts +224 -0
  376. package/src/RadioList/RadioList.doc.mjs +4 -2
  377. package/src/RadioList/RadioList.tsx +7 -2
  378. package/src/RadioList/RadioListItem.tsx +5 -3
  379. package/src/Resizable/ResizeHandle.tsx +133 -328
  380. package/src/Resizable/resizeGesture.ts +368 -0
  381. package/src/SegmentedControl/SegmentedControl.doc.mjs +3 -3
  382. package/src/SegmentedControl/SegmentedControl.tsx +179 -5
  383. package/src/SegmentedControl/SegmentedControlContext.ts +6 -0
  384. package/src/SegmentedControl/SegmentedControlItem.tsx +12 -1
  385. package/src/SegmentedControl/useSegmentedSelectionMotion.ts +1640 -0
  386. package/src/SegmentedControl/useSegmentedTouchTracking.ts +308 -0
  387. package/src/Selector/Selector.tsx +136 -89
  388. package/src/Selector/optionShape.ts +64 -0
  389. package/src/Selector/selectableOptionEntries.ts +39 -0
  390. package/src/Selector/utils.ts +9 -68
  391. package/src/SideNav/SideNavItem.tsx +3 -7
  392. package/src/Slider/sliderTouchController.ts +2 -2
  393. package/src/Spinner/Spinner.tsx +77 -63
  394. package/src/Switch/switchTouch.ts +2 -10
  395. package/src/Switch/useSwitchTouch.ts +38 -104
  396. package/src/Table/BaseTable.tsx +46 -12
  397. package/src/TextInput/TextInput.tsx +11 -10
  398. package/src/Toast/Toast.doc.mjs +4 -3
  399. package/src/Toast/Toast.tsx +57 -32
  400. package/src/Toast/ToastViewport.tsx +121 -35
  401. package/src/Toast/types.ts +9 -3
  402. package/src/Token/Token.tsx +15 -4
  403. package/src/Token/TokenNamingContext.ts +28 -0
  404. package/src/Tokenizer/Tokenizer.doc.mjs +16 -0
  405. package/src/Tokenizer/Tokenizer.tsx +89 -85
  406. package/src/Tokenizer/TokenizerBottomSheet.tsx +219 -93
  407. package/src/Tokenizer/TokenizerItemRemovableContext.ts +24 -0
  408. package/src/Tooltip/Tooltip.doc.mjs +123 -54
  409. package/src/Tooltip/Tooltip.tsx +36 -39
  410. package/src/Tooltip/index.ts +0 -1
  411. package/src/Tooltip/useTooltip.doc.mjs +171 -33
  412. package/src/Tooltip/useTooltip.tsx +98 -86
  413. package/src/TopNav/TopNavItem.tsx +6 -5
  414. package/src/TopNav/TopNavMegaMenuItem.tsx +6 -5
  415. package/src/TopNav/TopNavMenu.tsx +6 -5
  416. package/src/Typeahead/TypeaheadItem.doc.mjs +6 -3
  417. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  418. package/src/animator/createAnimator.doc.mjs +153 -0
  419. package/src/animator/createAnimator.ts +324 -0
  420. package/src/gestures/GestureHost.ts +198 -20
  421. package/src/gestures/PressTracker.ts +4 -3
  422. package/src/gestures/README.md +7 -1
  423. package/src/hooks/actionGroupTracker.ts +32 -61
  424. package/src/hooks/index.ts +2 -0
  425. package/src/hooks/pressGroupContext.ts +21 -0
  426. package/src/hooks/useActionGroupTracking.ts +224 -0
  427. package/src/hooks/useAnimator.doc.mjs +109 -0
  428. package/src/hooks/useAnimator.ts +67 -0
  429. package/src/hooks/useAttachment.ts +1 -1
  430. package/src/hooks/useHighlightedOptionScroll.ts +123 -15
  431. package/src/hooks/useInputStatusIcon.tsx +3 -2
  432. package/src/hooks/useLongPress.doc.mjs +2 -2
  433. package/src/hooks/useLongPress.ts +136 -15
  434. package/src/hooks/useMediaQuery.doc.mjs +2 -2
  435. package/src/hooks/useMediaQuery.ts +13 -4
  436. package/src/hooks/useMenuPress.ts +8 -2
  437. package/src/i18n/generated-english/InfoTip/InfoTip.generated.ts +13 -0
  438. package/src/i18n/generated-english/PowerSearch/PowerSearch.generated.ts +1 -0
  439. package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +43 -0
  440. package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +6 -0
  441. package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +15 -0
  442. package/src/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.ts +7 -1
  443. package/src/i18n/generated-locales/en.generated.ts +43 -0
  444. package/src/i18n/generated-locales/pseudo.generated.ts +44 -0
  445. package/src/index.ts +14 -0
  446. package/src/internal/SheetConfirmation.tsx +101 -0
  447. package/src/internal/indicatorPress.stylex.ts +24 -0
  448. package/src/internal/sheetDraft.ts +80 -0
  449. package/src/internal/touch-sheet.ts +21 -0
  450. package/src/internal/useDismissSearchOnTouchDrag.ts +69 -0
  451. package/src/motion/MEASUREMENTS.md +7 -0
  452. package/src/motion/README.md +9 -5
  453. package/src/motion/animator.ts +61 -29
  454. package/src/motion/reducedMotion.ts +79 -1
  455. package/src/motion/roles.ts +20 -1
  456. package/src/motion/uikit/alert.ts +43 -0
  457. package/src/motion/uikit/index.ts +5 -5
  458. package/src/motion/uikit/segmented.ts +74 -0
  459. package/src/motion/uikit/springs.ts +5 -21
  460. package/src/privateAttributes/pressGroupItem.stylex.ts +23 -0
  461. package/src/privateAttributes/segmentTitle.stylex.ts +22 -0
  462. package/src/utils/browserClickWait.ts +133 -0
  463. package/src/utils/clickGuard.ts +64 -1
  464. package/src/utils/dateParser.ts +16 -0
  465. package/src/utils/focusReturn.ts +30 -0
  466. package/src/utils/interactionOverlay.stylex.ts +3 -2
  467. package/src/utils/pressFeedback.ts +19 -6
  468. package/src/utils/triggerFocus.ts +80 -0
  469. package/dist/internal/tokenizer-presentation.d.ts +0 -21
  470. package/dist/internal/tokenizer-presentation.d.ts.map +0 -1
  471. package/dist/internal/tokenizer-presentation.js +0 -21
  472. package/src/internal/tokenizer-presentation.ts +0 -25
@@ -0,0 +1,101 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file SheetConfirmation.tsx
7
+ * @input Dialog, Layout, Heading, Text, Button; caller-owned copy
8
+ * @output SheetConfirmation — the confirmation a touch sheet opens over
9
+ * itself for Clear all and for discarding a changed draft
10
+ * @position Core-internal, shared by the Tokenizer sheet and the PowerSearch
11
+ * sheets; not a public export
12
+ *
13
+ * AlertDialog fixes its purpose to form and its safe action to ghost. A touch
14
+ * sheet's confirmation allows scrim dismissal. Its two full-width large
15
+ * actions are stacked and separated: the destructive action first in reading
16
+ * order, the safe action focused first. The alert-dialog theme target stays.
17
+ */
18
+
19
+ import {useId} from 'react';
20
+ import * as stylex from '@stylexjs/stylex';
21
+ import {Button} from '../Button/Button';
22
+ import {Dialog} from '../Dialog/Dialog';
23
+ import {Heading} from '../Heading/Heading';
24
+ import {Layout} from '../Layout/Layout';
25
+ import {LayoutContent} from '../Layout/LayoutContent';
26
+ import {LayoutFooter} from '../Layout/LayoutFooter';
27
+ import {Stack} from '../Stack/Stack';
28
+ import {Text} from '../Text/Text';
29
+ import {themeProps} from '../utils/themeProps';
30
+
31
+ export interface SheetConfirmationProps {
32
+ isOpen: boolean;
33
+ onOpenChange: (isOpen: boolean) => void;
34
+ title: string;
35
+ description: string;
36
+ cancelLabel: string;
37
+ actionLabel: string;
38
+ onAction: () => void;
39
+ }
40
+
41
+ const styles = stylex.create({
42
+ action: {width: '100%'},
43
+ });
44
+
45
+ export function SheetConfirmation({
46
+ isOpen,
47
+ onOpenChange,
48
+ title,
49
+ description,
50
+ cancelLabel,
51
+ actionLabel,
52
+ onAction,
53
+ }: SheetConfirmationProps) {
54
+ const titleId = useId();
55
+ const descriptionId = useId();
56
+ return (
57
+ <Dialog
58
+ {...themeProps('alert-dialog')}
59
+ isOpen={isOpen}
60
+ onOpenChange={onOpenChange}
61
+ purpose="info"
62
+ role="alertdialog"
63
+ aria-labelledby={titleId}
64
+ aria-describedby={descriptionId}
65
+ width={400}>
66
+ <Layout
67
+ content={
68
+ <LayoutContent>
69
+ <Heading level={2} id={titleId}>
70
+ {title}
71
+ </Heading>
72
+ <Text type="body" color="secondary" id={descriptionId}>
73
+ {description}
74
+ </Text>
75
+ </LayoutContent>
76
+ }
77
+ footer={
78
+ <LayoutFooter>
79
+ <Stack direction="vertical" gap={4} hAlign="stretch">
80
+ <Button
81
+ label={actionLabel}
82
+ variant="destructive"
83
+ size="lg"
84
+ onClick={onAction}
85
+ xstyle={styles.action}
86
+ />
87
+ <Button
88
+ label={cancelLabel}
89
+ variant="secondary"
90
+ size="lg"
91
+ onClick={() => onOpenChange(false)}
92
+ data-autofocus
93
+ xstyle={styles.action}
94
+ />
95
+ </Stack>
96
+ </LayoutFooter>
97
+ }
98
+ />
99
+ </Dialog>
100
+ );
101
+ }
@@ -0,0 +1,24 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file indicatorPress.stylex.ts
5
+ * @input Uses StyleX
6
+ * @output Exports `indicatorPressScope`, the marker of a first-party
7
+ * indicator that paints its own press
8
+ * @position Internal entry for Astryx's own replacement indicators;
9
+ * CheckboxInput reads it
10
+ */
11
+
12
+ import * as stylex from '@stylexjs/stylex';
13
+
14
+ /**
15
+ * Marks a first-party replacement indicator that paints its own press, for
16
+ * a shape that CheckboxInput's rounded-square press layer would tint past,
17
+ * such as a circle. CheckboxInput leaves that layer off over an indicator
18
+ * with this marker.
19
+ *
20
+ * @internal Not public API: the touch press reaches the indicator through a
21
+ * private property.
22
+ */
23
+ export const indicatorPressScope: ReturnType<typeof stylex.defineMarker> =
24
+ stylex.defineMarker();
@@ -0,0 +1,80 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ /**
3
+ * @file sheetDraft.ts
4
+ * @input A sheet's selection at open, its draft, and the last edit made
5
+ * @output SheetDraftChange, hasSameSelection, nameSheetDraftChange — the
6
+ * rules a touch sheet's Save and dismissal share
7
+ * @position Core-internal, shared by the Tokenizer sheet and the Lab sheets
8
+ * through `internal/touch-sheet`; not a public export
9
+ *
10
+ * A touch sheet edits a draft and reports it once, on Save, with one change:
11
+ * the last edit that still holds, else the nearest net add or remove. A
12
+ * dismissal asks before discarding only while the draft differs from the
13
+ * selection at open, as a set: a row unchecked and checked again is no change.
14
+ */
15
+
16
+ interface SheetDraftItem {
17
+ id: string | number;
18
+ }
19
+
20
+ /** An edit of a sheet's draft, and the shape Save reports. */
21
+ export type SheetDraftChange<T> = {
22
+ item: T;
23
+ type: 'add' | 'create' | 'remove';
24
+ };
25
+
26
+ /** Whether two selections hold the same items, in any order. */
27
+ export function hasSameSelection<T extends SheetDraftItem>(
28
+ a: ReadonlyArray<T>,
29
+ b: ReadonlyArray<T>,
30
+ ): boolean {
31
+ if (a.length !== b.length) {
32
+ return false;
33
+ }
34
+ const ids = new Set(a.map(item => item.id));
35
+ return b.every(item => ids.has(item.id));
36
+ }
37
+
38
+ /**
39
+ * The change Save reports for a draft that differs from the selection at
40
+ * open, or `null` when nothing differs. The last edit names it when it still
41
+ * holds: its item is in the draft and was not selected at open, or was
42
+ * selected at open and is gone. Otherwise, after a removal, a `remove` names
43
+ * an item that is gone; otherwise an `add` (`create` when the last edit
44
+ * created that item) names an item that is new; otherwise a `remove` names
45
+ * an item that is gone.
46
+ */
47
+ export function nameSheetDraftChange<T extends SheetDraftItem>(
48
+ valueAtOpen: ReadonlyArray<T>,
49
+ draftValue: ReadonlyArray<T>,
50
+ lastDraftChange: SheetDraftChange<T> | null,
51
+ ): SheetDraftChange<T> | null {
52
+ const wasSelected = (id: T['id']) => valueAtOpen.some(item => item.id === id);
53
+ const isSelected = (id: T['id']) => draftValue.some(item => item.id === id);
54
+ const added = draftValue.find(item => !wasSelected(item.id));
55
+ const removed = valueAtOpen.find(item => !isSelected(item.id));
56
+ const lastChangeIsNet =
57
+ lastDraftChange != null &&
58
+ (lastDraftChange.type === 'remove'
59
+ ? wasSelected(lastDraftChange.item.id) &&
60
+ !isSelected(lastDraftChange.item.id)
61
+ : isSelected(lastDraftChange.item.id) &&
62
+ !wasSelected(lastDraftChange.item.id));
63
+ if (lastChangeIsNet) {
64
+ return lastDraftChange;
65
+ }
66
+ if (lastDraftChange?.type === 'remove' && removed != null) {
67
+ return {item: removed, type: 'remove'};
68
+ }
69
+ if (added != null) {
70
+ const type: SheetDraftChange<T>['type'] =
71
+ lastDraftChange?.item.id === added.id && lastDraftChange.type === 'create'
72
+ ? 'create'
73
+ : 'add';
74
+ return {item: added, type};
75
+ }
76
+ if (removed != null) {
77
+ return {item: removed, type: 'remove'};
78
+ }
79
+ return null;
80
+ }
@@ -0,0 +1,21 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ /**
3
+ * @file touch-sheet.ts
4
+ * @input The touch sheets' shared confirmation, search-drag dismissal and
5
+ * draft rules
6
+ * @output `@astryxdesign/core/internal/touch-sheet`: SheetConfirmation,
7
+ * useDismissSearchOnTouchDrag, hasSameSelection and nameSheetDraftChange,
8
+ * re-exported by name for Lab's sheets
9
+ * @position An internal entry reserved for Astryx's own packages:
10
+ * undocumented, outside the public API and its compatibility promise,
11
+ * versioned in lockstep with Core, and allowed only in Core and Lab by the
12
+ * `@astryx/no-core-internal-import` lint rule. Core components import the
13
+ * same modules by relative path. Named re-exports only.
14
+ *
15
+ * SYNC: When modified, update scripts/sync-exports.js.
16
+ */
17
+ export {SheetConfirmation} from './SheetConfirmation';
18
+ export type {SheetConfirmationProps} from './SheetConfirmation';
19
+ export {useDismissSearchOnTouchDrag} from './useDismissSearchOnTouchDrag';
20
+ export {hasSameSelection, nameSheetDraftChange} from './sheetDraft';
21
+ export type {SheetDraftChange} from './sheetDraft';
@@ -0,0 +1,69 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file useDismissSearchOnTouchDrag.ts
7
+ * @input Caller-owned search inputs, a focus target, and touch events from a
8
+ * separate results list
9
+ * @output useDismissSearchOnTouchDrag — touch handlers for the results list
10
+ * @position Core-internal, shared by the touch sheets; not a public export
11
+ *
12
+ * A direct vertical touch drag on the results moves focus off a focused
13
+ * search input. The on-screen keyboard then leaves and the rows come into
14
+ * view; the query stays. Focus goes to the caller's target (the sheet's
15
+ * panel), never to the page body behind an open modal. Scroll events are not
16
+ * observed: filtering can clamp scrollTop and fire scroll while someone is
17
+ * typing. Small moves, taps and multi-touch gestures leave focus alone.
18
+ */
19
+
20
+ import {useRef, type TouchEvent} from 'react';
21
+
22
+ const DRAG_THRESHOLD_PX = 8;
23
+
24
+ type SearchInput = HTMLInputElement | null | undefined;
25
+
26
+ export function useDismissSearchOnTouchDrag(
27
+ getSearchInputs: () => ReadonlyArray<SearchInput>,
28
+ getFocusTarget?: () => HTMLElement | null | undefined,
29
+ ) {
30
+ const startYRef = useRef<number | null>(null);
31
+ const reset = () => {
32
+ startYRef.current = null;
33
+ };
34
+
35
+ return {
36
+ onTouchStart: (event: TouchEvent<HTMLElement>) => {
37
+ startYRef.current =
38
+ event.touches.length === 1 ? event.touches[0].clientY : null;
39
+ },
40
+ onTouchMove: (event: TouchEvent<HTMLElement>) => {
41
+ if (event.touches.length !== 1) {
42
+ reset();
43
+ return;
44
+ }
45
+ const startY = startYRef.current;
46
+ if (
47
+ startY == null ||
48
+ Math.abs(event.touches[0].clientY - startY) < DRAG_THRESHOLD_PX
49
+ ) {
50
+ return;
51
+ }
52
+ reset();
53
+ const focusedSearch = getSearchInputs().find(
54
+ input => input != null && input === document.activeElement,
55
+ );
56
+ if (focusedSearch == null) {
57
+ return;
58
+ }
59
+ const target = getFocusTarget?.();
60
+ if (target != null) {
61
+ target.focus({preventScroll: true});
62
+ } else {
63
+ focusedSearch.blur();
64
+ }
65
+ },
66
+ onTouchEnd: reset,
67
+ onTouchCancel: reset,
68
+ };
69
+ }
@@ -219,6 +219,13 @@ Bookmarks sheet.
219
219
  | M-SG18 | iPad S1 (touch; pointer if available) | tap, hold, drag; hover | differences from iPhone | B |
220
220
  | M-SG19 | Safari showing the segmented stories vs S1 | the segmented storyboards side by side | synced recordings (parity proof) | B |
221
221
 
222
+ Done (UIKit lab, iOS 26.2 simulator, Oct 23–24 2026; in the segmented control's
223
+ own table, `uikit/segmented.ts`, tagged `measured:`): M-SG02 (the selection
224
+ spring and the drag clamp; the tracking spring is the shared
225
+ `springs.fingerTracking`; the lift was measured too and is not in the table,
226
+ since a pressed thumb's lift is a theme's) and M-SG03 (the tap's frames,
227
+ fitted per frame).
228
+
222
229
  ## Sheets (UISheetPresentationController)
223
230
 
224
231
  Probe app "SheetProbe" on an iPhone 16 Pro (iPad Pro 11" for M-SH11 / M-SH20 /
@@ -19,9 +19,11 @@ roles through `resolveMotion`.
19
19
  | `uikit/scroll.ts` | UIScrollView: deceleration rates, rubber band, bounce-back spring, `delaysContentTouches`, scroll to top. |
20
20
  | `uikit/timing.ts` | Non-spring clocks and curves: press highlight, Core Animation's named curves, keyboard, Reduced Motion cross-fade. |
21
21
  | `uikit/paging.ts` | A paging UIScrollView: the integrator that settles a release on its page, the page rule, the catch, `setContentOffset(animated:)`. |
22
+ | `uikit/alert.ts` | UIAlertController: how a finger is tracked across the actions (highlight onset and bounds). |
22
23
  | `uikit/navigation.ts` | UINavigationController: push velocity, parallax, dimming, transition clock, interactive pop finish rule. |
23
24
  | `uikit/progressBar.ts` | UIProgressView's fill: the whole-track duration and curve, its minimum length and empty alpha; the reduced-motion pulse (three roles). |
24
25
  | `uikit/gestures.ts` | Gesture recognizer thresholds, the velocity filter and haptic stand-ins, as `{value, unit}` entries (sources in JSDoc). |
26
+ | `uikit/segmented.ts` | UISegmentedControl: the selection indicator's spring; under Reduce Motion the animator's cross-fade replaces it. |
25
27
  | `uikit/switch.ts` | UISwitch on iOS 26.2: geometry, the lift, settle, travel and tracking springs, the flip distance, the track colour. |
26
28
  | `roles.ts` | The internal motion roles: the springs, durations and curves `spec:AST-094` FR4 names, registered by the shared tables, and a role's CSS form read back. |
27
29
  | `roleValue.ts` | A role's CSS form, written: a spring's duration and bounce, a duration in ms, a curve's `cubic-bezier()`. |
@@ -63,7 +65,7 @@ the timings that decide who gets a touch are not roles.
63
65
  ## Animator
64
66
 
65
67
  ```
66
- import {createAnimator} from '../motion/animator';
68
+ import {createMotionAnimator} from '../motion/animator';
67
69
  import {coast} from '../motion/coast';
68
70
  import {solveSpringTowardRamp, toSpring} from '../motion/spring';
69
71
  import {resolveMotion} from '../motion/resolveMotion';
@@ -72,7 +74,7 @@ import {registerSpringsTable, springs} from '../motion/uikit';
72
74
  // Once, so the springs are registered as their roles:
73
75
  registerSpringsTable();
74
76
 
75
- const animator = createAnimator(sheet);
77
+ const animator = createMotionAnimator(sheet);
76
78
  // The animator plays a motion role (spec:AST-094 FR4), its table value, as the
77
79
  // per-role tables stay internal (DEC-15); math on a spring reads the role with
78
80
  // resolveMotion.
@@ -137,8 +139,10 @@ await handle.finished; // true if it ran to the end, false if interrupted
137
139
  presented call's second frame) runs on over two frames, the start moves to
138
140
  the call's first read after it, with every call of that task. Everything
139
141
  the call starts shares that start
140
- (`handle.started`); a retarget keeps an explicit one, and `{at}` puts
141
- several animators on one clock. `{start: 'commit'}` lets the browser date
142
+ (`handle.started`); a retarget of a curve that still moves keeps an
143
+ explicit one, while one on a tail that already shows as at rest (within two
144
+ sample tolerances of its target, and slower than one a frame) counts as a
145
+ call from rest. `{at}` puts several animators on one clock. `{start: 'commit'}` lets the browser date
142
146
  a retarget too; `{start: 'presented'}` waits two frames, until the
143
147
  element at rest has been presented. `handle.curve(property)` is the curve
144
148
  a call plays, for a companion to follow. `{additive: true}` retargets the
@@ -167,7 +171,7 @@ await handle.finished; // true if it ran to the end, false if interrupted
167
171
  - `animatorFor(element)` returns the one animator for an element, so code
168
172
  that animates it from several places (a swipe on x, a removal on y)
169
173
  composes in one `translate` track.
170
- - `createAnimator(dialog, {pseudoElement: '::backdrop'})` drives a
174
+ - `createMotionAnimator(dialog, {pseudoElement: '::backdrop'})` drives a
171
175
  pseudo-element; with no inline style to hold it, a static filling animation
172
176
  holds its end value until the next animation replaces it, while the
173
177
  pseudo-element exists. A dialog's `::backdrop` is made again each time the
@@ -4,11 +4,12 @@
4
4
  * @file animator.ts
5
5
  * @input An element, target values, and a spring, momentum curves (coast.ts)
6
6
  * or any closed-form curve
7
- * @output Exports `createAnimator`: a compositor animator for translate,
8
- * rotate, scale and opacity, with presentation values and velocities read
9
- * from the analytic curves, velocity-preserving retargeting, freeze-in-place
10
- * `stop`, completion promises, a shared clock, and UIKit's Reduced Motion
11
- * substitution; plus its option, handle and transition types
7
+ * @output Exports `createMotionAnimator`, a compositor animator for
8
+ * translate, rotate, scale and opacity, and its option, handle and
9
+ * transition types. It reads presentation values and velocities from the
10
+ * analytic curves. It retargets with the velocity kept, freezes in place on
11
+ * `stop`, and gives completion promises, a shared clock, and UIKit's
12
+ * Reduced Motion substitution.
12
13
  * @position Motion foundation (DOM). Internal to core: components use it for
13
14
  * every touch-presentation animation; not exported from the package entry
14
15
  *
@@ -244,18 +245,18 @@ export interface AnimateOptions {
244
245
  crossfadeAs?: 'entrance' | 'exit';
245
246
  /**
246
247
  * When the call's animations start. By default a call from rest starts
247
- * when the browser commits it, and a call that continues motion on screen
248
- * (a retarget) starts now, from the value on screen. Ignored with `at`.
248
+ * when the browser commits it. A call that continues motion on screen (a
249
+ * retarget) starts now, from the value on screen. A curve whose tail
250
+ * already shows as at rest counts as rest. Ignored with `at`.
249
251
  * - `'commit'`: a call that continues motion also starts when the browser
250
- * commits it, dated by the browser rather than by the main thread, as a
251
- * call from rest is.
252
- * - `'presented'`: a call from rest leaves its element at rest and creates
253
- * its animations two frames later, once the frame that carries the
254
- * element at rest has been presented; they then start at their commit. A
255
- * busy UI process delays the motion instead of skipping into it, for two
256
- * frames more before an idle start. Any other change to the animator
257
- * before then creates the animations first, in call order. A call that
258
- * continues motion on screen (a retarget) starts now, as by default.
252
+ * commits it. The browser dates it, as it dates a call from rest.
253
+ * - `'presented'`: a call from rest leaves its element at rest. Its
254
+ * animations are created two frames later, once the frame with the
255
+ * element at rest has been presented. They then start at their commit,
256
+ * so a busy UI process delays the motion instead of skipping into it.
257
+ * Any other change to the animator before then creates the animations
258
+ * first, in call order. A call that continues motion on screen starts
259
+ * now, as by default.
259
260
  */
260
261
  start?: 'commit' | 'presented';
261
262
  /**
@@ -297,7 +298,7 @@ export interface MotionCurve {
297
298
  }
298
299
 
299
300
  /**
300
- * Options of `createAnimator`.
301
+ * Options of `createMotionAnimator`.
301
302
  */
302
303
  /** How `set` puts values in place. */
303
304
  export interface SetOptions {
@@ -652,6 +653,18 @@ const SAMPLE_TOLERANCE: Record<MotionProperty, number> = {
652
653
  /** Keyframes start on this grid (ms) and are split where the curve needs it. */
653
654
  const SAMPLE_GRID_MS = 1000 / 30;
654
655
 
656
+ /**
657
+ * A curve within this many sample tolerances of its target can show as at
658
+ * rest. A call on it then starts as one from rest does, at the browser's start.
659
+ */
660
+ const REST_DISTANCE_TOLERANCES = 2;
661
+
662
+ /**
663
+ * A curve shows as at rest only while it moves at most one `SAMPLE_TOLERANCE`
664
+ * a frame at this rate.
665
+ */
666
+ const REST_FRAMES_PER_SECOND = 60;
667
+
655
668
  /** A curve that has not settled by then (an undamped spring) snaps. */
656
669
  const MAX_DURATION_MS = 30_000;
657
670
 
@@ -803,7 +816,7 @@ export function animatorFor(
803
816
  const key = options.pseudoElement ?? '';
804
817
  let animator = byPseudo.get(key);
805
818
  if (animator == null) {
806
- animator = createAnimator(element, options);
819
+ animator = createMotionAnimator(element, options);
807
820
  byPseudo.set(key, animator);
808
821
  }
809
822
  return animator;
@@ -920,7 +933,7 @@ const REDUCED_TRANSITION: SpringTransition = {
920
933
  *
921
934
  * @example
922
935
  * ```
923
- * const animator = createAnimator(sheet);
936
+ * const animator = createMotionAnimator(sheet);
924
937
  * // finger lifts at 1200 px/s heading for the detent at 0 (a component
925
938
  * // passes the spring of its motion role):
926
939
  * animator.animate({y: 0}, {spring: {response: 0.45, dampingRatio: 0.9}, velocity: {y: 1200}});
@@ -929,7 +942,7 @@ const REDUCED_TRANSITION: SpringTransition = {
929
942
  * animator.stop(['y']);
930
943
  * ```
931
944
  */
932
- export function createAnimator(
945
+ export function createMotionAnimator(
933
946
  element: HTMLElement | null,
934
947
  options: AnimatorOptions = {},
935
948
  ): Animator {
@@ -1165,6 +1178,22 @@ export function createAnimator(
1165
1178
  return curveAt(property, time);
1166
1179
  };
1167
1180
 
1181
+ /**
1182
+ * Whether a curve's tail already shows as at rest at `time`. Under a
1183
+ * starved main thread the browser commits a call late. A call that starts
1184
+ * at its own time then skips that far into its curve. One that starts at
1185
+ * the commit holds an element that hardly moves.
1186
+ */
1187
+ const showsAtRest = (
1188
+ property: MotionProperty,
1189
+ segment: Segment,
1190
+ time: number,
1191
+ ): boolean =>
1192
+ Math.abs(valueAt(property, time) - segment.target) <=
1193
+ REST_DISTANCE_TOLERANCES * SAMPLE_TOLERANCE[property] &&
1194
+ Math.abs(velocityAt(property, time)) <=
1195
+ SAMPLE_TOLERANCE[property] * REST_FRAMES_PER_SECOND;
1196
+
1168
1197
  const velocityAt = (property: MotionProperty, time: number): number => {
1169
1198
  const held = segments.get(property);
1170
1199
  if (held != null && isHeld(held)) {
@@ -2033,10 +2062,10 @@ export function createAnimator(
2033
2062
  // -- starting from rest ---------------------------------------------------
2034
2063
 
2035
2064
  /**
2036
- * A call starts from rest when nothing on the channels it drives is moving
2037
- * (a curve still waiting for its first frame counts as rest) and nothing
2038
- * pins its clock (`at`). Returns its start group, or null for an explicit
2039
- * start.
2065
+ * A call starts from rest when nothing on the channels it drives moves on
2066
+ * screen and nothing pins its clock (`at`). A curve still waiting for its
2067
+ * first frame counts as rest, as does one whose tail already shows as at
2068
+ * rest. Returns its start group, or null for an explicit start.
2040
2069
  */
2041
2070
  const beginGroup = (
2042
2071
  time: number,
@@ -2070,10 +2099,12 @@ export function createAnimator(
2070
2099
  }
2071
2100
  return null;
2072
2101
  }
2073
- // A call that continues motion starts now unless it asks for the
2074
- // browser's start (`commit`). `presented` asks only for a call from rest:
2075
- // an element still moving is not at rest, so a retarget starts now, from
2076
- // the value and velocity on screen (spec:AST-094 FR6).
2102
+ // A call that continues motion starts now, unless it asks for the
2103
+ // browser's start (`commit`). `presented` asks only for a call from rest.
2104
+ // A curve that still moves is not at rest, so a call on it starts now,
2105
+ // from the value and velocity on screen. A tail that shows as at rest
2106
+ // counts as rest, so a call on it waits, under `presented` for its two
2107
+ // frames.
2077
2108
  for (const channel of start === 'commit' ? [] : channels) {
2078
2109
  for (const property of CHANNELS[channel]) {
2079
2110
  const segment = segments.get(property);
@@ -2084,7 +2115,8 @@ export function createAnimator(
2084
2115
  time < endOf(property, segment) &&
2085
2116
  (segment.group == null ||
2086
2117
  segment.group.resolved ||
2087
- shownSince(property, segment) != null)
2118
+ shownSince(property, segment) != null) &&
2119
+ !showsAtRest(property, segment, time)
2088
2120
  ) {
2089
2121
  return null;
2090
2122
  }
@@ -4,7 +4,7 @@
4
4
  * @file reducedMotion.ts
5
5
  * @input The Reduced Motion preference, the primary pointer, the motion tables
6
6
  * @output reducedMotionFade (the fade the animator would play, for motion it
7
- * does not drive) and the two media queries a StyleX transition spells
7
+ * does not drive), playReducedMotionDip, and the queries a transition spells
8
8
  * @position The one Reduced Motion policy (design:reduced-motion) for code
9
9
  * beside the animator: a raw Web Animations fade, a CSS transition
10
10
  *
@@ -102,3 +102,81 @@ export function reducedMotionFade(
102
102
  easing: `cubic-bezier(${curve.join(', ')})`,
103
103
  };
104
104
  }
105
+
106
+ /** A running Reduced Motion dip. */
107
+ export interface ReducedMotionDip {
108
+ /** Stops the dip. A change that has not landed yet never lands. */
109
+ cancel(): void;
110
+ }
111
+
112
+ /**
113
+ * Plays `fade` on `element` as a dip, and runs `land` at its middle: the
114
+ * fade-out, the change, then the fade-in. The fade-out holds at 0 until `land`
115
+ * has run, and the fade-in starts only after it. So the change never shows at
116
+ * full opacity, however late the main thread runs. A timer at the middle can
117
+ * fire after the fade-in has begun.
118
+ *
119
+ * `land` must apply the change before it returns: the fade-in starts right
120
+ * after it. `from` is the opacity the fade-out starts at: a leaving element
121
+ * fades out from where it is.
122
+ *
123
+ * @example
124
+ * ```
125
+ * const dip = playReducedMotionDip(scroller, fade, () => scroller.scrollTo({top}));
126
+ * // A newer change replaces it:
127
+ * dip.cancel();
128
+ * ```
129
+ */
130
+ export function playReducedMotionDip(
131
+ element: Element,
132
+ fade: ReducedMotionFade,
133
+ land: () => void,
134
+ from = 1,
135
+ ): ReducedMotionDip {
136
+ const half = fade.duration / 2;
137
+ let isCancelled = false;
138
+ let fadeIn: Animation | null = null;
139
+ const fadeOut = element.animate(
140
+ [{opacity: from, easing: fade.easing}, {opacity: 0}],
141
+ {duration: half, fill: 'forwards'},
142
+ );
143
+ fadeOut.finished.then(
144
+ () => {
145
+ if (isCancelled) {
146
+ return;
147
+ }
148
+ land();
149
+ // The fade-in holds 0 until it starts: after a long stall, its start can
150
+ // come after the frame that runs this.
151
+ fadeIn = element.animate(
152
+ [{opacity: 0, easing: fade.easing}, {opacity: 1}],
153
+ {duration: half, fill: 'backwards'},
154
+ );
155
+ // The fade-in keeps the dip's own schedule: it starts where the fade-out
156
+ // ended, so the dip keeps its length. The clock is read after the
157
+ // landing, because a frame's timestamp does not count the landing's own
158
+ // work. After a long stall, half of the fade-in still plays.
159
+ const fadeOutEnd = endTime(fadeOut, half);
160
+ if (fadeOutEnd != null) {
161
+ fadeIn.startTime = Math.max(fadeOutEnd, performance.now() - half / 2);
162
+ }
163
+ // The fade-in now holds the opacity, so the held 0 can go.
164
+ fadeOut.cancel();
165
+ },
166
+ // A cancelled fade-out rejects `finished`: nothing lands.
167
+ () => {},
168
+ );
169
+ return {
170
+ cancel() {
171
+ isCancelled = true;
172
+ fadeOut.cancel();
173
+ fadeIn?.cancel();
174
+ },
175
+ };
176
+ }
177
+
178
+ /** When `animation` was due to end, on its timeline (ms), if it has started. */
179
+ function endTime(animation: Animation, duration: number): number | null {
180
+ const start = animation.startTime;
181
+ return typeof start === 'number' ? start + duration : null;
182
+ }
@@ -5,7 +5,8 @@
5
5
  * @input The motion tables (motion/uikit and each component's own table)
6
6
  * @output registerMotionTable, motionRoleOf, motionRoleIn, listMotionRoles,
7
7
  * motionRoleVariable, and the CSS form of a role's value
8
- * (formatMotionRoleValue, parseMotionRoleValue)
8
+ * (formatMotionRoleValue, parseMotionRoleValue), and parseCssEasing for a
9
+ * CSS transition's easing
9
10
  * @position Motion foundation, internal to core: read by the code that
10
11
  * resolves a role when a motion starts. No public API writes a role: touch
11
12
  * motion stays internal until the public motion-token set is decided.
@@ -260,3 +261,21 @@ export function parseMotionRoleValue(
260
261
  ? points
261
262
  : null;
262
263
  }
264
+
265
+ /** The CSS easing keywords, as the control points CSS gives them. */
266
+ const EASING_KEYWORDS: Readonly<Record<string, MotionCurvePoints>> = {
267
+ linear: [0, 0, 1, 1],
268
+ ease: [0.25, 0.1, 0.25, 1],
269
+ 'ease-in': [0.42, 0, 1, 1],
270
+ 'ease-out': [0, 0, 0.58, 1],
271
+ 'ease-in-out': [0.42, 0, 0.58, 1],
272
+ };
273
+
274
+ /**
275
+ * Reads a CSS easing, a keyword or a `cubic-bezier()`, as a curve role's value
276
+ * is read. Returns null for any other easing, such as `steps()`.
277
+ */
278
+ export function parseCssEasing(text: string): MotionCurvePoints | null {
279
+ const value = text.trim();
280
+ return EASING_KEYWORDS[value] ?? parseMotionRoleValue('curve', value);
281
+ }