@astryxdesign/core 0.7.8 → 0.7.9-canary.0a64fdb

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 (276) 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/Calendar/styles.d.ts +1 -1
  6. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  7. package/dist/CheckboxInput/CheckboxInput.js +54 -11
  8. package/dist/ClickableCard/ClickableCard.d.ts +1 -1
  9. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  10. package/dist/ClickableCard/ClickableCard.js +5 -1
  11. package/dist/DateInput/PickerWheel.d.ts.map +1 -1
  12. package/dist/DateInput/PickerWheel.js +7 -1
  13. package/dist/DateRangeInput/DateRangeInput.js +1 -1
  14. package/dist/Dialog/Dialog.d.ts +2 -1
  15. package/dist/Dialog/Dialog.d.ts.map +1 -1
  16. package/dist/Dialog/Dialog.js +12 -1
  17. package/dist/Drawer/useDrawerDialogPresence.d.ts +2 -1
  18. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  19. package/dist/Drawer/useDrawerDialogPresence.js +11 -2
  20. package/dist/DropdownMenu/DropdownMenu.d.ts +9 -1
  21. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  22. package/dist/DropdownMenu/DropdownMenu.js +9 -4
  23. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  24. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +3 -2
  25. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  26. package/dist/DropdownMenu/DropdownMenuItem.js +3 -2
  27. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  28. package/dist/DropdownMenu/DropdownMenuRadioItem.js +3 -2
  29. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  30. package/dist/DropdownMenu/DropdownMenuSubMenu.js +3 -2
  31. package/dist/Field/inputDisabledFocus.d.ts +4 -4
  32. package/dist/Field/inputStyles.stylex.d.ts +1 -1
  33. package/dist/FileInput/FileInput.d.ts.map +1 -1
  34. package/dist/FileInput/FileInput.js +16 -2
  35. package/dist/Icon/Icon.d.ts +1 -1
  36. package/dist/InfoTip/InfoTip.d.ts +1 -0
  37. package/dist/InfoTip/InfoTip.d.ts.map +1 -1
  38. package/dist/InfoTip/InfoTip.js +1 -0
  39. package/dist/InputGroup/InputGroup.d.ts +4 -3
  40. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  41. package/dist/InputGroup/InputGroup.js +2 -2
  42. package/dist/InputGroup/groupStyles.d.ts +1 -1
  43. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  44. package/dist/InputGroup/groupStyles.js +1 -1
  45. package/dist/Item/Item.d.ts +2 -1
  46. package/dist/Item/Item.d.ts.map +1 -1
  47. package/dist/Item/Item.js +29 -6
  48. package/dist/Layer/holdEntranceInput.d.ts +24 -0
  49. package/dist/Layer/holdEntranceInput.d.ts.map +1 -0
  50. package/dist/Layer/holdEntranceInput.js +65 -0
  51. package/dist/Layer/inputHold.d.ts +49 -0
  52. package/dist/Layer/inputHold.d.ts.map +1 -0
  53. package/dist/Layer/inputHold.js +636 -0
  54. package/dist/Layer/preserveAnimations.d.ts +1 -5
  55. package/dist/Layer/preserveAnimations.d.ts.map +1 -1
  56. package/dist/Layer/preserveAnimations.js +12 -214
  57. package/dist/Layout/LayoutContent.d.ts +3 -1
  58. package/dist/Layout/LayoutContent.d.ts.map +1 -1
  59. package/dist/Layout/LayoutContent.js +12 -4
  60. package/dist/Layout/LayoutPanel.d.ts +4 -1
  61. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  62. package/dist/Layout/LayoutPanel.js +13 -4
  63. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  64. package/dist/Lightbox/Lightbox.js +4 -0
  65. package/dist/MetadataList/MetadataList.js +1 -1
  66. package/dist/MobileNav/MobileNav.d.ts +11 -1
  67. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  68. package/dist/MobileNav/MobileNav.js +39 -1
  69. package/dist/MoreMenu/MoreMenu.d.ts +5 -3
  70. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  71. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  72. package/dist/RadioList/RadioListItem.js +22 -4
  73. package/dist/SelectableCard/SelectableCard.d.ts +1 -1
  74. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  75. package/dist/SelectableCard/SelectableCard.js +5 -1
  76. package/dist/Spinner/Spinner.d.ts.map +1 -1
  77. package/dist/Spinner/Spinner.js +12 -2
  78. package/dist/Stack/StackItem.d.ts +8 -4
  79. package/dist/Stack/StackItem.d.ts.map +1 -1
  80. package/dist/Stack/StackItem.js +17 -4
  81. package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
  82. package/dist/Token/Token.d.ts.map +1 -1
  83. package/dist/Token/Token.js +9 -0
  84. package/dist/Token/TokenLink.d.ts +1 -1
  85. package/dist/Token/TokenLink.d.ts.map +1 -1
  86. package/dist/Token/TokenLink.js +4 -1
  87. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  88. package/dist/Tooltip/useTooltip.js +162 -59
  89. package/dist/TreeList/TreeListItem.d.ts +2 -1
  90. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  91. package/dist/TreeList/TreeListItem.js +27 -3
  92. package/dist/astryx.css +35 -8
  93. package/dist/gestures/GestureHost.d.ts +2 -2
  94. package/dist/gestures/GestureHost.d.ts.map +1 -1
  95. package/dist/gestures/GestureHost.js +21 -6
  96. package/dist/gestures/PanGestureRecognizer.d.ts +11 -1
  97. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  98. package/dist/gestures/PanGestureRecognizer.js +15 -1
  99. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +6 -1
  100. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -1
  101. package/dist/gestures/nativeScroll.d.ts +3 -6
  102. package/dist/gestures/nativeScroll.d.ts.map +1 -1
  103. package/dist/gestures/nativeScroll.js +7 -52
  104. package/dist/gestures/wheelSegmenter.d.ts +68 -1
  105. package/dist/gestures/wheelSegmenter.d.ts.map +1 -1
  106. package/dist/gestures/wheelSegmenter.js +199 -10
  107. package/dist/hooks/StackItemScrollRegion.d.ts +31 -0
  108. package/dist/hooks/StackItemScrollRegion.d.ts.map +1 -0
  109. package/dist/hooks/StackItemScrollRegion.js +40 -0
  110. package/dist/hooks/menuPressGesture.d.ts +133 -21
  111. package/dist/hooks/menuPressGesture.d.ts.map +1 -1
  112. package/dist/hooks/menuPressGesture.js +155 -30
  113. package/dist/hooks/menuPressValues.d.ts +16 -0
  114. package/dist/hooks/menuPressValues.d.ts.map +1 -0
  115. package/dist/hooks/menuPressValues.js +18 -0
  116. package/dist/hooks/useClickableContainer.d.ts +27 -5
  117. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  118. package/dist/hooks/useClickableContainer.js +41 -5
  119. package/dist/hooks/useFocusTrap.d.ts +10 -0
  120. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  121. package/dist/hooks/useFocusTrap.js +225 -132
  122. package/dist/hooks/useMenuPress.d.ts +34 -1
  123. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  124. package/dist/hooks/useMenuPress.js +93 -5
  125. package/dist/hooks/usePressFeedback.d.ts +6 -6
  126. package/dist/hooks/usePressFeedback.js +6 -6
  127. package/dist/hooks/useScrollRegionProps.d.ts +35 -0
  128. package/dist/hooks/useScrollRegionProps.d.ts.map +1 -0
  129. package/dist/hooks/useScrollRegionProps.js +51 -0
  130. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts +8 -0
  131. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts.map +1 -0
  132. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.js +12 -0
  133. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  134. package/dist/i18n/generated-locales/en.generated.js +1 -0
  135. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  136. package/dist/i18n/generated-locales/pseudo.generated.js +1 -0
  137. package/dist/motion/carryAnimations.d.ts +58 -0
  138. package/dist/motion/carryAnimations.d.ts.map +1 -0
  139. package/dist/motion/carryAnimations.js +305 -0
  140. package/dist/motion/transientCopy.d.ts +4 -2
  141. package/dist/motion/transientCopy.d.ts.map +1 -1
  142. package/dist/motion/transientCopy.js +34 -5
  143. package/dist/motion/uikit/gestures.d.ts +41 -0
  144. package/dist/motion/uikit/gestures.d.ts.map +1 -1
  145. package/dist/motion/uikit/gestures.js +25 -0
  146. package/dist/motion/uikit/index.d.ts +1 -1
  147. package/dist/motion/uikit/index.d.ts.map +1 -1
  148. package/dist/motion/uikit/index.js +1 -1
  149. package/dist/privateAttributes/menuPressLit.stylex.d.ts +52 -0
  150. package/dist/privateAttributes/menuPressLit.stylex.d.ts.map +1 -0
  151. package/dist/privateAttributes/menuPressLit.stylex.js +99 -0
  152. package/dist/privateAttributes/press.stylex.d.ts +139 -0
  153. package/dist/privateAttributes/press.stylex.d.ts.map +1 -0
  154. package/dist/privateAttributes/press.stylex.js +98 -0
  155. package/dist/theme/tokens.stylex.d.ts +2 -2
  156. package/dist/theme/tokens.stylex.js +1 -1
  157. package/dist/utils/flatTree.d.ts +6 -3
  158. package/dist/utils/flatTree.d.ts.map +1 -1
  159. package/dist/utils/flatTree.js +13 -3
  160. package/dist/utils/hitArea.d.ts.map +1 -1
  161. package/dist/utils/hitArea.js +82 -5
  162. package/dist/utils/inputStream.d.ts +14 -1
  163. package/dist/utils/inputStream.d.ts.map +1 -1
  164. package/dist/utils/inputStream.js +40 -9
  165. package/dist/utils/interactionOverlay.stylex.d.ts +2 -1
  166. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  167. package/dist/utils/interactionOverlay.stylex.js +7 -2
  168. package/dist/utils/pressFeedback.d.ts +7 -0
  169. package/dist/utils/pressFeedback.d.ts.map +1 -1
  170. package/dist/utils/pressFeedback.js +32 -7
  171. package/dist/utils/pressGesture.d.ts +6 -0
  172. package/dist/utils/pressGesture.d.ts.map +1 -1
  173. package/dist/utils/pressGesture.js +17 -0
  174. package/dist/utils/rowPressLayer.stylex.d.ts +14 -0
  175. package/dist/utils/rowPressLayer.stylex.d.ts.map +1 -0
  176. package/dist/utils/rowPressLayer.stylex.js +25 -0
  177. package/dist/utils/scrollView.d.ts +25 -0
  178. package/dist/utils/scrollView.d.ts.map +1 -0
  179. package/dist/utils/scrollView.js +108 -0
  180. package/dist/utils/selectionLock.d.ts.map +1 -1
  181. package/dist/utils/selectionLock.js +1 -10
  182. package/dist/utils/touchHitArea.stylex.d.ts +35 -0
  183. package/dist/utils/touchHitArea.stylex.d.ts.map +1 -0
  184. package/dist/utils/touchHitArea.stylex.js +32 -0
  185. package/dist/utils/triggerFocus.d.ts +5 -0
  186. package/dist/utils/triggerFocus.d.ts.map +1 -1
  187. package/dist/utils/triggerFocus.js +9 -2
  188. package/locales/en.json +4 -0
  189. package/locales/pseudo.json +3 -0
  190. package/package.json +5 -5
  191. package/src/AppShell/observeMainOverflow.ts +9 -6
  192. package/src/BottomSheet/BottomSheet.tsx +5 -0
  193. package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -2
  194. package/src/CheckboxInput/CheckboxInput.tsx +71 -9
  195. package/src/ClickableCard/ClickableCard.tsx +8 -1
  196. package/src/DateInput/PickerWheel.tsx +7 -2
  197. package/src/DateRangeInput/DateRangeInput.tsx +1 -1
  198. package/src/Dialog/Dialog.doc.mjs +1 -1
  199. package/src/Dialog/Dialog.tsx +12 -1
  200. package/src/Drawer/Drawer.doc.mjs +1 -1
  201. package/src/Drawer/useDrawerDialogPresence.ts +9 -2
  202. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -2
  203. package/src/DropdownMenu/DropdownMenu.tsx +29 -5
  204. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -1
  205. package/src/DropdownMenu/DropdownMenuItem.tsx +8 -4
  206. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -1
  207. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -1
  208. package/src/FileInput/FileInput.tsx +16 -2
  209. package/src/InfoTip/InfoTip.doc.mjs +26 -2
  210. package/src/InfoTip/InfoTip.tsx +1 -0
  211. package/src/InputGroup/InputGroup.doc.mjs +4 -3
  212. package/src/InputGroup/InputGroup.tsx +4 -3
  213. package/src/InputGroup/groupStyles.ts +3 -1
  214. package/src/Item/Item.tsx +51 -9
  215. package/src/Layer/holdEntranceInput.ts +84 -0
  216. package/src/Layer/inputHold.ts +734 -0
  217. package/src/Layer/preserveAnimations.ts +12 -275
  218. package/src/Layout/LayoutContent.doc.mjs +6 -3
  219. package/src/Layout/LayoutContent.tsx +10 -4
  220. package/src/Layout/LayoutPanel.doc.mjs +6 -3
  221. package/src/Layout/LayoutPanel.tsx +11 -4
  222. package/src/Lightbox/Lightbox.tsx +4 -0
  223. package/src/MetadataList/MetadataList.tsx +1 -1
  224. package/src/MobileNav/MobileNav.doc.mjs +3 -3
  225. package/src/MobileNav/MobileNav.tsx +39 -1
  226. package/src/MoreMenu/MoreMenu.doc.mjs +2 -4
  227. package/src/MoreMenu/MoreMenu.tsx +5 -3
  228. package/src/RadioList/RadioListItem.doc.mjs +3 -2
  229. package/src/RadioList/RadioListItem.tsx +25 -7
  230. package/src/SelectableCard/SelectableCard.tsx +8 -1
  231. package/src/Spinner/Spinner.tsx +13 -3
  232. package/src/Stack/Stack.doc.mjs +1 -1
  233. package/src/Stack/StackItem.tsx +27 -13
  234. package/src/Table/plugins/sortable/useTableSortable.tsx +1 -1
  235. package/src/Token/Token.tsx +18 -1
  236. package/src/Token/TokenLink.tsx +7 -1
  237. package/src/Tooltip/useTooltip.tsx +175 -79
  238. package/src/TreeList/TreeListItem.tsx +36 -2
  239. package/src/gestures/GestureHost.ts +21 -5
  240. package/src/gestures/PanGestureRecognizer.ts +19 -2
  241. package/src/gestures/README.md +14 -5
  242. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +6 -1
  243. package/src/gestures/nativeScroll.ts +12 -68
  244. package/src/gestures/wheelSegmenter.ts +243 -10
  245. package/src/hooks/StackItemScrollRegion.tsx +57 -0
  246. package/src/hooks/menuPressGesture.ts +244 -38
  247. package/src/hooks/menuPressValues.ts +18 -0
  248. package/src/hooks/useClickableContainer.doc.mjs +8 -2
  249. package/src/hooks/useClickableContainer.ts +72 -6
  250. package/src/hooks/useFocusTrap.ts +268 -151
  251. package/src/hooks/useMenuPress.ts +118 -11
  252. package/src/hooks/usePressFeedback.doc.mjs +3 -3
  253. package/src/hooks/usePressFeedback.ts +6 -6
  254. package/src/hooks/useScrollRegionProps.ts +76 -0
  255. package/src/i18n/generated-english/hooks/useScrollRegionProps.generated.ts +13 -0
  256. package/src/i18n/generated-locales/en.generated.ts +1 -0
  257. package/src/i18n/generated-locales/pseudo.generated.ts +1 -0
  258. package/src/motion/MEASUREMENTS.md +11 -0
  259. package/src/motion/carryAnimations.ts +389 -0
  260. package/src/motion/transientCopy.ts +45 -5
  261. package/src/motion/uikit/gestures.ts +22 -0
  262. package/src/motion/uikit/index.ts +1 -0
  263. package/src/privateAttributes/menuPressLit.stylex.ts +104 -0
  264. package/src/privateAttributes/press.stylex.ts +244 -0
  265. package/src/theme/tokens.stylex.ts +1 -1
  266. package/src/utils/flatTree.ts +15 -3
  267. package/src/utils/hitArea.ts +107 -5
  268. package/src/utils/inputStream.ts +47 -10
  269. package/src/utils/interactionOverlay.stylex.ts +7 -2
  270. package/src/utils/pressFeedback.ts +31 -6
  271. package/src/utils/pressGesture.ts +24 -1
  272. package/src/utils/rowPressLayer.stylex.ts +27 -0
  273. package/src/utils/scrollView.ts +135 -0
  274. package/src/utils/selectionLock.ts +5 -10
  275. package/src/utils/touchHitArea.stylex.ts +41 -0
  276. package/src/utils/triggerFocus.ts +17 -4
@@ -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,8 +23,10 @@
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
@@ -34,13 +37,26 @@
34
37
  /** The events a window's capture phase sees: its own, and the document's. */
35
38
 
36
39
  const streams = new WeakMap();
40
+ /** The type of the latest pointer event each window's stream delivered. */
41
+ const lastPointerTypes = new WeakMap();
42
+
43
+ /**
44
+ * The type of the latest pointer event `view`'s stream delivered: `mouse`,
45
+ * `pen` or `touch`, or `null` before any. The stream hears a pointer event
46
+ * type only while a subscriber listens to it, as press feedback does on any
47
+ * page with a pressable. Reading it adds no listener.
48
+ */
49
+ export function getLastPointerType(view) {
50
+ return lastPointerTypes.get(view) ?? null;
51
+ }
37
52
 
38
53
  /**
39
54
  * Listen to `type` on `view`'s capture phase through its shared native
40
55
  * listener. Returns the unsubscribe; calling it again does nothing.
41
56
  */
42
57
  export function subscribeInput(view, type, listener, {
43
- cancels = false
58
+ cancels = false,
59
+ first = false
44
60
  } = {}) {
45
61
  let channels = streams.get(view);
46
62
  if (channels == null) {
@@ -57,9 +73,15 @@ export function subscribeInput(view, type, listener, {
57
73
  }
58
74
  const subscriber = {
59
75
  listener: listener,
60
- cancels
76
+ cancels,
77
+ isFirst: first
61
78
  };
62
- channel.subscribers.push(subscriber);
79
+ const firstLater = first ? channel.subscribers.findIndex(other => !other.isFirst) : -1;
80
+ if (firstLater === -1) {
81
+ channel.subscribers.push(subscriber);
82
+ } else {
83
+ channel.subscribers.splice(firstLater, 0, subscriber);
84
+ }
63
85
  register(view, type, channel);
64
86
  let isSubscribed = true;
65
87
  return () => {
@@ -101,7 +123,7 @@ function register(view, type, channel) {
101
123
  if (wanted == null) {
102
124
  return;
103
125
  }
104
- const listener = event => dispatch(channel, event);
126
+ const listener = event => dispatch(view, channel, event);
105
127
  view.addEventListener(type, listener, {
106
128
  capture: true,
107
129
  passive: !wanted
@@ -111,7 +133,14 @@ function register(view, type, channel) {
111
133
  cancels: wanted
112
134
  };
113
135
  }
114
- function dispatch(channel, event) {
136
+ function dispatch(view, channel, event) {
137
+ // Recorded before any subscriber runs, so each reads the pointer at hand.
138
+ const {
139
+ pointerType
140
+ } = event;
141
+ if (typeof pointerType === 'string' && pointerType !== '') {
142
+ lastPointerTypes.set(view, pointerType);
143
+ }
115
144
  // A subscriber may subscribe or unsubscribe while the event runs; the
116
145
  // event goes to those subscribed when it arrived.
117
146
  for (const subscriber of [...channel.subscribers]) {
@@ -119,7 +148,9 @@ function dispatch(channel, event) {
119
148
  continue;
120
149
  }
121
150
  try {
122
- subscriber.listener(event);
151
+ if (subscriber.listener(event) === true && subscriber.isFirst) {
152
+ return;
153
+ }
123
154
  } catch (error) {
124
155
  report(error);
125
156
  }
@@ -3,7 +3,8 @@
3
3
  * @input StyleX and the semantic interaction-overlay color tokens
4
4
  * @output Reusable background-color and background-image state styles, the
5
5
  * touch press's registered strength variable (`pressVars`) and its clocks
6
- * (`pressConsts`)
6
+ * (`pressConsts`). The list row's compositor press layer and its clocks
7
+ * are internal (privateAttributes/press.stylex.ts, utils/rowPressLayer.stylex.ts)
7
8
  * @position Internal styling utility for interactive core surfaces
8
9
  *
9
10
  * SYNC: When modified, update pressFeedback.ts, pressGesture.ts (the fade
@@ -1 +1 @@
1
- {"version":3,"file":"interactionOverlay.stylex.d.ts","sourceRoot":"","sources":["../../src/utils/interactionOverlay.stylex.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AAmCH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAG3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS;;WAEpB,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW;IACtB,iEAAiE;;CAEjE,CAAC;AA8HH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8HnC,CAAC"}
1
+ {"version":3,"file":"interactionOverlay.stylex.d.ts","sourceRoot":"","sources":["../../src/utils/interactionOverlay.stylex.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;GAeG;AAmCH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAG3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS;;WAEpB,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW;IACtB,iEAAiE;;CAEjE,CAAC;AAkIH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8HnC,CAAC"}
@@ -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
@@ -142,7 +143,11 @@ const pressRelease = "x10jkm1t-B";
142
143
  * (strength ≈ 0.2 at the midpoint), which is what a deselect crossfade reads
143
144
  * as. Not the system's `--ease-standard`: that curve is for things that move,
144
145
  * and is so front-loaded (strength 0.05 at the midpoint) that the release
145
- * would read as half its clock.
146
+ * would read as half its clock. It is the constants table's
147
+ * `timing.press.highlightOutCurve`, which the list row's layer mirrors too
148
+ * (rowPressLayer.stylex.ts); interactionOverlay.cell.test.ts fails if either
149
+ * drifts. A copy, not an import: this module reaches nearly every component,
150
+ * and the row layer's constants stay with the rows.
146
151
  */
147
152
  const RELEASE_EASE = 'cubic-bezier(0, 0, 0.2, 1)';
148
153
 
@@ -29,6 +29,13 @@ export declare const PRESS_GESTURE_MEMORY_MS = 3000;
29
29
  * Reduce Motion a tempo may shorten the fade, never lengthen it past 200 ms.
30
30
  */
31
31
  export declare function pressFadeMs(element: Element): number;
32
+ /**
33
+ * Ends the press the controller follows on `element`, and its paint, at once.
34
+ * A clickable container calls it when a press starts on an interactive
35
+ * element inside it: that press does not activate the container, so the
36
+ * container shows no press.
37
+ */
38
+ export declare function cancelPress(element: Element): void;
32
39
  /**
33
40
  * Install the touch press controller on this document, once, however many
34
41
  * times it is called: the listeners exist while at least one caller holds it.
@@ -1 +1 @@
1
- {"version":3,"file":"pressFeedback.d.ts","sourceRoot":"","sources":["../../src/utils/pressFeedback.ts"],"names":[],"mappings":"AAkDA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAErD,qDAAqD;AACrD,eAAO,MAAM,cAAc,EAAE;IAAC,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,EAAE,CAAA;CAE/D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AA0E5C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAUpD;AAkoBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,IAAI,CA0BjD"}
1
+ {"version":3,"file":"pressFeedback.d.ts","sourceRoot":"","sources":["../../src/utils/pressFeedback.ts"],"names":[],"mappings":"AAuDA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAErD,qDAAqD;AACrD,eAAO,MAAM,cAAc,EAAE;IAAC,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,EAAE,CAAA;CAE/D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AA0E5C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAUpD;AA6ND;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAOlD;AA4aD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,IAAI,CA0BjD"}
@@ -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
@@ -36,6 +40,7 @@ import { MENU_PRESS_MARKER } from "../hooks/menuPressMarker.js";
36
40
  import { idlePressGesture, PRESS_FADE_MS, PRESS_FLASH_MS, PRESS_ONSET_MS, PRESS_SCROLL_BRAKE_MS, pressGestureStep } from "./pressGesture.js";
37
41
  import { isCoarsePointer, watchCoarsePointer } from "./coarsePointer.js";
38
42
  import { subscribeInput } from "./inputStream.js";
43
+ import { isInsideScrollView } from "./scrollView.js";
39
44
  import { TOUCH_QUERY } from "./touchPresentation.js";
40
45
  import { holdsPressThroughDrag } from "../privateAttributes/pressHoldsDrag.stylex.js";
41
46
  import { isTrackedByGroup } from "../privateAttributes/pressGroupItem.stylex.js";
@@ -208,7 +213,11 @@ function paintElement(element, paint) {
208
213
  element.removeAttribute(PRESSED_ATTRIBUTE);
209
214
  return;
210
215
  }
211
- element.setAttribute(PRESSED_ATTRIBUTE, paint);
216
+ // A step that keeps the paint writes nothing, so the element sees one
217
+ // change per paint.
218
+ if (element.getAttribute(PRESSED_ATTRIBUTE) !== paint) {
219
+ element.setAttribute(PRESSED_ATTRIBUTE, paint);
220
+ }
212
221
  }
213
222
  function clearTimer(slot) {
214
223
  if (slot.live?.timer != null) {
@@ -334,6 +343,21 @@ function finish(slot) {
334
343
  }
335
344
  }
336
345
 
346
+ /**
347
+ * Ends the press the controller follows on `element`, and its paint, at once.
348
+ * A clickable container calls it when a press starts on an interactive
349
+ * element inside it: that press does not activate the container, so the
350
+ * container shows no press.
351
+ */
352
+ export function cancelPress(element) {
353
+ if (finger.live?.element === element) {
354
+ finish(finger);
355
+ }
356
+ if (button.live?.element === element) {
357
+ finish(button);
358
+ }
359
+ }
360
+
337
361
  /** A new press on an element owns its paint: the other slot's gesture there ends. */
338
362
  function takeOver(other, element) {
339
363
  if (other.live?.element === element) {
@@ -466,7 +490,8 @@ function onPointerDown(event) {
466
490
  apply(finger, pressGestureStep(finger.live.gesture, {
467
491
  kind: 'down',
468
492
  x: event.clientX,
469
- y: event.clientY
493
+ y: event.clientY,
494
+ delayed: isInsideScrollView(element)
470
495
  }));
471
496
  }
472
497
  function onPointerMove(event) {
@@ -71,6 +71,12 @@ export type PressEvent = {
71
71
  kind: 'down';
72
72
  x: number;
73
73
  y: number;
74
+ /**
75
+ * Whether this touch waits {@link PRESS_ONSET_MS} before it paints:
76
+ * a surface inside a scroller. Defaults to
77
+ * `true`.
78
+ */
79
+ delayed?: boolean;
74
80
  }
75
81
  /**
76
82
  * A mouse button or the Space key went down on the surface. The
@@ -1 +1 @@
1
- {"version":3,"file":"pressGesture.d.ts","sourceRoot":"","sources":["../../src/utils/pressGesture.ts"],"names":[],"mappings":"AA4BA;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,MAA8B,CAAC;AAE3D;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,2EAA2E;AAC3E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GACpB,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,UAAU,GAClB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAC;AACtC;;;;GAIG;GACD;IAAC,IAAI,EAAE,YAAY,CAAA;CAAC;AACtB,0EAA0E;GACxE;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAC,GACpC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAC;AACd,4FAA4F;GAC1F;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC;AAClB,iEAAiE;GAC/D;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC;AACjB,yDAAyD;GACvD;IAAC,IAAI,EAAE,UAAU,CAAA;CAAC;AACpB,wFAAwF;GACtF;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC;AAEtB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;CACnD;AAkBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,UAAU,GAChB,SAAS,CA6GX;AAED,wBAAgB,gBAAgB,IAAI,YAAY,CAE/C"}
1
+ {"version":3,"file":"pressGesture.d.ts","sourceRoot":"","sources":["../../src/utils/pressGesture.ts"],"names":[],"mappings":"AAgCA;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,MAA8B,CAAC;AAE3D;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,2EAA2E;AAC3E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GACpB,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,UAAU,GAClB;IACE,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AACH;;;;GAIG;GACD;IAAC,IAAI,EAAE,YAAY,CAAA;CAAC;AACtB,0EAA0E;GACxE;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAC,GACpC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAC;AACd,4FAA4F;GAC1F;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC;AAClB,iEAAiE;GAC/D;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC;AACjB,yDAAyD;GACvD;IAAC,IAAI,EAAE,UAAU,CAAA;CAAC;AACpB,wFAAwF;GACtF;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC;AAEtB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;CACnD;AAkBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,UAAU,GAChB,SAAS,CAsHX;AAED,wBAAgB,gBAAgB,IAAI,YAAY,CAE/C"}
@@ -21,6 +21,10 @@
21
21
  // primary pointer, so a mouse, trackpad or Space press on such a device comes
22
22
  // here as `buttonDown`: painted at once and faded on release.
23
23
  //
24
+ // Only a finger inside a scroller waits. The controller tells the machine
25
+ // which touch waits (`down`'s `delayed`), and a touch that does not wait goes
26
+ // straight to `pressed`. After that the machine is the same.
27
+ //
24
28
  // The constants were measured against native apps. The machine knows nothing
25
29
  // of the DOM, so {@link pressGestureStep}'s cases are the state diagram.
26
30
 
@@ -123,6 +127,19 @@ function step(gesture, phase, paint, timer) {
123
127
  */
124
128
  export function pressGestureStep(gesture, event) {
125
129
  if (event.kind === 'down') {
130
+ // A surface with no scroller above it: nothing can turn this touch into a
131
+ // scroll, so it paints in the frame it lands, as a UIControl highlights.
132
+ if (event.delayed === false) {
133
+ return {
134
+ gesture: {
135
+ originX: event.x,
136
+ originY: event.y,
137
+ phase: 'pressed'
138
+ },
139
+ paint: 'on',
140
+ timer: null
141
+ };
142
+ }
126
143
  // A new touch always starts armed and painting nothing, whatever the last
127
144
  // gesture ended as. This is the only way out of `dead`.
128
145
  return {
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A list row's release (`rowPressLayerStyles.cell`), mirrored for the
3
+ * stylesheet. StyleX evaluates a style at build time and cannot read the
4
+ * constants table, so these are the table's press release values
5
+ * (`timing.press`, motion/uikit/timing.ts). interactionOverlay.cell.test.ts
6
+ * fails if they drift.
7
+ */
8
+ export declare const cellPressConsts: {
9
+ /** `timing.press.highlightOutMs`, in ms. */
10
+ cellReleaseMs: number;
11
+ /** `timing.press.highlightOutCurve`, as CSS. */
12
+ cellReleaseEase: string;
13
+ };
14
+ //# sourceMappingURL=rowPressLayer.stylex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rowPressLayer.stylex.d.ts","sourceRoot":"","sources":["../../src/utils/rowPressLayer.stylex.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;IAC1B,4CAA4C;;IAE5C,gDAAgD;;CAEhD,CAAC"}
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file rowPressLayer.stylex.ts
5
+ * @input StyleX
6
+ * @output The list row press layer's clocks (`cellPressConsts`)
7
+ * @position Internal to core: no package entry exports it. Only the row
8
+ * layer (privateAttributes/press.stylex.ts) reads it, so a component
9
+ * without a press row ships none of it; interactionOverlay.exports.test.ts
10
+ * keeps it off the published paths.
11
+ */
12
+
13
+ import * as stylex from '@stylexjs/stylex';
14
+
15
+ /**
16
+ * A list row's release (`rowPressLayerStyles.cell`), mirrored for the
17
+ * stylesheet. StyleX evaluates a style at build time and cannot read the
18
+ * constants table, so these are the table's press release values
19
+ * (`timing.press`, motion/uikit/timing.ts). interactionOverlay.cell.test.ts
20
+ * fails if they drift.
21
+ */
22
+ export const cellPressConsts = {
23
+ cellReleaseMs: 200,
24
+ cellReleaseEase: "cubic-bezier(0, 0, 0.2, 1)"
25
+ };
@@ -0,0 +1,25 @@
1
+ /** Overflow values that let a box scroll. */
2
+ export declare const SCROLLABLE_OVERFLOW: ReadonlySet<string>;
3
+ export interface AllowedPans {
4
+ readonly x: boolean;
5
+ readonly y: boolean;
6
+ }
7
+ /** Which pans a `touch-action` value lets the browser perform. */
8
+ export declare function parseTouchAction(value: string): AllowedPans;
9
+ /**
10
+ * The viewport's overflow on an axis. It scrolls unless the root or the body
11
+ * clips it, as a scroll lock does with `overflow: hidden`.
12
+ */
13
+ export declare function rootOverflow(doc: Document, axis: 'x' | 'y'): string;
14
+ /**
15
+ * Whether a touch on `element` lands inside a scroll view, UIKit's question
16
+ * for a touch: a box above it, the page included, overflows on an axis it
17
+ * scrolls, and `touch-action` on the way up leaves that axis to the browser.
18
+ * A `position: fixed` box ends the walk, because it does not move with any
19
+ * scroller above it. A wheel scrolls whatever `touch-action` says, so a
20
+ * wheel's question passes `readsTouchAction: false`.
21
+ */
22
+ export declare function isInsideScrollView(element: Element, { readsTouchAction }?: {
23
+ readsTouchAction?: boolean;
24
+ }): boolean;
25
+ //# sourceMappingURL=scrollView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollView.d.ts","sourceRoot":"","sources":["../../src/utils/scrollView.ts"],"names":[],"mappings":"AAgBA,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAIlD,CAAC;AAKH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAiB3D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAgBnE;AAQD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,EAAC,gBAAuB,EAAC,GAAE;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3D,OAAO,CA4CT"}
@@ -0,0 +1,108 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file scrollView.ts
5
+ * @input An element and its computed styles
6
+ * @output Exports parseTouchAction, rootOverflow, SCROLLABLE_OVERFLOW and
7
+ * isInsideScrollView: whether a touch on the element lands inside a box the
8
+ * browser can scroll
9
+ * @position The one definition of "inside a scroll view", shared by the
10
+ * press feedback controller (utils/pressFeedback.ts) and the gesture
11
+ * core's native-scroll probe (gestures/nativeScroll.ts), so Core's main
12
+ * entry can ask it without the gesture core
13
+ */
14
+
15
+ import { parentAcrossShadow } from "./flatTree.js";
16
+
17
+ /** Overflow values that let a box scroll. */
18
+ export const SCROLLABLE_OVERFLOW = new Set(['auto', 'scroll', 'overlay']);
19
+
20
+ /** How far a box must overflow, in px, before it counts as scrolling. */
21
+ const OVERFLOW_TOLERANCE_PX = 1;
22
+ /** Which pans a `touch-action` value lets the browser perform. */
23
+ export function parseTouchAction(value) {
24
+ const tokens = value.trim().split(/\s+/);
25
+ if (tokens.includes('auto') || tokens.includes('manipulation')) {
26
+ return {
27
+ x: true,
28
+ y: true
29
+ };
30
+ }
31
+ if (tokens.includes('none')) {
32
+ return {
33
+ x: false,
34
+ y: false
35
+ };
36
+ }
37
+ return {
38
+ x: tokens.some(token => token === 'pan-x' || token === 'pan-left' || token === 'pan-right'),
39
+ y: tokens.some(token => token === 'pan-y' || token === 'pan-up' || token === 'pan-down')
40
+ };
41
+ }
42
+
43
+ /**
44
+ * The viewport's overflow on an axis. It scrolls unless the root or the body
45
+ * clips it, as a scroll lock does with `overflow: hidden`.
46
+ */
47
+ export function rootOverflow(doc, axis) {
48
+ const view = doc.defaultView;
49
+ if (view == null) {
50
+ return 'hidden';
51
+ }
52
+ for (const element of [doc.documentElement, doc.body]) {
53
+ if (element == null) {
54
+ continue;
55
+ }
56
+ const style = view.getComputedStyle(element);
57
+ const value = axis === 'x' ? style.overflowX : style.overflowY;
58
+ if (value === 'hidden' || value === 'clip') {
59
+ return 'hidden';
60
+ }
61
+ }
62
+ return 'auto';
63
+ }
64
+ function overflows(element, axis) {
65
+ return axis === 'y' ? element.scrollHeight - element.clientHeight > OVERFLOW_TOLERANCE_PX : element.scrollWidth - element.clientWidth > OVERFLOW_TOLERANCE_PX;
66
+ }
67
+
68
+ /**
69
+ * Whether a touch on `element` lands inside a scroll view, UIKit's question
70
+ * for a touch: a box above it, the page included, overflows on an axis it
71
+ * scrolls, and `touch-action` on the way up leaves that axis to the browser.
72
+ * A `position: fixed` box ends the walk, because it does not move with any
73
+ * scroller above it. A wheel scrolls whatever `touch-action` says, so a
74
+ * wheel's question passes `readsTouchAction: false`.
75
+ */
76
+ export function isInsideScrollView(element, {
77
+ readsTouchAction = true
78
+ } = {}) {
79
+ const doc = element.ownerDocument;
80
+ const view = doc.defaultView;
81
+ if (view == null) {
82
+ return false;
83
+ }
84
+ const root = doc.scrollingElement ?? doc.documentElement;
85
+ let panX = true;
86
+ let panY = true;
87
+ for (let node = element; node != null;) {
88
+ if (node instanceof Element) {
89
+ const style = view.getComputedStyle(node);
90
+ if (readsTouchAction) {
91
+ const pans = parseTouchAction(style.touchAction || 'auto');
92
+ panX &&= pans.x;
93
+ panY &&= pans.y;
94
+ }
95
+ if (node === root || node === doc.documentElement) {
96
+ break;
97
+ }
98
+ if (panY && SCROLLABLE_OVERFLOW.has(style.overflowY) && overflows(node, 'y') || panX && SCROLLABLE_OVERFLOW.has(style.overflowX) && overflows(node, 'x')) {
99
+ return true;
100
+ }
101
+ if (style.position === 'fixed') {
102
+ return false;
103
+ }
104
+ }
105
+ node = parentAcrossShadow(node);
106
+ }
107
+ return panY && SCROLLABLE_OVERFLOW.has(rootOverflow(doc, 'y')) && overflows(root, 'y') || panX && SCROLLABLE_OVERFLOW.has(rootOverflow(doc, 'x')) && overflows(root, 'x');
108
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"selectionLock.d.ts","sourceRoot":"","sources":["../../src/utils/selectionLock.ts"],"names":[],"mappings":"AAoDA;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE9D;AAWD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAC3B,MAAM,EAAE,WAAW,GAAG,IAAI,GACzB,MAAM,IAAI,CA4BZ;AAED,mEAAmE;AACnE,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAC9C;;;OAGG;IACH,iBAAiB,IAAI,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,EAClC,UAAU,CAAC,EAAE,MAAM,IAAI,GACtB,iBAAiB,CAuGnB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,aAAa,CAAC,aAAa,CAAC,CAiB9B;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,QAAQ,EACb,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,WAAW,GAAG,IAAI,GACzB,OAAO,CA+CT"}
1
+ {"version":3,"file":"selectionLock.d.ts","sourceRoot":"","sources":["../../src/utils/selectionLock.ts"],"names":[],"mappings":"AAwDA;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE9D;AAWD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAC3B,MAAM,EAAE,WAAW,GAAG,IAAI,GACzB,MAAM,IAAI,CA4BZ;AAED,mEAAmE;AACnE,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAC9C;;;OAGG;IACH,iBAAiB,IAAI,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,EAClC,UAAU,CAAC,EAAE,MAAM,IAAI,GACtB,iBAAiB,CAuGnB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,aAAa,CAAC,aAAa,CAAC,CAiB9B;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,QAAQ,EACb,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,WAAW,GAAG,IAAI,GACzB,OAAO,CA+CT"}
@@ -28,7 +28,7 @@
28
28
  //
29
29
  // A mouse never takes the lock, so its released behavior stays (AST-017).
30
30
 
31
- import { containsAlongFlatTree, parentAcrossShadow } from "./flatTree.js";
31
+ import { containsAlongFlatTree, deepActiveElement, parentAcrossShadow } from "./flatTree.js";
32
32
  import { subscribeInput } from "./inputStream.js";
33
33
  import { isIosWebKit } from "./touchQueries.js";
34
34
 
@@ -477,15 +477,6 @@ function openShadowRootsOf(target) {
477
477
  return roots;
478
478
  }
479
479
 
480
- /** The focused element, inside open shadow roots too. */
481
- function deepActiveElement(doc) {
482
- let active = doc?.activeElement ?? null;
483
- while (active?.shadowRoot?.activeElement != null) {
484
- active = active.shadowRoot.activeElement;
485
- }
486
- return active;
487
- }
488
-
489
480
  /**
490
481
  * The selection-lock styles on `set`, refcounted per element; idempotent
491
482
  * release.
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @file touchHitArea.stylex.ts
3
+ * @input Uses StyleX and the insets that utils/hitArea.ts writes on a host
4
+ * @output Exports `touchHitAreaStyles.layer`, a host's invisible hit band
5
+ * under a coarse pointer
6
+ * @position Internal styling utility for CheckboxInput and RadioListItem
7
+ *
8
+ * The band is the host's `::after`, grown past each edge by the measured
9
+ * inset. A clip path cuts out the host's box, so its content keeps its taps.
10
+ * A tap on the band lands on the host. SYNC: hitArea.ts HIT_INSET_PROPERTIES.
11
+ */
12
+ import * as stylex from '@stylexjs/stylex';
13
+ export declare const touchHitAreaStyles: Readonly<{
14
+ readonly layer: Readonly<{
15
+ readonly '::after': stylex.StyleXClassNameFor<"::after", {
16
+ readonly content: {
17
+ readonly default: null;
18
+ readonly "@media (pointer: coarse)": "\"\"";
19
+ };
20
+ readonly position: {
21
+ readonly default: null;
22
+ readonly "@media (pointer: coarse)": "absolute";
23
+ };
24
+ readonly inset: {
25
+ readonly default: null;
26
+ readonly "@media (pointer: coarse)": "calc(var(--astryx-hit-inset-top, 0px) * -1) calc(var(--astryx-hit-inset-right, 0px) * -1) calc(var(--astryx-hit-inset-bottom, 0px) * -1) calc(var(--astryx-hit-inset-left, 0px) * -1)";
27
+ };
28
+ readonly clipPath: {
29
+ readonly default: null;
30
+ readonly "@media (pointer: coarse)": "polygon(evenodd, 0 0, 100% 0, 100% 100%, 0 100%, 0 0, var(--astryx-hit-inset-left, 0px) var(--astryx-hit-inset-top, 0px), calc(100% - var(--astryx-hit-inset-right, 0px)) var(--astryx-hit-inset-top, 0px), calc(100% - var(--astryx-hit-inset-right, 0px)) calc(100% - var(--astryx-hit-inset-bottom, 0px)), var(--astryx-hit-inset-left, 0px) calc(100% - var(--astryx-hit-inset-bottom, 0px)), var(--astryx-hit-inset-left, 0px) var(--astryx-hit-inset-top, 0px))";
31
+ };
32
+ }>;
33
+ }>;
34
+ }>;
35
+ //# sourceMappingURL=touchHitArea.stylex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"touchHitArea.stylex.d.ts","sourceRoot":"","sources":["../../src/utils/touchHitArea.stylex.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAU3C,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAgB7B,CAAC"}
@@ -0,0 +1,32 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file touchHitArea.stylex.ts
5
+ * @input Uses StyleX and the insets that utils/hitArea.ts writes on a host
6
+ * @output Exports `touchHitAreaStyles.layer`, a host's invisible hit band
7
+ * under a coarse pointer
8
+ * @position Internal styling utility for CheckboxInput and RadioListItem
9
+ *
10
+ * The band is the host's `::after`, grown past each edge by the measured
11
+ * inset. A clip path cuts out the host's box, so its content keeps its taps.
12
+ * A tap on the band lands on the host. SYNC: hitArea.ts HIT_INSET_PROPERTIES.
13
+ */
14
+
15
+ import * as stylex from '@stylexjs/stylex';
16
+
17
+ // StyleX reads these at build time, so they are spelled out.
18
+ const TOUCH = '@media (pointer: coarse)';
19
+ // The insets are measured in the viewport, so the sides are physical.
20
+ const TOP = 'var(--astryx-hit-inset-top, 0px)';
21
+ const RIGHT = 'var(--astryx-hit-inset-right, 0px)';
22
+ const BOTTOM = 'var(--astryx-hit-inset-bottom, 0px)';
23
+ const LEFT = 'var(--astryx-hit-inset-left, 0px)';
24
+ export const touchHitAreaStyles = {
25
+ layer: {
26
+ k5JduY: "x1fjtqre",
27
+ kwXMNM: "x7b72wb",
28
+ kv0HGH: "x16x82qr",
29
+ kJYu5r: "x1c440c0",
30
+ $$css: true
31
+ }
32
+ };
@@ -21,6 +21,11 @@ export declare function isFocusableTrigger(element: HTMLElement): boolean;
21
21
  * too, so a plain wrapper ignores its children's focus.
22
22
  */
23
23
  export declare function isFocusForTrigger(event: Event, mode: TriggerFocusMode): boolean;
24
+ /**
25
+ * `isFocusForTrigger` for focus already on `target`, inside `trigger`: the
26
+ * same rule, read when a trigger attaches with focus inside it.
27
+ */
28
+ export declare function isFocusOnTrigger(target: EventTarget | null, trigger: HTMLElement | null, mode: TriggerFocusMode): boolean;
24
29
  /** Remembers whether a trigger's current focus counted when it arrived. */
25
30
  export interface TriggerFocusGate {
26
31
  /** On focusin: whether this focus opens the layer. */
@@ -1 +1 @@
1
- {"version":3,"file":"triggerFocus.d.ts","sourceRoot":"","sources":["../../src/utils/triggerFocus.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAShE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAWT;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;CACzD;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,IAAI,gBAAgB,CAezD"}
1
+ {"version":3,"file":"triggerFocus.d.ts","sourceRoot":"","sources":["../../src/utils/triggerFocus.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAShE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAMT;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAQT;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;CACzD;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,IAAI,gBAAgB,CAezD"}
@@ -34,14 +34,21 @@ export function isFocusableTrigger(element) {
34
34
  * too, so a plain wrapper ignores its children's focus.
35
35
  */
36
36
  export function isFocusForTrigger(event, mode) {
37
+ return isFocusOnTrigger(event.target, event.currentTarget, mode);
38
+ }
39
+
40
+ /**
41
+ * `isFocusForTrigger` for focus already on `target`, inside `trigger`: the
42
+ * same rule, read when a trigger attaches with focus inside it.
43
+ */
44
+ export function isFocusOnTrigger(target, trigger, mode) {
37
45
  if (mode === 'always') {
38
46
  return true;
39
47
  }
40
48
  if (mode === 'never') {
41
49
  return false;
42
50
  }
43
- const trigger = event.currentTarget;
44
- return trigger != null && (event.target === trigger || isFocusableTrigger(trigger));
51
+ return trigger != null && (target === trigger || isFocusableTrigger(trigger));
45
52
  }
46
53
 
47
54
  /** Remembers whether a trigger's current focus counted when it arrived. */
package/locales/en.json CHANGED
@@ -1323,6 +1323,10 @@
1323
1323
  "defaultMessage": "Loading",
1324
1324
  "description": "Screen-reader-only default name for a standalone Spinner's role=\"status\" element, used when the consumer supplies neither `aria-label` nor a visible string label; also announced once when a busy input or selector starts loading, in place of its decorative Spinner. Present-progressive form. Kept separate from `button.loading` and `typeahead.loading` — translations may diverge."
1325
1325
  },
1326
+ "@astryx.scrollRegion.label": {
1327
+ "defaultMessage": "Content",
1328
+ "description": "Accessible name of a scrolling content region (LayoutContent, LayoutPanel or StackItem) when the caller gives none. A screen reader announces it with the region's group role while the region scrolls."
1329
+ },
1326
1330
  "@astryx.chatComposerDrawer.expand": {
1327
1331
  "defaultMessage": "Expand {label}",
1328
1332
  "description": "Screen-reader-only label on the ChatComposerDrawer toggle when the drawer is collapsed. `{label}` is the drawer's visible name — example: `Expand Attachments`. Pairs with `collapse`."