@astryxdesign/core 0.7.5 → 0.7.6-canary.00507ba

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 (595) hide show
  1. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  2. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  3. package/dist/AlertDialog/AlertDialog.js +5 -5
  4. package/dist/AppShell/AppShell.d.ts.map +1 -1
  5. package/dist/AppShell/AppShell.js +183 -5
  6. package/dist/AppShell/observeMainOverflow.d.ts +9 -0
  7. package/dist/AppShell/observeMainOverflow.d.ts.map +1 -0
  8. package/dist/AppShell/observeMainOverflow.js +125 -0
  9. package/dist/Avatar/Avatar.d.ts.map +1 -1
  10. package/dist/Avatar/Avatar.js +12 -3
  11. package/dist/Badge/Badge.d.ts.map +1 -1
  12. package/dist/Badge/Badge.js +7 -1
  13. package/dist/BottomSheet/BottomSheet.js +1 -1
  14. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  15. package/dist/BottomSheet/BottomSheetPanel.js +2 -1
  16. package/dist/BottomSheet/useSheetGestures.d.ts +12 -0
  17. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  18. package/dist/BottomSheet/useSheetGestures.js +30 -3
  19. package/dist/Button/Button.js +4 -4
  20. package/dist/Carousel/Carousel.d.ts +3 -1
  21. package/dist/Carousel/Carousel.d.ts.map +1 -1
  22. package/dist/Carousel/Carousel.js +12 -3
  23. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  24. package/dist/CheckboxInput/CheckboxInput.js +6 -5
  25. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  26. package/dist/ClickableCard/ClickableCard.js +37 -4
  27. package/dist/DateInput/DateInput.d.ts.map +1 -1
  28. package/dist/DateInput/DateInput.js +12 -4
  29. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  30. package/dist/DateInput/MonthScroller.js +101 -15
  31. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  32. package/dist/DateInput/TouchDateField.js +8 -3
  33. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  34. package/dist/DateRangeInput/DateRangeInput.js +1 -1
  35. package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
  36. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  37. package/dist/DateTimeInput/DateTimeInput.js +23 -12
  38. package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
  39. package/dist/DateTimeInput/NativeTimeSegment.js +5 -4
  40. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  41. package/dist/DateTimeInput/TouchDateTimeField.js +4 -3
  42. package/dist/Dialog/Dialog.d.ts.map +1 -1
  43. package/dist/Dialog/Dialog.js +34 -9
  44. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  45. package/dist/Dialog/DialogHeader.js +5 -4
  46. package/dist/Divider/Divider.d.ts.map +1 -1
  47. package/dist/Divider/Divider.js +2 -1
  48. package/dist/Drawer/Drawer.d.ts +1 -0
  49. package/dist/Drawer/Drawer.d.ts.map +1 -1
  50. package/dist/Drawer/Drawer.js +7 -2
  51. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  52. package/dist/DropdownMenu/DropdownMenu.js +7 -3
  53. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
  54. package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
  55. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +20 -2
  56. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
  57. package/dist/DropdownMenu/lazyMenuBottomSheet.js +31 -3
  58. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  59. package/dist/DropdownMenu/renderDropdownItems.js +21 -16
  60. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  61. package/dist/EmptyState/EmptyState.js +2 -1
  62. package/dist/Field/FieldLabel.d.ts +1 -1
  63. package/dist/Field/FieldLabel.d.ts.map +1 -1
  64. package/dist/Field/FieldLabel.js +4 -4
  65. package/dist/Field/InputClearButton.js +3 -3
  66. package/dist/Field/PanelSearchInput.js +2 -2
  67. package/dist/FieldStatus/FieldStatus.js +2 -2
  68. package/dist/FileInput/FileInput.d.ts.map +1 -1
  69. package/dist/FileInput/FileInput.js +7 -1
  70. package/dist/Heading/Heading.js +1 -1
  71. package/dist/Icon/Icon.js +1 -1
  72. package/dist/Indicator/CheckIndicator.d.ts.map +1 -1
  73. package/dist/Indicator/CheckIndicator.js +2 -1
  74. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  75. package/dist/Indicator/CheckboxIndicator.js +3 -1
  76. package/dist/Indicator/RadioIndicator.d.ts.map +1 -1
  77. package/dist/Indicator/RadioIndicator.js +3 -1
  78. package/dist/Item/Item.d.ts.map +1 -1
  79. package/dist/Item/Item.js +2 -1
  80. package/dist/Item/ItemSwipeLayer.js +1 -1
  81. package/dist/Layer/popoverOperations.d.ts +27 -0
  82. package/dist/Layer/popoverOperations.d.ts.map +1 -0
  83. package/dist/Layer/popoverOperations.js +159 -0
  84. package/dist/Layer/useLayer.d.ts +1 -1
  85. package/dist/Layer/useLayer.d.ts.map +1 -1
  86. package/dist/Layer/useLayer.js +93 -59
  87. package/dist/Layout/Layout.js +1 -1
  88. package/dist/Layout/LayoutContent.js +1 -1
  89. package/dist/Layout/LayoutFooter.js +1 -1
  90. package/dist/Layout/LayoutHeader.js +1 -1
  91. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  92. package/dist/Lightbox/Lightbox.js +5 -0
  93. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +5 -4
  94. package/dist/List/List.js +1 -1
  95. package/dist/List/ListItem.js +3 -3
  96. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  97. package/dist/MobileNav/MobileNav.js +7 -2
  98. package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +7 -6
  99. package/dist/MultiSelector/MultiSelector.d.ts +1 -1
  100. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  101. package/dist/MultiSelector/MultiSelector.js +26 -10
  102. package/dist/NumberInput/NumberInput.d.ts +3 -1
  103. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  104. package/dist/NumberInput/NumberInput.js +3 -3
  105. package/dist/NumberInput/numberParser.d.ts +3 -0
  106. package/dist/NumberInput/numberParser.d.ts.map +1 -1
  107. package/dist/NumberInput/numberParser.js +7 -44
  108. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  109. package/dist/ProgressBar/ProgressBar.js +16 -12
  110. package/dist/Resizable/useResizable.d.ts.map +1 -1
  111. package/dist/Resizable/useResizable.js +28 -2
  112. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  113. package/dist/SegmentedControl/SegmentedControlItem.js +4 -1
  114. package/dist/Selector/useSelectorPresentation.d.ts +8 -1
  115. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
  116. package/dist/Selector/useSelectorPresentation.js +20 -4
  117. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  118. package/dist/Skeleton/Skeleton.js +1 -1
  119. package/dist/Slider/Slider.d.ts.map +1 -1
  120. package/dist/Slider/Slider.js +10 -2
  121. package/dist/Spinner/Spinner.d.ts.map +1 -1
  122. package/dist/Spinner/Spinner.js +3 -3
  123. package/dist/Stack/Stack.js +1 -1
  124. package/dist/Stack/StackItem.js +1 -1
  125. package/dist/TabList/TabList.d.ts.map +1 -1
  126. package/dist/TabList/TabList.js +16 -1
  127. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  128. package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
  129. package/dist/Text/Text.js +1 -1
  130. package/dist/Text/useTruncation.d.ts.map +1 -1
  131. package/dist/Text/useTruncation.js +23 -5
  132. package/dist/TextArea/TextArea.d.ts +1 -1
  133. package/dist/TextArea/TextArea.d.ts.map +1 -1
  134. package/dist/TextArea/TextArea.js +13 -2
  135. package/dist/TextInput/TextInput.d.ts.map +1 -1
  136. package/dist/TextInput/TextInput.js +3 -3
  137. package/dist/TimeInput/TimeInput.d.ts +6 -2
  138. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  139. package/dist/TimeInput/TimeInput.js +21 -14
  140. package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
  141. package/dist/TimeInput/TouchTimeField.js +5 -4
  142. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  143. package/dist/Timestamp/Timestamp.js +2 -2
  144. package/dist/Timestamp/TimestampHoverCard.js +4 -4
  145. package/dist/Toast/Toast.d.ts.map +1 -1
  146. package/dist/Toast/Toast.js +60 -20
  147. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  148. package/dist/Toast/ToastViewport.js +82 -51
  149. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  150. package/dist/Tokenizer/Tokenizer.js +13 -2
  151. package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
  152. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  153. package/dist/Toolbar/Toolbar.js +2 -1
  154. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  155. package/dist/TopNav/TopNavMegaMenu.js +3 -0
  156. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  157. package/dist/TopNav/TopNavMenu.js +1 -0
  158. package/dist/Typeahead/Typeahead.d.ts +1 -1
  159. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  160. package/dist/Typeahead/Typeahead.js +9 -1
  161. package/dist/astryx.css +21 -4
  162. package/dist/gestures/GestureArena.d.ts +6 -0
  163. package/dist/gestures/GestureArena.d.ts.map +1 -1
  164. package/dist/gestures/GestureArena.js +39 -0
  165. package/dist/gestures/GestureHost.d.ts +352 -0
  166. package/dist/gestures/GestureHost.d.ts.map +1 -0
  167. package/dist/gestures/GestureHost.js +1773 -0
  168. package/dist/gestures/GestureRecognizer.d.ts +10 -0
  169. package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
  170. package/dist/gestures/GestureRecognizer.js +16 -0
  171. package/dist/gestures/LongPressGestureRecognizer.d.ts +1 -0
  172. package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -1
  173. package/dist/gestures/LongPressGestureRecognizer.js +3 -0
  174. package/dist/gestures/PanGestureRecognizer.d.ts +1 -0
  175. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  176. package/dist/gestures/PanGestureRecognizer.js +3 -0
  177. package/dist/gestures/PinchGestureRecognizer.d.ts +31 -0
  178. package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -0
  179. package/dist/gestures/PinchGestureRecognizer.js +128 -0
  180. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +71 -0
  181. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -0
  182. package/dist/gestures/ScreenEdgePanGestureRecognizer.js +223 -0
  183. package/dist/gestures/SwipeGestureRecognizer.d.ts +37 -0
  184. package/dist/gestures/SwipeGestureRecognizer.d.ts.map +1 -0
  185. package/dist/gestures/SwipeGestureRecognizer.js +148 -0
  186. package/dist/gestures/TapGestureRecognizer.d.ts +1 -0
  187. package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -1
  188. package/dist/gestures/TapGestureRecognizer.js +3 -0
  189. package/dist/gestures/VelocityTracker.d.ts +6 -2
  190. package/dist/gestures/VelocityTracker.d.ts.map +1 -1
  191. package/dist/gestures/VelocityTracker.js +7 -3
  192. package/dist/gestures/haptics.d.ts +65 -0
  193. package/dist/gestures/haptics.d.ts.map +1 -0
  194. package/dist/gestures/haptics.js +182 -0
  195. package/dist/gestures/nativeScroll.d.ts +42 -0
  196. package/dist/gestures/nativeScroll.d.ts.map +1 -0
  197. package/dist/gestures/nativeScroll.js +228 -0
  198. package/dist/gestures/touchAction.d.ts +60 -0
  199. package/dist/gestures/touchAction.d.ts.map +1 -0
  200. package/dist/gestures/touchAction.js +157 -0
  201. package/dist/gestures/touchActionRule.d.ts +34 -0
  202. package/dist/gestures/touchActionRule.d.ts.map +1 -0
  203. package/dist/gestures/touchActionRule.js +140 -0
  204. package/dist/gestures/types.d.ts +18 -7
  205. package/dist/gestures/types.d.ts.map +1 -1
  206. package/dist/gestures/types.js +22 -2
  207. package/dist/hooks/index.d.ts +1 -1
  208. package/dist/hooks/index.d.ts.map +1 -1
  209. package/dist/hooks/modalAnnounce.d.ts.map +1 -1
  210. package/dist/hooks/modalAnnounce.js +107 -61
  211. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -1
  212. package/dist/hooks/scrollKeyboardDelegation.js +7 -3
  213. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
  214. package/dist/hooks/useAdaptivePresentation.js +4 -1
  215. package/dist/hooks/useAnnounce.d.ts +101 -42
  216. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  217. package/dist/hooks/useAnnounce.js +161 -75
  218. package/dist/hooks/useAnnounceRenderedText.d.ts +11 -3
  219. package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
  220. package/dist/hooks/useAnnounceRenderedText.js +5 -3
  221. package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
  222. package/dist/hooks/useBusyAnnouncement.js +6 -12
  223. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  224. package/dist/hooks/useMenuHover.js +12 -1
  225. package/dist/hooks/useScrollOverflow.d.ts +2 -1
  226. package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
  227. package/dist/hooks/useScrollOverflow.js +56 -10
  228. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  229. package/dist/i18n/generated-locales/en.generated.js +6 -0
  230. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  231. package/dist/i18n/generated-locales/pseudo.generated.js +6 -0
  232. package/dist/motion/animator.d.ts +7 -1
  233. package/dist/motion/animator.d.ts.map +1 -1
  234. package/dist/motion/animator.js +119 -27
  235. package/dist/theme/defineTheme.d.ts +19 -5
  236. package/dist/theme/defineTheme.d.ts.map +1 -1
  237. package/dist/theme/defineTheme.js +64 -4
  238. package/dist/theme/domainTokens/domainTokenDefaults.d.ts +3 -0
  239. package/dist/theme/domainTokens/domainTokenDefaults.d.ts.map +1 -0
  240. package/dist/theme/domainTokens/domainTokenDefaults.js +19 -0
  241. package/dist/theme/domainTokens/index.d.ts +5 -4
  242. package/dist/theme/domainTokens/index.d.ts.map +1 -1
  243. package/dist/theme/domainTokens/index.js +5 -9
  244. package/dist/theme/index.d.ts +1 -0
  245. package/dist/theme/index.d.ts.map +1 -1
  246. package/dist/theme/motionKnobs.d.ts +56 -0
  247. package/dist/theme/motionKnobs.d.ts.map +1 -0
  248. package/dist/theme/motionKnobs.js +48 -0
  249. package/dist/theme/resolveThemeValues.d.ts +11 -4
  250. package/dist/theme/resolveThemeValues.d.ts.map +1 -1
  251. package/dist/theme/resolveThemeValues.js +40 -4
  252. package/dist/theme/themeAdaptations.d.ts +7 -3
  253. package/dist/theme/themeAdaptations.d.ts.map +1 -1
  254. package/dist/theme/themeAdaptations.js +36 -7
  255. package/dist/theme/themeMotion.d.ts +96 -0
  256. package/dist/theme/themeMotion.d.ts.map +1 -0
  257. package/dist/theme/themeMotion.js +177 -0
  258. package/dist/theme/tokenReferences.d.ts +31 -0
  259. package/dist/theme/tokenReferences.d.ts.map +1 -0
  260. package/dist/theme/tokenReferences.js +132 -0
  261. package/dist/theme/tokens.d.ts +1 -0
  262. package/dist/theme/tokens.d.ts.map +1 -1
  263. package/dist/theme/tokens.js +9 -129
  264. package/dist/theme/tokens.stylex.d.ts +12 -0
  265. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  266. package/dist/theme/tokens.stylex.js +12 -0
  267. package/dist/utils/focusReturn.d.ts +17 -1
  268. package/dist/utils/focusReturn.d.ts.map +1 -1
  269. package/dist/utils/focusReturn.js +11 -4
  270. package/dist/utils/getNodeText.d.ts +8 -0
  271. package/dist/utils/getNodeText.d.ts.map +1 -0
  272. package/dist/utils/getNodeText.js +37 -0
  273. package/dist/utils/interactionModality.d.ts +11 -2
  274. package/dist/utils/interactionModality.d.ts.map +1 -1
  275. package/dist/utils/interactionModality.js +58 -5
  276. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  277. package/dist/utils/interactionOverlay.stylex.js +17 -8
  278. package/dist/utils/plainDate.d.ts +2 -0
  279. package/dist/utils/plainDate.d.ts.map +1 -1
  280. package/dist/utils/plainDate.js +46 -3
  281. package/dist/utils/presentation.d.ts +50 -0
  282. package/dist/utils/presentation.d.ts.map +1 -0
  283. package/dist/utils/presentation.js +125 -0
  284. package/dist/utils/pressFeedback.d.ts.map +1 -1
  285. package/dist/utils/pressFeedback.js +20 -1
  286. package/dist/utils/primaryClick.d.ts +11 -0
  287. package/dist/utils/primaryClick.d.ts.map +1 -0
  288. package/dist/utils/primaryClick.js +25 -0
  289. package/dist/utils/sharedMutationObserver.d.ts +19 -11
  290. package/dist/utils/sharedMutationObserver.d.ts.map +1 -1
  291. package/dist/utils/sharedMutationObserver.js +66 -26
  292. package/dist/utils/timeFormat.d.ts +47 -0
  293. package/dist/utils/timeFormat.d.ts.map +1 -0
  294. package/dist/utils/timeFormat.js +240 -0
  295. package/dist/utils/touchPresentation.d.ts.map +1 -1
  296. package/dist/utils/touchPresentation.js +5 -3
  297. package/dist/utils/touchPresentation.stylex.d.ts +15 -0
  298. package/dist/utils/touchPresentation.stylex.d.ts.map +1 -0
  299. package/dist/utils/touchPresentation.stylex.js +33 -0
  300. package/dist/utils/unicodeDigits.d.ts +20 -0
  301. package/dist/utils/unicodeDigits.d.ts.map +1 -0
  302. package/dist/utils/unicodeDigits.js +70 -0
  303. package/locales/en.json +27 -3
  304. package/locales/pseudo.json +18 -0
  305. package/package.json +5 -4
  306. package/src/AlertDialog/AlertDialog.tsx +6 -5
  307. package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +18 -6
  308. package/src/AppShell/AppShell.doc.mjs +1 -1
  309. package/src/AppShell/AppShell.spec.md +9 -12
  310. package/src/AppShell/AppShell.test.tsx +164 -2
  311. package/src/AppShell/AppShell.tsx +225 -5
  312. package/src/AppShell/__tests__/AppShellMainKeyboard.a11y.browser.spec.ts +534 -0
  313. package/src/AppShell/observeMainOverflow.test.ts +173 -0
  314. package/src/AppShell/observeMainOverflow.ts +143 -0
  315. package/src/Avatar/Avatar.spec.md +22 -22
  316. package/src/Avatar/Avatar.tsx +18 -1
  317. package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +126 -0
  318. package/src/Badge/Badge.doc.mjs +1 -1
  319. package/src/Badge/Badge.tsx +19 -2
  320. package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +260 -0
  321. package/src/BottomSheet/BottomSheet.test.tsx +46 -0
  322. package/src/BottomSheet/BottomSheet.tsx +1 -1
  323. package/src/BottomSheet/BottomSheetPanel.tsx +2 -1
  324. package/src/BottomSheet/useSheetGestures.test.ts +52 -0
  325. package/src/BottomSheet/useSheetGestures.ts +37 -6
  326. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +18 -6
  327. package/src/Button/Button.tsx +4 -4
  328. package/src/Calendar/Calendar.spec.md +87 -48
  329. package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +21 -7
  330. package/src/Carousel/Carousel.doc.mjs +1 -1
  331. package/src/Carousel/Carousel.spec.md +9 -9
  332. package/src/Carousel/Carousel.test.tsx +124 -3
  333. package/src/Carousel/Carousel.tsx +10 -2
  334. package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
  335. package/src/Carousel/__tests__/Carousel.a11y.known-failures.ts +1 -16
  336. package/src/Chat/ChatComposerTokenElement.spec.md +45 -33
  337. package/src/CheckboxInput/CheckboxInput.tsx +6 -5
  338. package/src/ClickableCard/ClickableCard.test.tsx +96 -0
  339. package/src/ClickableCard/ClickableCard.tsx +48 -4
  340. package/src/Collapsible/Collapsible.spec.md +2 -0
  341. package/src/Collapsible/CollapsibleGroup.spec.md +57 -29
  342. package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +18 -7
  343. package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +18 -6
  344. package/src/ComplexSelector/ComplexSelector.test.tsx +37 -0
  345. package/src/ContextMenu/ContextMenu.test.tsx +35 -0
  346. package/src/DateInput/DateInput.test.tsx +115 -3
  347. package/src/DateInput/DateInput.tsx +29 -14
  348. package/src/DateInput/DateInputTouch.test.tsx +76 -0
  349. package/src/DateInput/MonthScroller.tsx +106 -20
  350. package/src/DateInput/MonthScrollerSettle.test.tsx +165 -0
  351. package/src/DateInput/TouchDateField.tsx +14 -3
  352. package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
  353. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -3
  354. package/src/DateRangeInput/DateRangeInput.tsx +16 -12
  355. package/src/DateTimeInput/DateTimeInput.doc.mjs +10 -8
  356. package/src/DateTimeInput/DateTimeInput.spec.md +75 -51
  357. package/src/DateTimeInput/DateTimeInput.test.tsx +81 -0
  358. package/src/DateTimeInput/DateTimeInput.tsx +46 -24
  359. package/src/DateTimeInput/NativeTimeSegment.tsx +4 -6
  360. package/src/DateTimeInput/TouchDateTimeField.tsx +3 -7
  361. package/src/Dialog/Dialog.test.tsx +216 -2
  362. package/src/Dialog/Dialog.tsx +42 -9
  363. package/src/Dialog/DialogHeader.tsx +5 -4
  364. package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +202 -0
  365. package/src/Divider/Divider.tsx +2 -1
  366. package/src/Drawer/Drawer.spec.md +111 -80
  367. package/src/Drawer/Drawer.test.tsx +35 -0
  368. package/src/Drawer/Drawer.tsx +13 -2
  369. package/src/Drawer/DrawerHeader.spec.md +181 -0
  370. package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +267 -0
  371. package/src/DropdownMenu/DropdownMenu.test.tsx +41 -0
  372. package/src/DropdownMenu/DropdownMenu.tsx +10 -3
  373. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +34 -0
  374. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -5
  375. package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +19 -7
  376. package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +21 -9
  377. package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +60 -0
  378. package/src/DropdownMenu/lazyMenuBottomSheet.ts +36 -7
  379. package/src/DropdownMenu/renderDropdownItems.tsx +24 -19
  380. package/src/EmptyState/EmptyState.tsx +2 -1
  381. package/src/Field/FieldLabel.tsx +5 -4
  382. package/src/Field/InputClearButton.tsx +3 -3
  383. package/src/Field/PanelSearchInput.tsx +2 -2
  384. package/src/FieldStatus/FieldStatus.tsx +2 -2
  385. package/src/FileInput/FileInput.test.tsx +21 -0
  386. package/src/FileInput/FileInput.tsx +4 -1
  387. package/src/FormLayout/FormLayout.spec.md +7 -8
  388. package/src/Heading/Heading.tsx +1 -1
  389. package/src/Icon/Icon.tsx +1 -1
  390. package/src/Indicator/CheckIndicator.spec.md +47 -42
  391. package/src/Indicator/CheckIndicator.tsx +2 -1
  392. package/src/Indicator/CheckboxIndicator.spec.md +40 -37
  393. package/src/Indicator/CheckboxIndicator.tsx +3 -1
  394. package/src/Indicator/Indicator.spec.md +188 -0
  395. package/src/Indicator/RadioIndicator.tsx +3 -1
  396. package/src/Item/Item.tsx +2 -1
  397. package/src/Item/ItemSwipeLayer.tsx +1 -1
  398. package/src/Kbd/Kbd.spec.md +81 -38
  399. package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +126 -0
  400. package/src/Layer/popoverOperations.test.ts +205 -0
  401. package/src/Layer/popoverOperations.ts +172 -0
  402. package/src/Layer/useLayer.test.tsx +348 -1
  403. package/src/Layer/useLayer.tsx +118 -71
  404. package/src/Layout/Layout.spec.md +127 -131
  405. package/src/Layout/Layout.tsx +1 -1
  406. package/src/Layout/LayoutContent.spec.md +205 -0
  407. package/src/Layout/LayoutContent.tsx +1 -1
  408. package/src/Layout/LayoutFooter.spec.md +190 -0
  409. package/src/Layout/LayoutFooter.tsx +1 -1
  410. package/src/Layout/LayoutHeader.spec.md +193 -0
  411. package/src/Layout/LayoutHeader.tsx +1 -1
  412. package/src/Layout/LayoutPanel.spec.md +194 -0
  413. package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +18 -6
  414. package/src/Lightbox/Lightbox.test.tsx +18 -0
  415. package/src/Lightbox/Lightbox.tsx +5 -0
  416. package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +8 -4
  417. package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
  418. package/src/List/List.tsx +1 -1
  419. package/src/List/ListItem.spec.md +205 -0
  420. package/src/List/ListItem.tsx +3 -3
  421. package/src/MetadataList/MetadataList.spec.md +187 -0
  422. package/src/MetadataList/MetadataListItem.spec.md +165 -0
  423. package/src/MobileNav/MobileNav.test.tsx +15 -0
  424. package/src/MobileNav/MobileNav.tsx +9 -1
  425. package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +89 -0
  426. package/src/MoreMenu/MoreMenu.test.tsx +11 -0
  427. package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +7 -8
  428. package/src/MultiSelector/MultiSelector.spec.md +7 -4
  429. package/src/MultiSelector/MultiSelector.test.tsx +270 -1
  430. package/src/MultiSelector/MultiSelector.tsx +25 -10
  431. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +8 -1
  432. package/src/NavMenu/NavHeadingMenu.spec.md +1 -5
  433. package/src/NumberInput/NumberInput.doc.mjs +13 -7
  434. package/src/NumberInput/NumberInput.spec.md +59 -37
  435. package/src/NumberInput/NumberInput.tsx +13 -3
  436. package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
  437. package/src/NumberInput/numberParser.ts +7 -45
  438. package/src/ProgressBar/ProgressBar.test.tsx +108 -32
  439. package/src/ProgressBar/ProgressBar.tsx +58 -10
  440. package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +21 -9
  441. package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +831 -0
  442. package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +21 -14
  443. package/src/Resizable/useResizable.test.ts +43 -0
  444. package/src/Resizable/useResizable.ts +32 -9
  445. package/src/SegmentedControl/SegmentedControl.test.tsx +84 -0
  446. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -5
  447. package/src/Selector/Selector.test.tsx +90 -1
  448. package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +8 -1
  449. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +8 -1
  450. package/src/Selector/useSelectorPresentation.ts +31 -3
  451. package/src/SideNav/SideNav.test.tsx +27 -0
  452. package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +176 -51
  453. package/src/Skeleton/Skeleton.tsx +3 -1
  454. package/src/Slider/Slider.test.tsx +31 -0
  455. package/src/Slider/Slider.tsx +8 -3
  456. package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
  457. package/src/Spinner/Spinner.tsx +5 -3
  458. package/src/Stack/Stack.tsx +1 -1
  459. package/src/Stack/StackItem.tsx +1 -1
  460. package/src/TabList/TabList.test.tsx +58 -4
  461. package/src/TabList/TabList.tsx +16 -1
  462. package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +163 -0
  463. package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
  464. package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
  465. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
  466. package/src/Text/Text.tsx +1 -1
  467. package/src/Text/useTruncation.test.tsx +128 -1
  468. package/src/Text/useTruncation.ts +23 -5
  469. package/src/TextArea/TextArea.spec.md +10 -13
  470. package/src/TextArea/TextArea.test.tsx +60 -0
  471. package/src/TextArea/TextArea.tsx +15 -1
  472. package/src/TextInput/TextInput.test.tsx +21 -0
  473. package/src/TextInput/TextInput.tsx +3 -1
  474. package/src/TimeInput/NativeTimeInput.test.tsx +17 -0
  475. package/src/TimeInput/Presentation.test.tsx +21 -0
  476. package/src/TimeInput/TimeInput.doc.mjs +8 -8
  477. package/src/TimeInput/TimeInput.spec.md +45 -48
  478. package/src/TimeInput/TimeInput.test.tsx +76 -0
  479. package/src/TimeInput/TimeInput.tsx +36 -18
  480. package/src/TimeInput/TouchTimeField.tsx +4 -6
  481. package/src/Timestamp/Timestamp.spec.md +6 -12
  482. package/src/Timestamp/Timestamp.test.tsx +30 -5
  483. package/src/Timestamp/Timestamp.tsx +6 -2
  484. package/src/Timestamp/TimestampHoverCard.tsx +4 -4
  485. package/src/Toast/Toast.spec.md +14 -20
  486. package/src/Toast/Toast.tsx +104 -36
  487. package/src/Toast/ToastViewport.test.tsx +719 -1
  488. package/src/Toast/ToastViewport.tsx +100 -50
  489. package/src/Tokenizer/Tokenizer.spec.md +5 -3
  490. package/src/Tokenizer/Tokenizer.test.tsx +68 -0
  491. package/src/Tokenizer/Tokenizer.tsx +14 -2
  492. package/src/Tokenizer/TokenizerBottomSheet.test.tsx +15 -4
  493. package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
  494. package/src/Toolbar/Toolbar.spec.md +5 -6
  495. package/src/Toolbar/Toolbar.test.tsx +30 -0
  496. package/src/Toolbar/Toolbar.tsx +2 -1
  497. package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +18 -6
  498. package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +18 -7
  499. package/src/TopNav/TopNav.test.tsx +27 -0
  500. package/src/TopNav/TopNavMegaMenu.test.tsx +21 -0
  501. package/src/TopNav/TopNavMegaMenu.tsx +4 -1
  502. package/src/TopNav/TopNavMenu.test.tsx +17 -0
  503. package/src/TopNav/TopNavMenu.tsx +1 -0
  504. package/src/Typeahead/Typeahead.test.tsx +40 -0
  505. package/src/Typeahead/Typeahead.tsx +12 -1
  506. package/src/__tests__/pressState.ts +8 -4
  507. package/src/gestures/GestureArena.ts +35 -0
  508. package/src/gestures/GestureHost.ts +2065 -0
  509. package/src/gestures/GestureRecognizer.ts +18 -0
  510. package/src/gestures/LongPressGestureRecognizer.ts +4 -0
  511. package/src/gestures/PanGestureRecognizer.ts +4 -0
  512. package/src/gestures/PinchGestureRecognizer.ts +148 -0
  513. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +256 -0
  514. package/src/gestures/SwipeGestureRecognizer.ts +197 -0
  515. package/src/gestures/TapGestureRecognizer.ts +4 -0
  516. package/src/gestures/VelocityTracker.ts +10 -3
  517. package/src/gestures/__tests__/GestureHost.test.ts +2087 -0
  518. package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
  519. package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
  520. package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +498 -0
  521. package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +108 -0
  522. package/src/gestures/__tests__/arena.test.ts +5 -0
  523. package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +193 -0
  524. package/src/gestures/__tests__/browser/build-fixture.mjs +46 -0
  525. package/src/gestures/__tests__/browser/fixture.ts +307 -0
  526. package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +1137 -0
  527. package/src/gestures/__tests__/browserNegotiation.test.ts +293 -0
  528. package/src/gestures/__tests__/haptics.test.ts +187 -0
  529. package/src/gestures/__tests__/harness.ts +21 -2
  530. package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
  531. package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
  532. package/src/gestures/haptics.ts +203 -0
  533. package/src/gestures/nativeScroll.ts +277 -0
  534. package/src/gestures/touchAction.ts +191 -0
  535. package/src/gestures/touchActionRule.ts +157 -0
  536. package/src/gestures/types.ts +30 -9
  537. package/src/hooks/index.ts +5 -1
  538. package/src/hooks/modalAnnounce.ts +129 -72
  539. package/src/hooks/scrollKeyboardDelegation.test.ts +33 -0
  540. package/src/hooks/scrollKeyboardDelegation.ts +9 -3
  541. package/src/hooks/useAdaptivePresentation.ts +4 -1
  542. package/src/hooks/useAnnounce.doc.mjs +35 -3
  543. package/src/hooks/useAnnounce.replace.test.tsx +516 -0
  544. package/src/hooks/useAnnounce.ts +209 -102
  545. package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +10 -1
  546. package/src/hooks/useAnnounceRenderedText.ts +17 -3
  547. package/src/hooks/useBusyAnnouncement.ts +7 -10
  548. package/src/hooks/useMenuHover.ts +15 -1
  549. package/src/hooks/useScrollOverflow.doc.mjs +1 -1
  550. package/src/hooks/useScrollOverflow.test.tsx +102 -1
  551. package/src/hooks/useScrollOverflow.ts +59 -10
  552. package/src/i18n/generated-locales/en.generated.ts +7 -0
  553. package/src/i18n/generated-locales/pseudo.generated.ts +7 -0
  554. package/src/motion/README.md +11 -1
  555. package/src/motion/animator.test.ts +151 -3
  556. package/src/motion/animator.ts +149 -33
  557. package/src/theme/Theme.doc.mjs +1 -1
  558. package/src/theme/defineTheme.ts +117 -8
  559. package/src/theme/derivedVarRegistry.test.ts +4 -0
  560. package/src/theme/domainTokens/domainTokenDefaults.ts +19 -0
  561. package/src/theme/domainTokens/index.ts +6 -10
  562. package/src/theme/expandMotionScale.test.ts +1 -1
  563. package/src/theme/index.ts +5 -0
  564. package/src/theme/motionKnobs.ts +82 -0
  565. package/src/theme/resolveThemeValues.ts +68 -6
  566. package/src/theme/themeAdaptations.ts +52 -12
  567. package/src/theme/themeMotion.test.ts +620 -0
  568. package/src/theme/themeMotion.ts +221 -0
  569. package/src/theme/tokenReferences.ts +149 -0
  570. package/src/theme/tokens.stylex.ts +10 -0
  571. package/src/theme/tokens.ts +15 -158
  572. package/src/utils/focusReturn.ts +17 -6
  573. package/src/utils/getNodeText.test.ts +24 -0
  574. package/src/utils/getNodeText.ts +37 -0
  575. package/src/utils/interactionModality.test.ts +45 -1
  576. package/src/utils/interactionModality.ts +64 -5
  577. package/src/utils/interactionOverlay.stylex.ts +12 -3
  578. package/src/utils/plainDate.test.ts +90 -0
  579. package/src/utils/plainDate.ts +58 -3
  580. package/src/utils/presentation.test.ts +380 -0
  581. package/src/utils/presentation.ts +180 -0
  582. package/src/utils/pressFeedback.test.ts +138 -0
  583. package/src/utils/pressFeedback.ts +34 -11
  584. package/src/utils/pressPaintPriority.test.ts +80 -0
  585. package/src/utils/primaryClick.test.ts +38 -0
  586. package/src/utils/primaryClick.ts +28 -0
  587. package/src/utils/sharedMutationObserver.test.ts +54 -1
  588. package/src/utils/sharedMutationObserver.ts +87 -29
  589. package/src/utils/timeFormat.test.ts +204 -0
  590. package/src/utils/timeFormat.ts +314 -0
  591. package/src/utils/touchPresentation.stylex.ts +43 -0
  592. package/src/utils/touchPresentation.test.ts +140 -1
  593. package/src/utils/touchPresentation.ts +5 -3
  594. package/src/utils/unicodeDigits.test.ts +44 -0
  595. package/src/utils/unicodeDigits.ts +71 -0
@@ -0,0 +1,620 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file themeMotion.test.ts
5
+ * @input vitest, the theme motion knobs, defineTheme and expandMotionScale
6
+ * @output Checks `spec:AST-108` FR1, FR2, FR5 and FR6's resolver: today's
7
+ * tokens at the defaults, each tempo bound and the clamp, each character's
8
+ * curves with exits unchanged, `reducedMotion` kept internal, a `MotionScaleConfig` that
9
+ * renders exactly as before and wins over `tempo`, explicit tokens winning
10
+ * over both, adaptation rules setting the knobs, and `resolveThemeMotion`
11
+ * @position Testing; validates themeMotion.ts and its use in defineTheme
12
+ */
13
+
14
+ import fs from 'node:fs';
15
+ import path from 'node:path';
16
+ import {describe, expect, it} from 'vitest';
17
+ import {defineTheme} from './defineTheme';
18
+ import {generateAdaptationCSS} from './generateThemeRules';
19
+ import {expandMotionScale} from './expandMotionScale';
20
+ import {
21
+ CHARACTER_EASE,
22
+ expandThemeMotion,
23
+ resolveMotionKnobs,
24
+ resolveThemeMotion,
25
+ type ThemeMotionKnobs,
26
+ } from './themeMotion';
27
+ import {durationDefaults, easeDefaults} from './tokens.stylex';
28
+
29
+ const TODAY_MS = [130, 175, 230, 310, 410, 550, 730, 975, 1300];
30
+ const STANDARD = 'cubic-bezier(0.24, 1, 0.4, 1)';
31
+
32
+ function durationsMs(tokens: Readonly<Record<string, string>>): number[] {
33
+ return Object.keys(durationDefaults).map(name =>
34
+ Number.parseFloat(tokens[name]),
35
+ );
36
+ }
37
+
38
+ describe('the motion knobs (spec:AST-108 FR1)', () => {
39
+ it('default to tempo 1, standard and system', () => {
40
+ expect(resolveMotionKnobs(undefined)).toEqual({
41
+ tempo: 1,
42
+ character: 'standard',
43
+ reducedMotion: 'system',
44
+ tempoIsSet: false,
45
+ });
46
+ });
47
+
48
+ it('clamp tempo to 0.75–1.5 and ignore a value that is no number', () => {
49
+ expect(resolveMotionKnobs({tempo: 0.5}).tempo).toBe(0.75);
50
+ expect(resolveMotionKnobs({tempo: 2}).tempo).toBe(1.5);
51
+ expect(resolveMotionKnobs({tempo: 1.2}).tempo).toBe(1.2);
52
+ expect(resolveMotionKnobs({tempo: Number.NaN})).toMatchObject({
53
+ tempo: 1,
54
+ tempoIsSet: false,
55
+ });
56
+ });
57
+
58
+ it('resolve reducedMotion to system, which no theme sets until always ships', () => {
59
+ expect(resolveMotionKnobs({}).reducedMotion).toBe('system');
60
+ // @ts-expect-error reducedMotion is not part of the public motion type.
61
+ const knobs: ThemeMotionKnobs = {reducedMotion: 'system'};
62
+ expect(resolveMotionKnobs(knobs).reducedMotion).toBe('system');
63
+ });
64
+ });
65
+
66
+ describe('the CSS motion tokens (spec:AST-108 FR2)', () => {
67
+ it('are today\u2019s at the defaults', () => {
68
+ expect(expandThemeMotion({})).toEqual({});
69
+ const explicit = expandThemeMotion({
70
+ tempo: 1,
71
+ character: 'standard',
72
+ });
73
+ expect(durationsMs(explicit)).toEqual(TODAY_MS);
74
+ expect(explicit['--ease-entrance']).toBe(STANDARD);
75
+ expect(explicit['--ease-move']).toBe(STANDARD);
76
+ const motion = resolveThemeMotion({});
77
+ expect(durationsMs(motion.durations)).toEqual(TODAY_MS);
78
+ expect(motion.easings).toEqual({
79
+ '--ease-standard': STANDARD,
80
+ '--ease-entrance': STANDARD,
81
+ '--ease-move': STANDARD,
82
+ });
83
+ expect(easeDefaults['--ease-entrance']).toBe(STANDARD);
84
+ expect(easeDefaults['--ease-move']).toBe(STANDARD);
85
+ });
86
+
87
+ it.each([0.75, 1.2, 1.5])(
88
+ 'scale every duration by tempo %s, to the ms',
89
+ tempo => {
90
+ const tokens = expandThemeMotion({tempo});
91
+ expect(durationsMs(tokens)).toEqual(
92
+ TODAY_MS.map(ms => Math.round(ms * tempo)),
93
+ );
94
+ },
95
+ );
96
+
97
+ it('clamp the scale: a tempo of 3 is 1.5', () => {
98
+ expect(durationsMs(expandThemeMotion({tempo: 3}))).toEqual(
99
+ TODAY_MS.map(ms => Math.round(ms * 1.5)),
100
+ );
101
+ });
102
+
103
+ it.each(['crisp', 'expressive'] as const)(
104
+ 'set the entrance and move curves at %s, and leave the standard and exit curves alone',
105
+ character => {
106
+ const tokens = expandThemeMotion({character});
107
+ expect(tokens['--ease-entrance']).toBe(CHARACTER_EASE[character]);
108
+ expect(tokens['--ease-move']).toBe(CHARACTER_EASE[character]);
109
+ expect(tokens).not.toHaveProperty('--ease-standard');
110
+ expect(tokens).not.toHaveProperty('--ease-exit');
111
+ expect(
112
+ Object.keys(tokens).some(name => name.startsWith('--duration')),
113
+ ).toBe(false);
114
+ },
115
+ );
116
+
117
+ it('keep entrances and moves on a theme\u2019s own standard curve at standard', () => {
118
+ const easing = 'cubic-bezier(0.2, 0, 0, 1)';
119
+ const tokens = expandThemeMotion({
120
+ fast: 175,
121
+ medium: 410,
122
+ ratio: 0.75,
123
+ easing,
124
+ });
125
+ expect(tokens['--ease-standard']).toBe(easing);
126
+ expect(tokens['--ease-entrance']).toBe(easing);
127
+ expect(tokens['--ease-move']).toBe(easing);
128
+ });
129
+ });
130
+
131
+ describe('existing motion configuration (spec:AST-108 FR5)', () => {
132
+ const scale = {fast: 100, medium: 250, ratio: 0.75};
133
+
134
+ it('a MotionScaleConfig generates exactly what it did', () => {
135
+ expect(expandThemeMotion(scale)).toEqual(expandMotionScale(scale));
136
+ });
137
+
138
+ it('implies no tempo for the animator', () => {
139
+ expect(resolveMotionKnobs(scale).tempoIsSet).toBe(false);
140
+ });
141
+
142
+ it('its durations win over tempo; tempo scales the durations it leaves out', () => {
143
+ const tokens = expandThemeMotion({...scale, tempo: 1.5});
144
+ expect(tokens).toMatchObject(expandMotionScale(scale));
145
+ // No slow band in the scale: tempo scales today\u2019s.
146
+ expect(tokens['--duration-slow']).toBe(`${Math.round(975 * 1.5)}ms`);
147
+ });
148
+
149
+ it('explicit tokens win over the knobs', () => {
150
+ const theme = defineTheme({
151
+ name: 'Knobbed',
152
+ motion: {tempo: 1.5, character: 'crisp'},
153
+ tokens: {'--duration-medium': '300ms', '--ease-entrance': 'linear'},
154
+ });
155
+ expect(theme.tokens['--duration-medium']).toBe('300ms');
156
+ expect(theme.tokens['--ease-entrance']).toBe('linear');
157
+ expect(theme.tokens['--duration-fast']).toBe(`${Math.round(175 * 1.5)}ms`);
158
+ expect(theme.tokens['--ease-move']).toBe(CHARACTER_EASE.crisp);
159
+ });
160
+
161
+ it('a child theme keeps each knob it leaves out and can set one back to its default', () => {
162
+ const base = defineTheme({
163
+ name: 'SlowCrisp',
164
+ motion: {tempo: 0.8, character: 'crisp'},
165
+ });
166
+ const quicker = defineTheme({
167
+ name: 'SlowCrispChild',
168
+ extends: base,
169
+ motion: {tempo: 1.2},
170
+ });
171
+ expect(quicker.tokens['--duration-medium']).toBe(
172
+ `${Math.round(410 * 1.2)}ms`,
173
+ );
174
+ expect(quicker.tokens['--ease-entrance']).toBe(CHARACTER_EASE.crisp);
175
+ const reset = defineTheme({
176
+ name: 'SlowCrispReset',
177
+ extends: base,
178
+ motion: {tempo: 1, character: 'standard'},
179
+ });
180
+ expect(reset.tokens['--duration-medium']).toBe('410ms');
181
+ expect(reset.tokens['--ease-entrance']).toBe(STANDARD);
182
+ });
183
+
184
+ it('a partial duration scale beside a knob is refused, not dropped', () => {
185
+ for (const motion of [
186
+ {fast: 100, tempo: 1.2},
187
+ {fast: 100, medium: 250, slow: 700, tempo: 1},
188
+ {easing: 'linear', character: 'standard' as const},
189
+ ]) {
190
+ expect(() => defineTheme({name: 'Partial', motion})).toThrow(
191
+ /must supply `fast`, `medium`, and `ratio`/,
192
+ );
193
+ }
194
+ // A field the child leaves out may come from its base.
195
+ const base = defineTheme({
196
+ name: 'ScaleBase',
197
+ motion: {fast: 175, medium: 410, ratio: 0.75},
198
+ });
199
+ const child = defineTheme({
200
+ name: 'ScaleChild',
201
+ extends: base,
202
+ motion: {fast: 100, tempo: 1.2},
203
+ });
204
+ expect(child.tokens['--duration-fast']).toBe('100ms');
205
+ });
206
+
207
+ it('a theme with no motion writes no motion token, so it renders as before', () => {
208
+ const plain = defineTheme({name: 'Plain'});
209
+ expect(
210
+ Object.keys(plain.tokens).filter(
211
+ name => name.startsWith('--duration') || name.startsWith('--ease'),
212
+ ),
213
+ ).toEqual([]);
214
+ });
215
+
216
+ it('an adaptation rule sets tempo and character like any motion value', () => {
217
+ const theme = defineTheme({
218
+ name: 'Adaptive',
219
+ adaptations: {
220
+ rules: [{when: {pointer: 'coarse'}, value: {motion: {tempo: 0.8}}}],
221
+ },
222
+ });
223
+ const css = JSON.stringify(theme);
224
+ expect(css).toContain(`${Math.round(410 * 0.8)}ms`);
225
+ });
226
+
227
+ it('an adaptation rule cannot set reducedMotion, a theme-wide setting', () => {
228
+ expect(() =>
229
+ defineTheme({
230
+ name: 'Bad',
231
+ adaptations: {
232
+ rules: [
233
+ {
234
+ when: {pointer: 'coarse'},
235
+ value: {
236
+ motion: {reducedMotion: 'system'} as never,
237
+ },
238
+ },
239
+ ],
240
+ },
241
+ }),
242
+ ).toThrow(/reducedMotion is a theme-wide setting/);
243
+ });
244
+ });
245
+
246
+ describe('resolveThemeMotion (spec:AST-108 FR6)', () => {
247
+ it('returns the knobs, durations and easings with explicit tokens applied', () => {
248
+ const motion = resolveThemeMotion({
249
+ motion: {tempo: 1.2, character: 'expressive'},
250
+ tokens: {'--duration-fast': '200ms'},
251
+ });
252
+ expect(motion.knobs).toEqual({
253
+ tempo: 1.2,
254
+ character: 'expressive',
255
+ reducedMotion: 'system',
256
+ tempoIsSet: true,
257
+ });
258
+ expect(motion.durations['--duration-fast']).toBe('200ms');
259
+ expect(motion.durations['--duration-medium']).toBe(
260
+ `${Math.round(410 * 1.2)}ms`,
261
+ );
262
+ expect(motion.easings['--ease-entrance']).toBe(CHARACTER_EASE.expressive);
263
+ expect(motion.easings['--ease-standard']).toBe(STANDARD);
264
+ });
265
+
266
+ it('resolves tokens written as references through the theme\u2019s tokens (architecture:theme-tokens INV6)', () => {
267
+ const motion = resolveThemeMotion({
268
+ tokens: {
269
+ '--duration-fast': '90ms',
270
+ '--duration-medium': 'var(--duration-fast)',
271
+ '--duration-slow': 'var(--duration-unknown, 700ms)',
272
+ '--ease-standard': 'linear',
273
+ '--ease-entrance': 'var(--ease-standard)',
274
+ },
275
+ });
276
+ expect(motion.durations['--duration-medium']).toBe('90ms');
277
+ expect(motion.durations['--duration-slow']).toBe('700ms');
278
+ expect(motion.easings['--ease-entrance']).toBe('linear');
279
+ expect(motion.easings['--ease-move']).toBe('linear');
280
+ expect(JSON.stringify(motion)).not.toContain('var(');
281
+ });
282
+
283
+ it('resolves a reference to the theme\u2019s own local token', () => {
284
+ const motion = resolveThemeMotion({
285
+ tokens: {'--duration-medium': 'var(--brand-beat)'},
286
+ localTokens: {'--brand-beat': '333ms'},
287
+ });
288
+ expect(motion.durations['--duration-medium']).toBe('333ms');
289
+ });
290
+ });
291
+
292
+ describe('a layer\u2019s own durations reach the busy loops under an enclosing tempo (spec:AST-108 FR4)', () => {
293
+ it('a theme with a duration scale and no tempo writes the loops\u2019 copies of its durations', () => {
294
+ const theme = defineTheme({
295
+ name: 'ScaledNested',
296
+ motion: {fast: 100, medium: 250, ratio: 0.75},
297
+ });
298
+ for (const name of ['--duration-fast', '--duration-medium-max']) {
299
+ expect(
300
+ theme.tokens[
301
+ name.replace('--duration-', '--_astryx-pre-tempo-duration-')
302
+ ],
303
+ ).toBe(theme.tokens[name]);
304
+ }
305
+ });
306
+
307
+ it('an explicit duration with no tempo writes its copy too', () => {
308
+ const theme = defineTheme({
309
+ name: 'ExplicitNested',
310
+ tokens: {'--duration-slow': '800ms'},
311
+ });
312
+ expect(theme.tokens['--_astryx-pre-tempo-duration-slow']).toBe('800ms');
313
+ });
314
+
315
+ it('an adaptation rule\u2019s own durations write their copies', () => {
316
+ const css = generateAdaptationCSS(
317
+ defineTheme({
318
+ name: 'AdaptiveDurations',
319
+ adaptations: {
320
+ rules: [
321
+ {
322
+ when: {pointer: 'coarse'},
323
+ value: {tokens: {'--duration-medium': '300ms'}},
324
+ },
325
+ ],
326
+ },
327
+ }),
328
+ ).component;
329
+ expect(css).toContain('--_astryx-pre-tempo-duration-medium: 300ms');
330
+ });
331
+ });
332
+
333
+ describe('a child of an installed built theme (spec:AST-108 FR5, INV15)', () => {
334
+ it('resolves base first, then generated, as a child of a defined theme does', () => {
335
+ const base = defineTheme({
336
+ name: 'BuiltBase',
337
+ motion: {tempo: 0.8},
338
+ tokens: {'--duration-medium': '333ms', '--ease-entrance': 'linear'},
339
+ });
340
+ // A built module carries the resolved tokens and the axes, not the input.
341
+ const built = {...base, __inputTokens: undefined};
342
+ const child = defineTheme({
343
+ name: 'BuiltChild',
344
+ extends: built,
345
+ motion: {tempo: 1.2},
346
+ });
347
+ // The child's tempo regenerates every duration over the base's tokens,
348
+ // its explicit one included (`architecture:theme-authoring-contract`).
349
+ expect(child.tokens['--duration-medium']).toBe(
350
+ `${Math.round(410 * 1.2)}ms`,
351
+ );
352
+ expect(child.tokens['--duration-fast']).toBe(`${Math.round(175 * 1.2)}ms`);
353
+ // It generates no entrance curve without a character, so the base's stays.
354
+ expect(child.tokens['--ease-entrance']).toBe('linear');
355
+ });
356
+ });
357
+
358
+ describe('an explicit --ease-standard (spec:AST-108 FR2)', () => {
359
+ it('is what --ease-entrance and --ease-move equal at standard, in the tokens and resolveThemeMotion alike', () => {
360
+ const curve = 'cubic-bezier(0.3, 0, 0.2, 1)';
361
+ for (const motion of [
362
+ undefined,
363
+ {character: 'standard' as const},
364
+ {tempo: 1.2},
365
+ ]) {
366
+ const theme = defineTheme({
367
+ name: 'OwnStandard',
368
+ motion,
369
+ tokens: {'--ease-standard': curve},
370
+ });
371
+ expect(theme.tokens['--ease-entrance'], JSON.stringify(motion)).toBe(
372
+ curve,
373
+ );
374
+ expect(theme.tokens['--ease-move'], JSON.stringify(motion)).toBe(curve);
375
+ expect(resolveThemeMotion(theme).easings['--ease-entrance']).toBe(curve);
376
+ }
377
+ // A child, and a rule, that set 'standard' match the --ease-standard
378
+ // beneath them: the base's, or the theme's.
379
+ const base = defineTheme({
380
+ name: 'EaseBase',
381
+ tokens: {'--ease-standard': curve},
382
+ });
383
+ const standard = {character: 'standard' as const};
384
+ const child = defineTheme({
385
+ name: 'EaseChild',
386
+ extends: base,
387
+ motion: standard,
388
+ });
389
+ const ruled = defineTheme({
390
+ name: 'EaseRule',
391
+ tokens: {'--ease-standard': curve},
392
+ adaptations: {
393
+ rules: [{when: {pointer: 'coarse'}, value: {motion: standard}}],
394
+ },
395
+ });
396
+ for (const tokens of [child.tokens, ruled.__adaptationRules?.[0]?.tokens]) {
397
+ expect(tokens?.['--ease-entrance']).toBe(curve);
398
+ expect(tokens?.['--ease-move']).toBe(curve);
399
+ }
400
+ });
401
+ });
402
+
403
+ describe('resolveThemeMotion reads a defined theme\u2019s motion (spec:AST-108 FR6)', () => {
404
+ it('takes the knobs a child inherits from its base', () => {
405
+ const base = defineTheme({name: 'KnobBase', motion: {tempo: 1.2}});
406
+ const child = defineTheme({name: 'KnobChild', extends: base});
407
+ expect(resolveThemeMotion(child).knobs.tempo).toBe(1.2);
408
+ });
409
+ });
410
+
411
+ describe('the press release follows tempo (spec:AST-108 FR4, component:Button FR15)', () => {
412
+ it('writes the tempo beside the duration tokens for the release fade, and nothing without one', () => {
413
+ expect(expandThemeMotion({tempo: 1.5})['--_astryx-motion-tempo']).toBe(
414
+ '1.5',
415
+ );
416
+ expect(
417
+ expandThemeMotion({character: 'crisp'})['--_astryx-motion-tempo'],
418
+ ).toBeUndefined();
419
+ });
420
+ });
421
+
422
+ describe('busy loops read the duration before tempo (spec:AST-108 FR4)', () => {
423
+ it.each([0.75, 1.5])(
424
+ 'at tempo %s the pre-tempo durations stay today\u2019s while the tokens scale',
425
+ tempo => {
426
+ const tokens = expandThemeMotion({tempo});
427
+ expect(tokens['--_astryx-pre-tempo-duration-slow-min']).toBe('730ms');
428
+ expect(tokens['--_astryx-pre-tempo-duration-medium-max']).toBe('550ms');
429
+ expect(tokens['--duration-slow-min']).toBe(
430
+ `${Math.round(730 * tempo)}ms`,
431
+ );
432
+ },
433
+ );
434
+
435
+ it('a duration scale still times the loops, and an explicit token too', () => {
436
+ const scale = {fast: 100, medium: 250, ratio: 0.75};
437
+ const tokens = expandThemeMotion({...scale, tempo: 1.5});
438
+ expect(tokens['--_astryx-pre-tempo-duration-medium-max']).toBe(
439
+ expandMotionScale(scale)['--duration-medium-max'],
440
+ );
441
+ const theme = defineTheme({
442
+ name: 'LoopTimed',
443
+ motion: {tempo: 1.5},
444
+ tokens: {'--duration-medium-max': '600ms'},
445
+ });
446
+ expect(theme.tokens['--_astryx-pre-tempo-duration-medium-max']).toBe(
447
+ '600ms',
448
+ );
449
+ });
450
+
451
+ it('names every property it writes beside the core tokens privately, with --_astryx- (architecture:theme-tokens INV1)', () => {
452
+ const core = new Set([
453
+ ...Object.keys(durationDefaults),
454
+ ...Object.keys(easeDefaults),
455
+ ]);
456
+ const tokens = expandThemeMotion({
457
+ fast: 100,
458
+ medium: 250,
459
+ ratio: 0.75,
460
+ tempo: 1.2,
461
+ character: 'crisp',
462
+ });
463
+ const extra = Object.keys(tokens).filter(name => !core.has(name));
464
+ expect(extra.length).toBeGreaterThan(0);
465
+ for (const name of extra) {
466
+ expect(name).toMatch(/^--_astryx-/);
467
+ }
468
+ });
469
+
470
+ it('Spinner and Skeleton read the pre-tempo duration first', () => {
471
+ const read = (file: string) =>
472
+ fs.readFileSync(path.join(__dirname, '..', file), 'utf8');
473
+ expect(read('Spinner/Spinner.tsx')).toContain(
474
+ "`var(--_astryx-pre-tempo-duration-slow-min, ${durationVars['--duration-slow-min']})`",
475
+ );
476
+ expect(read('Skeleton/Skeleton.tsx')).toContain(
477
+ "`var(--_astryx-pre-tempo-duration-medium-max, ${durationVars['--duration-medium-max']})`",
478
+ );
479
+ });
480
+ });
481
+
482
+ describe('an extending theme inherits motion field by field (spec:AST-108 FR5)', () => {
483
+ it('a child that sets no easing keeps its base\u2019s --ease-standard, an explicit one included', () => {
484
+ const base = defineTheme({
485
+ name: 'EasingBase',
486
+ motion: {fast: 150, medium: 300, ratio: 0.75, easing: 'ease-in'},
487
+ tokens: {'--ease-standard': 'linear'},
488
+ });
489
+ expect(base.tokens['--ease-standard']).toBe('linear');
490
+ const child = defineTheme({
491
+ name: 'EasingChild',
492
+ extends: base,
493
+ motion: {tempo: 1.2},
494
+ });
495
+ expect(child.tokens['--ease-standard']).toBe('linear');
496
+ // A child that sets its own easing generates it.
497
+ const own = defineTheme({
498
+ name: 'EasingOwn',
499
+ extends: base,
500
+ motion: {fast: 150, medium: 300, ratio: 0.75, easing: 'ease-out'},
501
+ });
502
+ expect(own.tokens['--ease-standard']).toBe('ease-out');
503
+ });
504
+
505
+ it('a grandchild that adds only a knob keeps the slow band its parent inherited', () => {
506
+ const base = defineTheme({
507
+ name: 'SlowBase',
508
+ motion: {fast: 100, medium: 250, slow: 700, ratio: 0.75},
509
+ });
510
+ // The child's own ratio regenerates its fast and medium bands only. Its
511
+ // unrelated token gives it authored input tokens of its own.
512
+ const child = defineTheme({
513
+ name: 'RatioChild',
514
+ extends: base,
515
+ motion: {fast: 100, medium: 250, ratio: 0.8},
516
+ tokens: {'--radius-element': '6px'},
517
+ });
518
+ expect(child.tokens['--duration-slow-min']).toBe('525ms');
519
+ for (const knob of [{character: 'expressive' as const}, {tempo: 1.2}]) {
520
+ const grandchild = defineTheme({
521
+ name: 'KnobGrandchild',
522
+ extends: child,
523
+ motion: knob,
524
+ });
525
+ for (const band of [
526
+ '--duration-slow-min',
527
+ '--duration-slow',
528
+ '--duration-slow-max',
529
+ ] as const) {
530
+ expect(grandchild.tokens[band]).toBe(child.tokens[band]);
531
+ }
532
+ }
533
+ });
534
+
535
+ it('an explicit --ease-standard without motion of its own keeps an inherited character\u2019s curves', () => {
536
+ const crisp = defineTheme({name: 'Crisp', motion: {character: 'crisp'}});
537
+ const crispEase = crisp.tokens['--ease-entrance'];
538
+ const child = defineTheme({
539
+ name: 'EaseChild',
540
+ extends: crisp,
541
+ tokens: {'--ease-standard': 'cubic-bezier(0.4, 0, 0.6, 1)'},
542
+ });
543
+ expect(child.tokens['--ease-standard']).toBe(
544
+ 'cubic-bezier(0.4, 0, 0.6, 1)',
545
+ );
546
+ expect(child.tokens['--ease-entrance']).toBe(crispEase);
547
+ expect(child.tokens['--ease-move']).toBe(crispEase);
548
+ const adaptive = defineTheme({
549
+ name: 'EaseRule',
550
+ motion: {character: 'expressive'},
551
+ adaptations: {
552
+ rules: [
553
+ {
554
+ when: {pointer: 'coarse'},
555
+ value: {
556
+ tokens: {'--ease-standard': 'cubic-bezier(0.4, 0, 0.6, 1)'},
557
+ },
558
+ },
559
+ ],
560
+ },
561
+ });
562
+ const rule = adaptive.__adaptationRules?.[0];
563
+ expect(rule?.tokens['--ease-standard']).toBe(
564
+ 'cubic-bezier(0.4, 0, 0.6, 1)',
565
+ );
566
+ expect(rule?.tokens['--ease-entrance']).toBeUndefined();
567
+ expect(rule?.tokens['--ease-move']).toBeUndefined();
568
+ });
569
+
570
+ it('a base duration scale keeps winning over a child\u2019s tempo', () => {
571
+ const base = defineTheme({
572
+ name: 'ScaledBase',
573
+ motion: {fast: 100, medium: 250, slow: 800, ratio: 0.75},
574
+ });
575
+ const child = defineTheme({
576
+ name: 'ScaledChild',
577
+ extends: base,
578
+ motion: {tempo: 1.2},
579
+ });
580
+ for (const name of [
581
+ '--duration-fast',
582
+ '--duration-medium',
583
+ '--duration-slow',
584
+ ]) {
585
+ expect(child.tokens[name], name).toBe(base.tokens[name]);
586
+ }
587
+ });
588
+
589
+ it('a child\u2019s knobs regenerate over its base\u2019s explicit durations: base first, then generated', () => {
590
+ const base = defineTheme({
591
+ name: 'ExplicitBase',
592
+ motion: {tempo: 0.8},
593
+ tokens: {'--duration-medium': '300ms'},
594
+ });
595
+ const quicker = defineTheme({
596
+ name: 'ExplicitChild',
597
+ extends: base,
598
+ motion: {tempo: 1.2},
599
+ });
600
+ expect(quicker.tokens['--duration-medium']).toBe(
601
+ `${Math.round(410 * 1.2)}ms`,
602
+ );
603
+ expect(quicker.tokens['--duration-fast']).toBe(
604
+ `${Math.round(175 * 1.2)}ms`,
605
+ );
606
+ const crisper = defineTheme({
607
+ name: 'ExplicitCrisp',
608
+ extends: base,
609
+ motion: {character: 'crisp'},
610
+ });
611
+ // The inherited tempo regenerates it too.
612
+ expect(crisper.tokens['--duration-medium']).toBe(
613
+ `${Math.round(410 * 0.8)}ms`,
614
+ );
615
+ expect(crisper.tokens['--duration-fast']).toBe(
616
+ `${Math.round(175 * 0.8)}ms`,
617
+ );
618
+ expect(crisper.tokens['--ease-entrance']).toBe(CHARACTER_EASE.crisp);
619
+ });
620
+ });