@astryxdesign/core 0.7.5 → 0.7.6-canary.0ef60dd

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 (559) 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/Avatar/Avatar.d.ts.map +1 -1
  5. package/dist/Avatar/Avatar.js +12 -3
  6. package/dist/Badge/Badge.d.ts.map +1 -1
  7. package/dist/Badge/Badge.js +7 -1
  8. package/dist/BottomSheet/BottomSheet.js +1 -1
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  10. package/dist/BottomSheet/BottomSheetPanel.js +2 -1
  11. package/dist/BottomSheet/useSheetGestures.d.ts +12 -0
  12. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  13. package/dist/BottomSheet/useSheetGestures.js +30 -3
  14. package/dist/Button/Button.js +4 -4
  15. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  16. package/dist/CheckboxInput/CheckboxInput.js +6 -5
  17. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  18. package/dist/ClickableCard/ClickableCard.js +37 -4
  19. package/dist/DateInput/DateInput.d.ts.map +1 -1
  20. package/dist/DateInput/DateInput.js +12 -4
  21. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  22. package/dist/DateInput/MonthScroller.js +101 -15
  23. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  24. package/dist/DateInput/TouchDateField.js +8 -3
  25. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  26. package/dist/DateRangeInput/DateRangeInput.js +1 -1
  27. package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
  28. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  29. package/dist/DateTimeInput/DateTimeInput.js +23 -12
  30. package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
  31. package/dist/DateTimeInput/NativeTimeSegment.js +5 -4
  32. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  33. package/dist/DateTimeInput/TouchDateTimeField.js +4 -3
  34. package/dist/Dialog/Dialog.d.ts.map +1 -1
  35. package/dist/Dialog/Dialog.js +34 -9
  36. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  37. package/dist/Dialog/DialogHeader.js +5 -4
  38. package/dist/Divider/Divider.d.ts.map +1 -1
  39. package/dist/Divider/Divider.js +2 -1
  40. package/dist/Drawer/Drawer.d.ts +1 -0
  41. package/dist/Drawer/Drawer.d.ts.map +1 -1
  42. package/dist/Drawer/Drawer.js +7 -2
  43. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  44. package/dist/DropdownMenu/DropdownMenu.js +7 -3
  45. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
  46. package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
  47. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +20 -2
  48. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
  49. package/dist/DropdownMenu/lazyMenuBottomSheet.js +31 -3
  50. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  51. package/dist/DropdownMenu/renderDropdownItems.js +21 -16
  52. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  53. package/dist/EmptyState/EmptyState.js +2 -1
  54. package/dist/Field/FieldLabel.d.ts +1 -1
  55. package/dist/Field/FieldLabel.d.ts.map +1 -1
  56. package/dist/Field/FieldLabel.js +4 -4
  57. package/dist/Field/InputClearButton.js +3 -3
  58. package/dist/Field/PanelSearchInput.js +2 -2
  59. package/dist/FieldStatus/FieldStatus.js +2 -2
  60. package/dist/FileInput/FileInput.d.ts.map +1 -1
  61. package/dist/FileInput/FileInput.js +7 -1
  62. package/dist/Heading/Heading.js +1 -1
  63. package/dist/Icon/Icon.js +1 -1
  64. package/dist/Indicator/CheckIndicator.d.ts.map +1 -1
  65. package/dist/Indicator/CheckIndicator.js +2 -1
  66. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  67. package/dist/Indicator/CheckboxIndicator.js +3 -1
  68. package/dist/Indicator/RadioIndicator.d.ts.map +1 -1
  69. package/dist/Indicator/RadioIndicator.js +3 -1
  70. package/dist/Item/Item.d.ts.map +1 -1
  71. package/dist/Item/Item.js +2 -1
  72. package/dist/Item/ItemSwipeLayer.js +1 -1
  73. package/dist/Layer/popoverOperations.d.ts +27 -0
  74. package/dist/Layer/popoverOperations.d.ts.map +1 -0
  75. package/dist/Layer/popoverOperations.js +159 -0
  76. package/dist/Layer/useLayer.d.ts +1 -1
  77. package/dist/Layer/useLayer.d.ts.map +1 -1
  78. package/dist/Layer/useLayer.js +93 -59
  79. package/dist/Layout/Layout.js +1 -1
  80. package/dist/Layout/LayoutContent.js +1 -1
  81. package/dist/Layout/LayoutFooter.js +1 -1
  82. package/dist/Layout/LayoutHeader.js +1 -1
  83. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  84. package/dist/Lightbox/Lightbox.js +5 -0
  85. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +5 -4
  86. package/dist/List/List.js +1 -1
  87. package/dist/List/ListItem.js +3 -3
  88. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  89. package/dist/MobileNav/MobileNav.js +7 -2
  90. package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +7 -6
  91. package/dist/MultiSelector/MultiSelector.d.ts +1 -1
  92. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  93. package/dist/MultiSelector/MultiSelector.js +26 -10
  94. package/dist/NumberInput/NumberInput.d.ts +3 -1
  95. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  96. package/dist/NumberInput/NumberInput.js +3 -3
  97. package/dist/NumberInput/numberParser.d.ts +3 -0
  98. package/dist/NumberInput/numberParser.d.ts.map +1 -1
  99. package/dist/NumberInput/numberParser.js +7 -44
  100. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  101. package/dist/ProgressBar/ProgressBar.js +16 -12
  102. package/dist/Resizable/useResizable.d.ts.map +1 -1
  103. package/dist/Resizable/useResizable.js +28 -2
  104. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  105. package/dist/SegmentedControl/SegmentedControlItem.js +4 -1
  106. package/dist/Selector/useSelectorPresentation.d.ts +8 -1
  107. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
  108. package/dist/Selector/useSelectorPresentation.js +20 -4
  109. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  110. package/dist/Skeleton/Skeleton.js +1 -1
  111. package/dist/Slider/Slider.d.ts.map +1 -1
  112. package/dist/Slider/Slider.js +10 -2
  113. package/dist/Spinner/Spinner.d.ts.map +1 -1
  114. package/dist/Spinner/Spinner.js +3 -3
  115. package/dist/Stack/Stack.js +1 -1
  116. package/dist/Stack/StackItem.js +1 -1
  117. package/dist/TabList/TabList.d.ts.map +1 -1
  118. package/dist/TabList/TabList.js +16 -1
  119. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  120. package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
  121. package/dist/Text/Text.js +1 -1
  122. package/dist/Text/useTruncation.d.ts.map +1 -1
  123. package/dist/Text/useTruncation.js +23 -5
  124. package/dist/TextArea/TextArea.d.ts +1 -1
  125. package/dist/TextArea/TextArea.d.ts.map +1 -1
  126. package/dist/TextArea/TextArea.js +13 -2
  127. package/dist/TextInput/TextInput.d.ts.map +1 -1
  128. package/dist/TextInput/TextInput.js +3 -3
  129. package/dist/TimeInput/TimeInput.d.ts +6 -2
  130. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  131. package/dist/TimeInput/TimeInput.js +21 -14
  132. package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
  133. package/dist/TimeInput/TouchTimeField.js +5 -4
  134. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  135. package/dist/Timestamp/Timestamp.js +2 -2
  136. package/dist/Timestamp/TimestampHoverCard.js +4 -4
  137. package/dist/Toast/Toast.d.ts.map +1 -1
  138. package/dist/Toast/Toast.js +60 -20
  139. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  140. package/dist/Toast/ToastViewport.js +82 -51
  141. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  142. package/dist/Tokenizer/Tokenizer.js +13 -2
  143. package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
  144. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  145. package/dist/Toolbar/Toolbar.js +2 -1
  146. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  147. package/dist/TopNav/TopNavMegaMenu.js +3 -0
  148. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  149. package/dist/TopNav/TopNavMenu.js +1 -0
  150. package/dist/Typeahead/Typeahead.d.ts +1 -1
  151. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  152. package/dist/Typeahead/Typeahead.js +9 -1
  153. package/dist/astryx.css +20 -4
  154. package/dist/gestures/GestureArena.d.ts +6 -0
  155. package/dist/gestures/GestureArena.d.ts.map +1 -1
  156. package/dist/gestures/GestureArena.js +39 -0
  157. package/dist/gestures/GestureHost.d.ts +352 -0
  158. package/dist/gestures/GestureHost.d.ts.map +1 -0
  159. package/dist/gestures/GestureHost.js +1773 -0
  160. package/dist/gestures/GestureRecognizer.d.ts +10 -0
  161. package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
  162. package/dist/gestures/GestureRecognizer.js +16 -0
  163. package/dist/gestures/LongPressGestureRecognizer.d.ts +1 -0
  164. package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -1
  165. package/dist/gestures/LongPressGestureRecognizer.js +3 -0
  166. package/dist/gestures/PanGestureRecognizer.d.ts +1 -0
  167. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  168. package/dist/gestures/PanGestureRecognizer.js +3 -0
  169. package/dist/gestures/PinchGestureRecognizer.d.ts +31 -0
  170. package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -0
  171. package/dist/gestures/PinchGestureRecognizer.js +128 -0
  172. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +71 -0
  173. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -0
  174. package/dist/gestures/ScreenEdgePanGestureRecognizer.js +223 -0
  175. package/dist/gestures/SwipeGestureRecognizer.d.ts +37 -0
  176. package/dist/gestures/SwipeGestureRecognizer.d.ts.map +1 -0
  177. package/dist/gestures/SwipeGestureRecognizer.js +148 -0
  178. package/dist/gestures/TapGestureRecognizer.d.ts +1 -0
  179. package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -1
  180. package/dist/gestures/TapGestureRecognizer.js +3 -0
  181. package/dist/gestures/VelocityTracker.d.ts +6 -2
  182. package/dist/gestures/VelocityTracker.d.ts.map +1 -1
  183. package/dist/gestures/VelocityTracker.js +7 -3
  184. package/dist/gestures/haptics.d.ts +65 -0
  185. package/dist/gestures/haptics.d.ts.map +1 -0
  186. package/dist/gestures/haptics.js +182 -0
  187. package/dist/gestures/nativeScroll.d.ts +42 -0
  188. package/dist/gestures/nativeScroll.d.ts.map +1 -0
  189. package/dist/gestures/nativeScroll.js +228 -0
  190. package/dist/gestures/touchAction.d.ts +60 -0
  191. package/dist/gestures/touchAction.d.ts.map +1 -0
  192. package/dist/gestures/touchAction.js +157 -0
  193. package/dist/gestures/touchActionRule.d.ts +34 -0
  194. package/dist/gestures/touchActionRule.d.ts.map +1 -0
  195. package/dist/gestures/touchActionRule.js +140 -0
  196. package/dist/gestures/types.d.ts +18 -7
  197. package/dist/gestures/types.d.ts.map +1 -1
  198. package/dist/gestures/types.js +22 -2
  199. package/dist/hooks/index.d.ts +1 -1
  200. package/dist/hooks/index.d.ts.map +1 -1
  201. package/dist/hooks/modalAnnounce.d.ts.map +1 -1
  202. package/dist/hooks/modalAnnounce.js +107 -61
  203. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
  204. package/dist/hooks/useAdaptivePresentation.js +4 -1
  205. package/dist/hooks/useAnnounce.d.ts +101 -42
  206. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  207. package/dist/hooks/useAnnounce.js +161 -75
  208. package/dist/hooks/useAnnounceRenderedText.d.ts +11 -3
  209. package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
  210. package/dist/hooks/useAnnounceRenderedText.js +5 -3
  211. package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
  212. package/dist/hooks/useBusyAnnouncement.js +6 -12
  213. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  214. package/dist/hooks/useMenuHover.js +12 -1
  215. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  216. package/dist/i18n/generated-locales/en.generated.js +5 -0
  217. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  218. package/dist/i18n/generated-locales/pseudo.generated.js +5 -0
  219. package/dist/motion/animator.d.ts +7 -1
  220. package/dist/motion/animator.d.ts.map +1 -1
  221. package/dist/motion/animator.js +119 -27
  222. package/dist/theme/defineTheme.d.ts +19 -5
  223. package/dist/theme/defineTheme.d.ts.map +1 -1
  224. package/dist/theme/defineTheme.js +64 -4
  225. package/dist/theme/domainTokens/domainTokenDefaults.d.ts +3 -0
  226. package/dist/theme/domainTokens/domainTokenDefaults.d.ts.map +1 -0
  227. package/dist/theme/domainTokens/domainTokenDefaults.js +19 -0
  228. package/dist/theme/domainTokens/index.d.ts +5 -4
  229. package/dist/theme/domainTokens/index.d.ts.map +1 -1
  230. package/dist/theme/domainTokens/index.js +5 -9
  231. package/dist/theme/index.d.ts +1 -0
  232. package/dist/theme/index.d.ts.map +1 -1
  233. package/dist/theme/motionKnobs.d.ts +56 -0
  234. package/dist/theme/motionKnobs.d.ts.map +1 -0
  235. package/dist/theme/motionKnobs.js +48 -0
  236. package/dist/theme/resolveThemeValues.d.ts +11 -4
  237. package/dist/theme/resolveThemeValues.d.ts.map +1 -1
  238. package/dist/theme/resolveThemeValues.js +40 -4
  239. package/dist/theme/themeAdaptations.d.ts +7 -3
  240. package/dist/theme/themeAdaptations.d.ts.map +1 -1
  241. package/dist/theme/themeAdaptations.js +36 -7
  242. package/dist/theme/themeMotion.d.ts +96 -0
  243. package/dist/theme/themeMotion.d.ts.map +1 -0
  244. package/dist/theme/themeMotion.js +177 -0
  245. package/dist/theme/tokenReferences.d.ts +31 -0
  246. package/dist/theme/tokenReferences.d.ts.map +1 -0
  247. package/dist/theme/tokenReferences.js +132 -0
  248. package/dist/theme/tokens.d.ts +1 -0
  249. package/dist/theme/tokens.d.ts.map +1 -1
  250. package/dist/theme/tokens.js +9 -129
  251. package/dist/theme/tokens.stylex.d.ts +12 -0
  252. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  253. package/dist/theme/tokens.stylex.js +12 -0
  254. package/dist/utils/focusReturn.d.ts +17 -1
  255. package/dist/utils/focusReturn.d.ts.map +1 -1
  256. package/dist/utils/focusReturn.js +11 -4
  257. package/dist/utils/getNodeText.d.ts +8 -0
  258. package/dist/utils/getNodeText.d.ts.map +1 -0
  259. package/dist/utils/getNodeText.js +37 -0
  260. package/dist/utils/interactionModality.d.ts +11 -2
  261. package/dist/utils/interactionModality.d.ts.map +1 -1
  262. package/dist/utils/interactionModality.js +58 -5
  263. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  264. package/dist/utils/interactionOverlay.stylex.js +17 -8
  265. package/dist/utils/plainDate.d.ts +2 -0
  266. package/dist/utils/plainDate.d.ts.map +1 -1
  267. package/dist/utils/plainDate.js +46 -3
  268. package/dist/utils/presentation.d.ts +50 -0
  269. package/dist/utils/presentation.d.ts.map +1 -0
  270. package/dist/utils/presentation.js +125 -0
  271. package/dist/utils/pressFeedback.d.ts.map +1 -1
  272. package/dist/utils/pressFeedback.js +20 -1
  273. package/dist/utils/primaryClick.d.ts +11 -0
  274. package/dist/utils/primaryClick.d.ts.map +1 -0
  275. package/dist/utils/primaryClick.js +25 -0
  276. package/dist/utils/timeFormat.d.ts +47 -0
  277. package/dist/utils/timeFormat.d.ts.map +1 -0
  278. package/dist/utils/timeFormat.js +240 -0
  279. package/dist/utils/touchPresentation.d.ts.map +1 -1
  280. package/dist/utils/touchPresentation.js +5 -3
  281. package/dist/utils/touchPresentation.stylex.d.ts +15 -0
  282. package/dist/utils/touchPresentation.stylex.d.ts.map +1 -0
  283. package/dist/utils/touchPresentation.stylex.js +33 -0
  284. package/dist/utils/unicodeDigits.d.ts +20 -0
  285. package/dist/utils/unicodeDigits.d.ts.map +1 -0
  286. package/dist/utils/unicodeDigits.js +70 -0
  287. package/locales/en.json +23 -3
  288. package/locales/pseudo.json +15 -0
  289. package/package.json +5 -4
  290. package/src/AlertDialog/AlertDialog.tsx +6 -5
  291. package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +18 -6
  292. package/src/Avatar/Avatar.spec.md +22 -22
  293. package/src/Avatar/Avatar.tsx +18 -1
  294. package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +126 -0
  295. package/src/Badge/Badge.doc.mjs +1 -1
  296. package/src/Badge/Badge.tsx +19 -2
  297. package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +260 -0
  298. package/src/BottomSheet/BottomSheet.test.tsx +46 -0
  299. package/src/BottomSheet/BottomSheet.tsx +1 -1
  300. package/src/BottomSheet/BottomSheetPanel.tsx +2 -1
  301. package/src/BottomSheet/useSheetGestures.test.ts +52 -0
  302. package/src/BottomSheet/useSheetGestures.ts +37 -6
  303. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +18 -6
  304. package/src/Button/Button.tsx +4 -4
  305. package/src/Calendar/Calendar.spec.md +87 -48
  306. package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +21 -7
  307. package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
  308. package/src/CheckboxInput/CheckboxInput.tsx +6 -5
  309. package/src/ClickableCard/ClickableCard.test.tsx +96 -0
  310. package/src/ClickableCard/ClickableCard.tsx +48 -4
  311. package/src/Collapsible/Collapsible.spec.md +2 -0
  312. package/src/Collapsible/CollapsibleGroup.spec.md +57 -29
  313. package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +18 -7
  314. package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +18 -6
  315. package/src/ComplexSelector/ComplexSelector.test.tsx +37 -0
  316. package/src/ContextMenu/ContextMenu.test.tsx +35 -0
  317. package/src/DateInput/DateInput.test.tsx +115 -3
  318. package/src/DateInput/DateInput.tsx +29 -14
  319. package/src/DateInput/DateInputTouch.test.tsx +76 -0
  320. package/src/DateInput/MonthScroller.tsx +106 -20
  321. package/src/DateInput/MonthScrollerSettle.test.tsx +165 -0
  322. package/src/DateInput/TouchDateField.tsx +14 -3
  323. package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
  324. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -3
  325. package/src/DateRangeInput/DateRangeInput.tsx +16 -12
  326. package/src/DateTimeInput/DateTimeInput.doc.mjs +10 -8
  327. package/src/DateTimeInput/DateTimeInput.spec.md +75 -51
  328. package/src/DateTimeInput/DateTimeInput.test.tsx +81 -0
  329. package/src/DateTimeInput/DateTimeInput.tsx +46 -24
  330. package/src/DateTimeInput/NativeTimeSegment.tsx +4 -6
  331. package/src/DateTimeInput/TouchDateTimeField.tsx +3 -7
  332. package/src/Dialog/Dialog.test.tsx +216 -2
  333. package/src/Dialog/Dialog.tsx +42 -9
  334. package/src/Dialog/DialogHeader.tsx +5 -4
  335. package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +202 -0
  336. package/src/Divider/Divider.tsx +2 -1
  337. package/src/Drawer/Drawer.spec.md +111 -80
  338. package/src/Drawer/Drawer.test.tsx +35 -0
  339. package/src/Drawer/Drawer.tsx +13 -2
  340. package/src/Drawer/DrawerHeader.spec.md +181 -0
  341. package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +267 -0
  342. package/src/DropdownMenu/DropdownMenu.test.tsx +41 -0
  343. package/src/DropdownMenu/DropdownMenu.tsx +10 -3
  344. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +34 -0
  345. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -5
  346. package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +19 -7
  347. package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +21 -9
  348. package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +60 -0
  349. package/src/DropdownMenu/lazyMenuBottomSheet.ts +36 -7
  350. package/src/DropdownMenu/renderDropdownItems.tsx +24 -19
  351. package/src/EmptyState/EmptyState.tsx +2 -1
  352. package/src/Field/FieldLabel.tsx +5 -4
  353. package/src/Field/InputClearButton.tsx +3 -3
  354. package/src/Field/PanelSearchInput.tsx +2 -2
  355. package/src/FieldStatus/FieldStatus.tsx +2 -2
  356. package/src/FileInput/FileInput.test.tsx +21 -0
  357. package/src/FileInput/FileInput.tsx +4 -1
  358. package/src/FormLayout/FormLayout.spec.md +7 -8
  359. package/src/Heading/Heading.tsx +1 -1
  360. package/src/Icon/Icon.tsx +1 -1
  361. package/src/Indicator/CheckIndicator.spec.md +47 -42
  362. package/src/Indicator/CheckIndicator.tsx +2 -1
  363. package/src/Indicator/CheckboxIndicator.spec.md +40 -37
  364. package/src/Indicator/CheckboxIndicator.tsx +3 -1
  365. package/src/Indicator/Indicator.spec.md +188 -0
  366. package/src/Indicator/RadioIndicator.tsx +3 -1
  367. package/src/Item/Item.tsx +2 -1
  368. package/src/Item/ItemSwipeLayer.tsx +1 -1
  369. package/src/Kbd/Kbd.spec.md +81 -38
  370. package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +126 -0
  371. package/src/Layer/popoverOperations.test.ts +205 -0
  372. package/src/Layer/popoverOperations.ts +172 -0
  373. package/src/Layer/useLayer.test.tsx +348 -1
  374. package/src/Layer/useLayer.tsx +118 -71
  375. package/src/Layout/Layout.spec.md +127 -131
  376. package/src/Layout/Layout.tsx +1 -1
  377. package/src/Layout/LayoutContent.spec.md +205 -0
  378. package/src/Layout/LayoutContent.tsx +1 -1
  379. package/src/Layout/LayoutFooter.spec.md +190 -0
  380. package/src/Layout/LayoutFooter.tsx +1 -1
  381. package/src/Layout/LayoutHeader.spec.md +193 -0
  382. package/src/Layout/LayoutHeader.tsx +1 -1
  383. package/src/Layout/LayoutPanel.spec.md +194 -0
  384. package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +18 -6
  385. package/src/Lightbox/Lightbox.test.tsx +18 -0
  386. package/src/Lightbox/Lightbox.tsx +5 -0
  387. package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +8 -4
  388. package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
  389. package/src/List/List.tsx +1 -1
  390. package/src/List/ListItem.spec.md +205 -0
  391. package/src/List/ListItem.tsx +3 -3
  392. package/src/MetadataList/MetadataList.spec.md +187 -0
  393. package/src/MetadataList/MetadataListItem.spec.md +165 -0
  394. package/src/MobileNav/MobileNav.test.tsx +15 -0
  395. package/src/MobileNav/MobileNav.tsx +9 -1
  396. package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +89 -0
  397. package/src/MoreMenu/MoreMenu.test.tsx +11 -0
  398. package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +7 -8
  399. package/src/MultiSelector/MultiSelector.spec.md +7 -4
  400. package/src/MultiSelector/MultiSelector.test.tsx +270 -1
  401. package/src/MultiSelector/MultiSelector.tsx +25 -10
  402. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +8 -1
  403. package/src/NavMenu/NavHeadingMenu.spec.md +1 -5
  404. package/src/NumberInput/NumberInput.doc.mjs +13 -7
  405. package/src/NumberInput/NumberInput.spec.md +59 -37
  406. package/src/NumberInput/NumberInput.tsx +13 -3
  407. package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
  408. package/src/NumberInput/numberParser.ts +7 -45
  409. package/src/ProgressBar/ProgressBar.test.tsx +108 -32
  410. package/src/ProgressBar/ProgressBar.tsx +58 -10
  411. package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +21 -9
  412. package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +831 -0
  413. package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +21 -14
  414. package/src/Resizable/useResizable.test.ts +43 -0
  415. package/src/Resizable/useResizable.ts +32 -9
  416. package/src/SegmentedControl/SegmentedControl.test.tsx +84 -0
  417. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -5
  418. package/src/Selector/Selector.test.tsx +90 -1
  419. package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +8 -1
  420. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +8 -1
  421. package/src/Selector/useSelectorPresentation.ts +31 -3
  422. package/src/SideNav/SideNav.test.tsx +27 -0
  423. package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +176 -51
  424. package/src/Skeleton/Skeleton.tsx +3 -1
  425. package/src/Slider/Slider.test.tsx +31 -0
  426. package/src/Slider/Slider.tsx +8 -3
  427. package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
  428. package/src/Spinner/Spinner.tsx +5 -3
  429. package/src/Stack/Stack.tsx +1 -1
  430. package/src/Stack/StackItem.tsx +1 -1
  431. package/src/TabList/TabList.test.tsx +58 -4
  432. package/src/TabList/TabList.tsx +16 -1
  433. package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +163 -0
  434. package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
  435. package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
  436. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
  437. package/src/Text/Text.tsx +1 -1
  438. package/src/Text/useTruncation.test.tsx +128 -1
  439. package/src/Text/useTruncation.ts +23 -5
  440. package/src/TextArea/TextArea.spec.md +10 -13
  441. package/src/TextArea/TextArea.test.tsx +60 -0
  442. package/src/TextArea/TextArea.tsx +15 -1
  443. package/src/TextInput/TextInput.test.tsx +21 -0
  444. package/src/TextInput/TextInput.tsx +3 -1
  445. package/src/TimeInput/NativeTimeInput.test.tsx +17 -0
  446. package/src/TimeInput/Presentation.test.tsx +21 -0
  447. package/src/TimeInput/TimeInput.doc.mjs +8 -8
  448. package/src/TimeInput/TimeInput.spec.md +45 -48
  449. package/src/TimeInput/TimeInput.test.tsx +76 -0
  450. package/src/TimeInput/TimeInput.tsx +36 -18
  451. package/src/TimeInput/TouchTimeField.tsx +4 -6
  452. package/src/Timestamp/Timestamp.spec.md +6 -12
  453. package/src/Timestamp/Timestamp.test.tsx +30 -5
  454. package/src/Timestamp/Timestamp.tsx +6 -2
  455. package/src/Timestamp/TimestampHoverCard.tsx +4 -4
  456. package/src/Toast/Toast.spec.md +14 -20
  457. package/src/Toast/Toast.tsx +104 -36
  458. package/src/Toast/ToastViewport.test.tsx +719 -1
  459. package/src/Toast/ToastViewport.tsx +100 -50
  460. package/src/Tokenizer/Tokenizer.spec.md +5 -3
  461. package/src/Tokenizer/Tokenizer.test.tsx +68 -0
  462. package/src/Tokenizer/Tokenizer.tsx +14 -2
  463. package/src/Tokenizer/TokenizerBottomSheet.test.tsx +15 -4
  464. package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
  465. package/src/Toolbar/Toolbar.spec.md +5 -6
  466. package/src/Toolbar/Toolbar.test.tsx +30 -0
  467. package/src/Toolbar/Toolbar.tsx +2 -1
  468. package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +18 -6
  469. package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +18 -7
  470. package/src/TopNav/TopNav.test.tsx +27 -0
  471. package/src/TopNav/TopNavMegaMenu.test.tsx +21 -0
  472. package/src/TopNav/TopNavMegaMenu.tsx +4 -1
  473. package/src/TopNav/TopNavMenu.test.tsx +17 -0
  474. package/src/TopNav/TopNavMenu.tsx +1 -0
  475. package/src/Typeahead/Typeahead.test.tsx +40 -0
  476. package/src/Typeahead/Typeahead.tsx +12 -1
  477. package/src/__tests__/pressState.ts +8 -4
  478. package/src/gestures/GestureArena.ts +35 -0
  479. package/src/gestures/GestureHost.ts +2065 -0
  480. package/src/gestures/GestureRecognizer.ts +18 -0
  481. package/src/gestures/LongPressGestureRecognizer.ts +4 -0
  482. package/src/gestures/PanGestureRecognizer.ts +4 -0
  483. package/src/gestures/PinchGestureRecognizer.ts +148 -0
  484. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +256 -0
  485. package/src/gestures/SwipeGestureRecognizer.ts +197 -0
  486. package/src/gestures/TapGestureRecognizer.ts +4 -0
  487. package/src/gestures/VelocityTracker.ts +10 -3
  488. package/src/gestures/__tests__/GestureHost.test.ts +2087 -0
  489. package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
  490. package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
  491. package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +498 -0
  492. package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +108 -0
  493. package/src/gestures/__tests__/arena.test.ts +5 -0
  494. package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +193 -0
  495. package/src/gestures/__tests__/browser/build-fixture.mjs +46 -0
  496. package/src/gestures/__tests__/browser/fixture.ts +307 -0
  497. package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +1137 -0
  498. package/src/gestures/__tests__/browserNegotiation.test.ts +293 -0
  499. package/src/gestures/__tests__/haptics.test.ts +187 -0
  500. package/src/gestures/__tests__/harness.ts +21 -2
  501. package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
  502. package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
  503. package/src/gestures/haptics.ts +203 -0
  504. package/src/gestures/nativeScroll.ts +277 -0
  505. package/src/gestures/touchAction.ts +191 -0
  506. package/src/gestures/touchActionRule.ts +157 -0
  507. package/src/gestures/types.ts +30 -9
  508. package/src/hooks/index.ts +5 -1
  509. package/src/hooks/modalAnnounce.ts +129 -72
  510. package/src/hooks/useAdaptivePresentation.ts +4 -1
  511. package/src/hooks/useAnnounce.doc.mjs +35 -3
  512. package/src/hooks/useAnnounce.replace.test.tsx +516 -0
  513. package/src/hooks/useAnnounce.ts +209 -102
  514. package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +10 -1
  515. package/src/hooks/useAnnounceRenderedText.ts +17 -3
  516. package/src/hooks/useBusyAnnouncement.ts +7 -10
  517. package/src/hooks/useMenuHover.ts +15 -1
  518. package/src/i18n/generated-locales/en.generated.ts +6 -0
  519. package/src/i18n/generated-locales/pseudo.generated.ts +6 -0
  520. package/src/motion/README.md +11 -1
  521. package/src/motion/animator.test.ts +151 -3
  522. package/src/motion/animator.ts +149 -33
  523. package/src/theme/Theme.doc.mjs +1 -1
  524. package/src/theme/defineTheme.ts +117 -8
  525. package/src/theme/derivedVarRegistry.test.ts +4 -0
  526. package/src/theme/domainTokens/domainTokenDefaults.ts +19 -0
  527. package/src/theme/domainTokens/index.ts +6 -10
  528. package/src/theme/expandMotionScale.test.ts +1 -1
  529. package/src/theme/index.ts +5 -0
  530. package/src/theme/motionKnobs.ts +82 -0
  531. package/src/theme/resolveThemeValues.ts +68 -6
  532. package/src/theme/themeAdaptations.ts +52 -12
  533. package/src/theme/themeMotion.test.ts +620 -0
  534. package/src/theme/themeMotion.ts +221 -0
  535. package/src/theme/tokenReferences.ts +149 -0
  536. package/src/theme/tokens.stylex.ts +10 -0
  537. package/src/theme/tokens.ts +15 -158
  538. package/src/utils/focusReturn.ts +17 -6
  539. package/src/utils/getNodeText.test.ts +24 -0
  540. package/src/utils/getNodeText.ts +37 -0
  541. package/src/utils/interactionModality.test.ts +45 -1
  542. package/src/utils/interactionModality.ts +64 -5
  543. package/src/utils/interactionOverlay.stylex.ts +12 -3
  544. package/src/utils/plainDate.test.ts +90 -0
  545. package/src/utils/plainDate.ts +58 -3
  546. package/src/utils/presentation.test.ts +380 -0
  547. package/src/utils/presentation.ts +180 -0
  548. package/src/utils/pressFeedback.test.ts +138 -0
  549. package/src/utils/pressFeedback.ts +34 -11
  550. package/src/utils/pressPaintPriority.test.ts +80 -0
  551. package/src/utils/primaryClick.test.ts +38 -0
  552. package/src/utils/primaryClick.ts +28 -0
  553. package/src/utils/timeFormat.test.ts +204 -0
  554. package/src/utils/timeFormat.ts +314 -0
  555. package/src/utils/touchPresentation.stylex.ts +43 -0
  556. package/src/utils/touchPresentation.test.ts +140 -1
  557. package/src/utils/touchPresentation.ts +5 -3
  558. package/src/utils/unicodeDigits.test.ts +44 -0
  559. package/src/utils/unicodeDigits.ts +71 -0
@@ -0,0 +1,221 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file themeMotion.ts
5
+ * @input A theme's motion configuration: the knobs (`tempo`, `character`),
6
+ * the existing `MotionScaleConfig`, or both
7
+ * @output The resolved knobs, the motion tokens they generate, and
8
+ * `resolveThemeMotion`, the internal resolver the animator and server code
9
+ * read (`spec:AST-108` FR1, FR2, FR5, FR6)
10
+ * @position Theme utility; consumed by resolveThemeValues.ts. Pure: no DOM,
11
+ * no import-time work, safe on the server.
12
+ *
13
+ * `tempo` scales every motion duration token, clamped to 0.75–1.5.
14
+ * `character` picks the entrance and move curves. Every theme follows each
15
+ * person's Reduce Motion setting (`reducedMotion` resolves to `'system'`).
16
+ * No spring reads the knobs yet. With the defaults (tempo 1, `'standard'`, `'system'`) every token is
17
+ * today's.
18
+ *
19
+ * A `MotionScaleConfig` keeps generating its duration tokens, and its fields
20
+ * win over `tempo` (FR5); explicit `tokens` win over both in
21
+ * resolveThemeValues.
22
+ *
23
+ * SYNC: When modified, update:
24
+ * - /packages/core/src/theme/themeMotion.test.ts
25
+ * - /packages/core/src/theme/resolveThemeValues.ts
26
+ * - /packages/core/src/theme/defineTheme.ts (the `motion` field's docs)
27
+ */
28
+
29
+ import {expandMotionScale, type MotionScaleConfig} from './expandMotionScale';
30
+ import {
31
+ resolveKnobs,
32
+ type MotionCharacter,
33
+ type ResolvedMotionKnobs,
34
+ type ThemeMotionKnobs,
35
+ } from './motionKnobs';
36
+ import {durationDefaults, easeDefaults} from './tokens.stylex';
37
+ import {resolveTokenReferences} from './tokenReferences';
38
+
39
+ export {
40
+ TEMPO_RANGE,
41
+ type MotionCharacter,
42
+ type ResolvedMotionKnobs,
43
+ type ThemeMotionKnobs,
44
+ type ThemeReducedMotion,
45
+ } from './motionKnobs';
46
+
47
+ /**
48
+ * A theme's `motion`: the knobs, the existing `MotionScaleConfig`, or both.
49
+ * A `MotionScaleConfig`'s fields win over `tempo` for the durations they set.
50
+ */
51
+ export type ThemeMotionConfig =
52
+ ThemeMotionKnobs | (MotionScaleConfig & ThemeMotionKnobs);
53
+
54
+ /**
55
+ * The entrance and move curve at each character. `'standard'` is the theme's
56
+ * `--ease-standard`, so a theme that overrides that easing keeps its entrances
57
+ * on it.
58
+ */
59
+ export const CHARACTER_EASE = {
60
+ crisp: 'cubic-bezier(0, 0, 0.2, 1)',
61
+ standard: null,
62
+ expressive: 'cubic-bezier(0.3, 1.2, 0.5, 1)',
63
+ } as const satisfies Record<MotionCharacter, string | null>;
64
+
65
+ /** The knobs of `config`, defaults filled in, `tempo` clamped. */
66
+ export function resolveMotionKnobs(
67
+ config: ThemeMotionConfig | undefined,
68
+ ): ResolvedMotionKnobs {
69
+ return resolveKnobs(config);
70
+ }
71
+
72
+ function isScaleConfig(
73
+ config: ThemeMotionConfig,
74
+ ): config is MotionScaleConfig & ThemeMotionKnobs {
75
+ return 'fast' in config && 'medium' in config && 'ratio' in config;
76
+ }
77
+
78
+ /** A duration token's value in ms (`'175ms'` → 175). */
79
+ function msOf(value: string): number {
80
+ return Number.parseFloat(value);
81
+ }
82
+
83
+ /**
84
+ * The private custom property a theme with a `tempo` writes beside its
85
+ * duration tokens: the press release fade (`utils/interactionOverlay.stylex.ts`)
86
+ * multiplies its clock by it.
87
+ */
88
+ export const MOTION_TEMPO_PROPERTY = '--_astryx-motion-tempo';
89
+
90
+ /** The duration tokens at `tempo`: today's values times it, to the ms. */
91
+ export function durationTokensAt(tempo: number): Record<string, string> {
92
+ const tokens: Record<string, string> = {};
93
+ for (const [name, value] of Object.entries(durationDefaults)) {
94
+ tokens[name] = `${Math.round(msOf(value) * tempo)}ms`;
95
+ }
96
+ return tokens;
97
+ }
98
+
99
+ /**
100
+ * The private custom property holding a duration token's value before
101
+ * `tempo` scaled it (`--duration-slow` → `--_astryx-pre-tempo-duration-slow`).
102
+ * Busy loops (Spinner, Skeleton) read it, falling back to the token, so their
103
+ * timing follows a duration scale or an explicit token but never `tempo`
104
+ * (FR4). Private, like every property the knobs add beside the core tokens
105
+ * (`architecture:theme-tokens` INV1).
106
+ */
107
+ export function preTempoName(token: string): string {
108
+ return token.replace(/^--duration-/, '--_astryx-pre-tempo-duration-');
109
+ }
110
+
111
+ /**
112
+ * The motion tokens `config` generates (FR2, FR5): `--duration-*` times
113
+ * `tempo`, with a `MotionScaleConfig`'s own durations winning, and the
114
+ * job-named `--ease-entrance` and `--ease-move` at the theme's character.
115
+ * A knob the config leaves out writes nothing, so a theme extending another
116
+ * keeps the base's value for it; a knob it sets is written even at its
117
+ * default, so a child can set a base's tempo back to 1.
118
+ */
119
+ export function expandThemeMotion(
120
+ config: ThemeMotionConfig,
121
+ ): Record<string, string> {
122
+ const knobs = resolveMotionKnobs(config);
123
+ const tokens: Record<string, string> = {};
124
+ if (knobs.tempoIsSet) {
125
+ Object.assign(tokens, durationTokensAt(knobs.tempo));
126
+ for (const [name, value] of Object.entries(durationDefaults)) {
127
+ tokens[preTempoName(name)] = value;
128
+ }
129
+ // The press release fade, a fixed clock in the stylesheet, scales by the
130
+ // tempo itself (FR4; `component:Button` FR15), read where it plays.
131
+ tokens[MOTION_TEMPO_PROPERTY] = String(knobs.tempo);
132
+ }
133
+ if (isScaleConfig(config)) {
134
+ const scale = expandMotionScale(config);
135
+ Object.assign(tokens, scale);
136
+ if (knobs.tempoIsSet) {
137
+ for (const [name, value] of Object.entries(scale)) {
138
+ if (name.startsWith('--duration-')) {
139
+ tokens[preTempoName(name)] = value;
140
+ }
141
+ }
142
+ }
143
+ }
144
+ const scaleEasing =
145
+ isScaleConfig(config) && config.easing != null ? config.easing : null;
146
+ const ease =
147
+ CHARACTER_EASE[knobs.character] ??
148
+ (config.character != null
149
+ ? (scaleEasing ?? easeDefaults['--ease-standard'])
150
+ : scaleEasing);
151
+ if (ease != null) {
152
+ tokens['--ease-entrance'] = ease;
153
+ tokens['--ease-move'] = ease;
154
+ }
155
+ return tokens;
156
+ }
157
+
158
+ /** What `resolveThemeMotion` returns for a theme. */
159
+ export interface ThemeMotion {
160
+ /** The knobs, defaults filled in. */
161
+ readonly knobs: ResolvedMotionKnobs;
162
+ /** Every `--duration-*` token's value. */
163
+ readonly durations: Readonly<Record<string, string>>;
164
+ /** `--ease-standard`, `--ease-entrance` and `--ease-move`. */
165
+ readonly easings: Readonly<Record<string, string>>;
166
+ }
167
+
168
+ /**
169
+ * A theme's motion values, for the animator and for server code (FR6): the
170
+ * knobs, and the duration and easing tokens they resolve to with the theme's
171
+ * explicit tokens applied. A token written as a reference (`var(--name)`)
172
+ * resolves through the theme's tokens, as `resolveThemeTokens` resolves it
173
+ * (`architecture:theme-tokens` INV6). Pure: it reads only `theme`.
174
+ */
175
+ export function resolveThemeMotion(theme: {
176
+ readonly motion?: ThemeMotionConfig;
177
+ readonly __axes?: {readonly motion?: ThemeMotionConfig};
178
+ readonly tokens?: Readonly<Record<string, unknown>>;
179
+ readonly localTokens?: Readonly<Record<string, unknown>>;
180
+ }): ThemeMotion {
181
+ // A defined theme's motion is its axes': its own merged with its base's.
182
+ const config = theme.__axes?.motion ?? theme.motion;
183
+ const knobs = resolveMotionKnobs(config);
184
+ const generated = config ? expandThemeMotion(config) : {};
185
+ // The graph the references resolve through: the defaults, the knobs'
186
+ // tokens, then the theme's own (a light/dark pair is not a motion value, so
187
+ // only plain strings take part).
188
+ const graph: Record<string, string> = {
189
+ ...durationDefaults,
190
+ ...easeDefaults,
191
+ ...generated,
192
+ };
193
+ for (const tokens of [theme.localTokens, theme.tokens]) {
194
+ for (const [name, value] of Object.entries(tokens ?? {})) {
195
+ if (typeof value === 'string') {
196
+ graph[name] = value;
197
+ }
198
+ }
199
+ }
200
+ const explicit = (name: string): boolean =>
201
+ typeof theme.tokens?.[name] === 'string' || name in generated;
202
+ const resolved = resolveTokenReferences(graph);
203
+ const durations: Record<string, string> = {};
204
+ for (const name of Object.keys(durationDefaults)) {
205
+ durations[name] = resolved[name];
206
+ }
207
+ const standard = resolved['--ease-standard'];
208
+ return {
209
+ knobs,
210
+ durations,
211
+ easings: {
212
+ '--ease-standard': standard,
213
+ '--ease-entrance': explicit('--ease-entrance')
214
+ ? resolved['--ease-entrance']
215
+ : standard,
216
+ '--ease-move': explicit('--ease-move')
217
+ ? resolved['--ease-move']
218
+ : standard,
219
+ },
220
+ };
221
+ }
@@ -0,0 +1,149 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file tokenReferences.ts
5
+ * @input A flat map of token names to raw CSS values
6
+ * @output `resolveTokenReferences`, which follows `var(--name[, fallback])`
7
+ * references through the map, and the CSS parsing helpers it shares
8
+ * (`splitTopLevelComma`, `findMatchingParen`)
9
+ * @position Theme utility with no imports: tokens.ts resolves a theme's token
10
+ * graph on it (evaluating color functions as it goes), and themeMotion.ts
11
+ * resolves motion tokens written as references on it. Pure; safe on the
12
+ * server.
13
+ *
14
+ * SYNC: When modified, update:
15
+ * - /packages/core/src/theme/tokens.ts
16
+ * - /packages/core/src/theme/themeMotion.ts
17
+ */
18
+
19
+ /**
20
+ * Split the arguments of a CSS function body on the first top-level comma.
21
+ * Handles nested functions such as rgba(), color-mix(), var(), and quoted strings.
22
+ */
23
+ export function splitTopLevelComma(input: string): [string, string] | null {
24
+ let depth = 0;
25
+ let quote: '"' | "'" | null = null;
26
+ let isEscaped = false;
27
+
28
+ for (let i = 0; i < input.length; i++) {
29
+ const char = input[i];
30
+
31
+ if (quote !== null) {
32
+ if (isEscaped) {
33
+ isEscaped = false;
34
+ } else if (char === '\\') {
35
+ isEscaped = true;
36
+ } else if (char === quote) {
37
+ quote = null;
38
+ }
39
+ continue;
40
+ }
41
+
42
+ if (char === '"' || char === "'") {
43
+ quote = char;
44
+ continue;
45
+ }
46
+
47
+ if (char === '(') {
48
+ depth++;
49
+ continue;
50
+ }
51
+
52
+ if (char === ')') {
53
+ depth = Math.max(0, depth - 1);
54
+ continue;
55
+ }
56
+
57
+ if (char === ',' && depth === 0) {
58
+ return [input.slice(0, i).trim(), input.slice(i + 1).trim()];
59
+ }
60
+ }
61
+
62
+ return null;
63
+ }
64
+
65
+ /** Index of the `)` matching the `(` at `openIndex`, or -1 when unbalanced. */
66
+ export function findMatchingParen(input: string, openIndex: number): number {
67
+ let depth = 0;
68
+ for (let i = openIndex; i < input.length; i++) {
69
+ const char = input[i];
70
+ if (char === '(') {
71
+ depth++;
72
+ } else if (char === ')') {
73
+ depth--;
74
+ if (depth === 0) {
75
+ return i;
76
+ }
77
+ }
78
+ }
79
+ return -1;
80
+ }
81
+
82
+ /**
83
+ * Resolves every value in `raw` to a concrete one: each `var(--name[,
84
+ * fallback])` is replaced by `name`'s resolved value, or by its fallback when
85
+ * `raw` has no `name`, and is kept as written when neither exists or the
86
+ * references form a cycle. `evaluate` then runs on each substituted value
87
+ * (tokens.ts evaluates CSS color functions there).
88
+ */
89
+ export function resolveTokenReferences(
90
+ raw: Readonly<Record<string, string>>,
91
+ evaluate: (expr: string) => string = expr => expr,
92
+ ): Record<string, string> {
93
+ const cache: Record<string, string> = {};
94
+
95
+ // `seen` tracks the reference chain, so a cycle resolves to the literal
96
+ // reference instead of recursing forever.
97
+ const substitute = (expr: string, seen: Set<string>): string => {
98
+ const start = expr.indexOf('var(');
99
+ if (start === -1) {
100
+ return expr;
101
+ }
102
+ const openIndex = start + 'var'.length;
103
+ const closeIndex = findMatchingParen(expr, openIndex);
104
+ if (closeIndex === -1) {
105
+ return expr;
106
+ }
107
+
108
+ const inner = expr.slice(openIndex + 1, closeIndex);
109
+ const commaSplit = splitTopLevelComma(inner);
110
+ const name = (commaSplit ? commaSplit[0] : inner).trim();
111
+ const fallback = commaSplit ? commaSplit[1] : null;
112
+
113
+ let replacement: string;
114
+ if (seen.has(name)) {
115
+ replacement = expr.slice(start, closeIndex + 1);
116
+ } else if (name in raw) {
117
+ seen.add(name);
118
+ replacement = reference(name, seen);
119
+ seen.delete(name);
120
+ } else if (fallback !== null) {
121
+ replacement = substitute(fallback.trim(), seen);
122
+ } else {
123
+ replacement = expr.slice(start, closeIndex + 1);
124
+ }
125
+
126
+ const rest = substitute(expr.slice(closeIndex + 1), seen);
127
+ return expr.slice(0, start) + replacement + rest;
128
+ };
129
+
130
+ const reference = (name: string, seen: Set<string>): string => {
131
+ if (name in cache) {
132
+ return cache[name];
133
+ }
134
+ const value = raw[name];
135
+ if (value === undefined) {
136
+ return '';
137
+ }
138
+ const resolved = evaluate(
139
+ value.includes('var(') ? substitute(value, seen) : value,
140
+ );
141
+ cache[name] = resolved;
142
+ return resolved;
143
+ };
144
+
145
+ for (const name of Object.keys(raw)) {
146
+ reference(name, new Set<string>());
147
+ }
148
+ return cache;
149
+ }
@@ -323,6 +323,16 @@ export type DurationVarName = keyof typeof durationDefaults;
323
323
 
324
324
  export const easeDefaults = {
325
325
  '--ease-standard': 'cubic-bezier(0.24, 1, 0.4, 1)',
326
+ /**
327
+ * Entrances: a layer or element arriving. A theme's `character` sets it
328
+ * (spec:AST-108 FR2); at `'standard'` it equals --ease-standard.
329
+ */
330
+ '--ease-entrance': 'cubic-bezier(0.24, 1, 0.4, 1)',
331
+ /**
332
+ * Moves: an element changing place or size on screen. A theme's
333
+ * `character` sets it; at `'standard'` it equals --ease-standard.
334
+ */
335
+ '--ease-move': 'cubic-bezier(0.24, 1, 0.4, 1)',
326
336
  '--ease-exit': 'cubic-bezier(0.3, 0, 0.6, 0.6)',
327
337
  } as const;
328
338
 
@@ -17,6 +17,7 @@
17
17
  *
18
18
  * SYNC: When modified, update:
19
19
  * - /packages/core/src/theme/useTheme.ts
20
+ * - /packages/core/src/theme/tokenReferences.ts (the `var()` resolver)
20
21
  * - /packages/core/src/theme/index.ts
21
22
  */
22
23
 
@@ -28,6 +29,11 @@ import {
28
29
  } from './defineTheme';
29
30
  import {parseColor, formatColor} from '../utils/color';
30
31
  import {generatedScopedStatusRoleDefaults} from './generateThemeRules';
32
+ import {
33
+ findMatchingParen,
34
+ resolveTokenReferences,
35
+ splitTopLevelComma,
36
+ } from './tokenReferences';
31
37
 
32
38
  /** Resolved color mode used when choosing the side of light/dark token values. */
33
39
  export type ResolvedThemeMode = 'light' | 'dark';
@@ -70,52 +76,6 @@ export const tokenVars: Record<TokenName, string> = Object.fromEntries(
70
76
  Object.keys(tokenDefaults).map(name => [name, tokenVar(name)]),
71
77
  ) as Record<TokenName, string>;
72
78
 
73
- /**
74
- * Split the arguments of a CSS function body on the first top-level comma.
75
- * Handles nested functions such as rgba(), color-mix(), var(), and quoted strings.
76
- */
77
- function splitTopLevelComma(input: string): [string, string] | null {
78
- let depth = 0;
79
- let quote: '"' | "'" | null = null;
80
- let isEscaped = false;
81
-
82
- for (let i = 0; i < input.length; i++) {
83
- const char = input[i];
84
-
85
- if (quote !== null) {
86
- if (isEscaped) {
87
- isEscaped = false;
88
- } else if (char === '\\') {
89
- isEscaped = true;
90
- } else if (char === quote) {
91
- quote = null;
92
- }
93
- continue;
94
- }
95
-
96
- if (char === '"' || char === "'") {
97
- quote = char;
98
- continue;
99
- }
100
-
101
- if (char === '(') {
102
- depth++;
103
- continue;
104
- }
105
-
106
- if (char === ')') {
107
- depth = Math.max(0, depth - 1);
108
- continue;
109
- }
110
-
111
- if (char === ',' && depth === 0) {
112
- return [input.slice(0, i).trim(), input.slice(i + 1).trim()];
113
- }
114
- }
115
-
116
- return null;
117
- }
118
-
119
79
  /** Parse a CSS light-dark(light, dark) function into its two argument values. */
120
80
  function parseLightDark(value: string): [light: string, dark: string] | null {
121
81
  const trimmed = value.trim();
@@ -158,27 +118,11 @@ function resolveXDSTokenValue(
158
118
  // Generated themes emit derived tokens as references to other tokens rather
159
119
  // than baked-in values, so a scoped CSS override of a base token re-themes the
160
120
  // subtree that references it. The CSS cascade resolves those references, but
161
- // non-CSS consumers (canvas, SVG, data-viz) need the concrete value. These
162
- // helpers replay the same resolution in JS: follow `var()` references through
163
- // the resolved token map (iteratively, guarding against cycles) and evaluate
164
- // the CSS color functions used by the theme generator against those values.
165
-
166
- /** Index of the `)` matching the `(` at `openIndex`, or -1 when unbalanced. */
167
- function findMatchingParen(input: string, openIndex: number): number {
168
- let depth = 0;
169
- for (let i = openIndex; i < input.length; i++) {
170
- const char = input[i];
171
- if (char === '(') {
172
- depth++;
173
- } else if (char === ')') {
174
- depth--;
175
- if (depth === 0) {
176
- return i;
177
- }
178
- }
179
- }
180
- return -1;
181
- }
121
+ // non-CSS consumers (canvas, SVG, data-viz) need the concrete value. The same
122
+ // resolution replays in JS: tokenReferences.ts follows `var()` references
123
+ // through the resolved token map (guarding against cycles), and these helpers
124
+ // evaluate the CSS color functions used by the theme generator against those
125
+ // values.
182
126
 
183
127
  /** Split a color-mix component into its color and optional percentage. */
184
128
  function parseMixComponent(
@@ -290,93 +234,6 @@ function evaluateColorFunctions(expr: string): string {
290
234
  );
291
235
  }
292
236
 
293
- /**
294
- * Substitute `var(--name[, fallback])` references with their resolved values.
295
- * `seen` tracks the reference chain so cycles resolve to the literal reference
296
- * instead of recursing forever.
297
- */
298
- function substituteVars(
299
- expr: string,
300
- raw: Record<string, string>,
301
- cache: Record<string, string>,
302
- seen: Set<string>,
303
- ): string {
304
- const start = expr.indexOf('var(');
305
- if (start === -1) {
306
- return expr;
307
- }
308
- const openIndex = start + 'var'.length;
309
- const closeIndex = findMatchingParen(expr, openIndex);
310
- if (closeIndex === -1) {
311
- return expr;
312
- }
313
-
314
- const inner = expr.slice(openIndex + 1, closeIndex);
315
- const commaSplit = splitTopLevelComma(inner);
316
- const name = (commaSplit ? commaSplit[0] : inner).trim();
317
- const fallback = commaSplit ? commaSplit[1] : null;
318
-
319
- let replacement: string;
320
- if (seen.has(name)) {
321
- replacement = expr.slice(start, closeIndex + 1);
322
- } else if (name in raw) {
323
- seen.add(name);
324
- replacement = resolveReference(name, raw, cache, seen);
325
- seen.delete(name);
326
- } else if (fallback !== null) {
327
- replacement = substituteVars(fallback.trim(), raw, cache, seen);
328
- } else {
329
- replacement = expr.slice(start, closeIndex + 1);
330
- }
331
-
332
- const rest = substituteVars(expr.slice(closeIndex + 1), raw, cache, seen);
333
- return expr.slice(0, start) + replacement + rest;
334
- }
335
-
336
- /** Fully resolve a single expression: substitute references, then evaluate colors. */
337
- function resolveExpression(
338
- expr: string,
339
- raw: Record<string, string>,
340
- cache: Record<string, string>,
341
- seen: Set<string>,
342
- ): string {
343
- if (!expr.includes('var(') && !expr.includes('color-mix(')) {
344
- return expr;
345
- }
346
- const substituted = substituteVars(expr, raw, cache, seen);
347
- return evaluateColorFunctions(substituted);
348
- }
349
-
350
- /** Resolve one token by name, memoizing the result in `cache`. */
351
- function resolveReference(
352
- name: string,
353
- raw: Record<string, string>,
354
- cache: Record<string, string>,
355
- seen: Set<string>,
356
- ): string {
357
- if (name in cache) {
358
- return cache[name];
359
- }
360
- const value = raw[name];
361
- if (value === undefined) {
362
- return '';
363
- }
364
- const resolved = resolveExpression(value, raw, cache, seen);
365
- cache[name] = resolved;
366
- return resolved;
367
- }
368
-
369
- /** Resolve every reference/color function in a raw token map to concrete values. */
370
- function resolveReferences(
371
- raw: Record<string, string>,
372
- ): Record<string, string> {
373
- const cache: Record<string, string> = {};
374
- for (const name of Object.keys(raw)) {
375
- resolveReference(name, raw, cache, new Set<string>());
376
- }
377
- return cache;
378
- }
379
-
380
237
  /**
381
238
  * Resolve all Astryx token values for a theme and effective color mode.
382
239
  *
@@ -403,7 +260,7 @@ export function resolveThemeTokens(
403
260
  }
404
261
 
405
262
  if (theme == null) {
406
- return resolveReferences(resolved);
263
+ return resolveTokenReferences(resolved, evaluateColorFunctions);
407
264
  }
408
265
 
409
266
  // A theme's local tokens resolve its references to them, then leave the
@@ -436,9 +293,9 @@ export function resolveThemeTokens(
436
293
  }
437
294
 
438
295
  return Object.fromEntries(
439
- Object.entries(resolveReferences(resolved)).filter(
440
- ([key]) => !localKeys.has(key),
441
- ),
296
+ Object.entries(
297
+ resolveTokenReferences(resolved, evaluateColorFunctions),
298
+ ).filter(([key]) => !localKeys.has(key)),
442
299
  );
443
300
  }
444
301
 
@@ -12,7 +12,10 @@
12
12
  * overlays (Dialog, DropdownMenu) that move focus programmatically.
13
13
  */
14
14
 
15
- import {getInteractionModality} from './interactionModality';
15
+ import {
16
+ getInteractionModality,
17
+ type InteractionModality,
18
+ } from './interactionModality';
16
19
 
17
20
  /**
18
21
  * True when focus rests on nothing in particular — no active element, or the
@@ -43,21 +46,29 @@ export function isFocusDetached(doc: Document = document): boolean {
43
46
  * autofocus target, the control that opened a Dialog, or a menu trigger the
44
47
  * caller renders. Pass `options` (for example `preventScroll`) as to `focus()`.
45
48
  *
49
+ * `modality` defaults to the page's last input. A caller moving focus inside a
50
+ * second document (a same-origin iframe, a Document Picture-in-Picture window)
51
+ * passes that document's, which it tracks with `trackInteractionModalityIn`.
52
+ *
46
53
  * Make sure modality tracking is active (`useInteractionModalityTracking()`)
47
54
  * in the component that calls this.
48
55
  */
49
56
  export function focusForLastInput(
50
57
  element: HTMLElement,
51
58
  options?: FocusOptions,
59
+ modality: InteractionModality = getInteractionModality(),
52
60
  ): void {
53
61
  // A text-entry field paints its own focus treatment to show where typing
54
- // goes, and an extra blur there can run validation or mark it touched.
62
+ // goes, and an extra blur there can run validation or mark it touched. The
63
+ // field's own window: one in an iframe or a Picture-in-Picture window is
64
+ // never an instance of the page's constructors.
65
+ const view = element.ownerDocument.defaultView ?? window;
55
66
  const isTextEntry =
56
- element instanceof HTMLInputElement ||
57
- element instanceof HTMLTextAreaElement ||
58
- element instanceof HTMLSelectElement ||
67
+ element instanceof view.HTMLInputElement ||
68
+ element instanceof view.HTMLTextAreaElement ||
69
+ element instanceof view.HTMLSelectElement ||
59
70
  element.isContentEditable;
60
- if (isTextEntry || getInteractionModality() !== 'pointer') {
71
+ if (isTextEntry || modality !== 'pointer') {
61
72
  if (options === undefined) {
62
73
  element.focus();
63
74
  } else {
@@ -0,0 +1,24 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {createElement} from 'react';
4
+ import {describe, expect, it} from 'vitest';
5
+
6
+ import {getNodeText} from './getNodeText';
7
+
8
+ describe('getNodeText', () => {
9
+ it('reads strings, numbers and element children, joined with spaces', () => {
10
+ expect(getNodeText('Name')).toBe('Name');
11
+ expect(getNodeText(42)).toBe('42');
12
+ expect(getNodeText(createElement('span', null, 'Amount (EUR)'))).toBe(
13
+ 'Amount (EUR)',
14
+ );
15
+ expect(getNodeText(['Total', createElement('b', null, 3)])).toBe('Total 3');
16
+ });
17
+
18
+ it('yields nothing for empty nodes and text a component renders from other props', () => {
19
+ for (const node of [null, undefined, true, false, []])
20
+ {expect(getNodeText(node)).toBe('');}
21
+ const Labelled = ({label}: {label: string}) => label;
22
+ expect(getNodeText(createElement(Labelled, {label: 'Hidden'}))).toBe('');
23
+ });
24
+ });