@astryxdesign/core 0.4.4 → 0.4.5-canary.013e728

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 (469) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -1
  3. package/dist/BottomSheet/BottomSheet.d.ts +11 -2
  4. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  5. package/dist/BottomSheet/BottomSheet.js +4 -0
  6. package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
  7. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheetPanel.js +65 -15
  9. package/dist/BottomSheet/index.d.ts +1 -1
  10. package/dist/BottomSheet/index.d.ts.map +1 -1
  11. package/dist/BottomSheet/snapOffsets.d.ts +57 -20
  12. package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
  13. package/dist/BottomSheet/snapOffsets.js +106 -30
  14. package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
  15. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  16. package/dist/BottomSheet/useSheetGestures.js +160 -64
  17. package/dist/Breadcrumbs/BreadcrumbItem.js +6 -6
  18. package/dist/Button/Button.js +5 -5
  19. package/dist/Calendar/Calendar.d.ts +17 -0
  20. package/dist/Calendar/Calendar.d.ts.map +1 -1
  21. package/dist/Calendar/Calendar.js +55 -15
  22. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
  23. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
  24. package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
  25. package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
  26. package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
  27. package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
  28. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  29. package/dist/Calendar/hooks/useCalendarDays.js +14 -10
  30. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  31. package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
  32. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
  33. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
  34. package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
  35. package/dist/Calendar/styles.js +3 -3
  36. package/dist/Center/Center.d.ts +23 -1
  37. package/dist/Center/Center.d.ts.map +1 -1
  38. package/dist/Center/Center.js +12 -6
  39. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  40. package/dist/Chat/ChatComposer.js +2 -2
  41. package/dist/Chat/ChatToolCalls.js +1 -1
  42. package/dist/Chat/useChatDictation.d.ts +1 -1
  43. package/dist/Chat/useChatDictation.d.ts.map +1 -1
  44. package/dist/Chat/useSpeechRecognition.d.ts +1 -1
  45. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  46. package/dist/Chat/useSpeechRecognition.js +4 -3
  47. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  48. package/dist/CheckboxInput/CheckboxInput.js +9 -0
  49. package/dist/Citation/Citation.js +3 -3
  50. package/dist/ClickableCard/ClickableCard.js +2 -2
  51. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  52. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  53. package/dist/ComplexSelector/ComplexSelector.js +8 -3
  54. package/dist/DateInput/DateInput.d.ts.map +1 -1
  55. package/dist/DateInput/DateInput.js +17 -9
  56. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  57. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  58. package/dist/DateRangeInput/DateRangeInput.js +47 -9
  59. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  60. package/dist/DateTimeInput/DateTimeInput.js +18 -10
  61. package/dist/Dialog/Dialog.d.ts.map +1 -1
  62. package/dist/Dialog/Dialog.js +3 -3
  63. package/dist/Field/FieldLabel.d.ts +2 -1
  64. package/dist/Field/FieldLabel.d.ts.map +1 -1
  65. package/dist/Field/FieldLabel.js +21 -3
  66. package/dist/Field/InputClearButton.d.ts +2 -1
  67. package/dist/Field/InputClearButton.d.ts.map +1 -1
  68. package/dist/Field/InputClearButton.js +12 -1
  69. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  70. package/dist/Field/inputStyles.stylex.js +4 -4
  71. package/dist/FileInput/FileInput.d.ts.map +1 -1
  72. package/dist/FileInput/FileInput.js +2 -2
  73. package/dist/FormLayout/FormLayout.d.ts +24 -2
  74. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  75. package/dist/FormLayout/FormLayout.js +7 -2
  76. package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
  77. package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
  78. package/dist/FormLayout/FormLayoutContext.js +19 -4
  79. package/dist/FormLayout/index.d.ts +1 -1
  80. package/dist/FormLayout/index.d.ts.map +1 -1
  81. package/dist/HoverCard/HoverCard.d.ts +13 -3
  82. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  83. package/dist/HoverCard/HoverCard.js +2 -0
  84. package/dist/HoverCard/index.d.ts +1 -1
  85. package/dist/HoverCard/index.d.ts.map +1 -1
  86. package/dist/HoverCard/useHoverCard.d.ts +17 -2
  87. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  88. package/dist/HoverCard/useHoverCard.js +78 -9
  89. package/dist/Item/Item.d.ts +9 -1
  90. package/dist/Item/Item.d.ts.map +1 -1
  91. package/dist/Item/Item.js +46 -8
  92. package/dist/Layer/index.d.ts +4 -2
  93. package/dist/Layer/index.d.ts.map +1 -1
  94. package/dist/Layer/index.js +2 -0
  95. package/dist/Layer/useLayer.d.ts.map +1 -1
  96. package/dist/Layer/useLayer.js +3 -2
  97. package/dist/Layer/useTouchTrigger.d.ts +113 -0
  98. package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
  99. package/dist/Layer/useTouchTrigger.js +241 -0
  100. package/dist/Layout/container.stylex.d.ts +4 -2
  101. package/dist/Layout/container.stylex.d.ts.map +1 -1
  102. package/dist/Layout/container.stylex.js +19 -11
  103. package/dist/Layout/index.d.ts +1 -0
  104. package/dist/Layout/index.d.ts.map +1 -1
  105. package/dist/Layout/index.js +4 -0
  106. package/dist/Layout/padding.stylex.d.ts +315 -12
  107. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  108. package/dist/Layout/padding.stylex.js +389 -12
  109. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  110. package/dist/Lightbox/Lightbox.js +2 -1
  111. package/dist/Link/Link.js +4 -4
  112. package/dist/Markdown/Markdown.d.ts +8 -0
  113. package/dist/Markdown/Markdown.d.ts.map +1 -1
  114. package/dist/Markdown/Markdown.js +31 -3
  115. package/dist/Markdown/parser.d.ts +14 -2
  116. package/dist/Markdown/parser.d.ts.map +1 -1
  117. package/dist/Markdown/parser.js +50 -2
  118. package/dist/MobileNav/MobileNav.d.ts +1 -0
  119. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  120. package/dist/MobileNav/MobileNav.js +24 -6
  121. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  122. package/dist/MultiSelector/MultiSelector.js +8 -3
  123. package/dist/NavItem/navItemStyles.stylex.d.ts +2 -2
  124. package/dist/NavItem/navItemStyles.stylex.js +2 -2
  125. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  126. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  127. package/dist/NumberInput/NumberInput.js +38 -5
  128. package/dist/Outline/Outline.js +2 -2
  129. package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
  130. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  131. package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
  132. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  133. package/dist/PowerSearch/PowerSearch.js +11 -12
  134. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  135. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  136. package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
  137. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  138. package/dist/PowerSearch/formatFilterValue.js +23 -8
  139. package/dist/RadioList/RadioList.d.ts.map +1 -1
  140. package/dist/RadioList/RadioList.js +12 -1
  141. package/dist/RadioList/RadioListItem.d.ts +2 -2
  142. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  143. package/dist/RadioList/RadioListItem.js +68 -38
  144. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  145. package/dist/Resizable/ResizeHandle.js +3 -3
  146. package/dist/Section/Section.d.ts +36 -1
  147. package/dist/Section/Section.d.ts.map +1 -1
  148. package/dist/Section/Section.js +12 -2
  149. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  150. package/dist/SegmentedControl/SegmentedControlItem.js +6 -1
  151. package/dist/SelectableCard/SelectableCard.js +1 -1
  152. package/dist/Selector/Selector.d.ts +26 -1
  153. package/dist/Selector/Selector.d.ts.map +1 -1
  154. package/dist/Selector/Selector.js +95 -17
  155. package/dist/Selector/SelectorOption.d.ts +14 -1
  156. package/dist/Selector/SelectorOption.d.ts.map +1 -1
  157. package/dist/Selector/SelectorOption.js +6 -0
  158. package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
  159. package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
  160. package/dist/Selector/SelectorRowLayoutContext.js +27 -0
  161. package/dist/Selector/types.d.ts +1 -0
  162. package/dist/Selector/types.d.ts.map +1 -1
  163. package/dist/SideNav/SideNavHeading.js +1 -1
  164. package/dist/SideNav/SideNavItem.js +1 -1
  165. package/dist/Slider/Slider.d.ts.map +1 -1
  166. package/dist/Slider/Slider.js +3 -3
  167. package/dist/Stack/Stack.d.ts +23 -1
  168. package/dist/Stack/Stack.d.ts.map +1 -1
  169. package/dist/Stack/Stack.js +12 -6
  170. package/dist/StatusDot/StatusDot.d.ts +43 -3
  171. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  172. package/dist/StatusDot/StatusDot.js +42 -5
  173. package/dist/Switch/Switch.d.ts.map +1 -1
  174. package/dist/Switch/Switch.js +9 -0
  175. package/dist/TabList/TabMenu.js +1 -1
  176. package/dist/Table/TableRow.js +4 -4
  177. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  178. package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
  179. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  180. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +1 -1
  181. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  182. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  183. package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
  184. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  185. package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
  186. package/dist/Table/plugins/tree/useTableTreeData.js +2 -2
  187. package/dist/TextArea/TextArea.d.ts.map +1 -1
  188. package/dist/TextArea/TextArea.js +6 -1
  189. package/dist/TextInput/TextInput.d.ts.map +1 -1
  190. package/dist/TextInput/TextInput.js +6 -1
  191. package/dist/Thumbnail/Thumbnail.js +1 -1
  192. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  193. package/dist/TimeInput/TimeInput.js +6 -1
  194. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  195. package/dist/Timestamp/Timestamp.js +6 -4
  196. package/dist/Timestamp/formatInstant.d.ts +3 -2
  197. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  198. package/dist/Timestamp/formatInstant.js +8 -8
  199. package/dist/Timestamp/tooltipEntries.d.ts +2 -1
  200. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  201. package/dist/Timestamp/tooltipEntries.js +5 -3
  202. package/dist/Token/Token.js +1 -1
  203. package/dist/Tooltip/Tooltip.d.ts +16 -3
  204. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  205. package/dist/Tooltip/Tooltip.js +2 -0
  206. package/dist/Tooltip/index.d.ts +1 -1
  207. package/dist/Tooltip/index.d.ts.map +1 -1
  208. package/dist/Tooltip/useTooltip.d.ts +21 -2
  209. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  210. package/dist/Tooltip/useTooltip.js +71 -13
  211. package/dist/TopNav/TopNavHeading.js +2 -2
  212. package/dist/TopNav/TopNavItem.js +2 -2
  213. package/dist/TopNav/TopNavMegaMenu.js +1 -1
  214. package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
  215. package/dist/TopNav/TopNavMenu.js +2 -2
  216. package/dist/TreeList/TreeListItem.js +1 -1
  217. package/dist/astryx.css +85 -60
  218. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
  219. package/dist/hooks/containerReveal.stylex.js +18 -18
  220. package/dist/hooks/scrollbarGutter.d.ts +28 -0
  221. package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
  222. package/dist/hooks/scrollbarGutter.js +103 -0
  223. package/dist/hooks/useResolvedRequired.d.ts +19 -0
  224. package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
  225. package/dist/hooks/useResolvedRequired.js +40 -0
  226. package/dist/hooks/useScrollLock.d.ts +4 -0
  227. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  228. package/dist/hooks/useScrollLock.js +13 -1
  229. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  230. package/dist/i18n/InternationalizationContext.js +2 -0
  231. package/dist/i18n/index.d.ts +6 -0
  232. package/dist/i18n/index.d.ts.map +1 -1
  233. package/dist/i18n/index.js +6 -0
  234. package/dist/i18n/useCollator.d.ts +12 -0
  235. package/dist/i18n/useCollator.d.ts.map +1 -0
  236. package/dist/i18n/useCollator.js +40 -0
  237. package/dist/i18n/useLocale.d.ts +3 -0
  238. package/dist/i18n/useLocale.d.ts.map +1 -0
  239. package/dist/i18n/useLocale.js +31 -0
  240. package/dist/theme/defineTheme.d.ts +5 -0
  241. package/dist/theme/defineTheme.d.ts.map +1 -1
  242. package/dist/theme/defineTheme.js +5 -0
  243. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  244. package/dist/theme/derivedVarRegistry.js +7 -0
  245. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  246. package/dist/theme/generateThemeRules.js +66 -5
  247. package/dist/utils/dateParser.d.ts +4 -3
  248. package/dist/utils/dateParser.d.ts.map +1 -1
  249. package/dist/utils/dateParser.js +8 -8
  250. package/dist/utils/plainDate.d.ts +9 -2
  251. package/dist/utils/plainDate.d.ts.map +1 -1
  252. package/dist/utils/plainDate.js +16 -4
  253. package/locales/af-ZA.json +958 -0
  254. package/locales/ar-SA.json +998 -0
  255. package/locales/ca-ES.json +974 -0
  256. package/locales/cs-CZ.json +990 -0
  257. package/locales/da-DK.json +966 -0
  258. package/locales/de-DE.json +966 -0
  259. package/locales/el-GR.json +990 -0
  260. package/locales/en.json +8 -0
  261. package/locales/es-ES.json +978 -0
  262. package/locales/fi-FI.json +990 -0
  263. package/locales/fr-FR.json +928 -0
  264. package/locales/he-IL.json +990 -0
  265. package/locales/hu-HU.json +990 -0
  266. package/locales/it-IT.json +978 -0
  267. package/locales/ja-JP.json +998 -0
  268. package/locales/ko-KR.json +990 -0
  269. package/locales/nl-NL.json +954 -0
  270. package/locales/no-NO.json +978 -0
  271. package/locales/pl-PL.json +982 -0
  272. package/locales/pseudo.json +6 -0
  273. package/locales/pt-BR.json +982 -0
  274. package/locales/pt-PT.json +982 -0
  275. package/locales/ro-RO.json +982 -0
  276. package/locales/ru-RU.json +990 -0
  277. package/locales/sr-SP.json +990 -0
  278. package/locales/sv-SE.json +986 -0
  279. package/locales/tr-TR.json +990 -0
  280. package/locales/uk-UA.json +990 -0
  281. package/locales/vi-VN.json +986 -0
  282. package/locales/zh-CN.json +998 -0
  283. package/locales/zh-TW.json +998 -0
  284. package/package.json +3 -3
  285. package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -1
  286. package/src/Banner/Banner.doc.mjs +2 -0
  287. package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
  288. package/src/BottomSheet/BottomSheet.test.tsx +177 -2
  289. package/src/BottomSheet/BottomSheet.tsx +16 -2
  290. package/src/BottomSheet/BottomSheetPanel.test.tsx +41 -0
  291. package/src/BottomSheet/BottomSheetPanel.tsx +95 -15
  292. package/src/BottomSheet/index.ts +5 -1
  293. package/src/BottomSheet/snapOffsets.test.ts +114 -47
  294. package/src/BottomSheet/snapOffsets.ts +119 -33
  295. package/src/BottomSheet/useSheetGestures.test.ts +113 -15
  296. package/src/BottomSheet/useSheetGestures.ts +196 -100
  297. package/src/Breadcrumbs/BreadcrumbItem.tsx +1 -1
  298. package/src/Button/Button.tsx +7 -7
  299. package/src/Calendar/Calendar.doc.mjs +16 -0
  300. package/src/Calendar/Calendar.test.tsx +137 -0
  301. package/src/Calendar/Calendar.tsx +80 -11
  302. package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
  303. package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
  304. package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
  305. package/src/Calendar/hooks/useCalendarDays.ts +13 -10
  306. package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
  307. package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
  308. package/src/Calendar/styles.ts +3 -3
  309. package/src/Center/Center.doc.mjs +48 -0
  310. package/src/Center/Center.test.tsx +158 -0
  311. package/src/Center/Center.tsx +50 -9
  312. package/src/Chat/ChatComposer.tsx +7 -4
  313. package/src/Chat/ChatToolCalls.tsx +1 -1
  314. package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
  315. package/src/Chat/useChatDictation.ts +1 -1
  316. package/src/Chat/useSpeechRecognition.ts +5 -3
  317. package/src/CheckboxInput/CheckboxInput.tsx +6 -0
  318. package/src/Citation/Citation.tsx +3 -3
  319. package/src/ClickableCard/ClickableCard.tsx +2 -2
  320. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  321. package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
  322. package/src/ComplexSelector/ComplexSelector.tsx +8 -5
  323. package/src/DateInput/DateInput.test.tsx +17 -1
  324. package/src/DateInput/DateInput.tsx +13 -9
  325. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  326. package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
  327. package/src/DateRangeInput/DateRangeInput.tsx +88 -8
  328. package/src/DateTimeInput/DateTimeInput.tsx +23 -8
  329. package/src/Dialog/Dialog.test.tsx +24 -0
  330. package/src/Dialog/Dialog.tsx +3 -0
  331. package/src/Field/Field.doc.mjs +3 -0
  332. package/src/Field/FieldLabel.tsx +20 -4
  333. package/src/Field/InputClearButton.test.tsx +134 -2
  334. package/src/Field/InputClearButton.tsx +42 -1
  335. package/src/Field/inputStyles.stylex.ts +16 -12
  336. package/src/FileInput/FileInput.tsx +5 -4
  337. package/src/FormLayout/FormLayout.doc.mjs +13 -0
  338. package/src/FormLayout/FormLayout.test.tsx +181 -4
  339. package/src/FormLayout/FormLayout.tsx +33 -2
  340. package/src/FormLayout/FormLayoutContext.ts +22 -7
  341. package/src/FormLayout/index.ts +1 -1
  342. package/src/HoverCard/HoverCard.doc.mjs +18 -0
  343. package/src/HoverCard/HoverCard.test.tsx +189 -0
  344. package/src/HoverCard/HoverCard.tsx +22 -2
  345. package/src/HoverCard/index.ts +1 -0
  346. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  347. package/src/HoverCard/useHoverCard.tsx +103 -7
  348. package/src/Item/Item.doc.mjs +1 -0
  349. package/src/Item/Item.test.tsx +50 -0
  350. package/src/Item/Item.tsx +41 -2
  351. package/src/Layer/index.ts +10 -0
  352. package/src/Layer/useLayer.tsx +13 -2
  353. package/src/Layer/useTouchTrigger.test.ts +70 -0
  354. package/src/Layer/useTouchTrigger.ts +366 -0
  355. package/src/Layout/Layout.doc.mjs +18 -0
  356. package/src/Layout/container.stylex.ts +11 -3
  357. package/src/Layout/index.ts +4 -0
  358. package/src/Layout/overlayPaddingReset.test.tsx +222 -0
  359. package/src/Layout/padding.stylex.ts +192 -12
  360. package/src/Lightbox/Lightbox.tsx +2 -1
  361. package/src/Link/Link.tsx +4 -4
  362. package/src/Markdown/Markdown.doc.mjs +3 -0
  363. package/src/Markdown/Markdown.test.tsx +78 -0
  364. package/src/Markdown/Markdown.tsx +41 -1
  365. package/src/Markdown/parser.ts +60 -2
  366. package/src/MobileNav/MobileNav.tsx +61 -5
  367. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
  368. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
  369. package/src/MultiSelector/MultiSelector.test.tsx +1 -1
  370. package/src/MultiSelector/MultiSelector.tsx +8 -5
  371. package/src/NavItem/navItemStyles.stylex.ts +2 -2
  372. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  373. package/src/NumberInput/NumberInput.doc.mjs +24 -0
  374. package/src/NumberInput/NumberInput.test.tsx +138 -0
  375. package/src/NumberInput/NumberInput.tsx +44 -6
  376. package/src/Outline/Outline.doc.mjs +2 -0
  377. package/src/Outline/Outline.tsx +1 -1
  378. package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
  379. package/src/PowerSearch/PowerSearch.tsx +17 -8
  380. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  381. package/src/PowerSearch/formatFilterValue.test.ts +22 -2
  382. package/src/PowerSearch/formatFilterValue.ts +31 -6
  383. package/src/RadioList/RadioList.doc.mjs +1 -1
  384. package/src/RadioList/RadioList.test.tsx +170 -2
  385. package/src/RadioList/RadioList.tsx +9 -1
  386. package/src/RadioList/RadioListItem.tsx +83 -51
  387. package/src/Resizable/ResizeHandle.test.tsx +22 -0
  388. package/src/Resizable/ResizeHandle.tsx +9 -3
  389. package/src/Section/Section.doc.mjs +55 -0
  390. package/src/Section/Section.test.tsx +201 -4
  391. package/src/Section/Section.tsx +69 -0
  392. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  393. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -2
  394. package/src/SelectableCard/SelectableCard.tsx +1 -1
  395. package/src/Selector/Selector.doc.mjs +16 -2
  396. package/src/Selector/Selector.test.tsx +525 -1
  397. package/src/Selector/Selector.tsx +166 -21
  398. package/src/Selector/SelectorOption.doc.mjs +7 -0
  399. package/src/Selector/SelectorOption.tsx +21 -0
  400. package/src/Selector/SelectorRowLayoutContext.ts +32 -0
  401. package/src/Selector/types.ts +4 -4
  402. package/src/SideNav/SideNavHeading.tsx +2 -2
  403. package/src/SideNav/SideNavItem.tsx +1 -1
  404. package/src/Slider/Slider.tsx +11 -1
  405. package/src/Stack/Stack.doc.mjs +72 -0
  406. package/src/Stack/Stack.test.tsx +156 -0
  407. package/src/Stack/Stack.tsx +50 -8
  408. package/src/StatusDot/StatusDot.doc.mjs +13 -0
  409. package/src/StatusDot/StatusDot.test.tsx +115 -8
  410. package/src/StatusDot/StatusDot.tsx +74 -9
  411. package/src/Switch/Switch.tsx +6 -0
  412. package/src/TabList/TabMenu.tsx +1 -1
  413. package/src/Table/TableRow.tsx +4 -4
  414. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +2 -1
  415. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +2 -1
  416. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +22 -4
  417. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
  418. package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
  419. package/src/Table/plugins/tree/useTableTreeData.tsx +2 -2
  420. package/src/TextArea/TextArea.doc.mjs +1 -1
  421. package/src/TextArea/TextArea.tsx +3 -1
  422. package/src/TextInput/TextInput.tsx +3 -1
  423. package/src/Thumbnail/Thumbnail.tsx +1 -1
  424. package/src/TimeInput/TimeInput.tsx +3 -1
  425. package/src/Timestamp/Timestamp.test.tsx +27 -7
  426. package/src/Timestamp/Timestamp.tsx +8 -4
  427. package/src/Timestamp/formatInstant.ts +9 -7
  428. package/src/Timestamp/tooltipEntries.test.ts +11 -6
  429. package/src/Timestamp/tooltipEntries.ts +6 -2
  430. package/src/Token/Token.tsx +1 -1
  431. package/src/Tooltip/Tooltip.doc.mjs +18 -0
  432. package/src/Tooltip/Tooltip.test.tsx +254 -1
  433. package/src/Tooltip/Tooltip.tsx +22 -2
  434. package/src/Tooltip/index.ts +1 -0
  435. package/src/Tooltip/useTooltip.doc.mjs +2 -0
  436. package/src/Tooltip/useTooltip.tsx +99 -21
  437. package/src/TopNav/TopNavHeading.tsx +1 -1
  438. package/src/TopNav/TopNavItem.tsx +2 -2
  439. package/src/TopNav/TopNavMegaMenu.tsx +1 -1
  440. package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
  441. package/src/TopNav/TopNavMenu.tsx +2 -2
  442. package/src/TreeList/TreeListItem.tsx +1 -1
  443. package/src/hooks/containerReveal.stylex.ts +54 -18
  444. package/src/hooks/scrollbarGutter.test.ts +167 -0
  445. package/src/hooks/scrollbarGutter.ts +121 -0
  446. package/src/hooks/useResolvedRequired.ts +42 -0
  447. package/src/hooks/useScrollLock.doc.mjs +4 -4
  448. package/src/hooks/useScrollLock.test.ts +73 -0
  449. package/src/hooks/useScrollLock.ts +14 -0
  450. package/src/i18n/InternationalizationContext.ts +2 -0
  451. package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
  452. package/src/i18n/__tests__/useCollator.test.tsx +115 -0
  453. package/src/i18n/__tests__/useLocale.test.tsx +52 -0
  454. package/src/i18n/index.ts +6 -0
  455. package/src/i18n/useCollator.doc.mjs +84 -0
  456. package/src/i18n/useCollator.ts +44 -0
  457. package/src/i18n/useLocale.doc.mjs +70 -0
  458. package/src/i18n/useLocale.ts +34 -0
  459. package/src/i18n/useTranslator.doc.mjs +1 -1
  460. package/src/theme/defineTheme.test.ts +9 -3
  461. package/src/theme/defineTheme.ts +5 -0
  462. package/src/theme/derivedVarRegistry.test.ts +19 -5
  463. package/src/theme/derivedVarRegistry.ts +4 -0
  464. package/src/theme/generateThemeRules.test.ts +118 -0
  465. package/src/theme/generateThemeRules.ts +83 -5
  466. package/src/utils/dateParser.test.ts +20 -0
  467. package/src/utils/dateParser.ts +14 -7
  468. package/src/utils/plainDate.test.ts +56 -0
  469. package/src/utils/plainDate.ts +17 -4
@@ -12,6 +12,7 @@ export const docs = {
12
12
  {name: 'delay', type: 'number', description: 'Delay before showing the hover card on hover, in milliseconds.', default: '300'},
13
13
  {name: 'hideDelay', type: 'number', description: 'Delay before hiding after mouse or focus leaves, in milliseconds.', default: '200'},
14
14
  {name: 'focusTrigger', type: "'auto' | 'always' | 'never'", description: 'When focus should open the hover card. auto only attaches focus listeners to naturally focusable elements.', default: "'auto'"},
15
+ {name: 'touchTrigger', type: "'auto' | 'tap' | 'none'", description: 'What a tap does where there is no hover. auto opens on tap unless the trigger performs an action of its own; tap always opens; none never opens on touch.', default: "'auto'"},
15
16
  {name: 'isEnabled', type: 'boolean', description: 'Whether hover and focus triggers are enabled.', default: 'true'},
16
17
  {name: 'label', type: 'string', description: 'Accessible name for the hover card popup. When provided, the popup is exposed as a named role="dialog"; when omitted, it falls back to role="group" (a group may validly be unnamed).'},
17
18
  {name: 'isOpen', type: 'boolean', description: 'Controlled open state. true force-shows, false force-hides, undefined lets hover/focus manage visibility.'},
@@ -52,6 +53,7 @@ export const docsDense = {
52
53
  delay: 'show delay in ms.',
53
54
  hideDelay: 'hide delay after mouse/focus leave in ms.',
54
55
  focusTrigger: 'when focus opens hover card; auto = naturally focusable elements only.',
56
+ touchTrigger: 'tap behavior with no hover; auto = tap unless trigger acts, tap = always, none = never.',
55
57
  isEnabled: 'whether hover/focus triggers are enabled.',
56
58
  label: 'accessible name for popup. with label: named role="dialog"; without: role="group".',
57
59
  isOpen: 'controlled open state: true force-show, false force-hide, undefined unmanaged.',
@@ -4,8 +4,8 @@
4
4
 
5
5
  /**
6
6
  * @file useHoverCard.ts
7
- * @input Uses useLayer, React hooks
8
- * @output Exports useHoverCard hook for hover/focus triggered layers
7
+ * @input Uses useLayer, useTouchTrigger, React hooks
8
+ * @output Exports useHoverCard hook for hover/focus/tap triggered layers
9
9
  * @position Layer hook; builds on useLayer for hover card behavior
10
10
  *
11
11
  * SYNC: When modified, update:
@@ -26,6 +26,10 @@ import {
26
26
  type LayerAlignment,
27
27
  type LayerPlacement,
28
28
  } from '../Layer/useLayer';
29
+ import {
30
+ useTouchTrigger,
31
+ type LayerTouchTrigger,
32
+ } from '../Layer/useTouchTrigger';
29
33
  import {layerAnimations} from '../Layer/layerAnimations.stylex';
30
34
  import {
31
35
  colorVars,
@@ -58,6 +62,11 @@ const styles = stylex.create({
58
62
  */
59
63
  export type HoverCardFocusTrigger = 'auto' | 'always' | 'never';
60
64
 
65
+ /**
66
+ * Touch trigger behavior for hover cards
67
+ */
68
+ export type HoverCardTouchTrigger = LayerTouchTrigger;
69
+
61
70
  export interface HoverCardOptions {
62
71
  /**
63
72
  * Position placement relative to anchor
@@ -93,6 +102,17 @@ export interface HoverCardOptions {
93
102
  */
94
103
  focusTrigger?: HoverCardFocusTrigger;
95
104
 
105
+ /**
106
+ * What a tap does on a touch pointer, where there is no hover:
107
+ * - `auto`: tap opens the card, unless the trigger performs an action of its
108
+ * own (a button, a link, a form control) — that tap belongs to the control
109
+ * - `tap`: tap always opens the card, even on a trigger that acts
110
+ * - `none`: touch never opens the card
111
+ *
112
+ * @default 'auto'
113
+ */
114
+ touchTrigger?: HoverCardTouchTrigger;
115
+
96
116
  /**
97
117
  * Whether the hover card is enabled.
98
118
  * When false, hover/focus triggers are disabled.
@@ -240,6 +260,7 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
240
260
  delay = 300,
241
261
  hideDelay = 200,
242
262
  focusTrigger = 'auto',
263
+ touchTrigger = 'auto',
243
264
  isEnabled = true,
244
265
  label,
245
266
  isOpen,
@@ -276,6 +297,30 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
276
297
  }
277
298
  }, []);
278
299
 
300
+ // Touch resolves immediately: the hover delays exist to filter out a pointer
301
+ // passing across the trigger, and a tap is never that.
302
+ const showNow = useCallback(() => {
303
+ clearTimeouts();
304
+ layer.show();
305
+ }, [clearTimeouts, layer]);
306
+
307
+ const hideNow = useCallback(() => {
308
+ clearTimeouts();
309
+ isHoveringContentRef.current = false;
310
+ layer.hide();
311
+ }, [clearTimeouts, layer]);
312
+
313
+ const touch = useTouchTrigger({
314
+ touchTrigger,
315
+ isEnabled,
316
+ isControlled: isOpen !== undefined,
317
+ isOpen: layer.isOpen,
318
+ layerId: layer.id,
319
+ triggerRef,
320
+ show: showNow,
321
+ hide: hideNow,
322
+ });
323
+
279
324
  // Schedule show with delay (suppressed when isOpen is false)
280
325
  const scheduleShow = useCallback(() => {
281
326
  if (!isEnabled || isOpen === false) {
@@ -303,17 +348,42 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
303
348
 
304
349
  // Event handlers
305
350
  const handleMouseEnter = useCallback(() => {
351
+ // A tap synthesizes mouseenter. On touch the tap path owns the decision,
352
+ // so hover must not also fire — without this a hover card opens on every
353
+ // tap of its trigger and has nothing to close it.
354
+ if (touch.isTouchPointerRef.current) {
355
+ return;
356
+ }
306
357
  scheduleShow();
307
- }, [scheduleShow]);
358
+ }, [touch, scheduleShow]);
308
359
 
309
360
  const handleMouseLeave = useCallback(() => {
361
+ // On touch the synthesized mouseleave arrives with the next tap elsewhere,
362
+ // which the outside-tap dismissal already handles.
363
+ if (touch.isTouchPointerRef.current) {
364
+ return;
365
+ }
310
366
  scheduleHide();
311
- }, [scheduleHide]);
367
+ }, [touch, scheduleHide]);
368
+
369
+ // Tap-to-open on touch; on a mouse this does nothing and hover still rules.
370
+ const handlePointerDown = useCallback(
371
+ (event: PointerEvent) => {
372
+ touch.handlePointerDown(event);
373
+ },
374
+ [touch],
375
+ );
312
376
 
313
377
  const handleFocusIn = useCallback(() => {
314
378
  if (!isEnabled) {
315
379
  return;
316
380
  }
381
+ // A tap focuses the trigger it activates. Opening on that focus would
382
+ // reinstate exactly the behavior the touch path just decided against —
383
+ // and on an action trigger it covers the thing the user tapped.
384
+ if (touch.isTouchInteraction()) {
385
+ return;
386
+ }
317
387
  // Skip showing if we're in the middle of an Escape dismiss
318
388
  if (isEscapeDismissingRef.current) {
319
389
  isEscapeDismissingRef.current = false;
@@ -321,7 +391,7 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
321
391
  }
322
392
  clearTimeouts();
323
393
  layer.show();
324
- }, [isEnabled, clearTimeouts, layer]);
394
+ }, [isEnabled, touch, clearTimeouts, layer]);
325
395
 
326
396
  const handleFocusOut = useCallback(
327
397
  (e: FocusEvent) => {
@@ -346,13 +416,15 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
346
416
  e.stopPropagation();
347
417
  // Hide immediately without refocusing (we're already on trigger)
348
418
  clearTimeouts();
419
+ touch.clearTapOpen();
349
420
  layer.hide();
350
421
  }
351
422
  },
352
- [clearTimeouts, layer],
423
+ [touch, clearTimeouts, layer],
353
424
  );
354
425
 
355
426
  // Interaction ref that handles event listeners only
427
+ const {handlePointerEnter} = touch;
356
428
  const interactionRef: RefCallback<HTMLElement> = useCallback(
357
429
  (el: HTMLElement | null) => {
358
430
  // Cleanup previous element
@@ -365,12 +437,24 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
365
437
  handleFocusOut as EventListener,
366
438
  );
367
439
  triggerRef.current.removeEventListener('keydown', handleKeyDown);
440
+ triggerRef.current.removeEventListener(
441
+ 'pointerenter',
442
+ handlePointerEnter,
443
+ );
444
+ triggerRef.current.removeEventListener(
445
+ 'pointerdown',
446
+ handlePointerDown,
447
+ );
368
448
  }
369
449
 
370
450
  if (el) {
371
- // Attach hover listeners
451
+ // Attach hover listeners. `pointerenter` runs before the synthesized
452
+ // `mouseenter` a tap produces, which is what lets the hover path know
453
+ // it is looking at a finger.
454
+ el.addEventListener('pointerenter', handlePointerEnter);
372
455
  el.addEventListener('mouseenter', handleMouseEnter);
373
456
  el.addEventListener('mouseleave', handleMouseLeave);
457
+ el.addEventListener('pointerdown', handlePointerDown);
374
458
 
375
459
  // Attach focus listeners based on focusTrigger option
376
460
  const shouldAttachFocus =
@@ -395,6 +479,8 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
395
479
  handleFocusIn,
396
480
  handleFocusOut,
397
481
  handleKeyDown,
482
+ handlePointerEnter,
483
+ handlePointerDown,
398
484
  ],
399
485
  );
400
486
 
@@ -475,10 +561,18 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
475
561
  <div
476
562
  {...stylex.props(styles.content)}
477
563
  onMouseEnter={() => {
564
+ // Touch synthesizes these over the card too; letting a tap inside
565
+ // register as "hovering content" would block every later hide.
566
+ if (touch.isTouchPointerRef.current) {
567
+ return;
568
+ }
478
569
  isHoveringContentRef.current = true;
479
570
  clearTimeouts();
480
571
  }}
481
572
  onMouseLeave={() => {
573
+ if (touch.isTouchPointerRef.current) {
574
+ return;
575
+ }
482
576
  isHoveringContentRef.current = false;
483
577
  scheduleHide();
484
578
  }}
@@ -490,6 +584,7 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
490
584
  isEscapeDismissingRef.current = true;
491
585
  // Hide immediately
492
586
  clearTimeouts();
587
+ touch.clearTapOpen();
493
588
  layer.hide();
494
589
  // Refocus the trigger
495
590
  triggerRef.current?.focus();
@@ -526,6 +621,7 @@ export function useHoverCard(options: HoverCardOptions = {}): HoverCardReturn {
526
621
  clearTimeouts,
527
622
  scheduleHide,
528
623
  popoverXstyle,
624
+ touch,
529
625
  ],
530
626
  );
531
627
 
@@ -40,6 +40,7 @@ export const docs = {
40
40
  {name: 'density', type: "'compact' | 'balanced' | 'spacious'", description: 'Spacing density. "compact" uses 4px block padding, "balanced" uses 8px, and "spacious" uses 12px block and inline padding.', default: "'balanced'"},
41
41
  {name: 'labelLines', type: 'number', description: 'Max lines before label truncates with ellipsis.'},
42
42
  {name: 'descriptionLines', type: 'number', description: 'Max lines before description truncates with ellipsis.'},
43
+ {name: 'layout', type: "'stacked' | 'inline'", description: 'How the label and description sit together. stacked puts the description on its own line below the label; inline keeps both on one line, description ellipsizing first, so the row fits a fixed-height host.', default: "'stacked'"},
43
44
  {name: 'onClick', type: '(event: MouseEvent) => void', description: 'Click handler. Makes the item clickable with button semantics.'},
44
45
  {name: 'interactiveRef', type: 'RefObject<HTMLElement | null>', description: 'Ref to a nested control (e.g. a checkbox in startContent) that owns the item\'s keyboard access and action. The row becomes an enlarged click/tap target that delegates surface clicks to it (useClickableContainer) and renders no invisible button/anchor, so the row adds no second tab stop (WCAG 4.1.2). Mutually exclusive with onClick/href; those are ignored when set.'},
45
46
  {name: 'href', type: 'string', description: 'Link URL. Makes the item a link via an invisible anchor element.'},
@@ -508,4 +508,54 @@ describe('Item', () => {
508
508
  expect(screen.getByText('Alice')).toBeInTheDocument();
509
509
  expect(screen.getByText(/commented/)).toBeInTheDocument();
510
510
  });
511
+ it('puts the label and description in one row when layout is inline', () => {
512
+ const stacked = render(
513
+ <Item label="Private" description="Only members can access" />,
514
+ );
515
+ const stackedRow = screen.getByText('Private').parentElement;
516
+ stacked.unmount();
517
+
518
+ render(
519
+ <Item
520
+ label="Private"
521
+ description="Only members can access"
522
+ layout="inline"
523
+ />,
524
+ );
525
+ const inlineRow = screen.getByText('Private').parentElement;
526
+
527
+ // Same container, different styling: the shared content box switches from
528
+ // a column to a row, so its class list must differ from the stacked one.
529
+ expect(inlineRow?.className).not.toBe(stackedRow?.className);
530
+ });
531
+
532
+ it('ellipsizes a ReactNode description when layout is inline', () => {
533
+ // A stacked ReactNode description is left alone (it may wrap); an inline
534
+ // one is one line by definition, so it truncates like a string does.
535
+ const stacked = render(
536
+ <Item
537
+ label="Private"
538
+ description={<span>Only members can access</span>}
539
+ />,
540
+ );
541
+ const stackedDescription = screen.getByText('Only members can access')
542
+ .parentElement?.className;
543
+ stacked.unmount();
544
+
545
+ render(
546
+ <Item
547
+ label="Private"
548
+ description={<span>Only members can access</span>}
549
+ layout="inline"
550
+ />,
551
+ );
552
+ expect(
553
+ screen.getByText('Only members can access').parentElement?.className,
554
+ ).not.toBe(stackedDescription);
555
+ });
556
+
557
+ it('ignores inline layout when there is no description', () => {
558
+ render(<Item label="Private" layout="inline" />);
559
+ expect(screen.getByText('Private')).toBeInTheDocument();
560
+ });
511
561
  });
package/src/Item/Item.tsx CHANGED
@@ -106,6 +106,15 @@ export interface ItemProps extends BaseProps<HTMLElement> {
106
106
  */
107
107
  descriptionLines?: number;
108
108
 
109
+ /**
110
+ * How the label and description sit together. `stacked` puts the description
111
+ * on its own line below the label; `inline` keeps both on one line, with the
112
+ * description ellipsizing first, so the row fits a fixed-height host.
113
+ *
114
+ * @default 'stacked'
115
+ */
116
+ layout?: 'stacked' | 'inline';
117
+
109
118
  /**
110
119
  * Click handler. Makes the item clickable with button semantics.
111
120
  */
@@ -213,7 +222,7 @@ const styles = stylex.create({
213
222
  transitionTimingFunction: easeVars['--ease-standard'],
214
223
  backgroundColor: {
215
224
  default: 'transparent',
216
- ':hover': {
225
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
217
226
  '@media (hover: hover)': colorVars['--color-overlay-hover'],
218
227
  },
219
228
  ':active': colorVars['--color-overlay-pressed'],
@@ -264,6 +273,25 @@ const styles = stylex.create({
264
273
  minWidth: 0,
265
274
  textAlign: 'start',
266
275
  },
276
+ // `layout="inline"`: label and description share one line, so the row fits a
277
+ // fixed-height host such as a Selector trigger inside an InputGroup.
278
+ inlineContent: {
279
+ flexDirection: 'row',
280
+ // Centered, not baseline-aligned: two different font sizes on a shared
281
+ // baseline make a line box taller than either line, which would push a
282
+ // fixed-height host (a Selector trigger) a pixel off its size token.
283
+ alignItems: 'center',
284
+ columnGap: spacingVars['--spacing-1'],
285
+ },
286
+ inlineLabel: {
287
+ flexShrink: 0,
288
+ },
289
+ // The description yields width first, so the label — the part that identifies
290
+ // the item — is the last thing to ellipsize.
291
+ inlineDescription: {
292
+ flexShrink: 1,
293
+ minWidth: 0,
294
+ },
267
295
  label: {
268
296
  // Falls back to the primary text token; a parent (e.g. a destructive menu
269
297
  // item) can recolor the label by setting --_item-label-color.
@@ -358,6 +386,7 @@ export function Item({
358
386
  density = 'balanced',
359
387
  labelLines,
360
388
  descriptionLines,
389
+ layout = 'stacked',
361
390
  onClick,
362
391
  interactiveRef,
363
392
  href,
@@ -420,12 +449,16 @@ export function Item({
420
449
  ? styles.labelSingleTruncate
421
450
  : null;
422
451
 
452
+ // Inline rows are one line by definition, so the description always
453
+ // ellipsizes there — a ReactNode description cannot wrap the row open.
454
+ const isInline = layout === 'inline' && description != null;
455
+
423
456
  const descriptionTruncateStyle =
424
457
  descriptionLines != null
425
458
  ? descriptionLines === 1
426
459
  ? styles.descriptionSingleTruncate
427
460
  : styles.descriptionMultiTruncate
428
- : isStringDescription
461
+ : isStringDescription || isInline
429
462
  ? styles.descriptionSingleTruncate
430
463
  : null;
431
464
 
@@ -434,6 +467,7 @@ export function Item({
434
467
  <span
435
468
  {...stylex.props(
436
469
  styles.label,
470
+ isInline && styles.inlineLabel,
437
471
  labelTruncateStyle,
438
472
  labelLines != null &&
439
473
  labelLines > 1 &&
@@ -445,6 +479,7 @@ export function Item({
445
479
  <span
446
480
  {...stylex.props(
447
481
  styles.description,
482
+ isInline && styles.inlineDescription,
448
483
  descriptionTruncateStyle,
449
484
  descriptionLines != null &&
450
485
  descriptionLines > 1 &&
@@ -481,6 +516,7 @@ export function Item({
481
516
  <span
482
517
  {...stylex.props(
483
518
  styles.content,
519
+ isInline && styles.inlineContent,
484
520
  isDisabled && styles.disabledContent,
485
521
  )}>
486
522
  {labelAndDescription}
@@ -494,6 +530,7 @@ export function Item({
494
530
  tabIndex={isDisabled ? -1 : undefined}
495
531
  {...stylex.props(
496
532
  styles.invisibleAnchor,
533
+ isInline && styles.inlineContent,
497
534
  isDisabled && styles.disabledContent,
498
535
  )}>
499
536
  {labelAndDescription}
@@ -505,6 +542,7 @@ export function Item({
505
542
  disabled={isDisabled}
506
543
  {...stylex.props(
507
544
  styles.invisibleButton,
545
+ isInline && styles.inlineContent,
508
546
  isDisabled && styles.disabledContent,
509
547
  )}>
510
548
  {labelAndDescription}
@@ -513,6 +551,7 @@ export function Item({
513
551
  <span
514
552
  {...stylex.props(
515
553
  styles.content,
554
+ isInline && styles.inlineContent,
516
555
  isDisabled && styles.disabledContent,
517
556
  )}>
518
557
  {labelAndDescription}
@@ -29,6 +29,14 @@ export type {
29
29
  FixedLayerReturn,
30
30
  } from './useLayer';
31
31
 
32
+ // Shared touch behavior for the hover layers
33
+ export {useTouchTrigger, isActionTrigger} from './useTouchTrigger';
34
+ export type {
35
+ LayerTouchTrigger,
36
+ UseTouchTriggerOptions,
37
+ UseTouchTriggerReturn,
38
+ } from './useTouchTrigger';
39
+
32
40
  // Layer provider
33
41
  export {LayerProvider} from './LayerProvider';
34
42
  export type {LayerProviderProps} from './LayerProvider';
@@ -50,6 +58,7 @@ export type {
50
58
  export {useHoverCard, HoverCard} from '../HoverCard';
51
59
  export type {
52
60
  HoverCardFocusTrigger,
61
+ HoverCardTouchTrigger,
53
62
  HoverCardOptions,
54
63
  HoverCardReturn,
55
64
  HoverCardProps,
@@ -59,6 +68,7 @@ export type {
59
68
  export {useTooltip, Tooltip} from '../Tooltip';
60
69
  export type {
61
70
  TooltipFocusTrigger,
71
+ TooltipTouchTrigger,
62
72
  TooltipOptions,
63
73
  TooltipReturn,
64
74
  TooltipProps,
@@ -29,6 +29,7 @@ import {createPortal} from 'react-dom';
29
29
  import {addAnchorName, removeAnchorName} from './anchorName';
30
30
  import {resolveLayerPortalTarget} from './layerHost';
31
31
  import {typeScaleVars, typographyVars} from '../theme/tokens.stylex';
32
+ import {overlayPaddingReset} from '../Layout/padding.stylex';
32
33
 
33
34
  const styles = stylex.create({
34
35
  // Base reset for all layers
@@ -771,7 +772,12 @@ export function useLayer(
771
772
  : styles.offsetInline(toCssLength(offset))
772
773
  : null;
773
774
 
774
- const stylexResult = stylex.props(styles.base, offsetStyle, xstyle);
775
+ const stylexResult = stylex.props(
776
+ styles.base,
777
+ overlayPaddingReset.reset,
778
+ offsetStyle,
779
+ xstyle,
780
+ );
775
781
  const combinedClassName = extraClassName
776
782
  ? `${extraClassName} ${stylexResult.className ?? ''}`
777
783
  : stylexResult.className;
@@ -835,7 +841,12 @@ export function useLayer(
835
841
  left: x,
836
842
  };
837
843
 
838
- const stylexResult = stylex.props(styles.base, styles.fixed, xstyle);
844
+ const stylexResult = stylex.props(
845
+ styles.base,
846
+ overlayPaddingReset.reset,
847
+ styles.fixed,
848
+ xstyle,
849
+ );
839
850
  const combinedClassName = extraClassName
840
851
  ? `${extraClassName} ${stylexResult.className ?? ''}`
841
852
  : stylexResult.className;
@@ -0,0 +1,70 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file useTouchTrigger.test.ts
5
+ * @input Uses vitest, isActionTrigger
6
+ * @output Unit tests for the action-trigger rule behind touchTrigger="auto"
7
+ * @position Testing; validates useTouchTrigger.ts implementation
8
+ *
9
+ * SYNC: When useTouchTrigger.ts changes, update tests to match new behavior
10
+ *
11
+ * The tap-versus-suppress decision rests entirely on this predicate, and it is
12
+ * the part a new element type silently falls through. The per-component tests
13
+ * (Tooltip.test.tsx, HoverCard.test.tsx) cover the gestures it feeds.
14
+ */
15
+
16
+ import {describe, it, expect} from 'vitest';
17
+ import {isActionTrigger} from './useTouchTrigger';
18
+
19
+ function element(html: string): HTMLElement {
20
+ const host = document.createElement('div');
21
+ host.innerHTML = html;
22
+ return host.firstElementChild as HTMLElement;
23
+ }
24
+
25
+ describe('isActionTrigger', () => {
26
+ it.each([
27
+ ['<button type="button">Save</button>'],
28
+ ['<input type="text" />'],
29
+ ['<select></select>'],
30
+ ['<textarea></textarea>'],
31
+ ['<summary>More</summary>'],
32
+ ['<label>Name</label>'],
33
+ ['<a href="/somewhere">Link</a>'],
34
+ ])('treats %s as an action', html => {
35
+ expect(isActionTrigger(element(html))).toBe(true);
36
+ });
37
+
38
+ it.each([
39
+ ['<span>Plain text</span>'],
40
+ ['<svg></svg>'],
41
+ ['<abbr title="what">WCAG</abbr>'],
42
+ // An anchor without href is a link that goes nowhere.
43
+ ['<a>Not a link</a>'],
44
+ ])('treats %s as inert', html => {
45
+ expect(isActionTrigger(element(html))).toBe(false);
46
+ });
47
+
48
+ it('reads an explicit role over the tag it sits on', () => {
49
+ expect(isActionTrigger(element('<span role="button">Go</span>'))).toBe(
50
+ true,
51
+ );
52
+ // Scenery: the role says this button is not the control it looks like.
53
+ expect(
54
+ isActionTrigger(element('<button role="presentation">x</button>')),
55
+ ).toBe(false);
56
+ });
57
+
58
+ it('does not treat mere focusability as an action', () => {
59
+ // The wrapper a text-only Tooltip renders: reachable by keyboard so the
60
+ // hint is not mouse-only, and it still does nothing when activated.
61
+ expect(isActionTrigger(element('<span tabindex="0">Term</span>'))).toBe(
62
+ false,
63
+ );
64
+ });
65
+
66
+ it('treats a contenteditable surface as an action', () => {
67
+ const editable = element('<div contenteditable="true"></div>');
68
+ expect(isActionTrigger(editable)).toBe(true);
69
+ });
70
+ });