@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
@@ -12,6 +12,10 @@
12
12
  */
13
13
 
14
14
  import * as stylex from '@stylexjs/stylex';
15
+ import {TEMPO_RANGE, expandThemeMotion} from '../theme/themeMotion';
16
+ import {readFileSync} from 'node:fs';
17
+ import {dirname, join} from 'node:path';
18
+ import {fileURLToPath} from 'node:url';
15
19
  import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
16
20
  import {
17
21
  durationToMs,
@@ -317,6 +321,122 @@ describe('the release', () => {
317
321
  expect(rows[0].hasAttribute(PRESSED_ATTRIBUTE)).toBe(false);
318
322
  });
319
323
 
324
+ it('scales the fade by the tempo its stylesheet reads, a theme\u2019s or an adaptation rule\u2019s (spec:AST-108 FR4, component:Button FR15)', () => {
325
+ // A rule writes the tempo (a media-query adaptation, say); browsers
326
+ // inherit it from the theme, jsdom only reads it where it is declared.
327
+ const style = document.createElement('style');
328
+ style.textContent = '.slow-row { --_astryx-motion-tempo: 1.5; }';
329
+ document.head.appendChild(style);
330
+ rows[0].classList.add('slow-row');
331
+ try {
332
+ press(rows[0], 'pointerdown', 10, 10);
333
+ vi.advanceTimersByTime(PRESS_ONSET_MS);
334
+ press(rows[0], 'pointerup', 10, 10);
335
+ vi.advanceTimersByTime(PRESS_FADE_MS);
336
+ expect(rows[0].getAttribute(PRESSED_ATTRIBUTE)).toBe('fading');
337
+ vi.advanceTimersByTime(PRESS_FADE_MS / 2);
338
+ expect(rows[0].hasAttribute(PRESSED_ATTRIBUTE)).toBe(false);
339
+ } finally {
340
+ style.remove();
341
+ }
342
+ });
343
+
344
+ it('under Reduce Motion a tempo may shorten the fade but never lengthens it past 200 ms (spec:AST-108 FR4)', () => {
345
+ vi.stubGlobal(
346
+ 'matchMedia',
347
+ (query: string): MediaQueryList =>
348
+ ({
349
+ matches: /prefers-reduced-motion:\s*reduce/.test(query),
350
+ media: query,
351
+ onchange: null,
352
+ addListener: () => undefined,
353
+ removeListener: () => undefined,
354
+ addEventListener: () => undefined,
355
+ removeEventListener: () => undefined,
356
+ dispatchEvent: () => false,
357
+ }) as MediaQueryList,
358
+ );
359
+ const style = document.createElement('style');
360
+ style.textContent =
361
+ '.slow-row { --_astryx-motion-tempo: 1.5; } .quick-row { --_astryx-motion-tempo: 0.75; }';
362
+ document.head.appendChild(style);
363
+ try {
364
+ rows[0].classList.add('slow-row');
365
+ press(rows[0], 'pointerdown', 10, 10);
366
+ vi.advanceTimersByTime(PRESS_ONSET_MS);
367
+ press(rows[0], 'pointerup', 10, 10);
368
+ vi.advanceTimersByTime(PRESS_FADE_MS);
369
+ expect(rows[0].hasAttribute(PRESSED_ATTRIBUTE)).toBe(false);
370
+ rows[0].classList.replace('slow-row', 'quick-row');
371
+ press(rows[0], 'pointerdown', 10, 10);
372
+ vi.advanceTimersByTime(PRESS_ONSET_MS);
373
+ press(rows[0], 'pointerup', 10, 10);
374
+ vi.advanceTimersByTime(PRESS_FADE_MS * 0.75);
375
+ expect(rows[0].hasAttribute(PRESSED_ATTRIBUTE)).toBe(false);
376
+ } finally {
377
+ rows[0].classList.remove('slow-row', 'quick-row');
378
+ style.remove();
379
+ vi.unstubAllGlobals();
380
+ }
381
+ });
382
+
383
+ it('bounds the release’s tempo at its own maximum, so the bound changes nothing', () => {
384
+ // The clock's 1.5 is TEMPO_RANGE.max, and every tempo a theme writes is
385
+ // clamped to it: a theme asking for 3 writes 1.5.
386
+ const source = readFileSync(
387
+ join(
388
+ dirname(fileURLToPath(import.meta.url)),
389
+ 'interactionOverlay.stylex.ts',
390
+ ),
391
+ 'utf8',
392
+ );
393
+ expect(source).toContain(
394
+ `min(var(--_astryx-motion-tempo, 1), ${TEMPO_RANGE.max})`,
395
+ );
396
+ expect(expandThemeMotion({tempo: 3})['--_astryx-motion-tempo']).toBe(
397
+ String(TEMPO_RANGE.max),
398
+ );
399
+ });
400
+
401
+ it('caps the stylesheet’s release fade under Reduce Motion', () => {
402
+ const source = readFileSync(
403
+ join(
404
+ dirname(fileURLToPath(import.meta.url)),
405
+ 'interactionOverlay.stylex.ts',
406
+ ),
407
+ 'utf8',
408
+ );
409
+ expect(source).toMatch(
410
+ /min\(\$\{pressConsts\.releaseMs\}ms, calc\(\$\{pressConsts\.releaseMs\}ms \* var\(--_astryx-motion-tempo, 1\)\)\)/,
411
+ );
412
+ expect(source).toMatch(
413
+ /'@media \(prefers-reduced-motion: reduce\)': PRESS_RELEASE_DURATION_REDUCED/,
414
+ );
415
+ });
416
+
417
+ it('keeps the 200 ms fade without a tempo', () => {
418
+ press(rows[0], 'pointerdown', 10, 10);
419
+ vi.advanceTimersByTime(PRESS_ONSET_MS);
420
+ press(rows[0], 'pointerup', 10, 10);
421
+ vi.advanceTimersByTime(PRESS_FADE_MS);
422
+ expect(rows[0].hasAttribute(PRESSED_ATTRIBUTE)).toBe(false);
423
+ });
424
+
425
+ it('times the stylesheet’s release fade by the same tempo', () => {
426
+ // The animation the attribute drives, scaled by the custom property a
427
+ // theme with a tempo writes beside its duration tokens.
428
+ const source = readFileSync(
429
+ join(
430
+ dirname(fileURLToPath(import.meta.url)),
431
+ 'interactionOverlay.stylex.ts',
432
+ ),
433
+ 'utf8',
434
+ );
435
+ expect(source).toMatch(
436
+ /calc\(\$\{pressConsts\.releaseMs\}ms \* min\(var\(--_astryx-motion-tempo, 1\),/,
437
+ );
438
+ });
439
+
320
440
  it('answers a tap too quick for the delay, at the release', () => {
321
441
  press(rows[0], 'pointerdown', 10, 10);
322
442
  vi.advanceTimersByTime(20);
@@ -418,6 +538,24 @@ describe('a phone or tablet paints a mouse or Space press itself', () => {
418
538
  expect(rows[1].hasAttribute(PRESSED_ATTRIBUTE)).toBe(false);
419
539
  });
420
540
 
541
+ it('fades a mouse press by the theme\u2019s tempo too (spec:AST-108 FR4, component:Button FR15)', () => {
542
+ const style = document.createElement('style');
543
+ style.textContent = '.slow-row { --_astryx-motion-tempo: 1.5; }';
544
+ document.head.appendChild(style);
545
+ rows[1].classList.add('slow-row');
546
+ try {
547
+ press(rows[1], 'pointerdown', 10, 100, 'mouse');
548
+ press(rows[1], 'pointerup', 10, 100, 'mouse');
549
+ vi.advanceTimersByTime(PRESS_FADE_MS);
550
+ expect(rows[1].getAttribute(PRESSED_ATTRIBUTE)).toBe('fading');
551
+ vi.advanceTimersByTime(PRESS_FADE_MS / 2);
552
+ expect(rows[1].hasAttribute(PRESSED_ATTRIBUTE)).toBe(false);
553
+ } finally {
554
+ rows[1].classList.remove('slow-row');
555
+ style.remove();
556
+ }
557
+ });
558
+
421
559
  it('keeps the paint while the mouse is dragged off the surface, as `:active` does', () => {
422
560
  press(rows[1], 'pointerdown', 10, 100, 'mouse');
423
561
  press(document.body, 'pointermove', 400, 900, 'mouse');
@@ -156,6 +156,24 @@ const TIMER_MS: Record<NonNullable<PressStep['timer']>, number> = {
156
156
  onset: PRESS_ONSET_MS,
157
157
  };
158
158
 
159
+ /**
160
+ * The release fade's clock on `element`, read once, at the release, from the
161
+ * property its stylesheet reads: the theme's `--_astryx-motion-tempo`
162
+ * (`spec:AST-108` FR4, `component:Button` FR15). Under Reduce Motion a tempo
163
+ * may shorten the fade, never lengthen it past 200 ms.
164
+ */
165
+ function fadeMs(element: Element): number {
166
+ const style = getComputedStyle(element);
167
+ const value = style.getPropertyValue('--_astryx-motion-tempo').trim();
168
+ const read = value === '' ? Number.NaN : Number(value);
169
+ const tempo = Number.isFinite(read) && read > 0 ? read : 1;
170
+ const scaled = PRESS_FADE_MS * tempo;
171
+ const reduced =
172
+ typeof window.matchMedia === 'function' &&
173
+ window.matchMedia('(prefers-reduced-motion: reduce)').matches;
174
+ return reduced ? Math.min(scaled, PRESS_FADE_MS) : scaled;
175
+ }
176
+
159
177
  const TIMER_EVENT = {
160
178
  fade: 'fadeEnd',
161
179
  flash: 'flashEnd',
@@ -217,17 +235,22 @@ function apply(slot: Slot, step: PressStep): void {
217
235
  // A TIMER, never `requestAnimationFrame`: iOS throttles frame callbacks
218
236
  // while a scroll runs, so a frame-based delay would fire late, after the
219
237
  // scroll, and paint a control nobody is pressing any more.
220
- live.timer = setTimeout(() => {
221
- if (slot.live != null) {
222
- slot.live.timer = null;
223
- }
224
- apply(
225
- slot,
226
- pressGestureStep(slot.live?.gesture ?? idlePressGesture(), {
227
- kind: TIMER_EVENT[kind],
228
- }),
229
- );
230
- }, TIMER_MS[kind]);
238
+ live.timer = setTimeout(
239
+ () => {
240
+ if (slot.live != null) {
241
+ slot.live.timer = null;
242
+ }
243
+ apply(
244
+ slot,
245
+ pressGestureStep(slot.live?.gesture ?? idlePressGesture(), {
246
+ kind: TIMER_EVENT[kind],
247
+ }),
248
+ );
249
+ },
250
+ // The release fade follows the theme's tempo (`spec:AST-108` FR4,
251
+ // `component:Button` FR15); the onset delay and the tap flash do not.
252
+ kind === 'fade' ? fadeMs(live.element) : TIMER_MS[kind],
253
+ );
231
254
  }
232
255
  }
233
256
 
@@ -0,0 +1,80 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file pressPaintPriority.test.ts
5
+ * @input Uses vitest, Babel with the StyleX plugin (the repository's shared
6
+ * module resolution) and interactionOverlay.stylex.ts
7
+ * @output Checks, in the compiled CSS, that the press paint outranks the
8
+ * coarse-pointer `:active` reset of the overlay
9
+ * @position Regression test for the cascade order of the press overlay
10
+ *
11
+ * WebKit applies `:active` during a touch. Under a coarse pointer the overlay
12
+ * turns the bare `:active` image off, and the press paint
13
+ * (`[data-astryx-press="on"]`) must still win: its rule has to sit in a
14
+ * higher StyleX priority than the reset. The order is a property of how
15
+ * each key is spelled: an imported `defineConsts` key compiles to a higher
16
+ * priority than the same literal, which put the reset above the paint and
17
+ * erased the touch-down frame.
18
+ */
19
+
20
+ import fs from 'node:fs';
21
+ import {createRequire} from 'node:module';
22
+ import path from 'node:path';
23
+ import {describe, expect, it} from 'vitest';
24
+ import stylexResolution from '../../../../scripts/stylex-module-resolution.cjs';
25
+
26
+ type Rule = [string, {ltr: string}, number];
27
+
28
+ // Babel's types are not part of core's typecheck; type the one call used.
29
+ const {transformSync} = createRequire(import.meta.url)('@babel/core') as {
30
+ transformSync: (
31
+ code: string,
32
+ options: Record<string, unknown>,
33
+ ) => {metadata?: unknown} | null;
34
+ };
35
+
36
+ function compiledRules(file: string): Rule[] {
37
+ const output = transformSync(fs.readFileSync(file, 'utf8'), {
38
+ filename: file,
39
+ babelrc: false,
40
+ configFile: false,
41
+ parserOpts: {plugins: ['typescript', 'jsx']},
42
+ plugins: [
43
+ [
44
+ '@stylexjs/babel-plugin',
45
+ {
46
+ dev: false,
47
+ runtimeInjection: false,
48
+ genConditionalClasses: true,
49
+ treeshakeCompensation: true,
50
+ unstable_moduleResolution: stylexResolution.stylexModuleResolution,
51
+ },
52
+ ],
53
+ ],
54
+ });
55
+ return (output?.metadata as {stylex?: Rule[]}).stylex ?? [];
56
+ }
57
+
58
+ describe('press overlay cascade', () => {
59
+ it('ranks the press paint above the coarse-pointer :active reset', () => {
60
+ const rules = compiledRules(
61
+ path.resolve(__dirname, 'interactionOverlay.stylex.ts'),
62
+ );
63
+ const resets = rules.filter(
64
+ // Matched without its condition's text: an imported key compiles to a
65
+ // placeholder until the bundle step.
66
+ ([, {ltr}]) =>
67
+ ltr.includes(':active') && ltr.includes('background-image:none'),
68
+ );
69
+ const paints = rules.filter(
70
+ ([, {ltr}]) =>
71
+ ltr.includes('[data-astryx-press="on"]') &&
72
+ ltr.includes('background-image:'),
73
+ );
74
+ expect(resets.length).toBeGreaterThan(0);
75
+ expect(paints.length).toBeGreaterThan(0);
76
+ const highestReset = Math.max(...resets.map(([, , priority]) => priority));
77
+ const lowestPaint = Math.min(...paints.map(([, , priority]) => priority));
78
+ expect(highestReset).toBeLessThan(lowestPaint);
79
+ });
80
+ });
@@ -0,0 +1,38 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file primaryClick.test.ts
5
+ * @input isPrimaryClick over button presses on Apple and other platforms
6
+ * @output Tests that only the main button, and not a ctrl-click on macOS,
7
+ * is a primary click (spec:AST-094 FR43)
8
+ * @position Unit tests of packages/core/src/utils/primaryClick.ts
9
+ */
10
+
11
+ import {afterEach, describe, expect, it, vi} from 'vitest';
12
+ import {isPrimaryClick} from './primaryClick';
13
+
14
+ function onPlatform(platform: string) {
15
+ vi.spyOn(navigator, 'platform', 'get').mockReturnValue(platform);
16
+ }
17
+
18
+ afterEach(() => {
19
+ vi.restoreAllMocks();
20
+ });
21
+
22
+ describe('isPrimaryClick (spec:AST-094 FR43)', () => {
23
+ it('takes the main button, and no right click or pen barrel button', () => {
24
+ onPlatform('Win32');
25
+ expect(isPrimaryClick({button: 0, ctrlKey: false})).toBe(true);
26
+ expect(isPrimaryClick({button: 2, ctrlKey: false})).toBe(false);
27
+ expect(isPrimaryClick({button: 1, ctrlKey: false})).toBe(false);
28
+ });
29
+
30
+ it("takes no ctrl-click on macOS, that platform's context click, and a ctrl-click elsewhere", () => {
31
+ onPlatform('MacIntel');
32
+ expect(isPrimaryClick({button: 0, ctrlKey: true})).toBe(false);
33
+ expect(isPrimaryClick({button: 0, ctrlKey: false})).toBe(true);
34
+ vi.restoreAllMocks();
35
+ onPlatform('Win32');
36
+ expect(isPrimaryClick({button: 0, ctrlKey: true})).toBe(true);
37
+ });
38
+ });
@@ -0,0 +1,28 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file primaryClick.ts
5
+ * @input A mouse or pen button press: its `button` and `ctrlKey`
6
+ * @output Exports isPrimaryClick
7
+ * @position Internal util, the one primary-click rule: the gesture host
8
+ * starts a press only for one, and the press controller paints only one;
9
+ * platform detection is utils/isApplePlatform.ts
10
+ *
11
+ * Deliberately absent from utils/index.ts: packages/core/src/index.ts does
12
+ * `export * from './utils'`, so naming it there would publish it as API.
13
+ */
14
+
15
+ import {isApplePlatform} from './isApplePlatform';
16
+
17
+ /**
18
+ * Whether a button press is a primary click: the main button, and not a
19
+ * ctrl-click on macOS or iPadOS, which is that platform's context click
20
+ * (`spec:AST-094` FR43). A right click, a pen's barrel button and a macOS
21
+ * ctrl-click start no press.
22
+ */
23
+ export function isPrimaryClick(event: {
24
+ readonly button: number;
25
+ readonly ctrlKey: boolean;
26
+ }): boolean {
27
+ return event.button === 0 && !(event.ctrlKey && isApplePlatform());
28
+ }
@@ -0,0 +1,204 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file timeFormat.test.ts
5
+ * @input Uses vitest and the timeFormat helpers
6
+ * @output Unit tests for locale hour cycles, locale time text, and parsing it back
7
+ * @position Testing; validates utils/timeFormat.ts
8
+ *
9
+ * SYNC: When timeFormat.ts changes, update tests to match new behavior
10
+ */
11
+
12
+ import {describe, expect, it} from 'vitest';
13
+ import {
14
+ formatLocaleTime,
15
+ parseLocaleTime,
16
+ resolveHourFormat,
17
+ type HourFormat,
18
+ } from './timeFormat';
19
+ import {parseTimeInput, type ISOTimeString} from './timeParser';
20
+
21
+ const iso = (time: string) => time as ISOTimeString;
22
+
23
+ describe('resolveHourFormat', () => {
24
+ it.each([
25
+ ['en', '12h'],
26
+ ['en-US', '12h'],
27
+ ['ko-KR', '12h'],
28
+ ['en-GB', '24h'],
29
+ ['de-DE', '24h'],
30
+ ['vi-VN', '24h'],
31
+ ['fr-FR', '24h'],
32
+ ] as const)('reads the hour cycle of %s as %s', (locale, expected) => {
33
+ expect(resolveHourFormat(locale)).toBe(expected);
34
+ });
35
+
36
+ it('honors a -u-hc- preference carried on the locale tag', () => {
37
+ expect(resolveHourFormat('en-US-u-hc-h23')).toBe('24h');
38
+ expect(resolveHourFormat('de-DE-u-hc-h12')).toBe('12h');
39
+ });
40
+
41
+ it('lets an explicit hour format win over the locale', () => {
42
+ expect(resolveHourFormat('de-DE', '12h')).toBe('12h');
43
+ expect(resolveHourFormat('en-US', '24h')).toBe('24h');
44
+ });
45
+
46
+ it('falls back to twelve-hour for a malformed tag', () => {
47
+ expect(resolveHourFormat('not a locale')).toBe('12h');
48
+ });
49
+ });
50
+
51
+ describe('formatLocaleTime', () => {
52
+ it('keeps the released English text exactly, with a plain space', () => {
53
+ expect(formatLocaleTime(iso('14:30'), 'en', '12h')).toBe('2:30 PM');
54
+ expect(formatLocaleTime(iso('00:05'), 'en', '12h')).toBe('12:05 AM');
55
+ expect(formatLocaleTime(iso('14:30:05'), 'en', '12h', true)).toBe(
56
+ '2:30:05 PM',
57
+ );
58
+ expect(formatLocaleTime(iso('09:05'), 'en', '24h')).toBe('09:05');
59
+ expect(formatLocaleTime(iso('09:05:07'), 'en', '24h', true)).toBe(
60
+ '09:05:07',
61
+ );
62
+ });
63
+
64
+ it("uses the locale's day-period words and their position", () => {
65
+ expect(formatLocaleTime(iso('14:30'), 'ko-KR', '12h')).toBe('오후 2:30');
66
+ expect(formatLocaleTime(iso('09:05'), 'zh-CN', '12h')).toBe('上午9:05');
67
+ expect(formatLocaleTime(iso('14:30'), 'es-ES', '12h')).toBe('2:30 p. m.');
68
+ });
69
+
70
+ it('writes noon as 12 in a twelve-hour reading, not 0', () => {
71
+ expect(formatLocaleTime(iso('12:30'), 'ja-JP', '12h')).toBe('午後12:30');
72
+ });
73
+
74
+ it('writes English twelve-hour text when the locale would drop the day period', () => {
75
+ // fr-CM's twelve-hour reading writes 02:30 and 14:30 both as "2:30".
76
+ expect(formatLocaleTime(iso('14:30'), 'fr-CM', '12h')).toBe('2:30 PM');
77
+ expect(formatLocaleTime(iso('02:30'), 'fr-CM', '12h')).toBe('2:30 AM');
78
+ expect(formatLocaleTime(iso('14:30'), 'fr-CM', '24h')).toBe('14:30');
79
+ });
80
+
81
+ it("uses the locale's separator and digits", () => {
82
+ expect(formatLocaleTime(iso('14:30'), 'fi-FI', '24h')).toBe('14.30');
83
+ expect(formatLocaleTime(iso('14:30'), 'ar-EG', '12h')).toBe('٢:٣٠ م');
84
+ });
85
+
86
+ it('returns empty text for an empty or malformed time', () => {
87
+ expect(formatLocaleTime(undefined, 'en', '12h')).toBe('');
88
+ expect(formatLocaleTime(iso('25:00'), 'en', '12h')).toBe('');
89
+ });
90
+ });
91
+
92
+ describe('parseLocaleTime', () => {
93
+ const LOCALES = [
94
+ 'en-US',
95
+ 'en-GB',
96
+ 'de-DE',
97
+ 'fi-FI',
98
+ 'fr-CA',
99
+ 'es-ES',
100
+ 'sv-SE',
101
+ 'vi-VN',
102
+ 'ja-JP',
103
+ 'ko-KR',
104
+ 'zh-TW',
105
+ 'ar-EG',
106
+ 'fa-IR',
107
+ 'he-IL',
108
+ // Twelve-hour readings whose separators or surrounding words differ from
109
+ // the twenty-four-hour reading: a dot (as, nds), "h" (oc), a word between
110
+ // the day period and the hour (brx, ee), a word before the hour (dz, nds,
111
+ // tok), and Tibetan digits (dz).
112
+ 'as',
113
+ 'brx',
114
+ 'dz',
115
+ 'ee',
116
+ 'nds',
117
+ 'oc',
118
+ 'tok',
119
+ // A one-letter day period that English input contains ("m" in "pm").
120
+ 'gd',
121
+ // A twelve-hour reading with no day period at all.
122
+ 'fr-CM',
123
+ ];
124
+ const TIMES = ['00:00', '00:30', '09:05', '11:59', '12:00', '12:30', '23:45'];
125
+ const FORMATS: HourFormat[] = ['12h', '24h'];
126
+
127
+ it.each(LOCALES)('reads back every time %s writes', locale => {
128
+ for (const hourFormat of FORMATS) {
129
+ for (const time of TIMES) {
130
+ const text = formatLocaleTime(iso(time), locale, hourFormat);
131
+ expect(
132
+ parseLocaleTime(text, locale),
133
+ `${locale} ${hourFormat} "${text}"`,
134
+ ).toBe(time);
135
+ }
136
+ const withSeconds = formatLocaleTime(
137
+ iso('14:30:05'),
138
+ locale,
139
+ hourFormat,
140
+ true,
141
+ );
142
+ expect(parseLocaleTime(withSeconds, locale, true)).toBe('14:30:05');
143
+ }
144
+ });
145
+
146
+ it('reads a spaced day period as the half of the day it names', () => {
147
+ // Previously parsed as 02:30: the English matcher missed "p. m.".
148
+ expect(parseLocaleTime('2:30 p. m.', 'es-ES')).toBe('14:30');
149
+ expect(parseLocaleTime('午後2:30', 'ja-JP')).toBe('14:30');
150
+ });
151
+
152
+ it('reads twelve-hour text whose pattern differs from the 24-hour one', () => {
153
+ expect(parseLocaleTime('অপৰাহ্ন ২.৩০', 'as')).toBe('14:30');
154
+ expect(parseLocaleTime('ɣetrɔ ga 2:30', 'ee')).toBe('14:30');
155
+ expect(parseLocaleTime('Klock 2.30:05 PM', 'nds', true)).toBe('14:30:05');
156
+ expect(parseLocaleTime('2h30:05 PM', 'oc', true)).toBe('14:30:05');
157
+ });
158
+
159
+ it("reads the locale's separator", () => {
160
+ // Previously "14.30" read only its "14" prefix.
161
+ expect(parseLocaleTime('14.30', 'fi-FI')).toBe('14:30');
162
+ expect(parseLocaleTime('14 h 30', 'fr-CA')).toBe('14:30');
163
+ });
164
+
165
+ it('does not read a day-period word out of the middle of an English word', () => {
166
+ // gd writes the morning as "m": the "m" of "pm" is not that word.
167
+ expect(parseLocaleTime('2:30 PM', 'gd')).toBe('14:30');
168
+ expect(parseLocaleTime('12:00 PM', 'gd')).toBe('12:00');
169
+ expect(parseLocaleTime('2pm', 'gd')).toBe('14:00');
170
+ expect(parseLocaleTime('2:30 p.m', 'gd')).toBe('14:30');
171
+ expect(parseLocaleTime('12:00 p.m', 'gd')).toBe('12:00');
172
+ expect(parseLocaleTime('2 p.m', 'gd')).toBe('14:00');
173
+ expect(parseLocaleTime('11 a.m', 'gd')).toBe('11:00');
174
+ expect(parseLocaleTime('2:30m', 'gd')).toBe('02:30');
175
+ });
176
+
177
+ it('still reads English input in every locale exactly as before', () => {
178
+ const inputs = [
179
+ '2:30 PM',
180
+ '2:30 p.m',
181
+ '2:30 p.m.',
182
+ '12:00 PM',
183
+ '12:00 AM',
184
+ '2pm',
185
+ '2 p.m',
186
+ '11 a.m',
187
+ '14:30',
188
+ '1430',
189
+ ];
190
+ for (const locale of LOCALES) {
191
+ for (const input of inputs) {
192
+ expect(parseLocaleTime(input, locale), `${locale} "${input}"`).toBe(
193
+ parseTimeInput(input),
194
+ );
195
+ }
196
+ }
197
+ });
198
+
199
+ it('rejects text no reading fits', () => {
200
+ expect(parseLocaleTime('', 'en-US')).toBeNull();
201
+ expect(parseLocaleTime('25:99', 'de-DE')).toBeNull();
202
+ expect(parseLocaleTime('午後14:30', 'ja-JP')).toBeNull();
203
+ });
204
+ });