@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,37 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file getNodeText.ts
5
+ * @input Receives a React node
6
+ * @output Exports getNodeText, the node's plain text
7
+ * @position Shared utility; consumed where a rendered node also needs a
8
+ * spoken name (Toast announcements, Table column-resize handle names)
9
+ */
10
+
11
+ import {isValidElement} from 'react';
12
+ import type {ReactNode} from 'react';
13
+
14
+ /**
15
+ * The plain text a node renders through strings, numbers and element
16
+ * children, joined with spaces. Text a component renders internally, from
17
+ * props other than `children`, is not reachable and yields `''`.
18
+ */
19
+ export function getNodeText(node: ReactNode): string {
20
+ if (node == null || typeof node === 'boolean') {
21
+ return '';
22
+ }
23
+ if (typeof node === 'string') {
24
+ return node;
25
+ }
26
+ if (typeof node === 'number') {
27
+ return String(node);
28
+ }
29
+ if (Array.isArray(node)) {
30
+ return node.map(getNodeText).filter(Boolean).join(' ');
31
+ }
32
+ if (isValidElement(node)) {
33
+ const {children} = node.props as {children?: ReactNode};
34
+ return getNodeText(children);
35
+ }
36
+ return '';
37
+ }
@@ -3,7 +3,8 @@
3
3
  /**
4
4
  * @file interactionModality.test.ts
5
5
  * @input The interaction-modality utility loaded more than once
6
- * @output Verifies document-wide continuity and shared Shift-key modality policy
6
+ * @output Verifies document-wide continuity, shared Shift-key modality policy,
7
+ * and a second document's separate value
7
8
  * @position Unit coverage for interactionModality.ts
8
9
  */
9
10
 
@@ -88,6 +89,49 @@ describe('interactionModality', () => {
88
89
  ).toHaveLength(1);
89
90
  });
90
91
 
92
+ it("keeps a second document's input apart from the page's", async () => {
93
+ const pageDocument = document.implementation.createHTMLDocument();
94
+ const secondDocument = document.implementation.createHTMLDocument();
95
+ vi.stubGlobal('document', pageDocument);
96
+ const tracker = await loadTracker();
97
+ tracker.__startInteractionModalityTrackingForTest();
98
+ tracker.trackInteractionModalityIn(secondDocument);
99
+
100
+ pageDocument.dispatchEvent(new Event('pointerdown'));
101
+ secondDocument.dispatchEvent(new KeyboardEvent('keydown', {key: 'Escape'}));
102
+ expect(tracker.getInteractionModality()).toBe('pointer');
103
+ expect(tracker.getInteractionModality(pageDocument)).toBe('pointer');
104
+ expect(tracker.getInteractionModality(secondDocument)).toBe('keyboard');
105
+
106
+ secondDocument.dispatchEvent(new Event('pointerdown'));
107
+ pageDocument.dispatchEvent(new KeyboardEvent('keydown', {key: 'Tab'}));
108
+ expect(tracker.getInteractionModality()).toBe('keyboard');
109
+ expect(tracker.getInteractionModality(secondDocument)).toBe('pointer');
110
+ });
111
+
112
+ it("releases a second document's listeners with its last consumer", async () => {
113
+ const secondDocument = document.implementation.createHTMLDocument();
114
+ const tracker = await loadTracker();
115
+ const removeEventListener = vi.spyOn(secondDocument, 'removeEventListener');
116
+ const releaseFirst = tracker.trackInteractionModalityIn(secondDocument);
117
+ const releaseSecond = tracker.trackInteractionModalityIn(secondDocument);
118
+ secondDocument.dispatchEvent(new Event('pointerdown'));
119
+ expect(tracker.getInteractionModality(secondDocument)).toBe('pointer');
120
+
121
+ releaseFirst();
122
+ releaseFirst();
123
+ secondDocument.dispatchEvent(new KeyboardEvent('keydown', {key: 'Tab'}));
124
+ expect(tracker.getInteractionModality(secondDocument)).toBe('keyboard');
125
+ expect(removeEventListener).not.toHaveBeenCalled();
126
+
127
+ releaseSecond();
128
+ expect(removeEventListener.mock.calls.map(([type]) => type).sort()).toEqual(
129
+ ['keydown', 'pointerdown'],
130
+ );
131
+ secondDocument.dispatchEvent(new Event('pointerdown'));
132
+ expect(tracker.getInteractionModality(secondDocument)).toBe('keyboard');
133
+ });
134
+
91
135
  it('uses the keyboard-safe default without a document', async () => {
92
136
  vi.stubGlobal('document', undefined);
93
137
  const serverModule = await loadTracker();
@@ -6,7 +6,9 @@
6
6
  * @file interactionModality.ts
7
7
  * @input Global pointerdown/keydown events
8
8
  * @output `useInteractionModalityTracking()` activates document-lifetime tracking;
9
- * `getInteractionModality()` reads how the user last interacted
9
+ * `getInteractionModality()` reads how the user last interacted;
10
+ * `trackInteractionModalityIn(doc)` and `getInteractionModality(doc)` do the
11
+ * same for a second document
10
12
  * @position Internal document-wide singleton; used where `:focus-visible` alone
11
13
  * is too broad
12
14
  *
@@ -26,8 +28,12 @@
26
28
  * The store lives on `document`, so duplicate Astryx bundles share one state
27
29
  * value and one listener pair. The first mounted consumer activates tracking;
28
30
  * the listeners then remain for the document lifetime so input during a gap
29
- * between consumers is not lost. Importing this module has no DOM side effects,
30
- * and server rendering keeps the keyboard-safe default.
31
+ * between consumers is not lost. A second document (a same-origin iframe, a
32
+ * Document Picture-in-Picture window) gets its own store when a component
33
+ * tracks it, since input there never reaches the page's listeners; its
34
+ * listeners stay only while a consumer there is mounted. Importing this module
35
+ * has no DOM side effects, and server rendering keeps the keyboard-safe
36
+ * default.
31
37
  */
32
38
 
33
39
  import {useEffect} from 'react';
@@ -37,6 +43,8 @@ export type InteractionModality = 'keyboard' | 'pointer';
37
43
  type InteractionModalityStore = {
38
44
  modality: InteractionModality;
39
45
  isListening: boolean;
46
+ /** Mounted consumers holding a second document's listeners. */
47
+ consumers?: number;
40
48
  onPointerDown: () => void;
41
49
  onKeyDown: (event: KeyboardEvent) => void;
42
50
  };
@@ -107,8 +115,59 @@ export function useInteractionModalityTracking(): void {
107
115
  useEffect(() => trackInteractionModality(), []);
108
116
  }
109
117
 
110
- /** How the user last interacted with the page. */
111
- export function getInteractionModality(): InteractionModality {
118
+ /**
119
+ * Track a second document while a consumer there is mounted: a component an
120
+ * app renders into a same-origin iframe or a Document Picture-in-Picture
121
+ * window gets input there that never reaches the page's listeners. The first
122
+ * consumer installs the document's listener pair and the last one's cleanup
123
+ * removes it. Read the value with `getInteractionModality(doc)`. The page's
124
+ * own document keeps its document-lifetime listeners.
125
+ */
126
+ export function trackInteractionModalityIn(
127
+ targetDocument: Document,
128
+ ): () => void {
129
+ if (typeof document !== 'undefined' && targetDocument === document) {
130
+ return trackInteractionModality();
131
+ }
132
+ const store = getStore(targetDocument);
133
+ store.consumers = (store.consumers ?? 0) + 1;
134
+ if (store.consumers === 1) {
135
+ store.isListening = true;
136
+ targetDocument.addEventListener('pointerdown', store.onPointerDown, {
137
+ capture: true,
138
+ passive: true,
139
+ });
140
+ targetDocument.addEventListener('keydown', store.onKeyDown, {
141
+ capture: true,
142
+ passive: true,
143
+ });
144
+ }
145
+ let isReleased = false;
146
+ return () => {
147
+ if (isReleased) {
148
+ return;
149
+ }
150
+ isReleased = true;
151
+ store.consumers = (store.consumers ?? 1) - 1;
152
+ if (store.consumers === 0) {
153
+ store.isListening = false;
154
+ targetDocument.removeEventListener('pointerdown', store.onPointerDown, {
155
+ capture: true,
156
+ });
157
+ targetDocument.removeEventListener('keydown', store.onKeyDown, {
158
+ capture: true,
159
+ });
160
+ }
161
+ };
162
+ }
163
+
164
+ /** How the user last interacted with the page, or with `targetDocument`. */
165
+ export function getInteractionModality(
166
+ targetDocument?: Document,
167
+ ): InteractionModality {
168
+ if (targetDocument != null) {
169
+ return getStore(targetDocument).modality;
170
+ }
112
171
  return typeof document === 'undefined'
113
172
  ? 'keyboard'
114
173
  : getStore(document).modality;
@@ -116,8 +116,14 @@ export const pressConsts = stylex.defineConsts({
116
116
  releaseMs: 200,
117
117
  });
118
118
 
119
- /** The release's clock as CSS. */
120
- const PRESS_RELEASE_DURATION = `${pressConsts.releaseMs}ms`;
119
+ /**
120
+ * The release's clock as CSS, scaled by the theme's `--_astryx-motion-tempo`
121
+ * (`spec:AST-108` FR4, `component:Button` FR15) up to 1.5, its maximum. The
122
+ * controller's timer reads the same property.
123
+ */
124
+ const PRESS_RELEASE_DURATION = `calc(${pressConsts.releaseMs}ms * min(var(--_astryx-motion-tempo, 1), 1.5))`;
125
+ /** The same clock under Reduce Motion: a tempo may shorten it, never lengthen it. */
126
+ const PRESS_RELEASE_DURATION_REDUCED = `min(${pressConsts.releaseMs}ms, calc(${pressConsts.releaseMs}ms * var(--_astryx-motion-tempo, 1)))`;
121
127
 
122
128
  const ENABLED = ':where(:not(:disabled,[aria-disabled="true"]))';
123
129
  const HOVER_HOVER = '@media (hover: hover)';
@@ -205,7 +211,10 @@ const pressReleaseAnimation = {
205
211
  },
206
212
  animationDuration: {
207
213
  default: null,
208
- '[data-astryx-press="fading"]': PRESS_RELEASE_DURATION,
214
+ '[data-astryx-press="fading"]': {
215
+ default: PRESS_RELEASE_DURATION,
216
+ '@media (prefers-reduced-motion: reduce)': PRESS_RELEASE_DURATION_REDUCED,
217
+ },
209
218
  },
210
219
  animationTimingFunction: {
211
220
  default: null,
@@ -7,6 +7,7 @@ import {
7
7
  plainDateFromISO,
8
8
  plainDateToISO,
9
9
  plainDateToDate,
10
+ dateTimeFormatFor,
10
11
  plainDateFromDate,
11
12
  plainDateToday,
12
13
  getDaysInMonth,
@@ -28,6 +29,7 @@ import {
28
29
  plainDateGetWeekNumber,
29
30
  plainDateFormat,
30
31
  formatSharedDate,
32
+ DATE_FORMAT_LONG,
31
33
  DATE_FORMAT_WITH_WEEKDAY,
32
34
  DATE_FORMAT_MONTH_YEAR,
33
35
  plainDateWeekFieldName,
@@ -754,6 +756,94 @@ describe('plainDateGetWeekNumber', () => {
754
756
  });
755
757
 
756
758
  describe('plainDateFormat', () => {
759
+ it('keeps one formatter per locale and options, whatever order the options are in', () => {
760
+ // A month of day labels, as a calendar renders them, reuses one formatter.
761
+ const first = dateTimeFormatFor('en-NZ', DATE_FORMAT_WITH_WEEKDAY);
762
+ expect(dateTimeFormatFor('en-NZ', DATE_FORMAT_WITH_WEEKDAY)).toBe(first);
763
+ expect(
764
+ dateTimeFormatFor('en-NZ', {
765
+ year: 'numeric',
766
+ day: 'numeric',
767
+ month: 'long',
768
+ weekday: 'long',
769
+ }),
770
+ ).toBe(first);
771
+ // Other options, or another locale, get their own.
772
+ expect(dateTimeFormatFor('en-NZ', DATE_FORMAT_MONTH_YEAR)).not.toBe(first);
773
+ expect(dateTimeFormatFor('en-ZA', DATE_FORMAT_WITH_WEEKDAY)).not.toBe(
774
+ first,
775
+ );
776
+ });
777
+
778
+ it('formats the same date after the host zone moves', () => {
779
+ // The page stays open while the device travels east: a formatter cached
780
+ // in the first zone must not move the date.
781
+ const zone = process.env.TZ;
782
+ try {
783
+ process.env.TZ = 'America/Los_Angeles';
784
+ expect(
785
+ plainDateFormat(
786
+ {year: 2026, month: 2, day: 1},
787
+ DATE_FORMAT_MONTH_YEAR,
788
+ 'en-IE',
789
+ ),
790
+ ).toBe('February 2026');
791
+ process.env.TZ = 'America/New_York';
792
+ expect(
793
+ plainDateFormat(
794
+ {year: 2026, month: 2, day: 1},
795
+ DATE_FORMAT_MONTH_YEAR,
796
+ 'en-IE',
797
+ ),
798
+ ).toBe('February 2026');
799
+ process.env.TZ = 'Pacific/Kiritimati';
800
+ expect(
801
+ plainDateFormat(
802
+ {year: 2026, month: 2, day: 1},
803
+ DATE_FORMAT_WITH_WEEKDAY,
804
+ 'en-IE',
805
+ ),
806
+ ).toBe('Sunday 1 February 2026');
807
+ } finally {
808
+ if (zone === undefined) {
809
+ delete process.env.TZ;
810
+ } else {
811
+ process.env.TZ = zone;
812
+ }
813
+ }
814
+ });
815
+
816
+ it('prints a zone name or a time of day in the host zone, as before', () => {
817
+ // A PlainDate has neither: such fields read local midnight in the zone
818
+ // current at the call, not the UTC the date-only path formats in.
819
+ const zone = process.env.TZ;
820
+ try {
821
+ process.env.TZ = 'America/Los_Angeles';
822
+ const withZone = plainDateFormat(
823
+ {year: 2026, month: 1, day: 25},
824
+ {...DATE_FORMAT_LONG, timeZoneName: 'short'},
825
+ 'en-US',
826
+ );
827
+ expect(withZone).toContain('January 25, 2026');
828
+ expect(withZone).toContain('PST');
829
+ expect(withZone).not.toContain('UTC');
830
+ process.env.TZ = 'America/New_York';
831
+ expect(
832
+ plainDateFormat(
833
+ {year: 2026, month: 1, day: 25},
834
+ {...DATE_FORMAT_LONG, timeZoneName: 'short'},
835
+ 'en-US',
836
+ ),
837
+ ).toContain('EST');
838
+ } finally {
839
+ if (zone === undefined) {
840
+ delete process.env.TZ;
841
+ } else {
842
+ process.env.TZ = zone;
843
+ }
844
+ }
845
+ });
846
+
757
847
  it('returns a human-readable date string with weekday', () => {
758
848
  const result = plainDateFormat(
759
849
  {year: 2026, month: 1, day: 25},
@@ -374,10 +374,65 @@ export function plainDateFormat(
374
374
  options: Intl.DateTimeFormatOptions,
375
375
  locale: Locale = 'en',
376
376
  ): string {
377
- return new Intl.DateTimeFormat(locale, {
377
+ const calendar = options.calendar ?? 'gregory';
378
+ if (options.timeZone != null) {
379
+ return dateTimeFormatFor(locale, {...options, calendar}).format(
380
+ plainDateToDate(pd),
381
+ );
382
+ }
383
+ if (TIME_OF_DAY_FIELDS.some(field => options[field] != null)) {
384
+ // A zone name or a time of day reads local midnight in the zone current
385
+ // at the call. A cached formatter would keep the zone it was built in,
386
+ // so this one is built for the call.
387
+ return new Intl.DateTimeFormat(locale, {...options, calendar}).format(
388
+ plainDateToDate(pd),
389
+ );
390
+ }
391
+ // Date fields alone: UTC midnight formatted in UTC, so neither the cached
392
+ // formatter nor the date depends on the host's zone, which can change while
393
+ // a page is open.
394
+ return dateTimeFormatFor(locale, {
378
395
  ...options,
379
- calendar: options.calendar ?? 'gregory',
380
- }).format(plainDateToDate(pd));
396
+ calendar,
397
+ timeZone: 'UTC',
398
+ }).format(utcTime(pd.year, pd.month - 1, pd.day));
399
+ }
400
+
401
+ /** Options that print a time of day or a zone, which a PlainDate lacks. */
402
+ const TIME_OF_DAY_FIELDS = [
403
+ 'timeZoneName',
404
+ 'hour',
405
+ 'minute',
406
+ 'second',
407
+ 'fractionalSecondDigits',
408
+ 'dayPeriod',
409
+ 'timeStyle',
410
+ ] as const satisfies ReadonlyArray<keyof Intl.DateTimeFormatOptions>;
411
+
412
+ /**
413
+ * One `Intl.DateTimeFormat` per locale and options, built on first use.
414
+ * Building a formatter costs far more than formatting with it, and a calendar
415
+ * formats each of a month's 42 day labels with the same options on every
416
+ * render. The options are keyed in a fixed order, so the same options written
417
+ * in another order share a formatter.
418
+ */
419
+ const dateTimeFormats = new Map<string, Intl.DateTimeFormat>();
420
+
421
+ /** @internal plainDateFormat's formatter cache; not part of the public API. */
422
+ export function dateTimeFormatFor(
423
+ locale: Locale,
424
+ options: Intl.DateTimeFormatOptions,
425
+ ): Intl.DateTimeFormat {
426
+ const key = JSON.stringify([
427
+ locale,
428
+ Object.entries(options).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),
429
+ ]);
430
+ let format = dateTimeFormats.get(key);
431
+ if (format == null) {
432
+ format = new Intl.DateTimeFormat(locale, options);
433
+ dateTimeFormats.set(key, format);
434
+ }
435
+ return format;
381
436
  }
382
437
 
383
438
  /**