@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
@@ -17,7 +17,7 @@
17
17
  * - /apps/storybook/stories/RadioList.stories.tsx
18
18
  * - /packages/cli/assets/templates/blocks/components/RadioList/ (showcase blocks)
19
19
  */
20
- import React, { use, useId, useRef } from 'react';
20
+ import React, { use, useCallback, useId, useRef } from 'react';
21
21
  import * as stylex from '@stylexjs/stylex';
22
22
  import { RadioListContext } from "./RadioList.js";
23
23
  import { RadioListReasonContext } from "./RadioListReasonContext.js";
@@ -31,9 +31,13 @@ import "../Indicator/indicator.markers.stylex.js";
31
31
  import { indicatorScope } from "../Indicator/indicator.markers.stylex.js";
32
32
  import { useIndicatorFocusRing } from "../hooks/useIndicatorFocusRing.js";
33
33
  import { usePressFeedback } from "../hooks/usePressFeedback.js";
34
+ import { useMergedRefs } from "../hooks/useMergedRefs.js";
35
+ import { watchHitArea, writeHitInsets } from "../utils/hitArea.js";
36
+ import { touchHitAreaStyles } from "../utils/touchHitArea.stylex.js";
34
37
  import { useIndicator } from "../Indicator/useIndicator.js";
35
38
  import { Item } from "../Item/Item.js";
36
39
  import { themeProps } from "../utils/themeProps.js";
40
+ import { rowPressLayerStyles } from "../privateAttributes/press.stylex.js";
37
41
 
38
42
  // The touch press's paint, declared by the shared overlay styles on the
39
43
  // element the controller writes to (`pressedAlpha`) at the press's strength,
@@ -104,7 +108,6 @@ const rowStyles = {
104
108
  kaIpWk: "x2u8bby",
105
109
  k7Eaqz: "xeuugli",
106
110
  kWkggS: "xjbqb8w",
107
- kKwaWg: "x18o3ruo",
108
111
  $$css: true
109
112
  },
110
113
  press: {
@@ -186,6 +189,18 @@ export function RadioListItem({
186
189
  // since the visible label is now a plain (non-`<label>`) text node — a real
187
190
  // `<label htmlFor>` would double-fire under delegation.
188
191
  const radioRef = useRef(null);
192
+
193
+ // Under a coarse pointer an option's row grows toward 44 px through an
194
+ // invisible band, and the row keeps its size. A tap on the band lands on
195
+ // the row, which hands it to the radio. The watch lives as long as the row
196
+ // is attached: the ref's cleanup stops it.
197
+ const watchRowHitArea = useCallback(row => {
198
+ if (row == null || isDisabled) {
199
+ return;
200
+ }
201
+ return watchHitArea(row, insets => writeHitInsets(row, insets));
202
+ }, [isDisabled]);
203
+ const mergedRowRef = useMergedRefs(ref, watchRowHitArea);
189
204
  const radioCircle = /*#__PURE__*/_jsxs("div", {
190
205
  ...stylex.props(styles.radioWrapper, wrapperSizeStyles[size], !isDisabled && styles.indicatorPressOverlay),
191
206
  ...focusProps,
@@ -251,7 +266,7 @@ export function RadioListItem({
251
266
  children: [radioCircle, startContent]
252
267
  }) : radioCircle;
253
268
  return /*#__PURE__*/_jsx(Item, {
254
- ref: ref,
269
+ ref: mergedRowRef,
255
270
  ...(isDisabled ? undefined : pressable),
256
271
  startContent: mediaContent
257
272
  // Delegate row-surface clicks (label text, description, and the empty
@@ -276,11 +291,14 @@ export function RadioListItem({
276
291
  // the painting row element (Item), the same element that carries the
277
292
  // theme target, so a theme's hover styling stays in step with the tint.
278
293
  !isDisabled && indicatorScope,
294
+ // The row keeps no press paint of its own: the circle paints, and
295
+ // reads the strength whose release the row keeps.
296
+ rowPressLayerStyles.cellWithoutLayer,
279
297
  // Restore the bare default look: zero Item's padding/radius and its
280
298
  // interactive hover/press background. Applied after Item's own base
281
299
  // styles so it wins within the base layer; a `radio-list-item` theme
282
300
  // still overrides it from the higher `astryx-theme` layer.
283
- rowStyles.root, !isDisabled && rowStyles.press, xstyle],
301
+ rowStyles.root, !isDisabled && rowStyles.press, !isDisabled && touchHitAreaStyles.layer, xstyle],
284
302
  ...mergeProps(
285
303
  // One target for every row, carrying its size and runtime state so a
286
304
  // theme can express "selected option at large" or restyle disabled
@@ -104,7 +104,7 @@ export interface SelectableCardProps extends Omit<BaseProps, 'onChange'> {
104
104
  * </SelectableCard>
105
105
  * ```
106
106
  */
107
- export declare function SelectableCard({ label, isSelected, onChange, onClick: onClickProp, onMouseUp: onMouseUpProp, isDisabled, children, padding, variant, elevation, width, height, maxWidth, ref, xstyle: xstyleProp, className: classNameProp, style, ...props }: SelectableCardProps): import("react").JSX.Element;
107
+ export declare function SelectableCard({ label, isSelected, onChange, onClick: onClickProp, onMouseUp: onMouseUpProp, onPointerDown: onPointerDownProp, isDisabled, children, padding, variant, elevation, width, height, maxWidth, ref, xstyle: xstyleProp, className: classNameProp, style, ...props }: SelectableCardProps): import("react").JSX.Element;
108
108
  export declare namespace SelectableCard {
109
109
  var displayName: string;
110
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SelectableCard.d.ts","sourceRoot":"","sources":["../../src/SelectableCard/SelectableCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,KAAK,SAAS,EAMd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAGtE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAG9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAuN5C,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACtE,yCAAyC;IACzC,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAE1B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IAExC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,yBAAyB;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA4CD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,OAAmB,EACnB,SAAkB,EAClB,KAAK,EACL,MAAM,EACN,QAAQ,EACR,GAAG,EACH,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,aAAa,EACxB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,mBAAmB,+BA6JrB;yBAhLe,cAAc"}
1
+ {"version":3,"file":"SelectableCard.d.ts","sourceRoot":"","sources":["../../src/SelectableCard/SelectableCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,KAAK,SAAS,EAMd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAItE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAG9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAuN5C,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACtE,yCAAyC;IACzC,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAE1B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IAExC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,yBAAyB;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA4CD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,aAAa,EAAE,iBAAiB,EAChC,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,OAAmB,EACnB,SAAkB,EAClB,KAAK,EACL,MAAM,EACN,QAAQ,EACR,GAAG,EACH,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,aAAa,EACxB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,mBAAmB,+BAkKrB;yBAtLe,cAAc"}
@@ -34,6 +34,7 @@ import * as stylex from '@stylexjs/stylex';
34
34
  import "../theme/tokens.stylex.js";
35
35
  import { colorVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
36
36
  import { isImeKeyEvent, mergeProps } from "../utils/index.js";
37
+ import { chainEventHandlers } from "../utils/chainEventHandlers.js";
37
38
  import { Card } from "../Card/Card.js";
38
39
  import { useClickableContainer } from "../hooks/useClickableContainer.js";
39
40
  import { closestLayerRoot } from "../privateAttributes/layerRoot.stylex.js";
@@ -257,6 +258,7 @@ export function SelectableCard({
257
258
  onChange,
258
259
  onClick: onClickProp,
259
260
  onMouseUp: onMouseUpProp,
261
+ onPointerDown: onPointerDownProp,
260
262
  isDisabled = false,
261
263
  children,
262
264
  padding,
@@ -311,7 +313,8 @@ export function SelectableCard({
311
313
  }, [isDisabled, requestChange]);
312
314
  const {
313
315
  onClick,
314
- onMouseUp
316
+ onMouseUp,
317
+ onPointerDown
315
318
  } = useClickableContainer({
316
319
  containerRef,
317
320
  interactiveRef,
@@ -361,6 +364,7 @@ export function SelectableCard({
361
364
  !isDisabled && interactionOverlayStyles.pressedAlpha, isDisabled && styles.disabled, xstyleProp],
362
365
  onClick: !isDisabled ? composedOnClick : undefined,
363
366
  onMouseUp: !isDisabled ? composedOnMouseUp : undefined,
367
+ onPointerDown: !isDisabled ? chainEventHandlers(onPointerDown, onPointerDownProp) : onPointerDownProp,
364
368
  ...props,
365
369
  onClickCapture: !isDisabled && handleLayerClickCapture ? e => {
366
370
  handleLayerClickCapture(e);
@@ -1 +1 @@
1
- {"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../src/Spinner/Spinner.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA6B5C,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;CAKV,CAAC;AA8XF,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,KAAK,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExE,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAW,EACX,KAAiB,EACjB,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,SAAS,EACb,EAAE,YAAY,+BAqId;yBAhJe,OAAO"}
1
+ {"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../src/Spinner/Spinner.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA6B5C,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;CAKV,CAAC;AAwYF,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,KAAK,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExE,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAW,EACX,KAAiB,EACjB,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,SAAS,EACb,EAAE,YAAY,+BAqId;yBAhJe,OAAO"}
@@ -211,12 +211,22 @@ function syncRotationPhase(rotor) {
211
211
  // Animation
212
212
  // =============================================================================
213
213
 
214
+ /**
215
+ * Full turns in one iteration of the rotation.
216
+ *
217
+ * Chromium wakes the main thread at each iteration boundary while the
218
+ * document listens for `animationiteration`. React listens for it on every
219
+ * root. One iteration holds 100 turns, so the wake comes once in 100 turns.
220
+ * Each turn is 360 degrees, so the ring looks the same.
221
+ */
222
+ const TURNS_PER_ITERATION = 100;
223
+
214
224
  /**
215
225
  * A `transform` animation runs on the compositor, so the ring keeps turning
216
226
  * while a script runs. A `stroke-dashoffset` animation would repaint the arc
217
227
  * on the main thread every frame, so it would stop while a script runs.
218
228
  */
219
- const rotation = "xqng64z-B";
229
+ const rotation = "x11cqc53-B";
220
230
 
221
231
  // =============================================================================
222
232
  // Styles
@@ -448,7 +458,7 @@ export function Spinner({
448
458
  ref: syncRotationPhase,
449
459
  "aria-hidden": "true",
450
460
  ...{
451
- className: "x1lliihq x15r89dc x6v0vjy x7yyq19 x1so62im x1qcljrn xnh0sag xa4qsjk x1ka1v4i x1esw782"
461
+ className: "x1lliihq x15r89dc x6v0vjy x7yyq19 x1so62im xidn0ey x14hxw50 xa4qsjk x129v4ae x1esw782"
452
462
  },
453
463
  children: /*#__PURE__*/_jsx("svg", {
454
464
  width: frameSize,
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * @file StackItem.tsx
3
- * @input Uses React, ElementType, stackItem utility
3
+ * @input Uses React, ElementType, stackItem utility, StackItemScrollRegion
4
4
  * @output Exports StackItem polymorphic component and StackItemProps
5
- * @position Layout/Stack component; uses stackItem.stylex.ts
5
+ * @position Layout/Stack component; uses stackItem.stylex.ts. A scrollable
6
+ * `div` or `span` item renders through StackItemScrollRegion, which names
7
+ * it while it scrolls.
6
8
  *
7
9
  * SYNC: When modified, update these files to stay in sync:
8
10
  * - /packages/core/src/Stack/Stack.doc.mjs
@@ -34,7 +36,9 @@ export interface StackItemProps extends BaseProps<HTMLElement> {
34
36
  * reset, so `<StackItem size="fill" isScrollable>` is a complete scroll
35
37
  * region — it grows to fill the stack and scrolls its own overflow with
36
38
  * no extra style plumbing. Matches `isScrollable` on `LayoutContent`
37
- * and `LayoutPanel`.
39
+ * and `LayoutPanel`. While its content overflows, a `div` or `span` item
40
+ * is a group named by the caller's `aria-label`, or by a translated
41
+ * "Content". Another element keeps its own role.
38
42
  * @default false
39
43
  */
40
44
  isScrollable?: boolean;
@@ -62,7 +66,7 @@ export interface StackItemProps extends BaseProps<HTMLElement> {
62
66
  * </HStack>
63
67
  * ```
64
68
  */
65
- export declare function StackItem({ crossAlignSelf, size, isScrollable, as: element, xstyle, className, style, children, ref, ...props }: StackItemProps): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
69
+ export declare function StackItem({ crossAlignSelf, size, isScrollable, as: element, xstyle, className, style, children, ref, ...props }: StackItemProps): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").FunctionComponentElement<import("../hooks/StackItemScrollRegion.js").StackItemScrollRegionProps>;
66
70
  export declare namespace StackItem {
67
71
  var displayName: string;
68
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"StackItem.d.ts","sourceRoot":"","sources":["../../src/Stack/StackItem.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAChF,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAU5B,MAAM,WAAW,cAAe,SAAQ,SAAS,CAAC,WAAW,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;;OAGG;IACH,cAAc,CAAC,EAAE,uBAAuB,CAAC;IAEzC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IAErB;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,EAAE,CAAC,EAAE,WAAW,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EACxB,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,EAAE,EAAE,OAAe,EACnB,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,GAAG,EACH,GAAG,KAAK,EACT,EAAE,cAAc,0FAqBhB;yBAhCe,SAAS"}
1
+ {"version":3,"file":"StackItem.d.ts","sourceRoot":"","sources":["../../src/Stack/StackItem.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAChF,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAW5B,MAAM,WAAW,cAAe,SAAQ,SAAS,CAAC,WAAW,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;;OAGG;IACH,cAAc,CAAC,EAAE,uBAAuB,CAAC;IAEzC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IAErB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,EAAE,CAAC,EAAE,WAAW,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EACxB,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,EAAE,EAAE,OAAe,EACnB,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,GAAG,EACH,GAAG,KAAK,EACT,EAAE,cAAc,0MA8BhB;yBAzCe,SAAS"}
@@ -2,9 +2,11 @@
2
2
 
3
3
  /**
4
4
  * @file StackItem.tsx
5
- * @input Uses React, ElementType, stackItem utility
5
+ * @input Uses React, ElementType, stackItem utility, StackItemScrollRegion
6
6
  * @output Exports StackItem polymorphic component and StackItemProps
7
- * @position Layout/Stack component; uses stackItem.stylex.ts
7
+ * @position Layout/Stack component; uses stackItem.stylex.ts. A scrollable
8
+ * `div` or `span` item renders through StackItemScrollRegion, which names
9
+ * it while it scrolls.
8
10
  *
9
11
  * SYNC: When modified, update these files to stay in sync:
10
12
  * - /packages/core/src/Stack/Stack.doc.mjs
@@ -16,6 +18,7 @@ import * as stylex from '@stylexjs/stylex';
16
18
  import { stackItem } from "./stackItem.stylex.js";
17
19
  import { mergeProps } from "../utils/mergeProps.js";
18
20
  import { themeProps } from "../utils/themeProps.js";
21
+ import { StackItemScrollRegion } from "../hooks/StackItemScrollRegion.js";
19
22
  const overflowStyles = {
20
23
  scrollable: {
21
24
  kVQacm: "xysyzu8",
@@ -52,12 +55,22 @@ export function StackItem({
52
55
  crossAlignSelf,
53
56
  size
54
57
  }), isScrollable && overflowStyles.scrollable, xstyle);
55
- return /*#__PURE__*/createElement(element, {
56
- ref: ref,
58
+ const elementProps = {
57
59
  ...mergeProps(themeProps('stack-item', {
58
60
  size
59
61
  }), stylexProps, className, style),
60
62
  ...props
63
+ };
64
+ if (isScrollable && (element === 'div' || element === 'span')) {
65
+ return /*#__PURE__*/createElement(StackItemScrollRegion, {
66
+ as: element,
67
+ ref,
68
+ elementProps
69
+ }, children);
70
+ }
71
+ return /*#__PURE__*/createElement(element, {
72
+ ref: ref,
73
+ ...elementProps
61
74
  }, children);
62
75
  }
63
76
  StackItem.displayName = 'StackItem';
@@ -223,7 +223,7 @@ function SortHeaderButton({
223
223
  })
224
224
  }), rank != null && /*#__PURE__*/_jsx("span", {
225
225
  ...{
226
- className: "x1k6wstc xo5v014 xqwr325"
226
+ className: "x1k6wstc xo5v014 xjse4m1"
227
227
  },
228
228
  "aria-hidden": "true",
229
229
  children: rank
@@ -1 +1 @@
1
- {"version":3,"file":"Token.d.ts","sourceRoot":"","sources":["../../src/Token/Token.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAM,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAiB1C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAK5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AAe3C;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,WAAW,CAAC;IACxD,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA6JD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,IAAW,EACX,KAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,WAAW,EACX,UAAU,EACV,aAAqB,EACrB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,cAAc,EACjC,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,eAAe,EAAE,YAAY,EAC7B,GAAG,EACH,GAAG,IAAI,EACR,EAAE,UAAU,+BA8QZ;yBApSe,KAAK"}
1
+ {"version":3,"file":"Token.d.ts","sourceRoot":"","sources":["../../src/Token/Token.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAM,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAiB1C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAM5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AAe3C;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,WAAW,CAAC;IACxD,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA6JD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,IAAW,EACX,KAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,WAAW,EACX,UAAU,EACV,aAAqB,EACrB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,cAAc,EACjC,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,eAAe,EAAE,YAAY,EAC7B,GAAG,EACH,GAAG,IAAI,EACR,EAAE,UAAU,+BA8RZ;yBApTe,KAAK"}
@@ -29,6 +29,7 @@ import { themeProps } from "../utils/themeProps.js";
29
29
  import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
30
30
  import { interactionOverlayStyles } from "../utils/interactionOverlay.stylex.js";
31
31
  import { usePressFeedback } from "../hooks/usePressFeedback.js";
32
+ import { cancelNestedTouchPress } from "../hooks/useClickableContainer.js";
32
33
  import { disabledInteractionProps } from "../utils/disabledInteraction.js";
33
34
  import { TokenNamingContext } from "./TokenNamingContext.js";
34
35
  import { registerEnglishFallback, useComponentTranslator } from "../i18n/useComponentTranslator.js";
@@ -391,6 +392,13 @@ export function Token({
391
392
  }
392
393
  effectiveOnClick(e);
393
394
  };
395
+ // A finger press on Remove or a control in end content does not run the
396
+ // token's action, so the token shows no press for it. The inner button,
397
+ // the first button child, is the token's own action.
398
+ const handleContainerPointerDown = e => {
399
+ rest.onPointerDown?.(e);
400
+ cancelNestedTouchPress(e, e.currentTarget, e.currentTarget.querySelector(':scope > button'));
401
+ };
394
402
  return /*#__PURE__*/_jsxs("span", {
395
403
  ref: ref,
396
404
  onClick: isDisabled ? undefined : handleContainerClick,
@@ -402,6 +410,7 @@ export function Token({
402
410
  }), focusOutlineProps.focusWithin(styles.base, sizeStyles[size], colorStyles[color], styles.interactive, interactionOverlayStyles.backgroundImage, isDisabled && styles.disabled, xstyle), className, style),
403
411
  ...rest,
404
412
  ...sharedProps,
413
+ onPointerDown: isDisabled ? rest.onPointerDown : handleContainerPointerDown,
405
414
  children: [icon, /*#__PURE__*/_jsx("button", {
406
415
  type: "button",
407
416
  onClick: effectiveOnClick,
@@ -62,7 +62,7 @@ export interface TokenLinkProps extends HTMLAttributes<HTMLElement> {
62
62
  * (including middle-click / cmd+click to open in a new tab) while the remove
63
63
  * button keeps handling its own clicks.
64
64
  */
65
- export declare function TokenLink({ ref, href, isDisabled, onLinkClick, LinkComponent, linkStyleProps, labelContent, icon, endContent, removeButton, onClick: onClickProp, onMouseUp: onMouseUpProp, ...containerProps }: TokenLinkProps): import("react").JSX.Element;
65
+ export declare function TokenLink({ ref, href, isDisabled, onLinkClick, LinkComponent, linkStyleProps, labelContent, icon, endContent, removeButton, onClick: onClickProp, onMouseUp: onMouseUpProp, onPointerDown: onPointerDownProp, ...containerProps }: TokenLinkProps): import("react").JSX.Element;
66
66
  export declare namespace TokenLink {
67
67
  var displayName: string;
68
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TokenLink.d.ts","sourceRoot":"","sources":["../../src/Token/TokenLink.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,GAAG,EACH,cAAc,EACd,iBAAiB,EAClB,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAKrD,MAAM,WAAW,cAAe,SAAQ,cAAc,CAAC,WAAW,CAAC;IACjE,8CAA8C;IAC9C,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC7C,+DAA+D;IAC/D,aAAa,EAAE,iBAAiB,CAAC;IACjC,mEAAmE;IACnE,cAAc,EAAE;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAC,CAAC;IAC5D,wEAAwE;IACxE,YAAY,EAAE,SAAS,CAAC;IACxB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,kEAAkE;IAClE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iEAAiE;IACjE,YAAY,EAAE,SAAS,CAAC;IACxB,kFAAkF;IAClF,CAAC,QAAQ,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,IAAI,EACJ,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,GAAG,cAAc,EAClB,EAAE,cAAc,+BAiDhB;yBA/De,SAAS"}
1
+ {"version":3,"file":"TokenLink.d.ts","sourceRoot":"","sources":["../../src/Token/TokenLink.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,GAAG,EACH,cAAc,EACd,iBAAiB,EAClB,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAKrD,MAAM,WAAW,cAAe,SAAQ,cAAc,CAAC,WAAW,CAAC;IACjE,8CAA8C;IAC9C,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC7C,+DAA+D;IAC/D,aAAa,EAAE,iBAAiB,CAAC;IACjC,mEAAmE;IACnE,cAAc,EAAE;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAC,CAAC;IAC5D,wEAAwE;IACxE,YAAY,EAAE,SAAS,CAAC;IACxB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,kEAAkE;IAClE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iEAAiE;IACjE,YAAY,EAAE,SAAS,CAAC;IACxB,kFAAkF;IAClF,CAAC,QAAQ,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,IAAI,EACJ,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,aAAa,EAAE,iBAAiB,EAChC,GAAG,cAAc,EAClB,EAAE,cAAc,+BAsDhB;yBArEe,SAAS"}
@@ -51,13 +51,15 @@ export function TokenLink({
51
51
  removeButton,
52
52
  onClick: onClickProp,
53
53
  onMouseUp: onMouseUpProp,
54
+ onPointerDown: onPointerDownProp,
54
55
  ...containerProps
55
56
  }) {
56
57
  const containerRef = useRef(null);
57
58
  const linkRef = useRef(null);
58
59
  const {
59
60
  onClick,
60
- onMouseUp
61
+ onMouseUp,
62
+ onPointerDown
61
63
  } = useClickableContainer({
62
64
  containerRef,
63
65
  interactiveRef: linkRef,
@@ -69,6 +71,7 @@ export function TokenLink({
69
71
  ...containerProps,
70
72
  onClick: isDisabled ? onClickProp : composeEventHandlers(onClickProp, onClick),
71
73
  onMouseUp: isDisabled ? onMouseUpProp : composeEventHandlers(onMouseUpProp, onMouseUp),
74
+ onPointerDown: isDisabled ? onPointerDownProp : composeEventHandlers(onPointerDownProp, onPointerDown),
72
75
  children: [icon, isDisabled ?
73
76
  /*#__PURE__*/
74
77
  // A disabled link stays a focusable link with no destination, as a
@@ -1 +1 @@
1
- {"version":3,"file":"useTooltip.d.ts","sourceRoot":"","sources":["../../src/Tooltip/useTooltip.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,OAAO,CAAC;AAGf,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AA8ClC;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,GAAG,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAE9B;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEtC;;;;OAIG;IACH,cAAc,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEzC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;;;OAOG;IACH,aAAa,EAAE,CACb,QAAQ,EAAE,SAAS,EACnB,KAAK,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,KAC5C,SAAS,CAAC;IAEf;;;;;;;;;;;;OAYG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;IAEjB;;;OAGG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,wBAAgB,UAAU,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CAomBtE"}
1
+ {"version":3,"file":"useTooltip.d.ts","sourceRoot":"","sources":["../../src/Tooltip/useTooltip.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,OAAO,CAAC;AAGf,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AA8ClC;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,GAAG,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAE9B;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEtC;;;;OAIG;IACH,cAAc,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEzC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;;;OAOG;IACH,aAAa,EAAE,CACb,QAAQ,EAAE,SAAS,EACnB,KAAK,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,KAC5C,SAAS,CAAC;IAEf;;;;;;;;;;;;OAYG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;IAEjB;;;OAGG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,wBAAgB,UAAU,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CAosBtE"}
@@ -13,7 +13,7 @@
13
13
  * - /packages/core/src/Tooltip/index.ts
14
14
  */
15
15
  import { useCallback, useEffect, useRef, useState } from 'react';
16
- import { createTriggerFocusGate } from "../utils/triggerFocus.js";
16
+ import { createTriggerFocusGate, isFocusOnTrigger } from "../utils/triggerFocus.js";
17
17
  import * as stylex from '@stylexjs/stylex';
18
18
  import { useLayerInternal } from "../Layer/useLayer.js";
19
19
  import { useTouchTriggerInternal } from "../Layer/useTouchTrigger.js";
@@ -116,6 +116,17 @@ export function useTooltip(options = {}) {
116
116
  const showTimeoutRef = useRef(null);
117
117
  const hideTimeoutRef = useRef(null);
118
118
  const triggerRef = useRef(null);
119
+ // Whether the tooltip is enabled now, for a show that runs after a render
120
+ // (a pending hover show) and for the trigger ref callback.
121
+ const isEnabledRef = useRef(isEnabled);
122
+ isEnabledRef.current = isEnabled;
123
+ // Counts the renders in which the tooltip is disabled. A pending show
124
+ // records it, so a show scheduled before a disable is dropped even when
125
+ // the tooltip is enabled again before the timer fires.
126
+ const disabledRendersRef = useRef(0);
127
+ if (!isEnabled) {
128
+ disabledRendersRef.current += 1;
129
+ }
119
130
 
120
131
  // Clear all timeouts
121
132
  const clearTimeouts = useCallback(() => {
@@ -260,22 +271,16 @@ export function useTooltip(options = {}) {
260
271
  return;
261
272
  }
262
273
  clearTimeouts();
274
+ const disabledRenders = disabledRendersRef.current;
263
275
  showTimeoutRef.current = setTimeout(() => {
264
- showLayer();
276
+ // A show runs only if the tooltip stayed enabled since it was
277
+ // scheduled: nothing would close a tooltip that opens after a disable.
278
+ if (disabledRendersRef.current === disabledRenders) {
279
+ showLayer();
280
+ }
265
281
  }, delay);
266
282
  }, [isEnabled, isOpen, clearTimeouts, showLayer, delay]);
267
283
 
268
- // A show scheduled while the triggers were enabled must not outlive them:
269
- // disabling also detaches the leave listener that would have cancelled it,
270
- // so the timer would open a tooltip that nothing ever closes. Only the
271
- // pending show is dropped; a pending hide still runs.
272
- useEffect(() => {
273
- if (!isEnabled && showTimeoutRef.current) {
274
- clearTimeout(showTimeoutRef.current);
275
- showTimeoutRef.current = null;
276
- }
277
- }, [isEnabled]);
278
-
279
284
  // Schedule hide with delay (suppressed when isOpen is true).
280
285
  // A small hover bridge (when hideDelay is 0) lets the pointer travel from the
281
286
  // trigger onto the tooltip surface without the tooltip vanishing — required
@@ -331,27 +336,26 @@ export function useTooltip(options = {}) {
331
336
  // Under `auto`, whether focus counts is decided when it arrives, and a
332
337
  // focus that counted still hides on blur (utils/triggerFocus.ts).
333
338
  const [focusGate] = useState(createTriggerFocusGate);
339
+
340
+ // Whether focus on `target` opens the tooltip. With a `trigger`, its
341
+ // `focusTrigger` rule applies too. Only `:focus-visible` focus opens it, and
342
+ // a tap never does: a tapped `<input>` also matches `:focus-visible`.
343
+ const opensOnFocus = useCallback((target, trigger) => {
344
+ if (trigger != null && !isFocusOnTrigger(target, trigger, focusTrigger)) {
345
+ return false;
346
+ }
347
+ return !isTouchInteraction() && target.matches(':focus-visible');
348
+ }, [focusTrigger, isTouchInteraction]);
334
349
  const handleFocusIn = useCallback(e => {
335
350
  if (!focusGate.focusIn(e, focusTrigger) || !isEnabled) {
336
351
  return;
337
352
  }
338
- // A tap focuses the trigger it activates, and `:focus-visible` does not
339
- // filter that out on every element: a tapped `<input>` or contenteditable
340
- // matches it. Those are exactly the action triggers `auto` just decided
341
- // to keep shut, so without this the focus reopens what the tap
342
- // suppressed, over the field the user is trying to type into.
343
- if (isTouchInteraction()) {
344
- return;
345
- }
346
- // Only show tooltip for keyboard focus (:focus-visible),
347
- // not programmatic focus (e.g. dialog auto-focus, touch tap)
348
- const target = e.target;
349
- if (!target.matches(':focus-visible')) {
353
+ if (!opensOnFocus(e.target, null)) {
350
354
  return;
351
355
  }
352
356
  clearTimeouts();
353
357
  showLayer();
354
- }, [focusGate, focusTrigger, isEnabled, isTouchInteraction, clearTimeouts, showLayer]);
358
+ }, [focusGate, focusTrigger, isEnabled, opensOnFocus, clearTimeouts, showLayer]);
355
359
 
356
360
  // A held tooltip's focus-leave close is the hold's own: it listens on the
357
361
  // trigger whatever `focusTrigger` is. This schedules the unheld hide, which
@@ -423,46 +427,145 @@ export function useTooltip(options = {}) {
423
427
  hideLayer();
424
428
  }, [handleTouchPointerDown, trackTriggerPress, isOpen, clearTimeouts, hideLayer]);
425
429
 
426
- // Interaction ref that handles event listeners only
430
+ // The trigger's listeners call the latest handlers through this ref, so the
431
+ // trigger ref callback keeps one identity.
432
+ const handlersRef = useRef({
433
+ handleMouseEnter,
434
+ handleMouseLeave,
435
+ handleFocusIn,
436
+ handleFocusOut,
437
+ handleHeldFocusOut,
438
+ handlePointerEnter,
439
+ handlePointerDown,
440
+ focusTrigger,
441
+ isOpen,
442
+ dropHold,
443
+ hideNow,
444
+ showNow,
445
+ opensOnFocus
446
+ });
447
+ handlersRef.current = {
448
+ handleMouseEnter,
449
+ handleMouseLeave,
450
+ handleFocusIn,
451
+ handleFocusOut,
452
+ handleHeldFocusOut,
453
+ handlePointerEnter,
454
+ handlePointerDown,
455
+ focusTrigger,
456
+ isOpen,
457
+ dropHold,
458
+ hideNow,
459
+ showNow,
460
+ opensOnFocus
461
+ };
462
+
463
+ // Removes the attached trigger's listeners (the trigger ref callback's
464
+ // cleanup).
465
+ const detachTriggerRef = useRef(null);
466
+ // Set when the trigger detached while the tooltip was disabled: the
467
+ // caller removed the wiring (DropdownMenu's Button while its menu is
468
+ // open), so the next enabled attach reads the focus that arrived meanwhile.
469
+ const wasSuppressedRef = useRef(false);
470
+
471
+ // The trigger's ref callback owns every trigger listener, and reads the
472
+ // trigger's state when it attaches and detaches.
427
473
  const interactionRef = useCallback(el => {
428
- // Cleanup previous element
429
- if (triggerRef.current) {
430
- triggerRef.current.removeEventListener('mouseenter', handleMouseEnter);
431
- triggerRef.current.removeEventListener('mouseleave', handleMouseLeave);
432
- triggerRef.current.removeEventListener('focusin', handleFocusIn);
433
- triggerRef.current.removeEventListener('focusout', handleFocusOut);
434
- triggerRef.current.removeEventListener('focusout', handleHeldFocusOut);
435
- stopPressTrackingRef.current?.();
436
- triggerRef.current.removeEventListener('pointerenter', handlePointerEnter);
437
- triggerRef.current.removeEventListener('pointerdown', handlePointerDown);
438
- }
439
- if (el) {
440
- // Attach hover listeners. `pointerenter` runs before the synthesized
441
- // `mouseenter` a tap produces, which is what lets the hover path know
442
- // it is looking at a finger.
443
- el.addEventListener('pointerenter', handlePointerEnter);
444
- el.addEventListener('mouseenter', handleMouseEnter);
445
- el.addEventListener('mouseleave', handleMouseLeave);
446
- // Press-to-dismiss on a mouse; tap-to-open on a touch pointer.
447
- el.addEventListener('pointerdown', handlePointerDown);
448
-
449
- // Focus listeners unless focus never opens the tooltip; `auto` decides
450
- // per event (utils/triggerFocus.ts).
451
- if (focusTrigger !== 'never') {
452
- el.addEventListener('focusin', handleFocusIn);
453
- el.addEventListener('focusout', handleFocusOut);
454
- }
474
+ // A caller that reports `null` by hand detaches the trigger, as the
475
+ // returned cleanup does.
476
+ if (el == null) {
477
+ detachTriggerRef.current?.();
478
+ return;
455
479
  }
456
-
457
- // Its own focus-leave listener: `focusTrigger="never"` attaches none.
458
- el?.addEventListener('focusout', handleHeldFocusOut);
480
+ if (el === triggerRef.current) {
481
+ return;
482
+ }
483
+ detachTriggerRef.current?.();
484
+ const latest = () => handlersRef.current;
485
+ // `pointerenter` runs before the synthesized `mouseenter` a tap produces,
486
+ // which is what lets the hover path know it is looking at a finger.
487
+ const onPointerEnter = e => latest().handlePointerEnter(e);
488
+ const onMouseEnter = () => latest().handleMouseEnter();
489
+ const onMouseLeave = e => latest().handleMouseLeave(e);
490
+ // Press-to-dismiss on a mouse; tap-to-open on a touch pointer.
491
+ const onPointerDown = e => latest().handlePointerDown(e);
492
+ // Focus counts unless focus never opens the tooltip; `auto` decides per
493
+ // event (isFocusForTrigger).
494
+ const onFocusIn = e => {
495
+ if (latest().focusTrigger !== 'never') {
496
+ latest().handleFocusIn(e);
497
+ }
498
+ };
499
+ const onFocusOut = e => {
500
+ if (latest().focusTrigger !== 'never') {
501
+ latest().handleFocusOut(e);
502
+ }
503
+ };
504
+ // A held tooltip's own focus-leave close, whatever `focusTrigger` is.
505
+ const onHeldFocusOut = e => latest().handleHeldFocusOut(e);
506
+ el.addEventListener('pointerenter', onPointerEnter);
507
+ el.addEventListener('mouseenter', onMouseEnter);
508
+ el.addEventListener('mouseleave', onMouseLeave);
509
+ el.addEventListener('pointerdown', onPointerDown);
510
+ el.addEventListener('focusin', onFocusIn);
511
+ el.addEventListener('focusout', onFocusOut);
512
+ el.addEventListener('focusout', onHeldFocusOut);
459
513
  triggerRef.current = el;
460
- }, [handleHeldFocusOut, focusTrigger, handleMouseEnter, handleMouseLeave, handleFocusIn, handleFocusOut, handlePointerEnter, handlePointerDown]);
514
+
515
+ // A trigger that attaches again after its wiring was removed
516
+ // (DropdownMenu's Button as its menu closes) missed the focus that
517
+ // arrived meanwhile. Show for it only if it would open the tooltip:
518
+ // returned keyboard focus does, focus returned after a pointer pick does
519
+ // not. Any other attach leaves the tooltip as it is, so a tooltip
520
+ // dismissed with Escape stays closed.
521
+ const focused = el.ownerDocument.activeElement;
522
+ const wasSuppressed = wasSuppressedRef.current;
523
+ if (isEnabledRef.current) {
524
+ wasSuppressedRef.current = false;
525
+ }
526
+ if (wasSuppressed && isEnabledRef.current && latest().isOpen === undefined && latest().focusTrigger !== 'never' && focused instanceof HTMLElement && el.contains(focused) && latest().opensOnFocus(focused, el)) {
527
+ latest().showNow();
528
+ }
529
+ const detach = () => {
530
+ if (detachTriggerRef.current === detach) {
531
+ detachTriggerRef.current = null;
532
+ }
533
+ el.removeEventListener('pointerenter', onPointerEnter);
534
+ el.removeEventListener('mouseenter', onMouseEnter);
535
+ el.removeEventListener('mouseleave', onMouseLeave);
536
+ el.removeEventListener('pointerdown', onPointerDown);
537
+ el.removeEventListener('focusin', onFocusIn);
538
+ el.removeEventListener('focusout', onFocusOut);
539
+ el.removeEventListener('focusout', onHeldFocusOut);
540
+ stopPressTrackingRef.current?.();
541
+ if (triggerRef.current === el) {
542
+ triggerRef.current = null;
543
+ }
544
+ // A caller removes the wiring as it disables the tooltip. Close an
545
+ // uncontrolled tooltip then, or the next attach shows a stale tooltip.
546
+ // A detach while enabled, such as a merged ref that changes identity
547
+ // on a re-render, keeps a hovered or held tooltip open.
548
+ if (!isEnabledRef.current && latest().isOpen === undefined) {
549
+ wasSuppressedRef.current = true;
550
+ latest().dropHold();
551
+ latest().hideNow();
552
+ }
553
+ };
554
+ detachTriggerRef.current = detach;
555
+ return detach;
556
+ }, []);
461
557
 
462
558
  // Combined ref - shorthand for calling both positionRef and interactionRef
463
559
  const ref = useCallback(el => {
464
560
  layerRef(el);
465
- interactionRef(el);
561
+ const detachInteraction = interactionRef(el);
562
+ if (el == null) {
563
+ return;
564
+ }
565
+ return () => {
566
+ detachInteraction?.();
567
+ layerRef(null);
568
+ };
466
569
  }, [layerRef, interactionRef]);
467
570
 
468
571
  // Cleanup on unmount
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @file TreeListItem.tsx
3
- * @input Uses React, StyleX, theme tokens, TreeListBranches
3
+ * @input Uses React, StyleX, theme tokens, TreeListBranches, the shared press
4
+ * overlays and the compositor press layer
4
5
  * @output Exports TreeListItem component (internal, not publicly exported)
5
6
  * @position Internal implementation; consumed by TreeList.tsx
6
7
  *