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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/dist/AppShell/observeMainOverflow.d.ts.map +1 -1
  2. package/dist/AppShell/observeMainOverflow.js +9 -6
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +5 -0
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  6. package/dist/BottomSheet/BottomSheetPanel.js +40 -8
  7. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  8. package/dist/BottomSheet/useSheetGestures.js +61 -21
  9. package/dist/Calendar/Calendar.d.ts +14 -2
  10. package/dist/Calendar/Calendar.d.ts.map +1 -1
  11. package/dist/Calendar/Calendar.js +63 -74
  12. package/dist/Calendar/getInitialFocusDate.d.ts +4 -1
  13. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -1
  14. package/dist/Calendar/getInitialFocusDate.js +7 -5
  15. package/dist/Calendar/hooks/useCalendarDays.d.ts +19 -2
  16. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  17. package/dist/Calendar/hooks/useCalendarDays.js +57 -64
  18. package/dist/Calendar/hooks/useCalendarNavigation.d.ts +28 -3
  19. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  20. package/dist/Calendar/hooks/useCalendarNavigation.js +33 -22
  21. package/dist/Calendar/styles.d.ts +1 -1
  22. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  23. package/dist/CheckboxInput/CheckboxInput.js +54 -11
  24. package/dist/ClickableCard/ClickableCard.d.ts +1 -1
  25. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  26. package/dist/ClickableCard/ClickableCard.js +5 -1
  27. package/dist/DateInput/DateInput.d.ts.map +1 -1
  28. package/dist/DateInput/DateInput.js +4 -1
  29. package/dist/DateInput/PickerWheel.d.ts.map +1 -1
  30. package/dist/DateInput/PickerWheel.js +7 -1
  31. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  32. package/dist/DateRangeInput/DateRangeInput.js +5 -2
  33. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  34. package/dist/DateTimeInput/DateTimeInput.js +4 -1
  35. package/dist/Dialog/Dialog.d.ts +2 -1
  36. package/dist/Dialog/Dialog.d.ts.map +1 -1
  37. package/dist/Dialog/Dialog.js +12 -1
  38. package/dist/Drawer/useDrawerDialogPresence.d.ts +2 -1
  39. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  40. package/dist/Drawer/useDrawerDialogPresence.js +11 -2
  41. package/dist/DropdownMenu/DropdownMenu.d.ts +9 -1
  42. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  43. package/dist/DropdownMenu/DropdownMenu.js +9 -4
  44. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  45. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +3 -2
  46. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  47. package/dist/DropdownMenu/DropdownMenuItem.js +3 -2
  48. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  49. package/dist/DropdownMenu/DropdownMenuRadioItem.js +3 -2
  50. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  51. package/dist/DropdownMenu/DropdownMenuSubMenu.js +3 -2
  52. package/dist/Field/inputDisabledFocus.d.ts +4 -4
  53. package/dist/Field/inputStyles.stylex.d.ts +1 -1
  54. package/dist/FileInput/FileInput.d.ts.map +1 -1
  55. package/dist/FileInput/FileInput.js +16 -2
  56. package/dist/HoverCard/useHoverCard.d.ts +3 -1
  57. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  58. package/dist/Icon/Icon.d.ts +1 -1
  59. package/dist/InfoTip/InfoTip.d.ts +1 -0
  60. package/dist/InfoTip/InfoTip.d.ts.map +1 -1
  61. package/dist/InfoTip/InfoTip.js +1 -0
  62. package/dist/InputGroup/InputGroup.d.ts +4 -3
  63. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  64. package/dist/InputGroup/InputGroup.js +2 -2
  65. package/dist/InputGroup/groupStyles.d.ts +1 -1
  66. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  67. package/dist/InputGroup/groupStyles.js +1 -1
  68. package/dist/Item/Item.d.ts +2 -1
  69. package/dist/Item/Item.d.ts.map +1 -1
  70. package/dist/Item/Item.js +29 -6
  71. package/dist/Layer/holdEntranceInput.d.ts +24 -0
  72. package/dist/Layer/holdEntranceInput.d.ts.map +1 -0
  73. package/dist/Layer/holdEntranceInput.js +65 -0
  74. package/dist/Layer/inputHold.d.ts +49 -0
  75. package/dist/Layer/inputHold.d.ts.map +1 -0
  76. package/dist/Layer/inputHold.js +636 -0
  77. package/dist/Layer/preserveAnimations.d.ts +1 -5
  78. package/dist/Layer/preserveAnimations.d.ts.map +1 -1
  79. package/dist/Layer/preserveAnimations.js +12 -214
  80. package/dist/Layer/useLayer.d.ts +3 -1
  81. package/dist/Layer/useLayer.d.ts.map +1 -1
  82. package/dist/Layer/useLayer.js +64 -4
  83. package/dist/Layout/LayoutContent.d.ts +3 -1
  84. package/dist/Layout/LayoutContent.d.ts.map +1 -1
  85. package/dist/Layout/LayoutContent.js +12 -4
  86. package/dist/Layout/LayoutPanel.d.ts +4 -1
  87. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  88. package/dist/Layout/LayoutPanel.js +13 -4
  89. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  90. package/dist/Lightbox/Lightbox.js +4 -0
  91. package/dist/MetadataList/MetadataList.js +1 -1
  92. package/dist/MobileNav/MobileNav.d.ts +11 -1
  93. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  94. package/dist/MobileNav/MobileNav.js +39 -1
  95. package/dist/MoreMenu/MoreMenu.d.ts +5 -3
  96. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  97. package/dist/NumberInput/NumberInput.d.ts +4 -2
  98. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  99. package/dist/NumberInput/NumberInput.js +244 -11
  100. package/dist/Popover/usePopover.d.ts +1 -0
  101. package/dist/Popover/usePopover.d.ts.map +1 -1
  102. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  103. package/dist/PowerSearch/PowerSearch.js +12 -5
  104. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -1
  105. package/dist/PowerSearch/PowerSearchBottomSheet.js +4 -2
  106. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  107. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  108. package/dist/PowerSearch/formatFilterValue.d.ts +9 -3
  109. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  110. package/dist/PowerSearch/formatFilterValue.js +14 -11
  111. package/dist/PowerSearch/formatTokenValue.d.ts +6 -2
  112. package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -1
  113. package/dist/PowerSearch/formatTokenValue.js +6 -3
  114. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  115. package/dist/RadioList/RadioListItem.js +22 -4
  116. package/dist/SelectableCard/SelectableCard.d.ts +1 -1
  117. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  118. package/dist/SelectableCard/SelectableCard.js +5 -1
  119. package/dist/Spinner/Spinner.d.ts.map +1 -1
  120. package/dist/Spinner/Spinner.js +14 -71
  121. package/dist/Spinner/index.d.ts +1 -1
  122. package/dist/Spinner/index.d.ts.map +1 -1
  123. package/dist/Spinner/spinnerRotor.d.ts +28 -0
  124. package/dist/Spinner/spinnerRotor.d.ts.map +1 -0
  125. package/dist/Spinner/spinnerRotor.js +98 -0
  126. package/dist/Stack/StackItem.d.ts +8 -4
  127. package/dist/Stack/StackItem.d.ts.map +1 -1
  128. package/dist/Stack/StackItem.js +17 -4
  129. package/dist/Switch/Switch.d.ts.map +1 -1
  130. package/dist/Switch/Switch.js +13 -10
  131. package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
  132. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  133. package/dist/Timestamp/Timestamp.js +14 -8
  134. package/dist/Timestamp/formatInstant.d.ts +10 -1
  135. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  136. package/dist/Timestamp/formatInstant.js +13 -27
  137. package/dist/Timestamp/tooltipEntries.d.ts +5 -3
  138. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  139. package/dist/Timestamp/tooltipEntries.js +6 -4
  140. package/dist/Token/Token.d.ts.map +1 -1
  141. package/dist/Token/Token.js +9 -0
  142. package/dist/Token/TokenLink.d.ts +1 -1
  143. package/dist/Token/TokenLink.d.ts.map +1 -1
  144. package/dist/Token/TokenLink.js +4 -1
  145. package/dist/Tokenizer/Tokenizer.d.ts +14 -10
  146. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  147. package/dist/Tokenizer/Tokenizer.js +189 -89
  148. package/dist/Tooltip/useTooltip.d.ts +3 -1
  149. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  150. package/dist/Tooltip/useTooltip.js +162 -59
  151. package/dist/TreeList/TreeListItem.d.ts +2 -1
  152. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  153. package/dist/TreeList/TreeListItem.js +27 -3
  154. package/dist/astryx.css +45 -18
  155. package/dist/gestures/GestureHost.d.ts +2 -2
  156. package/dist/gestures/GestureHost.d.ts.map +1 -1
  157. package/dist/gestures/GestureHost.js +21 -6
  158. package/dist/gestures/PanGestureRecognizer.d.ts +11 -1
  159. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  160. package/dist/gestures/PanGestureRecognizer.js +15 -1
  161. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +6 -1
  162. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -1
  163. package/dist/gestures/nativeScroll.d.ts +3 -6
  164. package/dist/gestures/nativeScroll.d.ts.map +1 -1
  165. package/dist/gestures/nativeScroll.js +7 -52
  166. package/dist/gestures/wheelSegmenter.d.ts +68 -1
  167. package/dist/gestures/wheelSegmenter.d.ts.map +1 -1
  168. package/dist/gestures/wheelSegmenter.js +199 -10
  169. package/dist/hooks/StackItemScrollRegion.d.ts +31 -0
  170. package/dist/hooks/StackItemScrollRegion.d.ts.map +1 -0
  171. package/dist/hooks/StackItemScrollRegion.js +40 -0
  172. package/dist/hooks/menuPressGesture.d.ts +133 -21
  173. package/dist/hooks/menuPressGesture.d.ts.map +1 -1
  174. package/dist/hooks/menuPressGesture.js +155 -30
  175. package/dist/hooks/menuPressValues.d.ts +16 -0
  176. package/dist/hooks/menuPressValues.d.ts.map +1 -0
  177. package/dist/hooks/menuPressValues.js +18 -0
  178. package/dist/hooks/useClickableContainer.d.ts +27 -5
  179. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  180. package/dist/hooks/useClickableContainer.js +41 -5
  181. package/dist/hooks/useFocusTrap.d.ts +10 -0
  182. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  183. package/dist/hooks/useFocusTrap.js +225 -132
  184. package/dist/hooks/useMenuPress.d.ts +34 -1
  185. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  186. package/dist/hooks/useMenuPress.js +93 -5
  187. package/dist/hooks/usePressFeedback.d.ts +6 -6
  188. package/dist/hooks/usePressFeedback.js +6 -6
  189. package/dist/hooks/useScrollRegionProps.d.ts +35 -0
  190. package/dist/hooks/useScrollRegionProps.d.ts.map +1 -0
  191. package/dist/hooks/useScrollRegionProps.js +51 -0
  192. package/dist/i18n/InternationalizationContext.d.ts +6 -0
  193. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  194. package/dist/i18n/InternationalizationProvider.d.ts +21 -3
  195. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  196. package/dist/i18n/InternationalizationProvider.js +8 -3
  197. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts +8 -0
  198. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts.map +1 -0
  199. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.js +12 -0
  200. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  201. package/dist/i18n/generated-locales/en.generated.js +1 -0
  202. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  203. package/dist/i18n/generated-locales/pseudo.generated.js +1 -0
  204. package/dist/i18n/index.d.ts +2 -0
  205. package/dist/i18n/index.d.ts.map +1 -1
  206. package/dist/i18n/index.js +1 -0
  207. package/dist/i18n/useCalendarSystem.d.ts +19 -0
  208. package/dist/i18n/useCalendarSystem.d.ts.map +1 -0
  209. package/dist/i18n/useCalendarSystem.js +61 -0
  210. package/dist/internal/spinner-rotor.d.ts +16 -0
  211. package/dist/internal/spinner-rotor.d.ts.map +1 -0
  212. package/dist/internal/spinner-rotor.js +16 -0
  213. package/dist/internal/touch.d.ts +14 -1
  214. package/dist/internal/touch.d.ts.map +1 -1
  215. package/dist/internal/touch.js +20 -2
  216. package/dist/motion/carryAnimations.d.ts +58 -0
  217. package/dist/motion/carryAnimations.d.ts.map +1 -0
  218. package/dist/motion/carryAnimations.js +305 -0
  219. package/dist/motion/transientCopy.d.ts +4 -2
  220. package/dist/motion/transientCopy.d.ts.map +1 -1
  221. package/dist/motion/transientCopy.js +34 -5
  222. package/dist/motion/uikit/gestures.d.ts +41 -0
  223. package/dist/motion/uikit/gestures.d.ts.map +1 -1
  224. package/dist/motion/uikit/gestures.js +25 -0
  225. package/dist/motion/uikit/index.d.ts +1 -1
  226. package/dist/motion/uikit/index.d.ts.map +1 -1
  227. package/dist/motion/uikit/index.js +1 -1
  228. package/dist/motion/uikit/timing.d.ts +14 -10
  229. package/dist/motion/uikit/timing.d.ts.map +1 -1
  230. package/dist/motion/uikit/timing.js +7 -5
  231. package/dist/privateAttributes/menuPressLit.stylex.d.ts +52 -0
  232. package/dist/privateAttributes/menuPressLit.stylex.d.ts.map +1 -0
  233. package/dist/privateAttributes/menuPressLit.stylex.js +99 -0
  234. package/dist/privateAttributes/press.stylex.d.ts +139 -0
  235. package/dist/privateAttributes/press.stylex.d.ts.map +1 -0
  236. package/dist/privateAttributes/press.stylex.js +97 -0
  237. package/dist/theme/themeMotion.d.ts +3 -2
  238. package/dist/theme/themeMotion.d.ts.map +1 -1
  239. package/dist/theme/themeMotion.js +3 -2
  240. package/dist/theme/tokens.stylex.d.ts +2 -2
  241. package/dist/theme/tokens.stylex.js +1 -1
  242. package/dist/utils/calendarSystem.d.ts +114 -0
  243. package/dist/utils/calendarSystem.d.ts.map +1 -0
  244. package/dist/utils/calendarSystem.js +386 -0
  245. package/dist/utils/flatTree.d.ts +6 -3
  246. package/dist/utils/flatTree.d.ts.map +1 -1
  247. package/dist/utils/flatTree.js +13 -3
  248. package/dist/utils/hitArea.d.ts.map +1 -1
  249. package/dist/utils/hitArea.js +82 -5
  250. package/dist/utils/inputStream.d.ts +14 -1
  251. package/dist/utils/inputStream.d.ts.map +1 -1
  252. package/dist/utils/inputStream.js +40 -9
  253. package/dist/utils/interactionOverlay.stylex.d.ts +5 -9
  254. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  255. package/dist/utils/interactionOverlay.stylex.js +29 -31
  256. package/dist/utils/plainDate.d.ts +23 -7
  257. package/dist/utils/plainDate.d.ts.map +1 -1
  258. package/dist/utils/plainDate.js +57 -18
  259. package/dist/utils/pressFeedback.d.ts +10 -2
  260. package/dist/utils/pressFeedback.d.ts.map +1 -1
  261. package/dist/utils/pressFeedback.js +40 -15
  262. package/dist/utils/pressGesture.d.ts +12 -6
  263. package/dist/utils/pressGesture.d.ts.map +1 -1
  264. package/dist/utils/pressGesture.js +26 -8
  265. package/dist/utils/scrollView.d.ts +25 -0
  266. package/dist/utils/scrollView.d.ts.map +1 -0
  267. package/dist/utils/scrollView.js +108 -0
  268. package/dist/utils/selectionLock.d.ts.map +1 -1
  269. package/dist/utils/selectionLock.js +1 -10
  270. package/dist/utils/touchHitArea.stylex.d.ts +35 -0
  271. package/dist/utils/touchHitArea.stylex.d.ts.map +1 -0
  272. package/dist/utils/touchHitArea.stylex.js +32 -0
  273. package/dist/utils/triggerFocus.d.ts +5 -0
  274. package/dist/utils/triggerFocus.d.ts.map +1 -1
  275. package/dist/utils/triggerFocus.js +9 -2
  276. package/locales/en.json +4 -0
  277. package/locales/pseudo.json +3 -0
  278. package/package.json +10 -4
  279. package/src/AppShell/observeMainOverflow.ts +9 -6
  280. package/src/BottomSheet/BottomSheet.tsx +5 -0
  281. package/src/BottomSheet/BottomSheetPanel.tsx +64 -7
  282. package/src/BottomSheet/useSheetGestures.ts +83 -20
  283. package/src/Calendar/Calendar.doc.mjs +76 -6
  284. package/src/Calendar/Calendar.tsx +123 -104
  285. package/src/Calendar/getInitialFocusDate.ts +22 -8
  286. package/src/Calendar/hooks/useCalendarDays.ts +89 -63
  287. package/src/Calendar/hooks/useCalendarNavigation.ts +68 -26
  288. package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -2
  289. package/src/CheckboxInput/CheckboxInput.tsx +71 -9
  290. package/src/ClickableCard/ClickableCard.tsx +8 -1
  291. package/src/DateInput/DateInput.tsx +2 -0
  292. package/src/DateInput/PickerWheel.tsx +7 -2
  293. package/src/DateRangeInput/DateRangeInput.tsx +3 -1
  294. package/src/DateTimeInput/DateTimeInput.tsx +2 -0
  295. package/src/Dialog/Dialog.doc.mjs +1 -1
  296. package/src/Dialog/Dialog.tsx +12 -1
  297. package/src/Drawer/Drawer.doc.mjs +1 -1
  298. package/src/Drawer/useDrawerDialogPresence.ts +9 -2
  299. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -2
  300. package/src/DropdownMenu/DropdownMenu.tsx +29 -5
  301. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -1
  302. package/src/DropdownMenu/DropdownMenuItem.tsx +8 -4
  303. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -1
  304. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -1
  305. package/src/FileInput/FileInput.tsx +16 -2
  306. package/src/HoverCard/useHoverCard.tsx +3 -1
  307. package/src/InfoTip/InfoTip.doc.mjs +26 -2
  308. package/src/InfoTip/InfoTip.tsx +1 -0
  309. package/src/InputGroup/InputGroup.doc.mjs +4 -3
  310. package/src/InputGroup/InputGroup.tsx +4 -3
  311. package/src/InputGroup/groupStyles.ts +3 -1
  312. package/src/Item/Item.tsx +51 -9
  313. package/src/Layer/holdEntranceInput.ts +84 -0
  314. package/src/Layer/inputHold.ts +734 -0
  315. package/src/Layer/preserveAnimations.ts +12 -275
  316. package/src/Layer/useLayer.tsx +77 -4
  317. package/src/Layout/LayoutContent.doc.mjs +6 -3
  318. package/src/Layout/LayoutContent.tsx +10 -4
  319. package/src/Layout/LayoutPanel.doc.mjs +6 -3
  320. package/src/Layout/LayoutPanel.tsx +11 -4
  321. package/src/Lightbox/Lightbox.tsx +4 -0
  322. package/src/MetadataList/MetadataList.tsx +1 -1
  323. package/src/MobileNav/MobileNav.doc.mjs +3 -3
  324. package/src/MobileNav/MobileNav.tsx +39 -1
  325. package/src/MoreMenu/MoreMenu.doc.mjs +2 -4
  326. package/src/MoreMenu/MoreMenu.tsx +5 -3
  327. package/src/NumberInput/NumberInput.doc.mjs +1 -1
  328. package/src/NumberInput/NumberInput.tsx +259 -11
  329. package/src/Popover/usePopover.tsx +1 -0
  330. package/src/PowerSearch/PowerSearch.doc.mjs +3 -3
  331. package/src/PowerSearch/PowerSearch.tsx +20 -3
  332. package/src/PowerSearch/PowerSearchBottomSheet.tsx +4 -1
  333. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  334. package/src/PowerSearch/formatFilterValue.ts +21 -11
  335. package/src/PowerSearch/formatTokenValue.ts +7 -1
  336. package/src/RadioList/RadioListItem.doc.mjs +3 -2
  337. package/src/RadioList/RadioListItem.tsx +25 -7
  338. package/src/SelectableCard/SelectableCard.tsx +8 -1
  339. package/src/Spinner/Spinner.tsx +7 -89
  340. package/src/Spinner/index.ts +1 -5
  341. package/src/Spinner/spinnerRotor.ts +113 -0
  342. package/src/Stack/Stack.doc.mjs +1 -1
  343. package/src/Stack/StackItem.tsx +27 -13
  344. package/src/Switch/Switch.tsx +7 -6
  345. package/src/Table/plugins/sortable/useTableSortable.tsx +1 -1
  346. package/src/Timestamp/Timestamp.doc.mjs +3 -3
  347. package/src/Timestamp/Timestamp.tsx +13 -8
  348. package/src/Timestamp/formatInstant.ts +49 -28
  349. package/src/Timestamp/tooltipEntries.ts +7 -3
  350. package/src/Token/Token.tsx +18 -1
  351. package/src/Token/TokenLink.tsx +7 -1
  352. package/src/Tokenizer/Tokenizer.doc.mjs +3 -3
  353. package/src/Tokenizer/Tokenizer.tsx +252 -115
  354. package/src/Tooltip/useTooltip.tsx +178 -80
  355. package/src/TreeList/TreeListItem.tsx +36 -2
  356. package/src/gestures/GestureHost.ts +21 -5
  357. package/src/gestures/PanGestureRecognizer.ts +19 -2
  358. package/src/gestures/README.md +14 -5
  359. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +6 -1
  360. package/src/gestures/nativeScroll.ts +12 -68
  361. package/src/gestures/wheelSegmenter.ts +243 -10
  362. package/src/hooks/StackItemScrollRegion.tsx +57 -0
  363. package/src/hooks/menuPressGesture.ts +244 -38
  364. package/src/hooks/menuPressValues.ts +18 -0
  365. package/src/hooks/useClickableContainer.doc.mjs +8 -2
  366. package/src/hooks/useClickableContainer.ts +72 -6
  367. package/src/hooks/useFocusTrap.ts +268 -151
  368. package/src/hooks/useMenuPress.ts +118 -11
  369. package/src/hooks/usePressFeedback.doc.mjs +3 -3
  370. package/src/hooks/usePressFeedback.ts +6 -6
  371. package/src/hooks/useScrollRegionProps.ts +76 -0
  372. package/src/i18n/InternationalizationContext.ts +6 -0
  373. package/src/i18n/InternationalizationProvider.doc.mjs +29 -1
  374. package/src/i18n/InternationalizationProvider.tsx +33 -3
  375. package/src/i18n/generated-english/hooks/useScrollRegionProps.generated.ts +13 -0
  376. package/src/i18n/generated-locales/en.generated.ts +1 -0
  377. package/src/i18n/generated-locales/pseudo.generated.ts +1 -0
  378. package/src/i18n/index.ts +2 -0
  379. package/src/i18n/useCalendarSystem.ts +95 -0
  380. package/src/internal/spinner-rotor.ts +20 -0
  381. package/src/internal/touch.ts +34 -1
  382. package/src/motion/MEASUREMENTS.md +11 -0
  383. package/src/motion/carryAnimations.ts +389 -0
  384. package/src/motion/transientCopy.ts +45 -5
  385. package/src/motion/uikit/gestures.ts +22 -0
  386. package/src/motion/uikit/index.ts +1 -0
  387. package/src/motion/uikit/timing.ts +7 -5
  388. package/src/privateAttributes/menuPressLit.stylex.ts +104 -0
  389. package/src/privateAttributes/press.stylex.ts +243 -0
  390. package/src/theme/themeMotion.ts +3 -2
  391. package/src/theme/tokens.stylex.ts +1 -1
  392. package/src/utils/calendarSystem.ts +548 -0
  393. package/src/utils/flatTree.ts +15 -3
  394. package/src/utils/hitArea.ts +107 -5
  395. package/src/utils/inputStream.ts +47 -10
  396. package/src/utils/interactionOverlay.stylex.ts +19 -22
  397. package/src/utils/plainDate.ts +84 -19
  398. package/src/utils/pressFeedback.ts +46 -14
  399. package/src/utils/pressGesture.ts +35 -9
  400. package/src/utils/scrollView.ts +135 -0
  401. package/src/utils/selectionLock.ts +5 -10
  402. package/src/utils/touchHitArea.stylex.ts +41 -0
  403. package/src/utils/triggerFocus.ts +17 -4
@@ -31,33 +31,18 @@
31
31
  import {isRtlElement} from '../hooks/isRtlElement';
32
32
  import type {NativeScrollProbe} from './types';
33
33
  import {parentAcrossShadow} from '../utils/flatTree';
34
+ import {
35
+ isInsideScrollView,
36
+ parseTouchAction,
37
+ rootOverflow,
38
+ SCROLLABLE_OVERFLOW as SCROLLABLE,
39
+ type AllowedPans,
40
+ } from '../utils/scrollView';
34
41
 
35
42
  export {parentAcrossShadow};
36
43
 
37
- export interface AllowedPans {
38
- readonly x: boolean;
39
- readonly y: boolean;
40
- }
41
-
42
- /** Which pans a `touch-action` value lets the browser perform. */
43
- export function parseTouchAction(value: string): AllowedPans {
44
- const tokens = value.trim().split(/\s+/);
45
- if (tokens.includes('auto') || tokens.includes('manipulation')) {
46
- return {x: true, y: true};
47
- }
48
- if (tokens.includes('none')) {
49
- return {x: false, y: false};
50
- }
51
- return {
52
- x: tokens.some(
53
- token =>
54
- token === 'pan-x' || token === 'pan-left' || token === 'pan-right',
55
- ),
56
- y: tokens.some(
57
- token => token === 'pan-y' || token === 'pan-up' || token === 'pan-down',
58
- ),
59
- };
60
- }
44
+ export {parseTouchAction};
45
+ export type {AllowedPans};
61
46
 
62
47
  interface ChainEntry {
63
48
  readonly element: Element;
@@ -66,15 +51,8 @@ interface ChainEntry {
66
51
  readonly isRtl: boolean;
67
52
  readonly stopsX: boolean;
68
53
  readonly stopsY: boolean;
69
- /**
70
- * The scroller sits beyond a `position: fixed` ancestor of the touch: it
71
- * still scrolls under the finger, but it does not carry the touched
72
- * element, so the element is not inside a scroll view (spec:AST-094 FR11).
73
- */
74
- readonly isBeyondFixed: boolean;
75
54
  }
76
55
 
77
- const SCROLLABLE = new Set(['auto', 'scroll', 'overlay']);
78
56
  const EDGE_TOLERANCE = 1;
79
57
 
80
58
  interface Chain {
@@ -94,7 +72,6 @@ function buildChain(target: Element, readsTouchAction: boolean): Chain {
94
72
  let allowX = true;
95
73
  let allowY = true;
96
74
  let reachedRoot = false;
97
- let isBeyondFixed = false;
98
75
  for (
99
76
  let node: Node | null = target;
100
77
  node != null;
@@ -128,15 +105,11 @@ function buildChain(target: Element, readsTouchAction: boolean): Chain {
128
105
  isRtl: isRtlElement(element as HTMLElement),
129
106
  stopsX: behaviorX !== 'auto',
130
107
  stopsY: behaviorY !== 'auto',
131
- isBeyondFixed,
132
108
  });
133
109
  }
134
110
  if (isRoot) {
135
111
  break;
136
112
  }
137
- if (style.position === 'fixed') {
138
- isBeyondFixed = true;
139
- }
140
113
  }
141
114
  if (!reachedRoot && root instanceof Element) {
142
115
  chain.push({
@@ -146,7 +119,6 @@ function buildChain(target: Element, readsTouchAction: boolean): Chain {
146
119
  isRtl: false,
147
120
  stopsX: false,
148
121
  stopsY: false,
149
- isBeyondFixed,
150
122
  });
151
123
  }
152
124
  return {entries: chain, allowsPan: allowX || allowY};
@@ -167,28 +139,6 @@ function overscrollBehavior(style: CSSStyleDeclaration): [string, string] {
167
139
  return [x || first, y || second];
168
140
  }
169
141
 
170
- /**
171
- * The viewport scrolls unless the root or the body clips it (a scroll lock
172
- * sets `overflow: hidden` on one of them).
173
- */
174
- function rootOverflow(doc: Document, axis: 'x' | 'y'): string {
175
- const view = doc.defaultView;
176
- if (view == null) {
177
- return 'hidden';
178
- }
179
- for (const element of [doc.documentElement, doc.body]) {
180
- if (element == null) {
181
- continue;
182
- }
183
- const style = view.getComputedStyle(element);
184
- const value = axis === 'x' ? style.overflowX : style.overflowY;
185
- if (value === 'hidden' || value === 'clip') {
186
- return 'hidden';
187
- }
188
- }
189
- return 'auto';
190
- }
191
-
192
142
  function canMoveY(element: Element, dy: number): boolean {
193
143
  if (element.scrollHeight - element.clientHeight <= EDGE_TOLERANCE) {
194
144
  return false;
@@ -288,15 +238,9 @@ export function createNativeScrollProbe(
288
238
  return chain?.allowsPan === true;
289
239
  },
290
240
  get isInsideScroller(): boolean {
291
- return getChain().some(
292
- entry =>
293
- !entry.isBeyondFixed &&
294
- ((entry.y &&
295
- entry.element.scrollHeight - entry.element.clientHeight >
296
- EDGE_TOLERANCE) ||
297
- (entry.x &&
298
- entry.element.scrollWidth - entry.element.clientWidth >
299
- EDGE_TOLERANCE)),
241
+ return (
242
+ target instanceof Element &&
243
+ isInsideScrollView(target, {readsTouchAction})
300
244
  );
301
245
  },
302
246
  };
@@ -5,6 +5,7 @@
5
5
  * @input A wheel stream's deltas along one axis, with their event times
6
6
  * @output Exports WheelSegmenter and isBunched. WheelSegmenter splits the
7
7
  * stream into gestures and reads a trackpad's lift (the onset of momentum).
8
+ * It keeps a trackpad's late or merged glide wheels in their flick.
8
9
  * isBunched tells one stall's merge from a frame.
9
10
  * @position Read by GestureHost.ts's wheel input: the web reports no
10
11
  * trackpad contact or phase, so both are inferred.
@@ -25,6 +26,12 @@ export interface WheelSegment {
25
26
  readonly decaying: boolean;
26
27
  /** This event came so soon after the one before that it is a merge. */
27
28
  readonly bunched: boolean;
29
+ /**
30
+ * The signed travel of the late wheel before this one, with any wheel
31
+ * merged with it. It is handed over when that wheel joined the glide and
32
+ * this one grows into a new gesture; else 0.
33
+ */
34
+ readonly carried: number;
28
35
  }
29
36
 
30
37
  /** Momentum arrives at frame rate: a pause this long ends it. */
@@ -38,6 +45,25 @@ const BUNCHED_MS = 1.5;
38
45
  const LIFT_RUN = 4;
39
46
  /** And how much of its size the run has lost by then. */
40
47
  const LIFT_DECAY = 0.8;
48
+ /** How near a wheel must lie to a sum of the glide's next steps, px. */
49
+ const FIT_PX = 1;
50
+ /** Or as a share of that sum, when the share is larger. */
51
+ const FIT_SHARE = 0.25;
52
+ /** The most glide steps one wheel is read as carrying. */
53
+ const MAX_STEPS = 64;
54
+ /** How near a late or rising wheel must lie to the glide's sum, as a share. */
55
+ const LATE_FIT_SHARE = 0.15;
56
+ /**
57
+ * How far a wheel may grow past the last unbunched one and still be the
58
+ * glide, px.
59
+ */
60
+ const RISE_PX = 0.5;
61
+ /** A stream's frame interval until it shows its own, ms. */
62
+ const FRAME_MS = 16;
63
+ /** The longest frame interval a trackpad reports at: 60 Hz, ms. */
64
+ const SLOWEST_FRAME_MS = 1000 / 60;
65
+ /** The intervals that set a gesture's frame before its window applies. */
66
+ const FIRST_PACES = 3;
41
67
 
42
68
  /**
43
69
  * Whether a wheel `intervalMs` after the one before is one stall's merge, not
@@ -59,6 +85,16 @@ export function isBunched(intervalMs: number): boolean {
59
85
  * decay, or a pause of 50 ms starts a new gesture. A bunched wheel is never
60
86
  * a jump. The decay reads it by its last step. Momentum never pauses,
61
87
  * reverses or grows.
88
+ *
89
+ * A stalled page receives a trackpad's glide late, and the engine merges the
90
+ * wheels it held. In momentum, a trackpad wheel that the glide's decay
91
+ * explains stays in the flick. It may come after a pause, or rise after more
92
+ * than a frame. It is at or below the next step, or near the sum of the next
93
+ * steps its stall spans. After such a wheel, a trackpad wheel that grows
94
+ * starts a new gesture and takes the late wheel's travel. The decay also
95
+ * reads a trackpad merge in momentum, by its last step. It reads one in a
96
+ * shrinking run too, where it explains the merge better than steady steps
97
+ * do. Other wheels keep the rules above.
62
98
  */
63
99
  export class WheelSegmenter {
64
100
  gesture = 0;
@@ -69,44 +105,137 @@ export class WheelSegmenter {
69
105
  private count = 0;
70
106
  private run = 0;
71
107
  private runStart = 0;
108
+ /** The decay's step-to-step ratio, from the last two one-step wheels. */
109
+ private ratio = 1;
110
+ /** The gesture's last on-pace intervals, ms: their median is its frame. */
111
+ private paces: number[] = [];
112
+ /** The intervals in a row that came slower than the frame allows, ms. */
113
+ private slower: number[] = [];
114
+ /** When the gesture's last wheel within two frames of the one before came. */
115
+ private onPace = -Infinity;
116
+ /** The gesture's last wheel that was not bunched, px. */
117
+ private paced = 0;
118
+ /** A wheel joined the glide late: a later one that grows is the fingers'. */
119
+ private resumed = false;
120
+ /**
121
+ * The signed travel of the last wheel that joined the glide late, with any
122
+ * wheel merged with it.
123
+ */
124
+ private joined = 0;
72
125
 
73
- push(time: number, delta: number, idleMs: number): WheelSegment {
126
+ /**
127
+ * Reads one wheel. `continuous` is whether it carries a trackpad's
128
+ * signature (`scrollTypeOf`). Only those wheels can join a glide late.
129
+ */
130
+ push(
131
+ time: number,
132
+ delta: number,
133
+ idleMs: number,
134
+ continuous = false,
135
+ ): WheelSegment {
74
136
  const size = Math.abs(delta);
75
137
  const sign = Math.sign(delta);
76
138
  const gap = time - this.last;
77
139
  const bunched = this.count > 0 && isBunched(gap);
140
+ const frame = this.frameMs();
78
141
  let boundary: WheelBoundary | null = null;
142
+ let carriedSteps: number | null = null;
79
143
  if (this.count === 0) {
80
144
  boundary = this.gesture === 0 ? 'first' : 'idle';
81
145
  } else if (this.phase === 'finger' && gap >= idleMs) {
82
146
  boundary = 'idle';
83
147
  } else if (this.phase === 'momentum') {
148
+ // A late wheel carries the steps of its whole stall, which began at the
149
+ // last wheel that came on pace.
150
+ const frames = Math.round((time - this.onPace) / frame);
151
+ const late = gap >= MOMENTUM_GAP_MS;
152
+ const rises = !bunched && size >= 2 && size > this.previous * 1.3 + 0.5;
84
153
  if (sign !== 0 && this.sign !== 0 && sign !== this.sign) {
85
154
  boundary = 'reversal';
86
- } else if (gap >= MOMENTUM_GAP_MS) {
87
- boundary = 'gap';
88
- } else if (!bunched && size >= 2 && size > this.previous * 1.3 + 0.5) {
155
+ } else if (late || rises) {
156
+ // A wheel that rises on pace is the fingers'. One that rises after a
157
+ // skipped frame may carry the frames its stall held.
158
+ if (continuous && sign === this.sign && (late || gap >= 1.5 * frame)) {
159
+ carriedSteps = this.glideSteps(
160
+ size,
161
+ Math.max(1, frames),
162
+ LATE_FIT_SHARE,
163
+ );
164
+ }
165
+ if (carriedSteps == null) {
166
+ boundary = late ? 'gap' : 'jump';
167
+ }
168
+ } else if (
169
+ continuous &&
170
+ this.resumed &&
171
+ !bunched &&
172
+ size > FIT_PX &&
173
+ size > this.paced + RISE_PX
174
+ ) {
175
+ // A glide only falls, so after a late wheel one that grows is the
176
+ // fingers'. A whole-pixel glide repeats a step as it slows.
89
177
  boundary = 'jump';
90
178
  }
91
179
  }
180
+ if (carriedSteps == null && boundary == null && bunched && continuous) {
181
+ if (this.phase === 'momentum') {
182
+ carriedSteps = this.glideSteps(size, MAX_STEPS);
183
+ } else if (this.run > 0) {
184
+ // In a shrinking run, the decay reads a merge only where it explains
185
+ // the merge better than steady steps do.
186
+ const decay = this.glideSteps(size, MAX_STEPS);
187
+ if (
188
+ decay != null &&
189
+ decay > 1 &&
190
+ Math.abs(size - this.glideSum(decay)) < this.steadyOff(size)
191
+ ) {
192
+ carriedSteps = decay;
193
+ }
194
+ }
195
+ }
92
196
  // A bunched wheel carries the steps of the frames it merged. The decay
93
197
  // goes on from its last step, so the steps after it read as they are.
94
198
  const steps =
95
- boundary == null && bunched && this.previous > 0
199
+ carriedSteps ??
200
+ (boundary == null && bunched && this.previous > 0
96
201
  ? Math.max(1, Math.round(size / this.previous))
97
- : 1;
202
+ : 1);
203
+ // On the decay, a wheel of several steps ends at the decay's own step.
204
+ const onDecay = carriedSteps != null && carriedSteps > 1;
205
+ // A bunched wheel is read by its last step, as the decay goes on from it.
206
+ const step = onDecay ? this.previous * this.ratio ** steps : size / steps;
98
207
  if (boundary != null) {
99
208
  this.gesture += 1;
100
209
  this.phase = 'finger';
101
210
  this.count = 0;
102
211
  this.run = 0;
212
+ this.ratio = 1;
213
+ this.resumed = false;
214
+ this.paces = [];
215
+ this.slower = [];
216
+ }
217
+ // The late wheel was the fingers' when the next one grows: the new
218
+ // gesture takes its travel.
219
+ const carried = boundary === 'jump' ? this.joined : 0;
220
+ const joinedLate = boundary == null && carriedSteps != null && !bunched;
221
+ if (joinedLate) {
222
+ this.resumed = true;
223
+ }
224
+ // A wheel merged with the late one is the same dispatch: it adds to it.
225
+ this.joined = joinedLate
226
+ ? delta
227
+ : bunched && boundary == null && this.joined !== 0
228
+ ? this.joined + delta
229
+ : 0;
230
+ if (!bunched) {
231
+ this.paced = size;
103
232
  }
104
233
  let liftNow = false;
105
234
  let decaying = false;
106
235
  if (this.phase === 'finger' && this.count >= 3 && size > 0) {
107
- // A bunched wheel is read by its last step, as the decay goes on from it.
108
- const step = size / steps;
109
- decaying = step <= this.previous * 0.995 && step >= this.previous * 0.5;
236
+ decaying = onDecay
237
+ ? this.ratio <= 0.995
238
+ : step <= this.previous * 0.995 && step >= this.previous * 0.5;
110
239
  if (decaying) {
111
240
  if (this.run === 0) {
112
241
  this.runStart = this.previous;
@@ -120,8 +249,17 @@ export class WheelSegmenter {
120
249
  liftNow = true;
121
250
  }
122
251
  }
252
+ if (steps === 1 && this.count > 0 && this.previous > 0 && step > 0) {
253
+ this.ratio = Math.min(1, Math.max(0.5, step / this.previous));
254
+ }
255
+ if (!bunched && boundary == null && gap < MOMENTUM_GAP_MS) {
256
+ this.notePace(gap, frame);
257
+ }
258
+ if (boundary != null || (!bunched && gap < 2 * frame)) {
259
+ this.onPace = time;
260
+ }
123
261
  this.count += 1;
124
- this.previous = size / steps;
262
+ this.previous = step;
125
263
  if (sign !== 0) {
126
264
  this.sign = sign;
127
265
  }
@@ -133,9 +271,104 @@ export class WheelSegmenter {
133
271
  liftNow,
134
272
  decaying: decaying && !liftNow,
135
273
  bunched: boundary == null && bunched,
274
+ carried,
136
275
  };
137
276
  }
138
277
 
278
+ /**
279
+ * Keep an interval for the frame. The gesture's first FIRST_PACES set it.
280
+ * After them, only an interval within half a frame and one and a half
281
+ * frames counts: a stall's squeezed wheels come faster. FIRST_PACES slower
282
+ * intervals in a row set the frame again, so a squeezed start cannot hold
283
+ * it down.
284
+ */
285
+ private notePace(gap: number, frame: number): void {
286
+ const inWindow = gap >= 0.5 * frame && gap <= 1.5 * frame;
287
+ if (this.paces.length < FIRST_PACES || inWindow) {
288
+ this.paces = [...this.paces.slice(-7), gap];
289
+ this.slower = [];
290
+ return;
291
+ }
292
+ this.slower = gap > 1.5 * frame ? [...this.slower, gap] : [];
293
+ if (this.slower.length >= FIRST_PACES) {
294
+ this.paces = this.slower;
295
+ this.slower = [];
296
+ }
297
+ }
298
+
299
+ /**
300
+ * The gesture's frame interval: the median of its last on-pace intervals,
301
+ * or FRAME_MS before it shows one. A trackpad reports at 60 Hz or faster,
302
+ * so a longer median is a stall's.
303
+ */
304
+ private frameMs(): number {
305
+ if (this.paces.length === 0) {
306
+ return FRAME_MS;
307
+ }
308
+ const sorted = [...this.paces].sort((a, b) => a - b);
309
+ const middle = sorted.length >> 1;
310
+ const median =
311
+ sorted.length % 2 === 1
312
+ ? sorted[middle]
313
+ : (sorted[middle - 1] + sorted[middle]) / 2;
314
+ return Math.min(median, SLOWEST_FRAME_MS);
315
+ }
316
+
317
+ /** The sum of the decay's next `count` steps from `previous`. */
318
+ private glideSum(count: number): number {
319
+ let next = this.previous * this.ratio;
320
+ let sum = 0;
321
+ for (let i = 0; i < count; i++) {
322
+ sum += next;
323
+ next *= this.ratio;
324
+ }
325
+ return sum;
326
+ }
327
+
328
+ /**
329
+ * How far a merge of `size` lies from whole steps of the run's steady
330
+ * size, or of its last step, whichever lies nearer.
331
+ */
332
+ private steadyOff(size: number): number {
333
+ return Math.min(
334
+ ...[this.runStart, this.previous]
335
+ .filter(step => step > 0)
336
+ .map(step =>
337
+ Math.abs(size - Math.max(1, Math.round(size / step)) * step),
338
+ ),
339
+ );
340
+ }
341
+
342
+ /**
343
+ * How many of the decay's next steps a trackpad wheel of `size` carries,
344
+ * at most `most`. A wheel at or below the next step carries one. A larger
345
+ * one carries the fewest steps whose sum lies within FIT_PX or `share` of
346
+ * it. The decay goes on from `previous` at `ratio` a step. Null when
347
+ * no sum lies that near.
348
+ */
349
+ private glideSteps(
350
+ size: number,
351
+ most: number,
352
+ share = FIT_SHARE,
353
+ ): number | null {
354
+ if (this.previous <= 0 || size <= 0) {
355
+ return null;
356
+ }
357
+ let next = this.previous * this.ratio;
358
+ if (size <= next + FIT_PX) {
359
+ return 1;
360
+ }
361
+ let sum = next;
362
+ for (let count = 2; count <= Math.min(most, MAX_STEPS); count++) {
363
+ next *= this.ratio;
364
+ sum += next;
365
+ if (Math.abs(size - sum) <= Math.max(FIT_PX, sum * share)) {
366
+ return count;
367
+ }
368
+ }
369
+ return null;
370
+ }
371
+
139
372
  /** The gesture ended on its own (its timer): the next event starts one. */
140
373
  end(): void {
141
374
  this.count = 0;
@@ -0,0 +1,57 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file StackItemScrollRegion.tsx
7
+ * @input A scrollable `div` or `span` StackItem's props, ref and children
8
+ * @output StackItemScrollRegion (internal; not re-exported from
9
+ * hooks/index.ts), which renders that element and names it as a group
10
+ * while its content overflows
11
+ * @position Internal client island for StackItem, which itself stays a
12
+ * static render. Only a scrollable `div` or `span` item measures its
13
+ * overflow, on the client; another element keeps its own role.
14
+ *
15
+ * SYNC: When modified, update:
16
+ * - /packages/core/src/Stack/StackItem.tsx
17
+ * - /packages/core/src/serverSafeComponents.test.ts
18
+ */
19
+
20
+ import {createElement, type AriaRole, type ReactNode, type Ref} from 'react';
21
+ import {useMergedRefs} from './useMergedRefs';
22
+ import {useScrollRegionProps} from './useScrollRegionProps';
23
+
24
+ export interface StackItemScrollRegionProps {
25
+ as: 'div' | 'span';
26
+ ref?: Ref<HTMLElement>;
27
+ elementProps: {
28
+ role?: AriaRole;
29
+ 'aria-label'?: string;
30
+ [prop: string]: unknown;
31
+ };
32
+ children?: ReactNode;
33
+ }
34
+
35
+ export function StackItemScrollRegion({
36
+ as: element,
37
+ ref,
38
+ elementProps,
39
+ children,
40
+ }: StackItemScrollRegionProps) {
41
+ const region = useScrollRegionProps({
42
+ isScrollable: true,
43
+ role: elementProps.role,
44
+ label: elementProps['aria-label'],
45
+ });
46
+ const mergedRef = useMergedRefs(ref, region.ref);
47
+ return createElement(
48
+ element,
49
+ {
50
+ ...elementProps,
51
+ ref: mergedRef,
52
+ role: region.role,
53
+ 'aria-label': region['aria-label'],
54
+ },
55
+ children,
56
+ );
57
+ }