@astryxdesign/core 0.7.8 → 0.7.9-canary.07992bb

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 (403) hide show
  1. package/dist/AppShell/observeMainOverflow.d.ts.map +1 -1
  2. package/dist/AppShell/observeMainOverflow.js +9 -6
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +5 -0
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  6. package/dist/BottomSheet/BottomSheetPanel.js +40 -8
  7. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  8. package/dist/BottomSheet/useSheetGestures.js +61 -21
  9. package/dist/Calendar/Calendar.d.ts +14 -2
  10. package/dist/Calendar/Calendar.d.ts.map +1 -1
  11. package/dist/Calendar/Calendar.js +63 -74
  12. package/dist/Calendar/getInitialFocusDate.d.ts +4 -1
  13. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -1
  14. package/dist/Calendar/getInitialFocusDate.js +7 -5
  15. package/dist/Calendar/hooks/useCalendarDays.d.ts +19 -2
  16. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  17. package/dist/Calendar/hooks/useCalendarDays.js +57 -64
  18. package/dist/Calendar/hooks/useCalendarNavigation.d.ts +28 -3
  19. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  20. package/dist/Calendar/hooks/useCalendarNavigation.js +33 -22
  21. package/dist/Calendar/styles.d.ts +1 -1
  22. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  23. package/dist/CheckboxInput/CheckboxInput.js +54 -11
  24. package/dist/ClickableCard/ClickableCard.d.ts +1 -1
  25. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  26. package/dist/ClickableCard/ClickableCard.js +5 -1
  27. package/dist/DateInput/DateInput.d.ts.map +1 -1
  28. package/dist/DateInput/DateInput.js +4 -1
  29. package/dist/DateInput/PickerWheel.d.ts.map +1 -1
  30. package/dist/DateInput/PickerWheel.js +7 -1
  31. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  32. package/dist/DateRangeInput/DateRangeInput.js +5 -2
  33. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  34. package/dist/DateTimeInput/DateTimeInput.js +4 -1
  35. package/dist/Dialog/Dialog.d.ts +2 -1
  36. package/dist/Dialog/Dialog.d.ts.map +1 -1
  37. package/dist/Dialog/Dialog.js +12 -1
  38. package/dist/Drawer/useDrawerDialogPresence.d.ts +2 -1
  39. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  40. package/dist/Drawer/useDrawerDialogPresence.js +11 -2
  41. package/dist/DropdownMenu/DropdownMenu.d.ts +9 -1
  42. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  43. package/dist/DropdownMenu/DropdownMenu.js +9 -4
  44. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  45. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +3 -2
  46. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  47. package/dist/DropdownMenu/DropdownMenuItem.js +3 -2
  48. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  49. package/dist/DropdownMenu/DropdownMenuRadioItem.js +3 -2
  50. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  51. package/dist/DropdownMenu/DropdownMenuSubMenu.js +3 -2
  52. package/dist/Field/inputDisabledFocus.d.ts +4 -4
  53. package/dist/Field/inputStyles.stylex.d.ts +1 -1
  54. package/dist/FileInput/FileInput.d.ts.map +1 -1
  55. package/dist/FileInput/FileInput.js +16 -2
  56. package/dist/HoverCard/useHoverCard.d.ts +3 -1
  57. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  58. package/dist/Icon/Icon.d.ts +1 -1
  59. package/dist/InfoTip/InfoTip.d.ts +1 -0
  60. package/dist/InfoTip/InfoTip.d.ts.map +1 -1
  61. package/dist/InfoTip/InfoTip.js +1 -0
  62. package/dist/InputGroup/InputGroup.d.ts +4 -3
  63. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  64. package/dist/InputGroup/InputGroup.js +2 -2
  65. package/dist/InputGroup/groupStyles.d.ts +1 -1
  66. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  67. package/dist/InputGroup/groupStyles.js +1 -1
  68. package/dist/Item/Item.d.ts +2 -1
  69. package/dist/Item/Item.d.ts.map +1 -1
  70. package/dist/Item/Item.js +29 -6
  71. package/dist/Layer/holdEntranceInput.d.ts +24 -0
  72. package/dist/Layer/holdEntranceInput.d.ts.map +1 -0
  73. package/dist/Layer/holdEntranceInput.js +65 -0
  74. package/dist/Layer/inputHold.d.ts +49 -0
  75. package/dist/Layer/inputHold.d.ts.map +1 -0
  76. package/dist/Layer/inputHold.js +636 -0
  77. package/dist/Layer/preserveAnimations.d.ts +1 -5
  78. package/dist/Layer/preserveAnimations.d.ts.map +1 -1
  79. package/dist/Layer/preserveAnimations.js +12 -214
  80. package/dist/Layer/useLayer.d.ts +3 -1
  81. package/dist/Layer/useLayer.d.ts.map +1 -1
  82. package/dist/Layer/useLayer.js +64 -4
  83. package/dist/Layout/LayoutContent.d.ts +3 -1
  84. package/dist/Layout/LayoutContent.d.ts.map +1 -1
  85. package/dist/Layout/LayoutContent.js +12 -4
  86. package/dist/Layout/LayoutPanel.d.ts +4 -1
  87. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  88. package/dist/Layout/LayoutPanel.js +13 -4
  89. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  90. package/dist/Lightbox/Lightbox.js +4 -0
  91. package/dist/MetadataList/MetadataList.js +1 -1
  92. package/dist/MobileNav/MobileNav.d.ts +11 -1
  93. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  94. package/dist/MobileNav/MobileNav.js +39 -1
  95. package/dist/MoreMenu/MoreMenu.d.ts +5 -3
  96. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  97. package/dist/NumberInput/NumberInput.d.ts +4 -2
  98. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  99. package/dist/NumberInput/NumberInput.js +244 -11
  100. package/dist/Popover/usePopover.d.ts +1 -0
  101. package/dist/Popover/usePopover.d.ts.map +1 -1
  102. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  103. package/dist/PowerSearch/PowerSearch.js +12 -5
  104. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -1
  105. package/dist/PowerSearch/PowerSearchBottomSheet.js +4 -2
  106. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  107. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  108. package/dist/PowerSearch/formatFilterValue.d.ts +9 -3
  109. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  110. package/dist/PowerSearch/formatFilterValue.js +14 -11
  111. package/dist/PowerSearch/formatTokenValue.d.ts +6 -2
  112. package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -1
  113. package/dist/PowerSearch/formatTokenValue.js +6 -3
  114. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  115. package/dist/RadioList/RadioListItem.js +22 -4
  116. package/dist/SelectableCard/SelectableCard.d.ts +1 -1
  117. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  118. package/dist/SelectableCard/SelectableCard.js +5 -1
  119. package/dist/Spinner/Spinner.d.ts.map +1 -1
  120. package/dist/Spinner/Spinner.js +14 -71
  121. package/dist/Spinner/index.d.ts +1 -1
  122. package/dist/Spinner/index.d.ts.map +1 -1
  123. package/dist/Spinner/spinnerRotor.d.ts +28 -0
  124. package/dist/Spinner/spinnerRotor.d.ts.map +1 -0
  125. package/dist/Spinner/spinnerRotor.js +98 -0
  126. package/dist/Stack/StackItem.d.ts +8 -4
  127. package/dist/Stack/StackItem.d.ts.map +1 -1
  128. package/dist/Stack/StackItem.js +17 -4
  129. package/dist/Switch/Switch.d.ts.map +1 -1
  130. package/dist/Switch/Switch.js +13 -10
  131. package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
  132. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  133. package/dist/Timestamp/Timestamp.js +14 -8
  134. package/dist/Timestamp/formatInstant.d.ts +10 -1
  135. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  136. package/dist/Timestamp/formatInstant.js +13 -27
  137. package/dist/Timestamp/tooltipEntries.d.ts +5 -3
  138. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  139. package/dist/Timestamp/tooltipEntries.js +6 -4
  140. package/dist/Token/Token.d.ts.map +1 -1
  141. package/dist/Token/Token.js +9 -0
  142. package/dist/Token/TokenLink.d.ts +1 -1
  143. package/dist/Token/TokenLink.d.ts.map +1 -1
  144. package/dist/Token/TokenLink.js +4 -1
  145. package/dist/Tokenizer/Tokenizer.d.ts +14 -10
  146. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  147. package/dist/Tokenizer/Tokenizer.js +189 -89
  148. package/dist/Tooltip/useTooltip.d.ts +3 -1
  149. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  150. package/dist/Tooltip/useTooltip.js +162 -59
  151. package/dist/TreeList/TreeListItem.d.ts +2 -1
  152. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  153. package/dist/TreeList/TreeListItem.js +27 -3
  154. package/dist/astryx.css +45 -18
  155. package/dist/gestures/GestureHost.d.ts +2 -2
  156. package/dist/gestures/GestureHost.d.ts.map +1 -1
  157. package/dist/gestures/GestureHost.js +21 -6
  158. package/dist/gestures/PanGestureRecognizer.d.ts +11 -1
  159. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  160. package/dist/gestures/PanGestureRecognizer.js +15 -1
  161. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +6 -1
  162. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -1
  163. package/dist/gestures/nativeScroll.d.ts +3 -6
  164. package/dist/gestures/nativeScroll.d.ts.map +1 -1
  165. package/dist/gestures/nativeScroll.js +7 -52
  166. package/dist/gestures/wheelSegmenter.d.ts +68 -1
  167. package/dist/gestures/wheelSegmenter.d.ts.map +1 -1
  168. package/dist/gestures/wheelSegmenter.js +199 -10
  169. package/dist/hooks/StackItemScrollRegion.d.ts +31 -0
  170. package/dist/hooks/StackItemScrollRegion.d.ts.map +1 -0
  171. package/dist/hooks/StackItemScrollRegion.js +40 -0
  172. package/dist/hooks/menuPressGesture.d.ts +133 -21
  173. package/dist/hooks/menuPressGesture.d.ts.map +1 -1
  174. package/dist/hooks/menuPressGesture.js +155 -30
  175. package/dist/hooks/menuPressValues.d.ts +16 -0
  176. package/dist/hooks/menuPressValues.d.ts.map +1 -0
  177. package/dist/hooks/menuPressValues.js +18 -0
  178. package/dist/hooks/useClickableContainer.d.ts +27 -5
  179. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  180. package/dist/hooks/useClickableContainer.js +41 -5
  181. package/dist/hooks/useFocusTrap.d.ts +10 -0
  182. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  183. package/dist/hooks/useFocusTrap.js +225 -132
  184. package/dist/hooks/useMenuPress.d.ts +34 -1
  185. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  186. package/dist/hooks/useMenuPress.js +93 -5
  187. package/dist/hooks/usePressFeedback.d.ts +6 -6
  188. package/dist/hooks/usePressFeedback.js +6 -6
  189. package/dist/hooks/useScrollRegionProps.d.ts +35 -0
  190. package/dist/hooks/useScrollRegionProps.d.ts.map +1 -0
  191. package/dist/hooks/useScrollRegionProps.js +51 -0
  192. package/dist/i18n/InternationalizationContext.d.ts +6 -0
  193. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  194. package/dist/i18n/InternationalizationProvider.d.ts +21 -3
  195. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  196. package/dist/i18n/InternationalizationProvider.js +8 -3
  197. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts +8 -0
  198. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts.map +1 -0
  199. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.js +12 -0
  200. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  201. package/dist/i18n/generated-locales/en.generated.js +1 -0
  202. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  203. package/dist/i18n/generated-locales/pseudo.generated.js +1 -0
  204. package/dist/i18n/index.d.ts +2 -0
  205. package/dist/i18n/index.d.ts.map +1 -1
  206. package/dist/i18n/index.js +1 -0
  207. package/dist/i18n/useCalendarSystem.d.ts +19 -0
  208. package/dist/i18n/useCalendarSystem.d.ts.map +1 -0
  209. package/dist/i18n/useCalendarSystem.js +61 -0
  210. package/dist/internal/spinner-rotor.d.ts +16 -0
  211. package/dist/internal/spinner-rotor.d.ts.map +1 -0
  212. package/dist/internal/spinner-rotor.js +16 -0
  213. package/dist/internal/touch.d.ts +14 -1
  214. package/dist/internal/touch.d.ts.map +1 -1
  215. package/dist/internal/touch.js +20 -2
  216. package/dist/motion/carryAnimations.d.ts +58 -0
  217. package/dist/motion/carryAnimations.d.ts.map +1 -0
  218. package/dist/motion/carryAnimations.js +305 -0
  219. package/dist/motion/transientCopy.d.ts +4 -2
  220. package/dist/motion/transientCopy.d.ts.map +1 -1
  221. package/dist/motion/transientCopy.js +34 -5
  222. package/dist/motion/uikit/gestures.d.ts +41 -0
  223. package/dist/motion/uikit/gestures.d.ts.map +1 -1
  224. package/dist/motion/uikit/gestures.js +25 -0
  225. package/dist/motion/uikit/index.d.ts +1 -1
  226. package/dist/motion/uikit/index.d.ts.map +1 -1
  227. package/dist/motion/uikit/index.js +1 -1
  228. package/dist/motion/uikit/timing.d.ts +14 -10
  229. package/dist/motion/uikit/timing.d.ts.map +1 -1
  230. package/dist/motion/uikit/timing.js +7 -5
  231. package/dist/privateAttributes/menuPressLit.stylex.d.ts +52 -0
  232. package/dist/privateAttributes/menuPressLit.stylex.d.ts.map +1 -0
  233. package/dist/privateAttributes/menuPressLit.stylex.js +99 -0
  234. package/dist/privateAttributes/press.stylex.d.ts +139 -0
  235. package/dist/privateAttributes/press.stylex.d.ts.map +1 -0
  236. package/dist/privateAttributes/press.stylex.js +97 -0
  237. package/dist/theme/themeMotion.d.ts +3 -2
  238. package/dist/theme/themeMotion.d.ts.map +1 -1
  239. package/dist/theme/themeMotion.js +3 -2
  240. package/dist/theme/tokens.stylex.d.ts +2 -2
  241. package/dist/theme/tokens.stylex.js +1 -1
  242. package/dist/utils/calendarSystem.d.ts +114 -0
  243. package/dist/utils/calendarSystem.d.ts.map +1 -0
  244. package/dist/utils/calendarSystem.js +386 -0
  245. package/dist/utils/flatTree.d.ts +6 -3
  246. package/dist/utils/flatTree.d.ts.map +1 -1
  247. package/dist/utils/flatTree.js +13 -3
  248. package/dist/utils/hitArea.d.ts.map +1 -1
  249. package/dist/utils/hitArea.js +82 -5
  250. package/dist/utils/inputStream.d.ts +14 -1
  251. package/dist/utils/inputStream.d.ts.map +1 -1
  252. package/dist/utils/inputStream.js +40 -9
  253. package/dist/utils/interactionOverlay.stylex.d.ts +5 -9
  254. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  255. package/dist/utils/interactionOverlay.stylex.js +29 -31
  256. package/dist/utils/plainDate.d.ts +23 -7
  257. package/dist/utils/plainDate.d.ts.map +1 -1
  258. package/dist/utils/plainDate.js +57 -18
  259. package/dist/utils/pressFeedback.d.ts +10 -2
  260. package/dist/utils/pressFeedback.d.ts.map +1 -1
  261. package/dist/utils/pressFeedback.js +40 -15
  262. package/dist/utils/pressGesture.d.ts +12 -6
  263. package/dist/utils/pressGesture.d.ts.map +1 -1
  264. package/dist/utils/pressGesture.js +26 -8
  265. package/dist/utils/scrollView.d.ts +25 -0
  266. package/dist/utils/scrollView.d.ts.map +1 -0
  267. package/dist/utils/scrollView.js +108 -0
  268. package/dist/utils/selectionLock.d.ts.map +1 -1
  269. package/dist/utils/selectionLock.js +1 -10
  270. package/dist/utils/touchHitArea.stylex.d.ts +35 -0
  271. package/dist/utils/touchHitArea.stylex.d.ts.map +1 -0
  272. package/dist/utils/touchHitArea.stylex.js +32 -0
  273. package/dist/utils/triggerFocus.d.ts +5 -0
  274. package/dist/utils/triggerFocus.d.ts.map +1 -1
  275. package/dist/utils/triggerFocus.js +9 -2
  276. package/locales/en.json +4 -0
  277. package/locales/pseudo.json +3 -0
  278. package/package.json +10 -4
  279. package/src/AppShell/observeMainOverflow.ts +9 -6
  280. package/src/BottomSheet/BottomSheet.tsx +5 -0
  281. package/src/BottomSheet/BottomSheetPanel.tsx +64 -7
  282. package/src/BottomSheet/useSheetGestures.ts +83 -20
  283. package/src/Calendar/Calendar.doc.mjs +76 -6
  284. package/src/Calendar/Calendar.tsx +123 -104
  285. package/src/Calendar/getInitialFocusDate.ts +22 -8
  286. package/src/Calendar/hooks/useCalendarDays.ts +89 -63
  287. package/src/Calendar/hooks/useCalendarNavigation.ts +68 -26
  288. package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -2
  289. package/src/CheckboxInput/CheckboxInput.tsx +71 -9
  290. package/src/ClickableCard/ClickableCard.tsx +8 -1
  291. package/src/DateInput/DateInput.tsx +2 -0
  292. package/src/DateInput/PickerWheel.tsx +7 -2
  293. package/src/DateRangeInput/DateRangeInput.tsx +3 -1
  294. package/src/DateTimeInput/DateTimeInput.tsx +2 -0
  295. package/src/Dialog/Dialog.doc.mjs +1 -1
  296. package/src/Dialog/Dialog.tsx +12 -1
  297. package/src/Drawer/Drawer.doc.mjs +1 -1
  298. package/src/Drawer/useDrawerDialogPresence.ts +9 -2
  299. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -2
  300. package/src/DropdownMenu/DropdownMenu.tsx +29 -5
  301. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -1
  302. package/src/DropdownMenu/DropdownMenuItem.tsx +8 -4
  303. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -1
  304. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -1
  305. package/src/FileInput/FileInput.tsx +16 -2
  306. package/src/HoverCard/useHoverCard.tsx +3 -1
  307. package/src/InfoTip/InfoTip.doc.mjs +26 -2
  308. package/src/InfoTip/InfoTip.tsx +1 -0
  309. package/src/InputGroup/InputGroup.doc.mjs +4 -3
  310. package/src/InputGroup/InputGroup.tsx +4 -3
  311. package/src/InputGroup/groupStyles.ts +3 -1
  312. package/src/Item/Item.tsx +51 -9
  313. package/src/Layer/holdEntranceInput.ts +84 -0
  314. package/src/Layer/inputHold.ts +734 -0
  315. package/src/Layer/preserveAnimations.ts +12 -275
  316. package/src/Layer/useLayer.tsx +77 -4
  317. package/src/Layout/LayoutContent.doc.mjs +6 -3
  318. package/src/Layout/LayoutContent.tsx +10 -4
  319. package/src/Layout/LayoutPanel.doc.mjs +6 -3
  320. package/src/Layout/LayoutPanel.tsx +11 -4
  321. package/src/Lightbox/Lightbox.tsx +4 -0
  322. package/src/MetadataList/MetadataList.tsx +1 -1
  323. package/src/MobileNav/MobileNav.doc.mjs +3 -3
  324. package/src/MobileNav/MobileNav.tsx +39 -1
  325. package/src/MoreMenu/MoreMenu.doc.mjs +2 -4
  326. package/src/MoreMenu/MoreMenu.tsx +5 -3
  327. package/src/NumberInput/NumberInput.doc.mjs +1 -1
  328. package/src/NumberInput/NumberInput.tsx +259 -11
  329. package/src/Popover/usePopover.tsx +1 -0
  330. package/src/PowerSearch/PowerSearch.doc.mjs +3 -3
  331. package/src/PowerSearch/PowerSearch.tsx +20 -3
  332. package/src/PowerSearch/PowerSearchBottomSheet.tsx +4 -1
  333. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  334. package/src/PowerSearch/formatFilterValue.ts +21 -11
  335. package/src/PowerSearch/formatTokenValue.ts +7 -1
  336. package/src/RadioList/RadioListItem.doc.mjs +3 -2
  337. package/src/RadioList/RadioListItem.tsx +25 -7
  338. package/src/SelectableCard/SelectableCard.tsx +8 -1
  339. package/src/Spinner/Spinner.tsx +7 -89
  340. package/src/Spinner/index.ts +1 -5
  341. package/src/Spinner/spinnerRotor.ts +113 -0
  342. package/src/Stack/Stack.doc.mjs +1 -1
  343. package/src/Stack/StackItem.tsx +27 -13
  344. package/src/Switch/Switch.tsx +7 -6
  345. package/src/Table/plugins/sortable/useTableSortable.tsx +1 -1
  346. package/src/Timestamp/Timestamp.doc.mjs +3 -3
  347. package/src/Timestamp/Timestamp.tsx +13 -8
  348. package/src/Timestamp/formatInstant.ts +49 -28
  349. package/src/Timestamp/tooltipEntries.ts +7 -3
  350. package/src/Token/Token.tsx +18 -1
  351. package/src/Token/TokenLink.tsx +7 -1
  352. package/src/Tokenizer/Tokenizer.doc.mjs +3 -3
  353. package/src/Tokenizer/Tokenizer.tsx +252 -115
  354. package/src/Tooltip/useTooltip.tsx +178 -80
  355. package/src/TreeList/TreeListItem.tsx +36 -2
  356. package/src/gestures/GestureHost.ts +21 -5
  357. package/src/gestures/PanGestureRecognizer.ts +19 -2
  358. package/src/gestures/README.md +14 -5
  359. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +6 -1
  360. package/src/gestures/nativeScroll.ts +12 -68
  361. package/src/gestures/wheelSegmenter.ts +243 -10
  362. package/src/hooks/StackItemScrollRegion.tsx +57 -0
  363. package/src/hooks/menuPressGesture.ts +244 -38
  364. package/src/hooks/menuPressValues.ts +18 -0
  365. package/src/hooks/useClickableContainer.doc.mjs +8 -2
  366. package/src/hooks/useClickableContainer.ts +72 -6
  367. package/src/hooks/useFocusTrap.ts +268 -151
  368. package/src/hooks/useMenuPress.ts +118 -11
  369. package/src/hooks/usePressFeedback.doc.mjs +3 -3
  370. package/src/hooks/usePressFeedback.ts +6 -6
  371. package/src/hooks/useScrollRegionProps.ts +76 -0
  372. package/src/i18n/InternationalizationContext.ts +6 -0
  373. package/src/i18n/InternationalizationProvider.doc.mjs +29 -1
  374. package/src/i18n/InternationalizationProvider.tsx +33 -3
  375. package/src/i18n/generated-english/hooks/useScrollRegionProps.generated.ts +13 -0
  376. package/src/i18n/generated-locales/en.generated.ts +1 -0
  377. package/src/i18n/generated-locales/pseudo.generated.ts +1 -0
  378. package/src/i18n/index.ts +2 -0
  379. package/src/i18n/useCalendarSystem.ts +95 -0
  380. package/src/internal/spinner-rotor.ts +20 -0
  381. package/src/internal/touch.ts +34 -1
  382. package/src/motion/MEASUREMENTS.md +11 -0
  383. package/src/motion/carryAnimations.ts +389 -0
  384. package/src/motion/transientCopy.ts +45 -5
  385. package/src/motion/uikit/gestures.ts +22 -0
  386. package/src/motion/uikit/index.ts +1 -0
  387. package/src/motion/uikit/timing.ts +7 -5
  388. package/src/privateAttributes/menuPressLit.stylex.ts +104 -0
  389. package/src/privateAttributes/press.stylex.ts +243 -0
  390. package/src/theme/themeMotion.ts +3 -2
  391. package/src/theme/tokens.stylex.ts +1 -1
  392. package/src/utils/calendarSystem.ts +548 -0
  393. package/src/utils/flatTree.ts +15 -3
  394. package/src/utils/hitArea.ts +107 -5
  395. package/src/utils/inputStream.ts +47 -10
  396. package/src/utils/interactionOverlay.stylex.ts +19 -22
  397. package/src/utils/plainDate.ts +84 -19
  398. package/src/utils/pressFeedback.ts +46 -14
  399. package/src/utils/pressGesture.ts +35 -9
  400. package/src/utils/scrollView.ts +135 -0
  401. package/src/utils/selectionLock.ts +5 -10
  402. package/src/utils/touchHitArea.stylex.ts +41 -0
  403. package/src/utils/triggerFocus.ts +17 -4
@@ -24,6 +24,9 @@
24
24
  // live control measures: only under a coarse primary pointer (AST-094), only on
25
25
  // screen, and in one read pass per frame within a 4 ms budget. Until the first
26
26
  // pass the insets are 0, so first paint never overlaps anything.
27
+ // The insets are lengths in the control's own box, so a pass measures in its
28
+ // layout px. A layer that opens from a smaller scale then keeps the insets of
29
+ // the size it settles at.
27
30
 
28
31
  import {observeContent} from './sharedMutationObserver';
29
32
 
@@ -330,6 +333,95 @@ function plainRect(element: Element): HitRect {
330
333
  return {left, top, right, bottom};
331
334
  }
332
335
 
336
+ /** A box that the transforms around it leave at its layout size. */
337
+ const UNSCALED = {x: 1, y: 1} as const;
338
+
339
+ /** One axis of a box's scale on screen: its client size over its layout size. */
340
+ function axisScale(onScreen: number, layout: number): number {
341
+ if (!(layout > 0) || !(onScreen > 0)) {
342
+ return 1;
343
+ }
344
+ const scale = onScreen / layout;
345
+ // Within rounding of 1 the box is at its layout size: no change to the rects.
346
+ return Math.abs(scale - 1) < 1e-3 ? 1 : scale;
347
+ }
348
+
349
+ /**
350
+ * How far the transforms around `element` scale its box on screen, per axis.
351
+ * A layer that opens from a smaller scale scales every rect inside it, while
352
+ * the layout box keeps the size the layer settles at. Only a scale is
353
+ * expected: a rotated or skewed box would read as a larger scale.
354
+ */
355
+ function screenScale(
356
+ element: Element,
357
+ onScreen: HitRect,
358
+ ): {x: number; y: number} {
359
+ // The offset size is the layout size in whole pixels, unaffected by
360
+ // transforms, and costs no style resolution. A box with none, such as an SVG
361
+ // element or a jsdom box, reads as unscaled.
362
+ const box = element as Partial<HTMLElement>;
363
+ const offsetWidth = box.offsetWidth ?? 0;
364
+ const offsetHeight = box.offsetHeight ?? 0;
365
+ if (offsetWidth === 0 || offsetHeight === 0) {
366
+ return UNSCALED;
367
+ }
368
+ // Within a pixel of its layout size the box reads as unscaled, which bounds
369
+ // the inset error at about a pixel. Only a box that a transform shrinks or
370
+ // grows reads its exact size from the computed style.
371
+ if (
372
+ Math.abs(onScreen.right - onScreen.left - offsetWidth) <= 1 &&
373
+ Math.abs(onScreen.bottom - onScreen.top - offsetHeight) <= 1
374
+ ) {
375
+ return UNSCALED;
376
+ }
377
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
378
+ if (style == null || !style.width.endsWith('px')) {
379
+ return UNSCALED;
380
+ }
381
+ const px = (value: string) => Number.parseFloat(value) || 0;
382
+ const isContentBox = style.boxSizing !== 'border-box';
383
+ const width =
384
+ px(style.width) +
385
+ (isContentBox
386
+ ? px(style.paddingLeft) +
387
+ px(style.paddingRight) +
388
+ px(style.borderLeftWidth) +
389
+ px(style.borderRightWidth)
390
+ : 0);
391
+ const height =
392
+ px(style.height) +
393
+ (isContentBox
394
+ ? px(style.paddingTop) +
395
+ px(style.paddingBottom) +
396
+ px(style.borderTopWidth) +
397
+ px(style.borderBottomWidth)
398
+ : 0);
399
+ return {
400
+ x: axisScale(onScreen.right - onScreen.left, width),
401
+ y: axisScale(onScreen.bottom - onScreen.top, height),
402
+ };
403
+ }
404
+
405
+ /**
406
+ * `rect` in the layout px of the box at `origin`: its offset from `origin`,
407
+ * divided by that box's scale on screen.
408
+ */
409
+ function inLayout(
410
+ rect: HitRect,
411
+ origin: HitRect,
412
+ scale: {x: number; y: number},
413
+ ): HitRect {
414
+ if (scale.x === 1 && scale.y === 1) {
415
+ return rect;
416
+ }
417
+ return {
418
+ left: origin.left + (rect.left - origin.left) / scale.x,
419
+ top: origin.top + (rect.top - origin.top) / scale.y,
420
+ right: origin.left + (rect.right - origin.left) / scale.x,
421
+ bottom: origin.top + (rect.bottom - origin.top) / scale.y,
422
+ };
423
+ }
424
+
333
425
  interface Candidate {
334
426
  readonly element: Element;
335
427
  readonly rect: HitRect;
@@ -373,14 +465,15 @@ function measureOne(
373
465
  candidates: ReadonlyArray<Candidate>,
374
466
  ): {target: HitRect; insets: HitInsets; neighbours: HitRect[]} {
375
467
  const target = plainRect(watch.element);
468
+ const scale = screenScale(watch.element, target);
376
469
  // Two targets each growing up to half the minimum reach each other from a
377
470
  // minimum apart.
378
471
  const reach = Math.max(0, watch.minSize);
379
472
  const band = grown(target, {
380
- top: reach,
381
- right: reach,
382
- bottom: reach,
383
- left: reach,
473
+ top: reach * scale.y,
474
+ right: reach * scale.x,
475
+ bottom: reach * scale.y,
476
+ left: reach * scale.x,
384
477
  });
385
478
  const neighbours = candidates
386
479
  .filter(
@@ -393,7 +486,16 @@ function measureOne(
393
486
  .map(({rect}) => rect);
394
487
  return {
395
488
  target,
396
- insets: clampedHitInsets(target, neighbours, watch.minSize),
489
+ // The insets are in the control's layout px. The returned rects stay in
490
+ // screen px for a touch's distance checks. A neighbour maps by the
491
+ // control's scale, as if it is in the same layer. A neighbour outside that
492
+ // layer then reads farther away. A touch compares screen distances, so it
493
+ // still counts that neighbour.
494
+ insets: clampedHitInsets(
495
+ inLayout(target, target, scale),
496
+ neighbours.map(rect => inLayout(rect, target, scale)),
497
+ watch.minSize,
498
+ ),
397
499
  neighbours,
398
500
  };
399
501
  }
@@ -4,7 +4,8 @@
4
4
  * @file inputStream.ts
5
5
  * @input A window, and subscribers to its input events (the press feedback
6
6
  * controller, the gesture host)
7
- * @output subscribeInput
7
+ * @output subscribeInput, and getLastPointerType: the type of the latest
8
+ * pointer event the stream delivered
8
9
  * @position The one entry for document-wide input listeners in core: one
9
10
  * native listener per event type on the window's capture phase, shared by
10
11
  * every subscriber
@@ -22,18 +23,21 @@
22
23
  // `blur` or `focus`. A subscriber for the window's own event checks
23
24
  // `event.target`.
24
25
  //
25
- // Subscribers run in subscription order. One that throws is reported, and
26
- // the rest still run.
26
+ // Subscribers run in subscription order, after the ones subscribed `first`.
27
+ // A first subscriber that returns `true` ends the dispatch: no later
28
+ // subscriber hears the event. One that throws is reported, and the rest still
29
+ // run.
27
30
  //
28
31
  // A type's native listener is passive, so it blocks no scroll. It is
29
32
  // non-passive only while a subscriber that cancels the event
30
33
  // (`{cancels: true}`) is subscribed. With no subscriber left, it is removed.
31
34
 
32
- type InputListener = (event: Event) => void;
35
+ type InputListener = (event: Event) => unknown;
33
36
 
34
37
  interface Subscriber {
35
38
  readonly listener: InputListener;
36
39
  readonly cancels: boolean;
40
+ readonly isFirst: boolean;
37
41
  }
38
42
 
39
43
  interface Channel {
@@ -50,12 +54,30 @@ export interface InputSubscriptionOptions {
50
54
  * @default false
51
55
  */
52
56
  readonly cancels?: boolean;
57
+ /**
58
+ * The subscriber runs before every subscriber that is not first. When it
59
+ * returns `true`, no later subscriber hears the event.
60
+ * @default false
61
+ */
62
+ readonly first?: boolean;
53
63
  }
54
64
 
55
65
  /** The events a window's capture phase sees: its own, and the document's. */
56
66
  export type InputEventMap = WindowEventMap & DocumentEventMap;
57
67
 
58
68
  const streams = new WeakMap<Window, Map<string, Channel>>();
69
+ /** The type of the latest pointer event each window's stream delivered. */
70
+ const lastPointerTypes = new WeakMap<Window, string>();
71
+
72
+ /**
73
+ * The type of the latest pointer event `view`'s stream delivered: `mouse`,
74
+ * `pen` or `touch`, or `null` before any. The stream hears a pointer event
75
+ * type only while a subscriber listens to it, as press feedback does on any
76
+ * page with a pressable. Reading it adds no listener.
77
+ */
78
+ export function getLastPointerType(view: Window): string | null {
79
+ return lastPointerTypes.get(view) ?? null;
80
+ }
59
81
 
60
82
  /**
61
83
  * Listen to `type` on `view`'s capture phase through its shared native
@@ -64,8 +86,8 @@ const streams = new WeakMap<Window, Map<string, Channel>>();
64
86
  export function subscribeInput<K extends keyof InputEventMap>(
65
87
  view: Window,
66
88
  type: K,
67
- listener: (event: InputEventMap[K]) => void,
68
- {cancels = false}: InputSubscriptionOptions = {},
89
+ listener: (event: InputEventMap[K]) => unknown,
90
+ {cancels = false, first = false}: InputSubscriptionOptions = {},
69
91
  ): () => void {
70
92
  let channels = streams.get(view);
71
93
  if (channels == null) {
@@ -80,8 +102,16 @@ export function subscribeInput<K extends keyof InputEventMap>(
80
102
  const subscriber: Subscriber = {
81
103
  listener: listener as InputListener,
82
104
  cancels,
105
+ isFirst: first,
83
106
  };
84
- channel.subscribers.push(subscriber);
107
+ const firstLater = first
108
+ ? channel.subscribers.findIndex(other => !other.isFirst)
109
+ : -1;
110
+ if (firstLater === -1) {
111
+ channel.subscribers.push(subscriber);
112
+ } else {
113
+ channel.subscribers.splice(firstLater, 0, subscriber);
114
+ }
85
115
  register(view, type, channel);
86
116
  let isSubscribed = true;
87
117
  return () => {
@@ -124,12 +154,17 @@ function register(view: Window, type: string, channel: Channel): void {
124
154
  if (wanted == null) {
125
155
  return;
126
156
  }
127
- const listener: InputListener = event => dispatch(channel, event);
157
+ const listener: InputListener = event => dispatch(view, channel, event);
128
158
  view.addEventListener(type, listener, {capture: true, passive: !wanted});
129
159
  channel.native = {listener, cancels: wanted};
130
160
  }
131
161
 
132
- function dispatch(channel: Channel, event: Event): void {
162
+ function dispatch(view: Window, channel: Channel, event: Event): void {
163
+ // Recorded before any subscriber runs, so each reads the pointer at hand.
164
+ const {pointerType} = event as Partial<PointerEvent>;
165
+ if (typeof pointerType === 'string' && pointerType !== '') {
166
+ lastPointerTypes.set(view, pointerType);
167
+ }
133
168
  // A subscriber may subscribe or unsubscribe while the event runs; the
134
169
  // event goes to those subscribed when it arrived.
135
170
  for (const subscriber of [...channel.subscribers]) {
@@ -137,7 +172,9 @@ function dispatch(channel: Channel, event: Event): void {
137
172
  continue;
138
173
  }
139
174
  try {
140
- subscriber.listener(event);
175
+ if (subscriber.listener(event) === true && subscriber.isFirst) {
176
+ return;
177
+ }
141
178
  } catch (error) {
142
179
  report(error);
143
180
  }
@@ -9,7 +9,8 @@
9
9
  * @input StyleX and the semantic interaction-overlay color tokens
10
10
  * @output Reusable background-color and background-image state styles, the
11
11
  * touch press's registered strength variable (`pressVars`) and its clocks
12
- * (`pressConsts`)
12
+ * (`pressConsts`). The list row's compositor press layer and its clocks
13
+ * are internal (privateAttributes/press.stylex.ts, utils/rowPressLayer.stylex.ts)
13
14
  * @position Internal styling utility for interactive core surfaces
14
15
  *
15
16
  * SYNC: When modified, update pressFeedback.ts, pressGesture.ts (the fade
@@ -41,7 +42,7 @@
41
42
  // background image, so a composer's color transition cannot fade the onset
42
43
  // in. `on` sets the strength to 1 on the first frame. `fading` animates it
43
44
  // from 1 to 0, not to the hover strength, because a finger has no hover. The
44
- // theme's motion tempo scales the release clock (AST-108).
45
+ // release plays the theme's exit motion tokens, which follow its tempo.
45
46
  //
46
47
  // The release is an animation, not a transition. Composers own their
47
48
  // `transition-*` longhands, and StyleX is last-wins per property. A
@@ -54,7 +55,8 @@
54
55
  // `animation-*` on the element that composes them. The touch arms own both.
55
56
 
56
57
  import * as stylex from '@stylexjs/stylex';
57
- import {colorVars} from '../theme/tokens.stylex';
58
+ import {reducedMotionFadeConsts} from '../motion/reducedMotion.stylex';
59
+ import {colorVars, durationVars, easeVars} from '../theme/tokens.stylex';
58
60
 
59
61
  /**
60
62
  * The touch press's strength on the surface the controller painted, 0 to 1.
@@ -72,26 +74,22 @@ export const pressVars = stylex.defineVars({
72
74
  });
73
75
 
74
76
  /**
75
- * The touch press's clocks that both the stylesheet and the controller read.
76
- *
77
- * `defineConsts`, so the one number is inlined here at build time and is the
78
- * controller's constant at run time (`PRESS_FADE_MS` in pressGesture.ts):
79
- * the release animation and the controller's clock cannot drift apart. When
80
- * that clock runs out, the controller waits for a release animation that a
81
- * busy main thread started late, then removes the attribute.
77
+ * The touch press's measured release clock, kept as a reference value. Press
78
+ * releases now play the theme's `--duration-exit`.
82
79
  */
83
80
  export const pressConsts = stylex.defineConsts({
84
- /** How long the release takes, in ms. UIKit's deselect clock. */
81
+ /** UIKit's deselect clock, in ms: the measured reference value. */
85
82
  releaseMs: 200,
86
83
  });
87
84
 
88
85
  /**
89
- * The release's clock as CSS, scaled by the theme's `--_astryx-motion-tempo`
90
- * up to 1.5, its maximum. The controller's timer reads the same property.
86
+ * The release's clock: the theme's exit duration. The token already
87
+ * follows the theme's tempo. The controller's timer reads the
88
+ * same property.
91
89
  */
92
- const PRESS_RELEASE_DURATION = `calc(${pressConsts.releaseMs}ms * min(var(--_astryx-motion-tempo, 1), 1.5))`;
93
- /** The same clock under Reduce Motion: a tempo may shorten it, never lengthen it. */
94
- const PRESS_RELEASE_DURATION_REDUCED = `min(${pressConsts.releaseMs}ms, calc(${pressConsts.releaseMs}ms * var(--_astryx-motion-tempo, 1)))`;
90
+ const PRESS_RELEASE_DURATION = durationVars['--duration-exit'];
91
+ /** The same clock under Reduce Motion, no longer than the Reduce Motion fade. */
92
+ const PRESS_RELEASE_DURATION_REDUCED = `min(${durationVars['--duration-exit']}, ${reducedMotionFadeConsts.duration})`;
95
93
 
96
94
  const ENABLED = ':where(:not(:disabled,[aria-disabled="true"]))';
97
95
  const HOVER_HOVER = '@media (hover: hover)';
@@ -144,13 +142,12 @@ const pressRelease = stylex.keyframes({
144
142
  });
145
143
 
146
144
  /**
147
- * The release's curve: a gentle ease-out that spends the whole clock fading
148
- * (strength ≈ 0.2 at the midpoint), which is what a deselect crossfade reads
149
- * as. Not the system's `--ease-standard`: that curve is for things that move,
150
- * and is so front-loaded (strength 0.05 at the midpoint) that the release
151
- * would read as half its clock.
145
+ * The release's curve: the theme's exit easing. The list row's layer
146
+ * (privateAttributes/press.stylex.ts) and Switch's press layers use the same
147
+ * token; interactionOverlay.cell.test.ts and Switch.test.tsx fail if they
148
+ * differ.
152
149
  */
153
- const RELEASE_EASE = 'cubic-bezier(0, 0, 0.2, 1)';
150
+ const RELEASE_EASE = easeVars['--ease-exit'];
154
151
 
155
152
  /**
156
153
  * The touch press's strength and its release, on the element the controller
@@ -9,6 +9,11 @@
9
9
 
10
10
  import type {ISODateString, PlainDate} from './dateTypes';
11
11
  import type {Locale} from '../i18n/types';
12
+ import {
13
+ formatCalendarDate,
14
+ isCalendarSystem,
15
+ type CalendarSystem,
16
+ } from './calendarSystem';
12
17
  import {firstCharacter} from './characters';
13
18
  import {standaloneMonthCapitalLanguages} from './standaloneMonthCapitals.generated';
14
19
 
@@ -374,8 +379,13 @@ export const DATE_FORMAT_MONTH_YEAR: Intl.DateTimeFormatOptions = {
374
379
  export function plainDateFormatStandaloneMonthYear(
375
380
  pd: PlainDate,
376
381
  locale: Locale,
382
+ calendar: Intl.DateTimeFormatOptions['calendar'] = 'gregory',
377
383
  ): string {
378
- const label = plainDateFormat(pd, DATE_FORMAT_MONTH_YEAR, locale);
384
+ const label = plainDateFormat(
385
+ pd,
386
+ {...DATE_FORMAT_MONTH_YEAR, calendar},
387
+ locale,
388
+ );
379
389
  let language: string;
380
390
  try {
381
391
  language = new Intl.Locale(locale).language;
@@ -450,35 +460,63 @@ export const DATE_FORMAT_SHORT_WITH_YEAR: Intl.DateTimeFormatOptions = {
450
460
  * when `options.calendar` is omitted. The explicit option remains supported for
451
461
  * compatibility with the public `Intl.DateTimeFormatOptions` signature; it is a
452
462
  * display-only escape hatch and does not change PlainDate arithmetic, parsing,
453
- * serialization, or any Astryx component's calendar semantics.
463
+ * serialization, or any Astryx component's calendar semantics. Another
464
+ * calendar names the month and day that Calendar shows in it.
454
465
  */
455
466
  export function plainDateFormat(
456
467
  pd: PlainDate,
457
468
  options: Intl.DateTimeFormatOptions,
458
469
  locale: Locale = 'en',
459
470
  ): string {
471
+ const calendar = options.calendar ?? 'gregory';
472
+ if (calendar !== 'gregory' && isCalendarSystem(calendar)) {
473
+ return formatCalendarDate(calendar, pd, options, locale);
474
+ }
475
+ const [format, date] = plainDateFormatInput(pd, options, locale);
476
+ return format.format(date);
477
+ }
478
+
479
+ /**
480
+ * The parts of `plainDateFormat`'s output, from the same formatter and date.
481
+ * Internal: not re-exported from `utils/index.ts`.
482
+ */
483
+ export function plainDateFormatToParts(
484
+ pd: PlainDate,
485
+ options: Intl.DateTimeFormatOptions,
486
+ locale: Locale,
487
+ ): Intl.DateTimeFormatPart[] {
488
+ const [format, date] = plainDateFormatInput(pd, options, locale);
489
+ return format.formatToParts(date);
490
+ }
491
+
492
+ function plainDateFormatInput(
493
+ pd: PlainDate,
494
+ options: Intl.DateTimeFormatOptions,
495
+ locale: Locale,
496
+ ): [Intl.DateTimeFormat, Date | number] {
460
497
  const calendar = options.calendar ?? 'gregory';
461
498
  if (options.timeZone != null) {
462
- return dateTimeFormatFor(locale, {...options, calendar}).format(
499
+ return [
500
+ dateTimeFormatFor(locale, {...options, calendar}),
463
501
  plainDateToDate(pd),
464
- );
502
+ ];
465
503
  }
466
504
  if (TIME_OF_DAY_FIELDS.some(field => options[field] != null)) {
467
505
  // A zone name or a time of day reads local midnight in the zone current
468
506
  // at the call. A cached formatter would keep the zone it was built in,
469
507
  // so this one is built for the call.
470
- return new Intl.DateTimeFormat(locale, {...options, calendar}).format(
508
+ return [
509
+ new Intl.DateTimeFormat(locale, {...options, calendar}),
471
510
  plainDateToDate(pd),
472
- );
511
+ ];
473
512
  }
474
513
  // Date fields alone: UTC midnight formatted in UTC, so neither the cached
475
514
  // formatter nor the date depends on the host's zone, which can change while
476
515
  // a page is open.
477
- return dateTimeFormatFor(locale, {
478
- ...options,
479
- calendar,
480
- timeZone: 'UTC',
481
- }).format(utcTime(pd.year, pd.month - 1, pd.day));
516
+ return [
517
+ dateTimeFormatFor(locale, {...options, calendar, timeZone: 'UTC'}),
518
+ utcTime(pd.year, pd.month - 1, pd.day),
519
+ ];
482
520
  }
483
521
 
484
522
  /** Options that print a time of day or a zone, which a PlainDate lacks. */
@@ -518,6 +556,20 @@ export function dateTimeFormatFor(
518
556
  return format;
519
557
  }
520
558
 
559
+ /**
560
+ * @internal `dateTimeFormatFor`, except that without `options.timeZone` it
561
+ * builds a formatter for the call. A cached formatter keeps the host zone it
562
+ * was built in.
563
+ */
564
+ export function dateTimeFormatAtCall(
565
+ locale: Locale,
566
+ options: Intl.DateTimeFormatOptions,
567
+ ): Intl.DateTimeFormat {
568
+ return options.timeZone === undefined
569
+ ? new Intl.DateTimeFormat(locale, options)
570
+ : dateTimeFormatFor(locale, options);
571
+ }
572
+
521
573
  /**
522
574
  * The locale's name for the "week of year" date field ("week", "Woche", "週"),
523
575
  * from CLDR through `Intl.DisplayNames`. Calendar names its week-number
@@ -543,23 +595,29 @@ export function plainDateWeekFieldName(locale: Locale = 'en'): string {
543
595
  return 'week';
544
596
  }
545
597
 
546
- const dayNumberFormats = new Map<Locale, Intl.NumberFormat>();
598
+ const dayNumberFormats = new Map<string, Intl.NumberFormat>();
547
599
 
548
600
  /**
549
601
  * A day of the month or a week number in the locale's own digits: `15` in
550
- * English, `۱۵` in Persian, `١٥` in Egyptian Arabic. Only the digits follow the
551
- * locale. The number stays the Gregorian day or ISO week that it names, so no
552
- * other calendar applies, and no grouping separator or unit word is added.
602
+ * English, `۱۵` in Persian, `١٥` in Egyptian Arabic. A `numberingSystem`
603
+ * replaces the locale's digits. Only the digits change. The number stays the
604
+ * value that it is given, so no calendar applies, and no grouping separator or
605
+ * unit word is added.
553
606
  * Internal: not re-exported from `utils/index.ts`.
554
607
  */
555
608
  export function plainDateFormatDayNumber(
556
609
  value: number,
557
610
  locale: Locale,
611
+ numberingSystem?: string,
558
612
  ): string {
559
- let format = dayNumberFormats.get(locale);
613
+ const key = `${locale}|${numberingSystem ?? ''}`;
614
+ let format = dayNumberFormats.get(key);
560
615
  if (format == null) {
561
- format = new Intl.NumberFormat(locale, {useGrouping: false});
562
- dayNumberFormats.set(locale, format);
616
+ format = new Intl.NumberFormat(locale, {
617
+ useGrouping: false,
618
+ numberingSystem,
619
+ });
620
+ dayNumberFormats.set(key, format);
563
621
  }
564
622
  return format.format(value);
565
623
  }
@@ -605,14 +663,21 @@ export const SHARED_DATE_FORMAT_OPTIONS: Record<
605
663
  * members. The shared entry point DateInput uses for the named-format path;
606
664
  * Timestamp maps the same members onto {@link SHARED_DATE_FORMAT_OPTIONS} in
607
665
  * its own `formatTimestamp` switch (its input is a `Date`, not a `PlainDate`).
666
+ * The locale-aware members write the date in `calendar`, which defaults to
667
+ * Gregorian. `system_date` stays the Gregorian ISO date in every calendar.
608
668
  */
609
669
  export function formatSharedDate(
610
670
  pd: PlainDate,
611
671
  format: SharedDateFormat,
612
672
  locale: Locale = 'en',
673
+ calendar: CalendarSystem = 'gregory',
613
674
  ): string {
614
675
  if (format === 'system_date') {
615
676
  return plainDateToISO(pd);
616
677
  }
617
- return plainDateFormat(pd, SHARED_DATE_FORMAT_OPTIONS[format], locale);
678
+ return plainDateFormat(
679
+ pd,
680
+ {...SHARED_DATE_FORMAT_OPTIONS[format], calendar},
681
+ locale,
682
+ );
618
683
  }
@@ -3,10 +3,10 @@
3
3
  /**
4
4
  * @file pressFeedback.ts
5
5
  * @input The press state machine (pressGesture.ts), the menu-press and
6
- * press-group markers and the document's pointer, keyboard, scroll and
6
+ * press-group markers, the scroll-view test (scrollView.ts) and the document's pointer, keyboard, scroll and
7
7
  * visibility events
8
8
  * @output PRESSABLE_ATTRIBUTE, PRESSED_ATTRIBUTE, pressableProps,
9
- * pressFadeMs and installPressFeedback
9
+ * pressFadeMs, installPressFeedback and cancelPress
10
10
  * @position The DOM half of the touch press model. usePressFeedback installs
11
11
  * it, and the CSS arms live in interactionOverlay.stylex.ts.
12
12
  *
@@ -23,9 +23,13 @@
23
23
  // Where the primary pointer is fine, the controller ignores the mouse and the
24
24
  // keyboard, and CSS `:active` keeps their press. Under a coarse primary
25
25
  // pointer the CSS drops `:active`, so the controller paints every press. A
26
- // finger's press paints after the delay. A mouse, trackpad or Space press
27
- // paints at once. The controller reads the same query as the stylesheet, so
28
- // they agree.
26
+ // mouse, trackpad or Space press paints at once. The controller reads the
27
+ // same query as the stylesheet, so they agree.
28
+ //
29
+ // A finger waits only inside a scroller. Outside one, a surface highlights in
30
+ // the frame the finger lands, as a UIControl does. Inside one, it waits the
31
+ // content-touch delay, because the touch can become a scroll. Rows follow the
32
+ // same rule.
29
33
  //
30
34
  // A surface's hold does nothing, so it keeps the browser's long-press text
31
35
  // selection (AST-094). Only an element whose hold does something suppresses
@@ -43,7 +47,10 @@ import {
43
47
  pressGestureStep,
44
48
  } from './pressGesture';
45
49
  import {isCoarsePointer, watchCoarsePointer} from './coarsePointer';
50
+ import {reducedMotionFadeConsts} from '../motion/reducedMotion.stylex';
51
+ import {parseMotionRoleValue} from '../motion/roles';
46
52
  import {subscribeInput} from './inputStream';
53
+ import {isInsideScrollView} from './scrollView';
47
54
  import {TOUCH_QUERY} from './touchPresentation';
48
55
  import {holdsPressThroughDrag} from '../privateAttributes/pressHoldsDrag.stylex';
49
56
  import {isTrackedByGroup} from '../privateAttributes/pressGroupItem.stylex';
@@ -151,19 +158,24 @@ const TIMER_MS: Record<NonNullable<PressStep['timer']>, number> = {
151
158
 
152
159
  /**
153
160
  * The release fade's clock on `element`, read once, at the release, from the
154
- * property its stylesheet reads: the theme's `--_astryx-motion-tempo`. Under
155
- * Reduce Motion a tempo may shorten the fade, never lengthen it past 200 ms.
161
+ * token its stylesheet reads: the theme's `--duration-exit`. Without a
162
+ * readable value it is the token's default. Under Reduce Motion it is no
163
+ * longer than the Reduce Motion fade, as in the stylesheet.
156
164
  */
157
165
  export function pressFadeMs(element: Element): number {
158
- const style = getComputedStyle(element);
159
- const value = style.getPropertyValue('--_astryx-motion-tempo').trim();
160
- const read = value === '' ? Number.NaN : Number(value);
161
- const tempo = Number.isFinite(read) && read > 0 ? read : 1;
162
- const scaled = PRESS_FADE_MS * tempo;
166
+ const exit =
167
+ parseMotionRoleValue(
168
+ 'duration',
169
+ getComputedStyle(element).getPropertyValue('--duration-exit'),
170
+ ) ?? PRESS_FADE_MS;
163
171
  const reduced =
164
172
  typeof window.matchMedia === 'function' &&
165
173
  window.matchMedia('(prefers-reduced-motion: reduce)').matches;
166
- return reduced ? Math.min(scaled, PRESS_FADE_MS) : scaled;
174
+ const bound = parseMotionRoleValue(
175
+ 'duration',
176
+ reducedMotionFadeConsts.duration,
177
+ );
178
+ return reduced && bound != null ? Math.min(exit, bound) : exit;
167
179
  }
168
180
 
169
181
  /**
@@ -247,7 +259,11 @@ function paintElement(element: HTMLElement, paint: PressPaint): void {
247
259
  element.removeAttribute(PRESSED_ATTRIBUTE);
248
260
  return;
249
261
  }
250
- element.setAttribute(PRESSED_ATTRIBUTE, paint);
262
+ // A step that keeps the paint writes nothing, so the element sees one
263
+ // change per paint.
264
+ if (element.getAttribute(PRESSED_ATTRIBUTE) !== paint) {
265
+ element.setAttribute(PRESSED_ATTRIBUTE, paint);
266
+ }
251
267
  }
252
268
 
253
269
  function clearTimer(slot: Slot): void {
@@ -381,6 +397,21 @@ function finish(slot: Slot): void {
381
397
  }
382
398
  }
383
399
 
400
+ /**
401
+ * Ends the press the controller follows on `element`, and its paint, at once.
402
+ * A clickable container calls it when a press starts on an interactive
403
+ * element inside it: that press does not activate the container, so the
404
+ * container shows no press.
405
+ */
406
+ export function cancelPress(element: Element): void {
407
+ if (finger.live?.element === element) {
408
+ finish(finger);
409
+ }
410
+ if (button.live?.element === element) {
411
+ finish(button);
412
+ }
413
+ }
414
+
384
415
  /** A new press on an element owns its paint: the other slot's gesture there ends. */
385
416
  function takeOver(other: Slot, element: HTMLElement): void {
386
417
  if (other.live?.element === element) {
@@ -521,6 +552,7 @@ function onPointerDown(event: PointerEvent): void {
521
552
  kind: 'down',
522
553
  x: event.clientX,
523
554
  y: event.clientY,
555
+ delayed: isInsideScrollView(element),
524
556
  }),
525
557
  );
526
558
  }