@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
@@ -21,7 +21,7 @@ import {
21
21
  type ReactNode,
22
22
  type RefCallback,
23
23
  } from 'react';
24
- import {createTriggerFocusGate} from '../utils/triggerFocus';
24
+ import {createTriggerFocusGate, isFocusOnTrigger} from '../utils/triggerFocus';
25
25
  import * as stylex from '@stylexjs/stylex';
26
26
  import {
27
27
  useLayerInternal,
@@ -185,7 +185,8 @@ export interface TooltipReturn {
185
185
 
186
186
  /**
187
187
  * Ref for the positioning anchor element.
188
- * Injects anchorName style for CSS anchor positioning.
188
+ * While the layer is shown, and until its exit animation ends, the trigger
189
+ * carries the layer's CSS anchor name.
189
190
  */
190
191
  positionRef: RefCallback<HTMLElement>;
191
192
 
@@ -199,6 +200,7 @@ export interface TooltipReturn {
199
200
  /**
200
201
  * The CSS anchor name to use for positioning.
201
202
  * Use this when you need to set anchorName manually (e.g., display:contents wrapper).
203
+ * Set it only while the layer is shown or its exit animation runs.
202
204
  */
203
205
  anchorId: string;
204
206
 
@@ -308,6 +310,17 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
308
310
  const showTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
309
311
  const hideTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
310
312
  const triggerRef = useRef<HTMLElement | null>(null);
313
+ // Whether the tooltip is enabled now, for a show that runs after a render
314
+ // (a pending hover show) and for the trigger ref callback.
315
+ const isEnabledRef = useRef(isEnabled);
316
+ isEnabledRef.current = isEnabled;
317
+ // Counts the renders in which the tooltip is disabled. A pending show
318
+ // records it, so a show scheduled before a disable is dropped even when
319
+ // the tooltip is enabled again before the timer fires.
320
+ const disabledRendersRef = useRef(0);
321
+ if (!isEnabled) {
322
+ disabledRendersRef.current += 1;
323
+ }
311
324
 
312
325
  // Clear all timeouts
313
326
  const clearTimeouts = useCallback(() => {
@@ -460,22 +473,16 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
460
473
  return;
461
474
  }
462
475
  clearTimeouts();
476
+ const disabledRenders = disabledRendersRef.current;
463
477
  showTimeoutRef.current = setTimeout(() => {
464
- showLayer();
478
+ // A show runs only if the tooltip stayed enabled since it was
479
+ // scheduled: nothing would close a tooltip that opens after a disable.
480
+ if (disabledRendersRef.current === disabledRenders) {
481
+ showLayer();
482
+ }
465
483
  }, delay);
466
484
  }, [isEnabled, isOpen, clearTimeouts, showLayer, delay]);
467
485
 
468
- // A show scheduled while the triggers were enabled must not outlive them:
469
- // disabling also detaches the leave listener that would have cancelled it,
470
- // so the timer would open a tooltip that nothing ever closes. Only the
471
- // pending show is dropped; a pending hide still runs.
472
- useEffect(() => {
473
- if (!isEnabled && showTimeoutRef.current) {
474
- clearTimeout(showTimeoutRef.current);
475
- showTimeoutRef.current = null;
476
- }
477
- }, [isEnabled]);
478
-
479
486
  // Schedule hide with delay (suppressed when isOpen is true).
480
487
  // A small hover bridge (when hideDelay is 0) lets the pointer travel from the
481
488
  // trigger onto the tooltip surface without the tooltip vanishing — required
@@ -537,23 +544,25 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
537
544
  // focus that counted still hides on blur (utils/triggerFocus.ts).
538
545
  const [focusGate] = useState(createTriggerFocusGate);
539
546
 
547
+ // Whether focus on `target` opens the tooltip. With a `trigger`, its
548
+ // `focusTrigger` rule applies too. Only `:focus-visible` focus opens it, and
549
+ // a tap never does: a tapped `<input>` also matches `:focus-visible`.
550
+ const opensOnFocus = useCallback(
551
+ (target: HTMLElement, trigger: HTMLElement | null): boolean => {
552
+ if (trigger != null && !isFocusOnTrigger(target, trigger, focusTrigger)) {
553
+ return false;
554
+ }
555
+ return !isTouchInteraction() && target.matches(':focus-visible');
556
+ },
557
+ [focusTrigger, isTouchInteraction],
558
+ );
559
+
540
560
  const handleFocusIn = useCallback(
541
561
  (e: Event) => {
542
562
  if (!focusGate.focusIn(e, focusTrigger) || !isEnabled) {
543
563
  return;
544
564
  }
545
- // A tap focuses the trigger it activates, and `:focus-visible` does not
546
- // filter that out on every element: a tapped `<input>` or contenteditable
547
- // matches it. Those are exactly the action triggers `auto` just decided
548
- // to keep shut, so without this the focus reopens what the tap
549
- // suppressed, over the field the user is trying to type into.
550
- if (isTouchInteraction()) {
551
- return;
552
- }
553
- // Only show tooltip for keyboard focus (:focus-visible),
554
- // not programmatic focus (e.g. dialog auto-focus, touch tap)
555
- const target = e.target as HTMLElement;
556
- if (!target.matches(':focus-visible')) {
565
+ if (!opensOnFocus(e.target as HTMLElement, null)) {
557
566
  return;
558
567
  }
559
568
  clearTimeouts();
@@ -563,7 +572,7 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
563
572
  focusGate,
564
573
  focusTrigger,
565
574
  isEnabled,
566
- isTouchInteraction,
575
+ opensOnFocus,
567
576
  clearTimeouts,
568
577
  showLayer,
569
578
  ],
@@ -656,66 +665,155 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
656
665
  ],
657
666
  );
658
667
 
659
- // Interaction ref that handles event listeners only
660
- const interactionRef: RefCallback<HTMLElement> = useCallback(
661
- (el: HTMLElement | null) => {
662
- // Cleanup previous element
663
- if (triggerRef.current) {
664
- triggerRef.current.removeEventListener('mouseenter', handleMouseEnter);
665
- triggerRef.current.removeEventListener('mouseleave', handleMouseLeave);
666
- triggerRef.current.removeEventListener('focusin', handleFocusIn);
667
- triggerRef.current.removeEventListener('focusout', handleFocusOut);
668
- triggerRef.current.removeEventListener('focusout', handleHeldFocusOut);
669
- stopPressTrackingRef.current?.();
670
- triggerRef.current.removeEventListener(
671
- 'pointerenter',
672
- handlePointerEnter,
673
- );
674
- triggerRef.current.removeEventListener(
675
- 'pointerdown',
676
- handlePointerDown,
677
- );
678
- }
668
+ // The trigger's listeners call the latest handlers through this ref, so the
669
+ // trigger ref callback keeps one identity.
670
+ const handlersRef = useRef({
671
+ handleMouseEnter,
672
+ handleMouseLeave,
673
+ handleFocusIn,
674
+ handleFocusOut,
675
+ handleHeldFocusOut,
676
+ handlePointerEnter,
677
+ handlePointerDown,
678
+ focusTrigger,
679
+ isOpen,
680
+ dropHold,
681
+ hideNow,
682
+ showNow,
683
+ opensOnFocus,
684
+ });
685
+ handlersRef.current = {
686
+ handleMouseEnter,
687
+ handleMouseLeave,
688
+ handleFocusIn,
689
+ handleFocusOut,
690
+ handleHeldFocusOut,
691
+ handlePointerEnter,
692
+ handlePointerDown,
693
+ focusTrigger,
694
+ isOpen,
695
+ dropHold,
696
+ hideNow,
697
+ showNow,
698
+ opensOnFocus,
699
+ };
679
700
 
680
- if (el) {
681
- // Attach hover listeners. `pointerenter` runs before the synthesized
682
- // `mouseenter` a tap produces, which is what lets the hover path know
683
- // it is looking at a finger.
684
- el.addEventListener('pointerenter', handlePointerEnter);
685
- el.addEventListener('mouseenter', handleMouseEnter);
686
- el.addEventListener('mouseleave', handleMouseLeave);
687
- // Press-to-dismiss on a mouse; tap-to-open on a touch pointer.
688
- el.addEventListener('pointerdown', handlePointerDown);
689
-
690
- // Focus listeners unless focus never opens the tooltip; `auto` decides
691
- // per event (utils/triggerFocus.ts).
692
- if (focusTrigger !== 'never') {
693
- el.addEventListener('focusin', handleFocusIn);
694
- el.addEventListener('focusout', handleFocusOut);
695
- }
701
+ // Removes the attached trigger's listeners (the trigger ref callback's
702
+ // cleanup).
703
+ const detachTriggerRef = useRef<(() => void) | null>(null);
704
+ // Set when the trigger detached while the tooltip was disabled: the
705
+ // caller removed the wiring (DropdownMenu's Button while its menu is
706
+ // open), so the next enabled attach reads the focus that arrived meanwhile.
707
+ const wasSuppressedRef = useRef(false);
708
+
709
+ // The trigger's ref callback owns every trigger listener, and reads the
710
+ // trigger's state when it attaches and detaches.
711
+ const interactionRef = useCallback((el: HTMLElement | null) => {
712
+ // A caller that reports `null` by hand detaches the trigger, as the
713
+ // returned cleanup does.
714
+ if (el == null) {
715
+ detachTriggerRef.current?.();
716
+ return;
717
+ }
718
+ if (el === triggerRef.current) {
719
+ return;
720
+ }
721
+ detachTriggerRef.current?.();
722
+ const latest = () => handlersRef.current;
723
+ // `pointerenter` runs before the synthesized `mouseenter` a tap produces,
724
+ // which is what lets the hover path know it is looking at a finger.
725
+ const onPointerEnter = (e: PointerEvent) => latest().handlePointerEnter(e);
726
+ const onMouseEnter = () => latest().handleMouseEnter();
727
+ const onMouseLeave = (e: Event) => latest().handleMouseLeave(e);
728
+ // Press-to-dismiss on a mouse; tap-to-open on a touch pointer.
729
+ const onPointerDown = (e: PointerEvent) => latest().handlePointerDown(e);
730
+ // Focus counts unless focus never opens the tooltip; `auto` decides per
731
+ // event (isFocusForTrigger).
732
+ const onFocusIn = (e: Event) => {
733
+ if (latest().focusTrigger !== 'never') {
734
+ latest().handleFocusIn(e);
735
+ }
736
+ };
737
+ const onFocusOut = (e: Event) => {
738
+ if (latest().focusTrigger !== 'never') {
739
+ latest().handleFocusOut(e);
696
740
  }
741
+ };
742
+ // A held tooltip's own focus-leave close, whatever `focusTrigger` is.
743
+ const onHeldFocusOut = (e: FocusEvent) => latest().handleHeldFocusOut(e);
744
+ el.addEventListener('pointerenter', onPointerEnter);
745
+ el.addEventListener('mouseenter', onMouseEnter);
746
+ el.addEventListener('mouseleave', onMouseLeave);
747
+ el.addEventListener('pointerdown', onPointerDown);
748
+ el.addEventListener('focusin', onFocusIn);
749
+ el.addEventListener('focusout', onFocusOut);
750
+ el.addEventListener('focusout', onHeldFocusOut);
751
+ triggerRef.current = el;
752
+
753
+ // A trigger that attaches again after its wiring was removed
754
+ // (DropdownMenu's Button as its menu closes) missed the focus that
755
+ // arrived meanwhile. Show for it only if it would open the tooltip:
756
+ // returned keyboard focus does, focus returned after a pointer pick does
757
+ // not. Any other attach leaves the tooltip as it is, so a tooltip
758
+ // dismissed with Escape stays closed.
759
+ const focused = el.ownerDocument.activeElement;
760
+ const wasSuppressed = wasSuppressedRef.current;
761
+ if (isEnabledRef.current) {
762
+ wasSuppressedRef.current = false;
763
+ }
764
+ if (
765
+ wasSuppressed &&
766
+ isEnabledRef.current &&
767
+ latest().isOpen === undefined &&
768
+ latest().focusTrigger !== 'never' &&
769
+ focused instanceof HTMLElement &&
770
+ el.contains(focused) &&
771
+ latest().opensOnFocus(focused, el)
772
+ ) {
773
+ latest().showNow();
774
+ }
697
775
 
698
- // Its own focus-leave listener: `focusTrigger="never"` attaches none.
699
- el?.addEventListener('focusout', handleHeldFocusOut);
700
- triggerRef.current = el;
701
- },
702
- [
703
- handleHeldFocusOut,
704
- focusTrigger,
705
- handleMouseEnter,
706
- handleMouseLeave,
707
- handleFocusIn,
708
- handleFocusOut,
709
- handlePointerEnter,
710
- handlePointerDown,
711
- ],
712
- );
776
+ const detach = () => {
777
+ if (detachTriggerRef.current === detach) {
778
+ detachTriggerRef.current = null;
779
+ }
780
+ el.removeEventListener('pointerenter', onPointerEnter);
781
+ el.removeEventListener('mouseenter', onMouseEnter);
782
+ el.removeEventListener('mouseleave', onMouseLeave);
783
+ el.removeEventListener('pointerdown', onPointerDown);
784
+ el.removeEventListener('focusin', onFocusIn);
785
+ el.removeEventListener('focusout', onFocusOut);
786
+ el.removeEventListener('focusout', onHeldFocusOut);
787
+ stopPressTrackingRef.current?.();
788
+ if (triggerRef.current === el) {
789
+ triggerRef.current = null;
790
+ }
791
+ // A caller removes the wiring as it disables the tooltip. Close an
792
+ // uncontrolled tooltip then, or the next attach shows a stale tooltip.
793
+ // A detach while enabled, such as a merged ref that changes identity
794
+ // on a re-render, keeps a hovered or held tooltip open.
795
+ if (!isEnabledRef.current && latest().isOpen === undefined) {
796
+ wasSuppressedRef.current = true;
797
+ latest().dropHold();
798
+ latest().hideNow();
799
+ }
800
+ };
801
+ detachTriggerRef.current = detach;
802
+ return detach;
803
+ }, []);
713
804
 
714
805
  // Combined ref - shorthand for calling both positionRef and interactionRef
715
- const ref: RefCallback<HTMLElement> = useCallback(
806
+ const ref = useCallback(
716
807
  (el: HTMLElement | null) => {
717
808
  layerRef(el);
718
- interactionRef(el);
809
+ const detachInteraction = interactionRef(el);
810
+ if (el == null) {
811
+ return;
812
+ }
813
+ return () => {
814
+ detachInteraction?.();
815
+ layerRef(null);
816
+ };
719
817
  },
720
818
  [layerRef, interactionRef],
721
819
  );
@@ -4,7 +4,8 @@
4
4
 
5
5
  /**
6
6
  * @file TreeListItem.tsx
7
- * @input Uses React, StyleX, theme tokens, TreeListBranches
7
+ * @input Uses React, StyleX, theme tokens, TreeListBranches, the shared press
8
+ * overlays and the compositor press layer
8
9
  * @output Exports TreeListItem component (internal, not publicly exported)
9
10
  * @position Internal implementation; consumed by TreeList.tsx
10
11
  *
@@ -27,8 +28,10 @@ import {
27
28
  } from '../theme/tokens.stylex';
28
29
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
29
30
  import {interactionOverlayStyles} from '../utils/interactionOverlay.stylex';
31
+ import {rowPressLayerStyles} from '../privateAttributes/press.stylex';
30
32
  import {usePressFeedback} from '../hooks/usePressFeedback';
31
33
  import {
34
+ cancelNestedTouchPress,
32
35
  hasInteractiveAncestor,
33
36
  useClickableContainer,
34
37
  } from '../hooks/useClickableContainer';
@@ -485,6 +488,28 @@ export function TreeListItem({
485
488
  interactiveRef: linkRef,
486
489
  disabled: isDisabled || !forwardsToLink,
487
490
  });
491
+
492
+ // A finger press that starts on a control inside the row does not activate
493
+ // the row, so the row shows no press for it. The row's own action, its link
494
+ // or invisible button, activates it. The Chevron does too when the row's
495
+ // surface toggles, since it runs that same toggle.
496
+ const actionButtonRef = useRef<HTMLButtonElement>(null);
497
+ const chevronRef = useRef<HTMLButtonElement>(null);
498
+ const surfaceToggles = onClick == null && handleClick != null;
499
+ const pressOnRow = (event: React.PointerEvent<HTMLDivElement>) => {
500
+ if (isDisabled) {
501
+ return;
502
+ }
503
+ const chevron = chevronRef.current;
504
+ const ownAction =
505
+ surfaceToggles &&
506
+ chevron != null &&
507
+ event.target instanceof Node &&
508
+ chevron.contains(event.target)
509
+ ? chevron
510
+ : (linkRef.current ?? actionButtonRef.current);
511
+ cancelNestedTouchPress(event, event.currentTarget, ownAction);
512
+ };
488
513
  const {onMouseUp: openLinkOnMiddleClick} = useClickableContainer({
489
514
  containerRef: linkRowRef,
490
515
  href,
@@ -566,6 +591,7 @@ export function TreeListItem({
566
591
  // focusable element to receive Enter/Space). The row's handleClick ignores
567
592
  // clicks originating inside a <button>, so this never double-toggles.
568
593
  <button
594
+ ref={chevronRef}
569
595
  type="button"
570
596
  aria-expanded={isExpanded}
571
597
  aria-label={t('@astryx.treeList.toggleChildren')}
@@ -642,6 +668,7 @@ export function TreeListItem({
642
668
  </LinkComponent>
643
669
  ) : onClick != null ? (
644
670
  <button
671
+ ref={actionButtonRef}
645
672
  type="button"
646
673
  onClick={onClick}
647
674
  aria-disabled={isDisabled || undefined}
@@ -712,6 +739,10 @@ export function TreeListItem({
712
739
  densityStyles[density],
713
740
  styles.interactive,
714
741
  interactionOverlayStyles.backgroundImage,
742
+ // The touch press on a compositor layer (after the
743
+ // overlay, whose own touch paint it turns off).
744
+ rowPressLayerStyles.cell,
745
+ rowPressLayerStyles.cellOnImage,
715
746
  isDisabled && styles.disabled,
716
747
  isSelected && styles.selected,
717
748
  xstyle,
@@ -732,7 +763,10 @@ export function TreeListItem({
732
763
  )}
733
764
  ref={forwardsToLink ? linkRowRef : undefined}
734
765
  onClick={forwardsToLink ? delegateToLink : handleClick}
735
- onMouseUp={forwardsToLink ? openLinkOnMiddleClick : undefined}>
766
+ onMouseUp={forwardsToLink ? openLinkOnMiddleClick : undefined}
767
+ onPointerDown={
768
+ forwardsToLink || handleClick != null ? pressOnRow : undefined
769
+ }>
736
770
  <div {...stylex.props(styles.indentedContent)}>{innerContent}</div>
737
771
  </div>
738
772
  </div>
@@ -3,7 +3,8 @@
3
3
  /**
4
4
  * @file GestureHost.ts
5
5
  * @input DOM touch, pointer, click, contextmenu, scroll and focus events of
6
- * one document; elements with recognizers and consumers attached
6
+ * one document; elements with recognizers and consumers attached; the
7
+ * input hold's held layers (Layer/inputHold `holdsTouch`)
7
8
  * @output Exports GestureHost (the DOM side of the gesture system) and
8
9
  * getGestureHost (one host per document)
9
10
  * @position Browser adapter of packages/core/src/gestures: turns real events
@@ -149,6 +150,7 @@ import {
149
150
  import {containsAlongFlatTree} from '../utils/flatTree';
150
151
  import {isIosWebKit} from '../utils/touchQueries';
151
152
  import {type WheelSegment, WheelSegmenter} from './wheelSegmenter';
153
+ import {holdsTouch} from '../Layer/inputHold';
152
154
  import {
153
155
  gestureHostStyle,
154
156
  type GestureHostStyle,
@@ -2126,9 +2128,12 @@ export class GestureHost {
2126
2128
  const recognizers: GestureRecognizer[] = [];
2127
2129
  let consumer: TouchConsumer | null = null;
2128
2130
  let consumerElement: Element | null = null;
2131
+ // A layer that the input hold holds takes no touch while it presents.
2132
+ // The host asks the hold, so the hold needs nothing from gestures/. A
2133
+ // root-entry component can then use the hold with no gesture code.
2129
2134
  if (
2130
2135
  target instanceof Node &&
2131
- [...this.touchGates].some(gate => gate(target))
2136
+ (holdsTouch(target) || [...this.touchGates].some(gate => gate(target)))
2132
2137
  ) {
2133
2138
  return {recognizers, consumer, consumerElement};
2134
2139
  }
@@ -2287,17 +2292,20 @@ export class GestureHost {
2287
2292
  };
2288
2293
  this.wheel = gesture;
2289
2294
  }
2290
- const {dx, dy} = wheelPixels(wheel, this.doc.defaultView);
2295
+ let {dx, dy} = wheelPixels(wheel, this.doc.defaultView);
2291
2296
  const horizontal = Math.abs(dx) > Math.abs(dy);
2292
2297
  // The splitter reads a pan's stream only. A ctrl-wheel pinch has no
2293
2298
  // fingers' phase or momentum to tell apart, and ends 100 ms after its
2294
2299
  // last wheel.
2295
2300
  let seg: WheelSegment | null = null;
2296
2301
  if (kind === 'pan') {
2302
+ // Only a trackpad's wheel can join its glide late; a mouse wheel's
2303
+ // notches keep the splitter's other rules.
2297
2304
  seg = this.segmenter.push(
2298
2305
  time,
2299
2306
  horizontal ? dx : dy,
2300
2307
  horizontal ? WHEEL_FOLLOW_END_MS : WHEEL_FOLLOW_END_V_MS,
2308
+ scrollTypeOf(wheel) === 'continuous',
2301
2309
  );
2302
2310
  } else {
2303
2311
  this.segmenter.end();
@@ -2309,6 +2317,14 @@ export class GestureHost {
2309
2317
  gesture = null;
2310
2318
  }
2311
2319
  }
2320
+ // A late wheel the glide took was the fingers' first when this one grows.
2321
+ if (seg != null && seg.carried !== 0) {
2322
+ if (horizontal) {
2323
+ dx += seg.carried;
2324
+ } else {
2325
+ dy += seg.carried;
2326
+ }
2327
+ }
2312
2328
  if (gesture == null) {
2313
2329
  gesture = this.beginWheel(wheel, kind, dx, dy, time);
2314
2330
  this.wheel = gesture;
@@ -2868,8 +2884,8 @@ export class GestureHost {
2868
2884
 
2869
2885
  /**
2870
2886
  * Hold touches away from every participant while `gate(target)` answers
2871
- * true (a presentation running in a layer: its content takes no touch
2872
- * until it settles). Returns the release.
2887
+ * true. Returns the release. The input hold's held layers need no gate,
2888
+ * because the host asks `holdsTouch` for every touch.
2873
2889
  */
2874
2890
  addTouchGate(gate: (target: Node) => boolean): () => void {
2875
2891
  this.touchGates.add(gate);
@@ -55,7 +55,12 @@ export interface PanGestureRecognizerOptions extends GestureRecognizerOptions<Pa
55
55
  minimumNumberOfTouches?: number;
56
56
  /** @default Infinity */
57
57
  maximumNumberOfTouches?: number;
58
- hysteresis?: number;
58
+ /**
59
+ * The travel that begins the pan, px. A function gives each press its own
60
+ * threshold: it reads the press's first touch when that touch lands.
61
+ * @default UIKit's 10
62
+ */
63
+ hysteresis?: number | ((touch: GestureTouch) => number);
59
64
  /** Movement that may begin the pan; anything else fails it. @default 'any' */
60
65
  direction?: PanDirection;
61
66
  /**
@@ -117,6 +122,11 @@ export class PanGestureRecognizer extends GestureRecognizer {
117
122
  travelAtBegan: Point = ZERO;
118
123
 
119
124
  private readonly tracker: VelocityTracker;
125
+ /**
126
+ * Read once per press. A finger that lands later keeps the press's
127
+ * threshold.
128
+ */
129
+ private readonly hysteresisFor: ((touch: GestureTouch) => number) | null;
120
130
  /** The lift's event time once the pan ended: its release (AST-100 FR2). */
121
131
  private releaseTime: number | undefined = undefined;
122
132
  /** The centroid where the gesture started, in client px. */
@@ -132,7 +142,10 @@ export class PanGestureRecognizer extends GestureRecognizer {
132
142
  this.minimumNumberOfTouches = options.minimumNumberOfTouches ?? 1;
133
143
  this.maximumNumberOfTouches =
134
144
  options.maximumNumberOfTouches ?? Number.POSITIVE_INFINITY;
135
- this.hysteresis = options.hysteresis ?? UIKIT_PAN.hysteresis.value;
145
+ const {hysteresis} = options;
146
+ this.hysteresisFor = typeof hysteresis === 'function' ? hysteresis : null;
147
+ this.hysteresis =
148
+ typeof hysteresis === 'number' ? hysteresis : UIKIT_PAN.hysteresis.value;
136
149
  this.direction = options.direction ?? 'any';
137
150
  this.axisRatio = options.axisRatio ?? 1;
138
151
  this.lockAxis = options.lockAxis ?? false;
@@ -237,6 +250,10 @@ export class PanGestureRecognizer extends GestureRecognizer {
237
250
  event: GestureEventContext,
238
251
  ): void {
239
252
  if (this.numberOfTouches === touches.length) {
253
+ const first = touches[0];
254
+ if (this.hysteresisFor != null && first != null) {
255
+ this.hysteresis = this.hysteresisFor(first);
256
+ }
240
257
  this.origin = centroid(this.touches.values());
241
258
  this.adjust = ZERO;
242
259
  this.raw = ZERO;
@@ -118,7 +118,8 @@ The pan reads its numbers the way `UIPanGestureRecognizer` does, as measured
118
118
  in the UIKit lab:
119
119
 
120
120
  - It begins once the centroid has moved `hysteresis` (10 px) along either
121
- axis, not as a distance.
121
+ axis, not as a distance. A function gives each press its own threshold,
122
+ read from the press's first touch when it lands.
122
123
  - `translation()` leaves out the travel the threshold took: a slow drag reads
123
124
  zero when the pan begins, and a step that overshoots keeps only the
124
125
  overshoot. A dragged surface does not jump. `totalTranslation()` is the
@@ -434,11 +435,15 @@ subscriber cancels it: the host cancels `touchend` and `contextmenu` there
434
435
  while a claiming participant is attached, never a `touchstart` or a
435
436
  `touchmove`, and the click guard (`../utils/clickGuard.ts`) keeps a
436
437
  cancelling `click` while it is armed, and from the menu press model's first
437
- arm on. A blocking `touchmove` sits on a claiming
438
+ arm on. A layer's input hold (`../Layer/inputHold.ts`) cancels pointer and
439
+ mouse events, clicks, `touchmove` and `touchend` there while a layer is held,
440
+ never a `touchstart`. A blocking `touchmove` sits on a claiming
438
441
  element and on a claimed touch's target, on the document while an element a
439
442
  claiming recognizer lives in is moving (Touches on moving elements), or on
440
- the window only while a page hold is held, so a page of pressables blocks
441
- no scroll.
443
+ the window only while a page hold or a layer's input hold is held, so a page
444
+ of pressables blocks no scroll. The stream records the type of the latest
445
+ pointer event it delivers (`getLastPointerType`); the input hold reads it as
446
+ a layer opens.
442
447
 
443
448
  ### Holding the page still
444
449
 
@@ -525,7 +530,11 @@ it never moves it; when the fingers carry on instead, their moves absorb
525
530
  what the pan showed past their travel, or short of it, so it never steps
526
531
  back and ends on their travel. Fingers that stop release still, once the end
527
532
  time passes. In momentum, a reversal, a delta that grows
528
- against the decay, or a 50 ms pause starts a new gesture. A finger, mouse or
533
+ against the decay, or a 50 ms pause starts a new gesture; a late, coalesced
534
+ trackpad wheel that continues the glide's deceleration (at or below the next
535
+ step, or near the sum of the next steps its stall spans) belongs to the same
536
+ flick. When the next wheel grows instead, it starts a new gesture with the late
537
+ wheel's travel. A finger, mouse or
529
538
  pen that comes down ends it, and a wheel claim keeps the page's text
530
539
  selection. A gesture a
531
540
  recognizer took is latched to it, as a browser latches a scroller: while it
@@ -76,12 +76,17 @@ interface EdgeLayout {
76
76
  */
77
77
  export interface ScreenEdgePanGestureRecognizerOptions extends Omit<
78
78
  PanGestureRecognizerOptions,
79
- 'direction' | 'allowedPointerTypes' | 'allowedScrollTypes'
79
+ 'direction' | 'allowedPointerTypes' | 'allowedScrollTypes' | 'hysteresis'
80
80
  > {
81
81
  /** The edges a touch may start from. @default ['leading'] */
82
82
  edges?: ReadonlyArray<ScreenEdge>;
83
83
  /** Width of the band at each edge, px. */
84
84
  edgeRegion?: number;
85
+ /**
86
+ * The travel that begins the pan in its edge zone, px. It is one number for
87
+ * every press, since the zone sets the threshold itself. @default UIKit's 15
88
+ */
89
+ hysteresis?: number;
85
90
  }
86
91
 
87
92
  export class ScreenEdgePanGestureRecognizer extends PanGestureRecognizer {