@astryxdesign/core 0.4.4 → 0.4.5-canary.0472ec1

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 (522) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -1
  3. package/dist/Blockquote/Blockquote.d.ts +4 -3
  4. package/dist/Blockquote/Blockquote.d.ts.map +1 -1
  5. package/dist/Blockquote/Blockquote.js +9 -10
  6. package/dist/BottomSheet/BottomSheet.d.ts +11 -2
  7. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheet.js +4 -0
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
  10. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  11. package/dist/BottomSheet/BottomSheetPanel.js +77 -18
  12. package/dist/BottomSheet/index.d.ts +1 -1
  13. package/dist/BottomSheet/index.d.ts.map +1 -1
  14. package/dist/BottomSheet/snapOffsets.d.ts +57 -20
  15. package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
  16. package/dist/BottomSheet/snapOffsets.js +106 -30
  17. package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
  18. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  19. package/dist/BottomSheet/useSheetGestures.js +160 -64
  20. package/dist/Breadcrumbs/BreadcrumbItem.js +6 -6
  21. package/dist/Button/Button.js +5 -5
  22. package/dist/Calendar/Calendar.d.ts +17 -0
  23. package/dist/Calendar/Calendar.d.ts.map +1 -1
  24. package/dist/Calendar/Calendar.js +55 -15
  25. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
  26. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
  27. package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
  28. package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
  29. package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
  30. package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
  31. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  32. package/dist/Calendar/hooks/useCalendarDays.js +14 -10
  33. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  34. package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
  35. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
  36. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
  37. package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
  38. package/dist/Calendar/styles.js +3 -3
  39. package/dist/Center/Center.d.ts +23 -1
  40. package/dist/Center/Center.d.ts.map +1 -1
  41. package/dist/Center/Center.js +12 -6
  42. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  43. package/dist/Chat/ChatComposer.js +2 -2
  44. package/dist/Chat/ChatToolCalls.js +1 -1
  45. package/dist/Chat/useChatDictation.d.ts +1 -1
  46. package/dist/Chat/useChatDictation.d.ts.map +1 -1
  47. package/dist/Chat/useSpeechRecognition.d.ts +1 -1
  48. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  49. package/dist/Chat/useSpeechRecognition.js +4 -3
  50. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  51. package/dist/CheckboxInput/CheckboxInput.js +9 -0
  52. package/dist/Citation/Citation.js +3 -3
  53. package/dist/ClickableCard/ClickableCard.js +2 -2
  54. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  55. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  56. package/dist/ComplexSelector/ComplexSelector.js +8 -3
  57. package/dist/DateInput/DateInput.d.ts +31 -2
  58. package/dist/DateInput/DateInput.d.ts.map +1 -1
  59. package/dist/DateInput/DateInput.js +92 -19
  60. package/dist/DateInput/MonthScroller.d.ts +35 -0
  61. package/dist/DateInput/MonthScroller.d.ts.map +1 -0
  62. package/dist/DateInput/MonthScroller.js +573 -0
  63. package/dist/DateInput/MonthYearWheels.d.ts +24 -0
  64. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
  65. package/dist/DateInput/MonthYearWheels.js +114 -0
  66. package/dist/DateInput/TouchDateField.d.ts +10 -0
  67. package/dist/DateInput/TouchDateField.d.ts.map +1 -0
  68. package/dist/DateInput/TouchDateField.js +810 -0
  69. package/dist/DateInput/Wheel.d.ts +41 -0
  70. package/dist/DateInput/Wheel.d.ts.map +1 -0
  71. package/dist/DateInput/Wheel.js +315 -0
  72. package/dist/DateInput/monthGeometry.d.ts +65 -0
  73. package/dist/DateInput/monthGeometry.d.ts.map +1 -0
  74. package/dist/DateInput/monthGeometry.js +98 -0
  75. package/dist/DateInput/tokens.stylex.d.ts +63 -0
  76. package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
  77. package/dist/DateInput/tokens.stylex.js +74 -0
  78. package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
  79. package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
  80. package/dist/DateInput/useOwnScrollGesture.js +202 -0
  81. package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
  82. package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
  83. package/dist/DateInput/usePointerDragScroll.js +216 -0
  84. package/dist/DateInput/useScrollSettle.d.ts +26 -0
  85. package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
  86. package/dist/DateInput/useScrollSettle.js +149 -0
  87. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  88. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  89. package/dist/DateRangeInput/DateRangeInput.js +47 -9
  90. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  91. package/dist/DateTimeInput/DateTimeInput.js +18 -10
  92. package/dist/Dialog/Dialog.d.ts.map +1 -1
  93. package/dist/Dialog/Dialog.js +3 -3
  94. package/dist/Field/FieldLabel.d.ts +2 -1
  95. package/dist/Field/FieldLabel.d.ts.map +1 -1
  96. package/dist/Field/FieldLabel.js +21 -3
  97. package/dist/Field/InputClearButton.d.ts +2 -1
  98. package/dist/Field/InputClearButton.d.ts.map +1 -1
  99. package/dist/Field/InputClearButton.js +12 -1
  100. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  101. package/dist/Field/inputStyles.stylex.js +4 -4
  102. package/dist/FileInput/FileInput.d.ts.map +1 -1
  103. package/dist/FileInput/FileInput.js +2 -2
  104. package/dist/FormLayout/FormLayout.d.ts +24 -2
  105. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  106. package/dist/FormLayout/FormLayout.js +7 -2
  107. package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
  108. package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
  109. package/dist/FormLayout/FormLayoutContext.js +19 -4
  110. package/dist/FormLayout/index.d.ts +1 -1
  111. package/dist/FormLayout/index.d.ts.map +1 -1
  112. package/dist/HoverCard/HoverCard.d.ts +13 -3
  113. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  114. package/dist/HoverCard/HoverCard.js +2 -0
  115. package/dist/HoverCard/index.d.ts +1 -1
  116. package/dist/HoverCard/index.d.ts.map +1 -1
  117. package/dist/HoverCard/useHoverCard.d.ts +17 -2
  118. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  119. package/dist/HoverCard/useHoverCard.js +78 -9
  120. package/dist/Item/Item.d.ts +9 -1
  121. package/dist/Item/Item.d.ts.map +1 -1
  122. package/dist/Item/Item.js +46 -8
  123. package/dist/Layer/index.d.ts +4 -2
  124. package/dist/Layer/index.d.ts.map +1 -1
  125. package/dist/Layer/index.js +2 -0
  126. package/dist/Layer/useLayer.d.ts.map +1 -1
  127. package/dist/Layer/useLayer.js +3 -2
  128. package/dist/Layer/useTouchTrigger.d.ts +113 -0
  129. package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
  130. package/dist/Layer/useTouchTrigger.js +241 -0
  131. package/dist/Layout/container.stylex.d.ts +4 -2
  132. package/dist/Layout/container.stylex.d.ts.map +1 -1
  133. package/dist/Layout/container.stylex.js +19 -11
  134. package/dist/Layout/index.d.ts +1 -0
  135. package/dist/Layout/index.d.ts.map +1 -1
  136. package/dist/Layout/index.js +4 -0
  137. package/dist/Layout/padding.stylex.d.ts +315 -12
  138. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  139. package/dist/Layout/padding.stylex.js +389 -12
  140. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  141. package/dist/Lightbox/Lightbox.js +2 -1
  142. package/dist/Link/Link.js +4 -4
  143. package/dist/Markdown/Markdown.d.ts +8 -0
  144. package/dist/Markdown/Markdown.d.ts.map +1 -1
  145. package/dist/Markdown/Markdown.js +31 -3
  146. package/dist/Markdown/parser.d.ts +14 -2
  147. package/dist/Markdown/parser.d.ts.map +1 -1
  148. package/dist/Markdown/parser.js +50 -2
  149. package/dist/MobileNav/MobileNav.d.ts +1 -0
  150. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  151. package/dist/MobileNav/MobileNav.js +24 -6
  152. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  153. package/dist/MultiSelector/MultiSelector.js +8 -3
  154. package/dist/NavItem/navItemStyles.stylex.d.ts +2 -2
  155. package/dist/NavItem/navItemStyles.stylex.js +2 -2
  156. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  157. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  158. package/dist/NumberInput/NumberInput.js +38 -5
  159. package/dist/Outline/Outline.js +2 -2
  160. package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
  161. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  162. package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
  163. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  164. package/dist/PowerSearch/PowerSearch.js +11 -12
  165. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  166. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  167. package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
  168. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  169. package/dist/PowerSearch/formatFilterValue.js +23 -8
  170. package/dist/RadioList/RadioList.d.ts.map +1 -1
  171. package/dist/RadioList/RadioList.js +12 -1
  172. package/dist/RadioList/RadioListItem.d.ts +2 -2
  173. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  174. package/dist/RadioList/RadioListItem.js +68 -38
  175. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  176. package/dist/Resizable/ResizeHandle.js +3 -3
  177. package/dist/Section/Section.d.ts +36 -1
  178. package/dist/Section/Section.d.ts.map +1 -1
  179. package/dist/Section/Section.js +12 -2
  180. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  181. package/dist/SegmentedControl/SegmentedControlItem.js +6 -1
  182. package/dist/SelectableCard/SelectableCard.js +1 -1
  183. package/dist/Selector/Selector.d.ts +26 -1
  184. package/dist/Selector/Selector.d.ts.map +1 -1
  185. package/dist/Selector/Selector.js +95 -17
  186. package/dist/Selector/SelectorOption.d.ts +14 -1
  187. package/dist/Selector/SelectorOption.d.ts.map +1 -1
  188. package/dist/Selector/SelectorOption.js +6 -0
  189. package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
  190. package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
  191. package/dist/Selector/SelectorRowLayoutContext.js +27 -0
  192. package/dist/Selector/types.d.ts +1 -0
  193. package/dist/Selector/types.d.ts.map +1 -1
  194. package/dist/SideNav/SideNavHeading.js +1 -1
  195. package/dist/SideNav/SideNavItem.js +1 -1
  196. package/dist/Slider/Slider.d.ts.map +1 -1
  197. package/dist/Slider/Slider.js +3 -3
  198. package/dist/Stack/Stack.d.ts +23 -1
  199. package/dist/Stack/Stack.d.ts.map +1 -1
  200. package/dist/Stack/Stack.js +12 -6
  201. package/dist/StatusDot/StatusDot.d.ts +43 -3
  202. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  203. package/dist/StatusDot/StatusDot.js +42 -5
  204. package/dist/Switch/Switch.d.ts.map +1 -1
  205. package/dist/Switch/Switch.js +9 -0
  206. package/dist/TabList/TabMenu.js +1 -1
  207. package/dist/Table/TableRow.js +4 -4
  208. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  209. package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
  210. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  211. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +1 -1
  212. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  213. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  214. package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
  215. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  216. package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
  217. package/dist/Table/plugins/tree/useTableTreeData.js +2 -2
  218. package/dist/TextArea/TextArea.d.ts.map +1 -1
  219. package/dist/TextArea/TextArea.js +6 -1
  220. package/dist/TextInput/TextInput.d.ts.map +1 -1
  221. package/dist/TextInput/TextInput.js +6 -1
  222. package/dist/Thumbnail/Thumbnail.js +1 -1
  223. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  224. package/dist/TimeInput/TimeInput.js +6 -1
  225. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  226. package/dist/Timestamp/Timestamp.js +6 -4
  227. package/dist/Timestamp/formatInstant.d.ts +3 -2
  228. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  229. package/dist/Timestamp/formatInstant.js +8 -8
  230. package/dist/Timestamp/tooltipEntries.d.ts +2 -1
  231. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  232. package/dist/Timestamp/tooltipEntries.js +5 -3
  233. package/dist/Token/Token.js +1 -1
  234. package/dist/Tooltip/Tooltip.d.ts +16 -3
  235. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  236. package/dist/Tooltip/Tooltip.js +2 -0
  237. package/dist/Tooltip/index.d.ts +1 -1
  238. package/dist/Tooltip/index.d.ts.map +1 -1
  239. package/dist/Tooltip/useTooltip.d.ts +21 -2
  240. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  241. package/dist/Tooltip/useTooltip.js +71 -13
  242. package/dist/TopNav/TopNavHeading.js +2 -2
  243. package/dist/TopNav/TopNavItem.js +2 -2
  244. package/dist/TopNav/TopNavMegaMenu.js +1 -1
  245. package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
  246. package/dist/TopNav/TopNavMenu.js +2 -2
  247. package/dist/TreeList/TreeListItem.js +1 -1
  248. package/dist/astryx.css +123 -60
  249. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
  250. package/dist/hooks/containerReveal.stylex.js +18 -18
  251. package/dist/hooks/scrollbarGutter.d.ts +28 -0
  252. package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
  253. package/dist/hooks/scrollbarGutter.js +103 -0
  254. package/dist/hooks/useResolvedRequired.d.ts +19 -0
  255. package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
  256. package/dist/hooks/useResolvedRequired.js +40 -0
  257. package/dist/hooks/useScrollLock.d.ts +4 -0
  258. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  259. package/dist/hooks/useScrollLock.js +13 -1
  260. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  261. package/dist/i18n/InternationalizationContext.js +2 -0
  262. package/dist/i18n/index.d.ts +6 -0
  263. package/dist/i18n/index.d.ts.map +1 -1
  264. package/dist/i18n/index.js +6 -0
  265. package/dist/i18n/useCollator.d.ts +12 -0
  266. package/dist/i18n/useCollator.d.ts.map +1 -0
  267. package/dist/i18n/useCollator.js +40 -0
  268. package/dist/i18n/useLocale.d.ts +3 -0
  269. package/dist/i18n/useLocale.d.ts.map +1 -0
  270. package/dist/i18n/useLocale.js +31 -0
  271. package/dist/theme/defineTheme.d.ts +5 -0
  272. package/dist/theme/defineTheme.d.ts.map +1 -1
  273. package/dist/theme/defineTheme.js +5 -0
  274. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  275. package/dist/theme/derivedVarRegistry.js +7 -0
  276. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  277. package/dist/theme/generateThemeRules.js +66 -5
  278. package/dist/theme/syntax/index.d.ts +6 -0
  279. package/dist/theme/syntax/index.d.ts.map +1 -1
  280. package/dist/theme/syntax/index.js +7 -2
  281. package/dist/utils/dateParser.d.ts +4 -3
  282. package/dist/utils/dateParser.d.ts.map +1 -1
  283. package/dist/utils/dateParser.js +8 -8
  284. package/dist/utils/index.d.ts +1 -1
  285. package/dist/utils/index.d.ts.map +1 -1
  286. package/dist/utils/index.js +1 -1
  287. package/dist/utils/plainDate.d.ts +11 -2
  288. package/dist/utils/plainDate.d.ts.map +1 -1
  289. package/dist/utils/plainDate.js +32 -4
  290. package/locales/af-ZA.json +958 -0
  291. package/locales/ar-SA.json +998 -0
  292. package/locales/ca-ES.json +974 -0
  293. package/locales/cs-CZ.json +990 -0
  294. package/locales/da-DK.json +966 -0
  295. package/locales/de-DE.json +966 -0
  296. package/locales/el-GR.json +990 -0
  297. package/locales/en.json +32 -0
  298. package/locales/es-ES.json +978 -0
  299. package/locales/fi-FI.json +990 -0
  300. package/locales/fr-FR.json +928 -0
  301. package/locales/he-IL.json +990 -0
  302. package/locales/hu-HU.json +990 -0
  303. package/locales/it-IT.json +978 -0
  304. package/locales/ja-JP.json +998 -0
  305. package/locales/ko-KR.json +990 -0
  306. package/locales/nl-NL.json +954 -0
  307. package/locales/no-NO.json +978 -0
  308. package/locales/pl-PL.json +982 -0
  309. package/locales/pseudo.json +24 -0
  310. package/locales/pt-BR.json +982 -0
  311. package/locales/pt-PT.json +982 -0
  312. package/locales/ro-RO.json +982 -0
  313. package/locales/ru-RU.json +990 -0
  314. package/locales/sr-SP.json +990 -0
  315. package/locales/sv-SE.json +986 -0
  316. package/locales/tr-TR.json +990 -0
  317. package/locales/uk-UA.json +990 -0
  318. package/locales/vi-VN.json +986 -0
  319. package/locales/zh-CN.json +998 -0
  320. package/locales/zh-TW.json +998 -0
  321. package/package.json +3 -3
  322. package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -1
  323. package/src/Banner/Banner.doc.mjs +2 -0
  324. package/src/Blockquote/Blockquote.doc.mjs +30 -7
  325. package/src/Blockquote/Blockquote.test.tsx +34 -3
  326. package/src/Blockquote/Blockquote.tsx +11 -9
  327. package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
  328. package/src/BottomSheet/BottomSheet.test.tsx +177 -2
  329. package/src/BottomSheet/BottomSheet.tsx +16 -2
  330. package/src/BottomSheet/BottomSheetPanel.test.tsx +91 -0
  331. package/src/BottomSheet/BottomSheetPanel.tsx +121 -15
  332. package/src/BottomSheet/index.ts +5 -1
  333. package/src/BottomSheet/snapOffsets.test.ts +114 -47
  334. package/src/BottomSheet/snapOffsets.ts +119 -33
  335. package/src/BottomSheet/useSheetGestures.test.ts +113 -15
  336. package/src/BottomSheet/useSheetGestures.ts +196 -100
  337. package/src/Breadcrumbs/BreadcrumbItem.tsx +1 -1
  338. package/src/Button/Button.tsx +7 -7
  339. package/src/Calendar/Calendar.doc.mjs +16 -0
  340. package/src/Calendar/Calendar.test.tsx +137 -0
  341. package/src/Calendar/Calendar.tsx +80 -11
  342. package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
  343. package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
  344. package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
  345. package/src/Calendar/hooks/useCalendarDays.ts +13 -10
  346. package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
  347. package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
  348. package/src/Calendar/styles.ts +3 -3
  349. package/src/Center/Center.doc.mjs +48 -0
  350. package/src/Center/Center.test.tsx +158 -0
  351. package/src/Center/Center.tsx +50 -9
  352. package/src/Chat/ChatComposer.tsx +7 -4
  353. package/src/Chat/ChatToolCalls.tsx +1 -1
  354. package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
  355. package/src/Chat/useChatDictation.ts +1 -1
  356. package/src/Chat/useSpeechRecognition.ts +5 -3
  357. package/src/CheckboxInput/CheckboxInput.tsx +6 -0
  358. package/src/Citation/Citation.tsx +3 -3
  359. package/src/ClickableCard/ClickableCard.tsx +2 -2
  360. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  361. package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
  362. package/src/ComplexSelector/ComplexSelector.tsx +8 -5
  363. package/src/DateInput/DateInput.test.tsx +17 -1
  364. package/src/DateInput/DateInput.tsx +90 -19
  365. package/src/DateInput/DateInputTouch.test.tsx +2393 -0
  366. package/src/DateInput/MonthScroller.tsx +784 -0
  367. package/src/DateInput/MonthYearWheels.tsx +147 -0
  368. package/src/DateInput/TouchDateField.tsx +1214 -0
  369. package/src/DateInput/Wheel.tsx +470 -0
  370. package/src/DateInput/monthGeometry.ts +118 -0
  371. package/src/DateInput/tokens.stylex.ts +99 -0
  372. package/src/DateInput/useOwnScrollGesture.ts +227 -0
  373. package/src/DateInput/usePointerDragScroll.ts +220 -0
  374. package/src/DateInput/useScrollSettle.ts +164 -0
  375. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  376. package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
  377. package/src/DateRangeInput/DateRangeInput.tsx +88 -8
  378. package/src/DateTimeInput/DateTimeInput.tsx +23 -8
  379. package/src/Dialog/Dialog.test.tsx +24 -0
  380. package/src/Dialog/Dialog.tsx +3 -0
  381. package/src/Field/Field.doc.mjs +3 -0
  382. package/src/Field/FieldLabel.tsx +20 -4
  383. package/src/Field/InputClearButton.test.tsx +134 -2
  384. package/src/Field/InputClearButton.tsx +42 -1
  385. package/src/Field/inputStyles.stylex.ts +16 -12
  386. package/src/FileInput/FileInput.tsx +5 -4
  387. package/src/FormLayout/FormLayout.doc.mjs +13 -0
  388. package/src/FormLayout/FormLayout.test.tsx +181 -4
  389. package/src/FormLayout/FormLayout.tsx +33 -2
  390. package/src/FormLayout/FormLayoutContext.ts +22 -7
  391. package/src/FormLayout/index.ts +1 -1
  392. package/src/HoverCard/HoverCard.doc.mjs +18 -0
  393. package/src/HoverCard/HoverCard.test.tsx +189 -0
  394. package/src/HoverCard/HoverCard.tsx +22 -2
  395. package/src/HoverCard/index.ts +1 -0
  396. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  397. package/src/HoverCard/useHoverCard.tsx +103 -7
  398. package/src/Item/Item.doc.mjs +1 -0
  399. package/src/Item/Item.test.tsx +50 -0
  400. package/src/Item/Item.tsx +41 -2
  401. package/src/Layer/index.ts +10 -0
  402. package/src/Layer/useLayer.tsx +13 -2
  403. package/src/Layer/useTouchTrigger.test.ts +70 -0
  404. package/src/Layer/useTouchTrigger.ts +366 -0
  405. package/src/Layout/Layout.doc.mjs +18 -0
  406. package/src/Layout/container.stylex.ts +11 -3
  407. package/src/Layout/index.ts +4 -0
  408. package/src/Layout/overlayPaddingReset.test.tsx +222 -0
  409. package/src/Layout/padding.stylex.ts +192 -12
  410. package/src/Lightbox/Lightbox.tsx +2 -1
  411. package/src/Link/Link.tsx +4 -4
  412. package/src/Markdown/Markdown.doc.mjs +3 -0
  413. package/src/Markdown/Markdown.test.tsx +78 -0
  414. package/src/Markdown/Markdown.tsx +41 -1
  415. package/src/Markdown/parser.ts +60 -2
  416. package/src/MobileNav/MobileNav.tsx +61 -5
  417. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
  418. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
  419. package/src/MultiSelector/MultiSelector.test.tsx +1 -1
  420. package/src/MultiSelector/MultiSelector.tsx +8 -5
  421. package/src/NavItem/navItemStyles.stylex.ts +2 -2
  422. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  423. package/src/NumberInput/NumberInput.doc.mjs +24 -0
  424. package/src/NumberInput/NumberInput.test.tsx +138 -0
  425. package/src/NumberInput/NumberInput.tsx +44 -6
  426. package/src/Outline/Outline.doc.mjs +2 -0
  427. package/src/Outline/Outline.tsx +1 -1
  428. package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
  429. package/src/PowerSearch/PowerSearch.tsx +17 -8
  430. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  431. package/src/PowerSearch/formatFilterValue.test.ts +22 -2
  432. package/src/PowerSearch/formatFilterValue.ts +31 -6
  433. package/src/RadioList/RadioList.doc.mjs +1 -1
  434. package/src/RadioList/RadioList.test.tsx +170 -2
  435. package/src/RadioList/RadioList.tsx +9 -1
  436. package/src/RadioList/RadioListItem.tsx +83 -51
  437. package/src/Resizable/ResizeHandle.test.tsx +22 -0
  438. package/src/Resizable/ResizeHandle.tsx +9 -3
  439. package/src/Section/Section.doc.mjs +55 -0
  440. package/src/Section/Section.test.tsx +201 -4
  441. package/src/Section/Section.tsx +69 -0
  442. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  443. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -2
  444. package/src/SelectableCard/SelectableCard.tsx +1 -1
  445. package/src/Selector/Selector.doc.mjs +16 -2
  446. package/src/Selector/Selector.test.tsx +525 -1
  447. package/src/Selector/Selector.tsx +166 -21
  448. package/src/Selector/SelectorOption.doc.mjs +7 -0
  449. package/src/Selector/SelectorOption.tsx +21 -0
  450. package/src/Selector/SelectorRowLayoutContext.ts +32 -0
  451. package/src/Selector/types.ts +4 -4
  452. package/src/SideNav/SideNavHeading.tsx +2 -2
  453. package/src/SideNav/SideNavItem.tsx +1 -1
  454. package/src/Slider/Slider.tsx +11 -1
  455. package/src/Stack/Stack.doc.mjs +72 -0
  456. package/src/Stack/Stack.test.tsx +156 -0
  457. package/src/Stack/Stack.tsx +50 -8
  458. package/src/StatusDot/StatusDot.doc.mjs +13 -0
  459. package/src/StatusDot/StatusDot.test.tsx +115 -8
  460. package/src/StatusDot/StatusDot.tsx +74 -9
  461. package/src/Switch/Switch.tsx +6 -0
  462. package/src/TabList/TabMenu.tsx +1 -1
  463. package/src/Table/TableRow.tsx +4 -4
  464. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +2 -1
  465. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +2 -1
  466. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +22 -4
  467. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
  468. package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
  469. package/src/Table/plugins/tree/useTableTreeData.tsx +2 -2
  470. package/src/TextArea/TextArea.doc.mjs +1 -1
  471. package/src/TextArea/TextArea.tsx +3 -1
  472. package/src/TextInput/TextInput.tsx +3 -1
  473. package/src/Thumbnail/Thumbnail.tsx +1 -1
  474. package/src/TimeInput/TimeInput.tsx +3 -1
  475. package/src/Timestamp/Timestamp.test.tsx +27 -7
  476. package/src/Timestamp/Timestamp.tsx +8 -4
  477. package/src/Timestamp/formatInstant.ts +9 -7
  478. package/src/Timestamp/tooltipEntries.test.ts +11 -6
  479. package/src/Timestamp/tooltipEntries.ts +6 -2
  480. package/src/Token/Token.tsx +1 -1
  481. package/src/Tooltip/Tooltip.doc.mjs +18 -0
  482. package/src/Tooltip/Tooltip.test.tsx +254 -1
  483. package/src/Tooltip/Tooltip.tsx +22 -2
  484. package/src/Tooltip/index.ts +1 -0
  485. package/src/Tooltip/useTooltip.doc.mjs +2 -0
  486. package/src/Tooltip/useTooltip.tsx +99 -21
  487. package/src/TopNav/TopNavHeading.tsx +1 -1
  488. package/src/TopNav/TopNavItem.tsx +2 -2
  489. package/src/TopNav/TopNavMegaMenu.tsx +1 -1
  490. package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
  491. package/src/TopNav/TopNavMenu.tsx +2 -2
  492. package/src/TreeList/TreeListItem.tsx +1 -1
  493. package/src/hooks/containerReveal.stylex.ts +54 -18
  494. package/src/hooks/scrollbarGutter.test.ts +167 -0
  495. package/src/hooks/scrollbarGutter.ts +121 -0
  496. package/src/hooks/useResolvedRequired.ts +42 -0
  497. package/src/hooks/useScrollLock.doc.mjs +4 -4
  498. package/src/hooks/useScrollLock.test.ts +73 -0
  499. package/src/hooks/useScrollLock.ts +14 -0
  500. package/src/i18n/InternationalizationContext.ts +2 -0
  501. package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
  502. package/src/i18n/__tests__/useCollator.test.tsx +115 -0
  503. package/src/i18n/__tests__/useLocale.test.tsx +52 -0
  504. package/src/i18n/index.ts +6 -0
  505. package/src/i18n/useCollator.doc.mjs +84 -0
  506. package/src/i18n/useCollator.ts +44 -0
  507. package/src/i18n/useLocale.doc.mjs +70 -0
  508. package/src/i18n/useLocale.ts +34 -0
  509. package/src/i18n/useTranslator.doc.mjs +1 -1
  510. package/src/theme/defineTheme.test.ts +9 -3
  511. package/src/theme/defineTheme.ts +5 -0
  512. package/src/theme/derivedVarRegistry.test.ts +19 -5
  513. package/src/theme/derivedVarRegistry.ts +4 -0
  514. package/src/theme/generateThemeRules.test.ts +118 -0
  515. package/src/theme/generateThemeRules.ts +83 -5
  516. package/src/theme/syntax/index.ts +6 -2
  517. package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
  518. package/src/utils/dateParser.test.ts +20 -0
  519. package/src/utils/dateParser.ts +14 -7
  520. package/src/utils/index.ts +2 -0
  521. package/src/utils/plainDate.test.ts +56 -0
  522. package/src/utils/plainDate.ts +33 -4
@@ -0,0 +1,222 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file overlayPaddingReset.test.tsx
5
+ * @input Uses vitest, @testing-library/react, overlay components from core
6
+ * @output Tests that overlay roots stop the container padding system at their
7
+ * boundary, and that the public theme token still crosses it
8
+ * @position Layout tests; validates overlayPaddingReset in padding.stylex.ts
9
+ *
10
+ * The container padding system talks to descendants through INHERITED custom
11
+ * properties, but an overlay leaves its parent's visual box while staying a DOM
12
+ * descendant of it. Every overlay root therefore has to stop those values (see
13
+ * #5208: a Section in a 640px sheet rendered 672px wide).
14
+ *
15
+ * jsdom does no layout, so these assert on the custom properties themselves —
16
+ * the definitions the layout is computed from. The widths they stand in for are
17
+ * verified in a browser; see the PR description.
18
+ *
19
+ * SYNC: When an overlay is added, add it to OVERLAYS below.
20
+ */
21
+
22
+ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
23
+ import {readFileSync} from 'node:fs';
24
+ import {join} from 'node:path';
25
+ import {render, screen} from '@testing-library/react';
26
+ import type {ReactNode} from 'react';
27
+ import {Dialog} from '../Dialog';
28
+ import {BottomSheet} from '../BottomSheet';
29
+ import {MobileNav} from '../MobileNav';
30
+ import {Lightbox} from '../Lightbox';
31
+ import {Popover} from '../Popover';
32
+ import {Section} from '../Section';
33
+
34
+ // jsdom implements neither the <dialog> methods nor matchMedia.
35
+ beforeEach(() => {
36
+ HTMLDialogElement.prototype.showModal = vi.fn(function (
37
+ this: HTMLDialogElement,
38
+ ) {
39
+ this.setAttribute('open', '');
40
+ });
41
+ HTMLDialogElement.prototype.show = vi.fn(function (this: HTMLDialogElement) {
42
+ this.setAttribute('open', '');
43
+ });
44
+ HTMLDialogElement.prototype.close = vi.fn(function (this: HTMLDialogElement) {
45
+ this.removeAttribute('open');
46
+ });
47
+ vi.stubGlobal(
48
+ 'matchMedia',
49
+ vi.fn().mockReturnValue({
50
+ matches: false,
51
+ media: '',
52
+ onchange: null,
53
+ addEventListener: vi.fn(),
54
+ removeEventListener: vi.fn(),
55
+ addListener: vi.fn(),
56
+ removeListener: vi.fn(),
57
+ dispatchEvent: vi.fn(),
58
+ }),
59
+ );
60
+ });
61
+
62
+ afterEach(() => {
63
+ vi.unstubAllGlobals();
64
+ });
65
+
66
+ /**
67
+ * Values descendants SUBTRACT (bleed margins). The overlay root has no padding
68
+ * of its own to escape, so these must read a literal zero.
69
+ */
70
+ const SUBTRACTED = [
71
+ '--container-padding-inline-start',
72
+ '--container-padding-inline-end',
73
+ '--container-padding-block-start',
74
+ '--container-padding-block-end',
75
+ ];
76
+
77
+ /**
78
+ * Values descendants ADD. These must be guaranteed-invalid (`initial`) rather
79
+ * than zero, so readers fall through to their own default instead of losing
80
+ * their padding — a computed empty string is what `initial` looks like here.
81
+ */
82
+ const CLEARED = [
83
+ '--layout-padding-outer-x',
84
+ '--layout-padding-outer-y',
85
+ '--layout-padding-inner-x',
86
+ '--layout-padding-inner-y',
87
+ '--_section-padding-propagated',
88
+ ];
89
+
90
+ /** What a cleared custom property reads back as. See the assertion below. */
91
+ const CLEARED_READBACK = ['', 'initial'];
92
+
93
+ /** Each overlay, rendered open inside a page Section that leaks 40px. */
94
+ const OVERLAYS: {
95
+ name: string;
96
+ render: (child: ReactNode) => ReactNode;
97
+ root: () => HTMLElement;
98
+ }[] = [
99
+ {
100
+ name: 'Dialog',
101
+ render: child => (
102
+ <Dialog isOpen onOpenChange={() => {}}>
103
+ {child}
104
+ </Dialog>
105
+ ),
106
+ root: () => screen.getByRole('dialog'),
107
+ },
108
+ {
109
+ name: 'BottomSheet',
110
+ render: child => (
111
+ <BottomSheet isOpen onOpenChange={() => {}} label="S">
112
+ {child}
113
+ </BottomSheet>
114
+ ),
115
+ root: () =>
116
+ document.querySelector<HTMLElement>(
117
+ '.astryx-bottom-sheet',
118
+ ) as HTMLElement,
119
+ },
120
+ {
121
+ name: 'MobileNav',
122
+ render: child => (
123
+ <MobileNav isOpen onOpenChange={() => {}} label="N">
124
+ {child}
125
+ </MobileNav>
126
+ ),
127
+ root: () => screen.getByRole('dialog'),
128
+ },
129
+ {
130
+ name: 'Lightbox',
131
+ render: () => (
132
+ <Lightbox
133
+ isOpen
134
+ onOpenChange={() => {}}
135
+ media={{src: 'a.png', alt: 'a'}}
136
+ />
137
+ ),
138
+ root: () => screen.getByRole('dialog'),
139
+ },
140
+ {
141
+ name: 'Popover (useLayer surface)',
142
+ render: child => (
143
+ <Popover isOpen onOpenChange={() => {}} label="P" content={child}>
144
+ <button type="button">t</button>
145
+ </Popover>
146
+ ),
147
+ root: () => document.querySelector<HTMLElement>('[popover]') as HTMLElement,
148
+ },
149
+ ];
150
+
151
+ describe('overlayPaddingReset', () => {
152
+ describe.each(OVERLAYS)('$name', ({render: renderOverlay, root}) => {
153
+ it('zeroes the values descendants subtract', () => {
154
+ render(<Section padding={10}>{renderOverlay(<div>c</div>)}</Section>);
155
+ const computed = getComputedStyle(root());
156
+ for (const name of SUBTRACTED) {
157
+ expect(computed.getPropertyValue(name), name).toBe('0px');
158
+ }
159
+ });
160
+
161
+ it('clears the values descendants add, so they fall to their default', () => {
162
+ render(<Section padding={10}>{renderOverlay(<div>c</div>)}</Section>);
163
+ const computed = getComputedStyle(root());
164
+ for (const name of CLEARED) {
165
+ // A browser resolves `initial` on a custom property to the
166
+ // guaranteed-invalid value and reports '' here; jsdom does not
167
+ // implement that and echoes the keyword. Either proves the
168
+ // declaration landed — and neither is the leaked '40px'.
169
+ expect(CLEARED_READBACK, name).toContain(
170
+ computed.getPropertyValue(name),
171
+ );
172
+ }
173
+ });
174
+ });
175
+
176
+ it('does not clear the public theme token', () => {
177
+ // The reset clears the PRIVATE propagation var only. The public
178
+ // `--astryx-section-padding` is theme surface, set once at the theme root,
179
+ // so it has to keep reaching inside every overlay — clearing it would
180
+ // blank a theme's section padding in every dialog. That is the whole
181
+ // reason the two names were split, and it is the mistake a later
182
+ // "simplification" would most plausibly make.
183
+ //
184
+ // jsdom does not inherit custom properties, so the cascade cannot show
185
+ // this; assert it where it is decided instead. (Verified in a browser: a
186
+ // theme's 20px still reaches a Section inside a Dialog nested under a
187
+ // 40px page Section.)
188
+ const source = readFileSync(join(__dirname, 'padding.stylex.ts'), 'utf8');
189
+ const reset = source.slice(
190
+ source.indexOf('export const overlayPaddingReset'),
191
+ );
192
+ expect(reset).toContain("'--_section-padding-propagated': 'initial'");
193
+ expect(reset).not.toContain('--astryx-section-padding');
194
+ });
195
+
196
+ it("stops an ancestor Section's propagated padding at the boundary", () => {
197
+ // The page Section propagates 40px. Without the reset it would reach the
198
+ // Section inside the overlay, which would pad itself 40px instead of the
199
+ // theme default — the second half of #5208.
200
+ render(
201
+ <Section padding={10}>
202
+ <Dialog isOpen onOpenChange={() => {}}>
203
+ <div data-testid="content">c</div>
204
+ </Dialog>
205
+ </Section>,
206
+ );
207
+ const dialog = screen.getByRole('dialog');
208
+ expect(CLEARED_READBACK).toContain(
209
+ getComputedStyle(dialog).getPropertyValue(
210
+ '--_section-padding-propagated',
211
+ ),
212
+ );
213
+ // ...while the page Section outside the overlay still propagates it.
214
+ // (jsdom does not resolve the token reference to its 40px value.)
215
+ const pageSection = document.querySelector<HTMLElement>('.astryx-section');
216
+ expect(
217
+ getComputedStyle(pageSection as HTMLElement).getPropertyValue(
218
+ '--_section-padding-propagated',
219
+ ),
220
+ ).toBe('var(--spacing-10)');
221
+ });
222
+ });
@@ -326,21 +326,201 @@ export const paddingBlockStyles = stylex.create({
326
326
  });
327
327
 
328
328
  /**
329
- * Propagation styles for --astryx-section-padding.
329
+ * Inline-start-only padding override styles.
330
+ * Use when a component needs to override the inline-start edge independently
331
+ * of inline-end. Logical, so it follows the writing direction (left in LTR,
332
+ * right in RTL).
333
+ */
334
+ export const paddingInlineStartStyles = stylex.create({
335
+ 0: {paddingInlineStart: spacingVars['--spacing-0']},
336
+ 0.5: {paddingInlineStart: spacingVars['--spacing-0-5']},
337
+ 1: {paddingInlineStart: spacingVars['--spacing-1']},
338
+ 1.5: {paddingInlineStart: spacingVars['--spacing-1-5']},
339
+ 2: {paddingInlineStart: spacingVars['--spacing-2']},
340
+ 3: {paddingInlineStart: spacingVars['--spacing-3']},
341
+ 4: {paddingInlineStart: spacingVars['--spacing-4']},
342
+ 5: {paddingInlineStart: spacingVars['--spacing-5']},
343
+ 6: {paddingInlineStart: spacingVars['--spacing-6']},
344
+ 8: {paddingInlineStart: spacingVars['--spacing-8']},
345
+ 10: {paddingInlineStart: spacingVars['--spacing-10']},
346
+ });
347
+
348
+ /**
349
+ * Inline-end-only padding override styles.
350
+ * The inline-end counterpart of paddingInlineStartStyles.
351
+ */
352
+ export const paddingInlineEndStyles = stylex.create({
353
+ 0: {paddingInlineEnd: spacingVars['--spacing-0']},
354
+ 0.5: {paddingInlineEnd: spacingVars['--spacing-0-5']},
355
+ 1: {paddingInlineEnd: spacingVars['--spacing-1']},
356
+ 1.5: {paddingInlineEnd: spacingVars['--spacing-1-5']},
357
+ 2: {paddingInlineEnd: spacingVars['--spacing-2']},
358
+ 3: {paddingInlineEnd: spacingVars['--spacing-3']},
359
+ 4: {paddingInlineEnd: spacingVars['--spacing-4']},
360
+ 5: {paddingInlineEnd: spacingVars['--spacing-5']},
361
+ 6: {paddingInlineEnd: spacingVars['--spacing-6']},
362
+ 8: {paddingInlineEnd: spacingVars['--spacing-8']},
363
+ 10: {paddingInlineEnd: spacingVars['--spacing-10']},
364
+ });
365
+
366
+ /**
367
+ * Container padding inline-start CSS variable style, set independently of
368
+ * inline-end so a per-edge override keeps edge-compensating children (Card,
369
+ * Divider, a nested Section) compensating against the padding actually
370
+ * applied on that edge.
371
+ */
372
+ export const containerPaddingInlineStartVarStyles = stylex.create({
373
+ 0: {'--container-padding-inline-start': spacingVars['--spacing-0']},
374
+ 0.5: {'--container-padding-inline-start': spacingVars['--spacing-0-5']},
375
+ 1: {'--container-padding-inline-start': spacingVars['--spacing-1']},
376
+ 1.5: {'--container-padding-inline-start': spacingVars['--spacing-1-5']},
377
+ 2: {'--container-padding-inline-start': spacingVars['--spacing-2']},
378
+ 3: {'--container-padding-inline-start': spacingVars['--spacing-3']},
379
+ 4: {'--container-padding-inline-start': spacingVars['--spacing-4']},
380
+ 5: {'--container-padding-inline-start': spacingVars['--spacing-5']},
381
+ 6: {'--container-padding-inline-start': spacingVars['--spacing-6']},
382
+ 8: {'--container-padding-inline-start': spacingVars['--spacing-8']},
383
+ 10: {'--container-padding-inline-start': spacingVars['--spacing-10']},
384
+ });
385
+
386
+ /**
387
+ * Container padding inline-end CSS variable style, the counterpart of
388
+ * containerPaddingInlineStartVarStyles.
389
+ */
390
+ export const containerPaddingInlineEndVarStyles = stylex.create({
391
+ 0: {'--container-padding-inline-end': spacingVars['--spacing-0']},
392
+ 0.5: {'--container-padding-inline-end': spacingVars['--spacing-0-5']},
393
+ 1: {'--container-padding-inline-end': spacingVars['--spacing-1']},
394
+ 1.5: {'--container-padding-inline-end': spacingVars['--spacing-1-5']},
395
+ 2: {'--container-padding-inline-end': spacingVars['--spacing-2']},
396
+ 3: {'--container-padding-inline-end': spacingVars['--spacing-3']},
397
+ 4: {'--container-padding-inline-end': spacingVars['--spacing-4']},
398
+ 5: {'--container-padding-inline-end': spacingVars['--spacing-5']},
399
+ 6: {'--container-padding-inline-end': spacingVars['--spacing-6']},
400
+ 8: {'--container-padding-inline-end': spacingVars['--spacing-8']},
401
+ 10: {'--container-padding-inline-end': spacingVars['--spacing-10']},
402
+ });
403
+
404
+ /**
405
+ * Block-start-only padding override styles.
406
+ * Use when a component needs to override the block-start (top) edge
407
+ * independently of block-end — e.g. a section that sits under a sticky
408
+ * header and needs less padding above than below.
409
+ */
410
+ export const paddingBlockStartStyles = stylex.create({
411
+ 0: {paddingBlockStart: spacingVars['--spacing-0']},
412
+ 0.5: {paddingBlockStart: spacingVars['--spacing-0-5']},
413
+ 1: {paddingBlockStart: spacingVars['--spacing-1']},
414
+ 1.5: {paddingBlockStart: spacingVars['--spacing-1-5']},
415
+ 2: {paddingBlockStart: spacingVars['--spacing-2']},
416
+ 3: {paddingBlockStart: spacingVars['--spacing-3']},
417
+ 4: {paddingBlockStart: spacingVars['--spacing-4']},
418
+ 5: {paddingBlockStart: spacingVars['--spacing-5']},
419
+ 6: {paddingBlockStart: spacingVars['--spacing-6']},
420
+ 8: {paddingBlockStart: spacingVars['--spacing-8']},
421
+ 10: {paddingBlockStart: spacingVars['--spacing-10']},
422
+ });
423
+
424
+ /**
425
+ * Block-end-only padding override styles.
426
+ * The block-end counterpart of paddingBlockStartStyles.
427
+ */
428
+ export const paddingBlockEndStyles = stylex.create({
429
+ 0: {paddingBlockEnd: spacingVars['--spacing-0']},
430
+ 0.5: {paddingBlockEnd: spacingVars['--spacing-0-5']},
431
+ 1: {paddingBlockEnd: spacingVars['--spacing-1']},
432
+ 1.5: {paddingBlockEnd: spacingVars['--spacing-1-5']},
433
+ 2: {paddingBlockEnd: spacingVars['--spacing-2']},
434
+ 3: {paddingBlockEnd: spacingVars['--spacing-3']},
435
+ 4: {paddingBlockEnd: spacingVars['--spacing-4']},
436
+ 5: {paddingBlockEnd: spacingVars['--spacing-5']},
437
+ 6: {paddingBlockEnd: spacingVars['--spacing-6']},
438
+ 8: {paddingBlockEnd: spacingVars['--spacing-8']},
439
+ 10: {paddingBlockEnd: spacingVars['--spacing-10']},
440
+ });
441
+
442
+ /**
443
+ * Propagation styles for `--_section-padding-propagated`.
330
444
  * When a parent section sets explicit padding, this propagates the value
331
445
  * through the CSS custom property cascade so nested sections that use
332
446
  * useThemeDefault inherit the parent's padding instead of the theme default.
447
+ *
448
+ * This is deliberately NOT the public `--astryx-section-padding` token. The
449
+ * two carry different authority: the public token is the THEME's section
450
+ * padding, set once at the theme root, while this one is one ancestor
451
+ * Section's padding, propagated down the tree. An overlay has to drop the
452
+ * inherited value at its boundary (see {@link overlayPaddingReset}) without
453
+ * dropping the theme's — impossible while both live under one name.
454
+ * `container.stylex.ts` reads this ahead of the public token, so a propagated
455
+ * value still wins over the theme for nested sections, as before.
333
456
  */
334
457
  export const sectionPaddingPropagationStyles = stylex.create({
335
- 0: {'--astryx-section-padding': spacingVars['--spacing-0']},
336
- 0.5: {'--astryx-section-padding': spacingVars['--spacing-0-5']},
337
- 1: {'--astryx-section-padding': spacingVars['--spacing-1']},
338
- 1.5: {'--astryx-section-padding': spacingVars['--spacing-1-5']},
339
- 2: {'--astryx-section-padding': spacingVars['--spacing-2']},
340
- 3: {'--astryx-section-padding': spacingVars['--spacing-3']},
341
- 4: {'--astryx-section-padding': spacingVars['--spacing-4']},
342
- 5: {'--astryx-section-padding': spacingVars['--spacing-5']},
343
- 6: {'--astryx-section-padding': spacingVars['--spacing-6']},
344
- 8: {'--astryx-section-padding': spacingVars['--spacing-8']},
345
- 10: {'--astryx-section-padding': spacingVars['--spacing-10']},
458
+ 0: {'--_section-padding-propagated': spacingVars['--spacing-0']},
459
+ 0.5: {'--_section-padding-propagated': spacingVars['--spacing-0-5']},
460
+ 1: {'--_section-padding-propagated': spacingVars['--spacing-1']},
461
+ 1.5: {'--_section-padding-propagated': spacingVars['--spacing-1-5']},
462
+ 2: {'--_section-padding-propagated': spacingVars['--spacing-2']},
463
+ 3: {'--_section-padding-propagated': spacingVars['--spacing-3']},
464
+ 4: {'--_section-padding-propagated': spacingVars['--spacing-4']},
465
+ 5: {'--_section-padding-propagated': spacingVars['--spacing-5']},
466
+ 6: {'--_section-padding-propagated': spacingVars['--spacing-6']},
467
+ 8: {'--_section-padding-propagated': spacingVars['--spacing-8']},
468
+ 10: {'--_section-padding-propagated': spacingVars['--spacing-10']},
469
+ });
470
+
471
+ /**
472
+ * Padding-variable reset for overlay roots (Dialog, BottomSheet, Drawer,
473
+ * MobileNav, Lightbox, and every layer surface).
474
+ *
475
+ * ## Why an overlay needs this
476
+ *
477
+ * The container padding system talks to descendants through inherited custom
478
+ * properties: a padded container announces its padding, and children read the
479
+ * value either to apply it or to cancel it with a negative margin
480
+ * (`Section`, `Divider`, `Layout`, `Table`).
481
+ *
482
+ * Inheritance follows the DOM, but an overlay leaves its parent's visual box —
483
+ * a fixed/top-layer `<dialog>` is a DOM descendant of the padded page while
484
+ * being nowhere near it on screen. It inherits values describing padding that
485
+ * is not there, and its content compensates against phantom space: a `Section`
486
+ * inside a 640px sheet rendered 672px wide and hung off both edges (#5208).
487
+ *
488
+ * Two families leak, and they need opposite treatments:
489
+ *
490
+ * - `--container-padding-*` -> `0px`. Descendants SUBTRACT these (bleed
491
+ * margins). The overlay root has no padding of its own to escape, so the
492
+ * honest answer is zero. Nested containers that do set padding (a Dialog's
493
+ * content wrapper) re-announce their own values below this point, so
494
+ * legitimate edge-to-edge bleed inside the overlay is unaffected.
495
+ * - `--layout-padding-*` and `--_section-padding-propagated` -> `initial`.
496
+ * Descendants ADD these, so zeroing them would strip padding rather than
497
+ * restore it. `initial` makes each guaranteed-invalid, so readers fall
498
+ * through their own `var(…, fallback)` chain and land on the theme default —
499
+ * which is what an overlay at the top of the tree should show.
500
+ *
501
+ * `initial` is also why propagation moved off `--astryx-section-padding`: that
502
+ * name is public theme surface, set at the theme root, and making it invalid
503
+ * here would blank the theme's own section padding inside every overlay.
504
+ *
505
+ * Apply on the overlay's outermost styled element.
506
+ *
507
+ * @example
508
+ * ```
509
+ * <dialog {...stylex.props(styles.dialog, overlayPaddingReset.reset)} />
510
+ * ```
511
+ */
512
+ export const overlayPaddingReset = stylex.create({
513
+ reset: {
514
+ // Subtracted by descendants — the overlay root has no padding to escape.
515
+ '--container-padding-inline-start': '0px',
516
+ '--container-padding-inline-end': '0px',
517
+ '--container-padding-block-start': '0px',
518
+ '--container-padding-block-end': '0px',
519
+ // Added by descendants — fall through to each reader's own default.
520
+ '--layout-padding-outer-x': 'initial',
521
+ '--layout-padding-outer-y': 'initial',
522
+ '--layout-padding-inner-x': 'initial',
523
+ '--layout-padding-inner-y': 'initial',
524
+ '--_section-padding-propagated': 'initial',
525
+ },
346
526
  });
@@ -36,6 +36,7 @@ import {mergeProps, mergeRefs, rtlStyles} from '../utils';
36
36
  import type {BaseProps} from '../BaseProps';
37
37
  import {themeProps} from '../utils/themeProps';
38
38
  import {focusOutlineStyles} from '../utils/focusOutline.stylex';
39
+ import {overlayPaddingReset} from '../Layout/padding.stylex';
39
40
  import {useTranslator} from '../i18n';
40
41
 
41
42
  /**
@@ -588,7 +589,7 @@ export function Lightbox({
588
589
  aria-label={currentItem.alt || t('@astryx.lightbox.mediaViewer')}
589
590
  {...mergeProps(
590
591
  themeProps('lightbox'),
591
- stylex.props(styles.dialog, xstyle),
592
+ stylex.props(styles.dialog, overlayPaddingReset.reset, xstyle),
592
593
  className,
593
594
  style,
594
595
  )}
package/src/Link/Link.tsx CHANGED
@@ -61,7 +61,7 @@ const styles = stylex.create({
61
61
  fontWeight: 'inherit',
62
62
  textDecoration: {
63
63
  default: 'none',
64
- ':hover': {
64
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
65
65
  '@media (hover: hover)': 'underline',
66
66
  },
67
67
  },
@@ -103,7 +103,7 @@ const linkColorStyles = stylex.create({
103
103
  primary: {
104
104
  color: {
105
105
  default: colorVars['--color-text-primary'],
106
- ':hover': {
106
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
107
107
  '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-primary']}, ${colorVars['--color-tint-hover']} 15%)`,
108
108
  },
109
109
  },
@@ -111,7 +111,7 @@ const linkColorStyles = stylex.create({
111
111
  secondary: {
112
112
  color: {
113
113
  default: colorVars['--color-text-secondary'],
114
- ':hover': {
114
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
115
115
  '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-secondary']}, ${colorVars['--color-tint-hover']} 15%)`,
116
116
  },
117
117
  },
@@ -125,7 +125,7 @@ const linkColorStyles = stylex.create({
125
125
  accent: {
126
126
  color: {
127
127
  default: colorVars['--color-text-accent'],
128
- ':hover': {
128
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
129
129
  '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-accent']}, ${colorVars['--color-tint-hover']} 15%)`,
130
130
  },
131
131
  },
@@ -169,6 +169,7 @@ export const docs = {
169
169
  { guidance: true, description: 'Set headingLevelStart to match the page hierarchy, e.g. start at 3 if the markdown sits inside an h2 section.' },
170
170
  { guidance: true, description: 'Use contentWidth to keep prose at a readable line length in wide layouts.' },
171
171
  { guidance: true, description: 'Use inlinePlugins for custom shorthand patterns like issue refs, diff refs, and mentions instead of preprocessing the markdown string.' },
172
+ { guidance: true, description: 'Pair with Outline and useOutlineFromMarkdown for section navigation: headings render generated id attributes that match the outline item ids, so hash links scroll to their target.' },
172
173
  { guidance: false, description: 'Use Markdown for hand-authored layouts; use Text and Heading directly when you control the content.' },
173
174
  ],
174
175
  },
@@ -381,6 +382,7 @@ export const docsZh = {
381
382
  { guidance: true, description: 'Set headingLevelStart to match the page hierarchy, e.g. start at 3 if the markdown sits inside an h2 section.' },
382
383
  { guidance: true, description: 'Use contentWidth to keep prose at a readable line length in wide layouts.' },
383
384
  { guidance: true, description: 'Use inlinePlugins for custom shorthand patterns like issue refs, diff refs, and mentions instead of preprocessing the markdown string.' },
385
+ { guidance: true, description: 'Pair with Outline and useOutlineFromMarkdown for section navigation: headings render generated id attributes that match the outline item ids, so hash links scroll to their target.' },
384
386
  { guidance: false, description: 'Use Markdown for hand-authored layouts; use Text and Heading directly when you control the content.' },
385
387
  ],
386
388
  },
@@ -396,6 +398,7 @@ export const docsDense = {
396
398
  { guidance: true, description: 'Set headingLevelStart to match the page hierarchy, e.g. start at 3 if the markdown sits inside an h2 section.' },
397
399
  { guidance: true, description: 'Use contentWidth to keep prose at a readable line length in wide layouts.' },
398
400
  { guidance: true, description: 'Use inlinePlugins for custom shorthand patterns (issue refs, diff refs, mentions) instead of preprocessing the markdown string.' },
401
+ { guidance: true, description: 'Headings render id attributes matching useOutlineFromMarkdown ids; pair with Outline for hash navigation.' },
399
402
  { guidance: false, description: 'Use Markdown for hand-authored layouts; use Text and Heading directly when you control the content.' },
400
403
  ],
401
404
  },
@@ -5,6 +5,7 @@ import {render, screen, fireEvent} from '@testing-library/react';
5
5
  import type {ReactNode} from 'react';
6
6
  import {Markdown} from './Markdown';
7
7
  import type {MarkdownInlinePlugin} from './Markdown';
8
+ import {parseOutlineFromMarkdown} from '../Outline/parseOutlineFromMarkdown';
8
9
 
9
10
  describe('Markdown', () => {
10
11
  it('renders with role="document"', () => {
@@ -23,6 +24,83 @@ describe('Markdown', () => {
23
24
  expect(screen.getByText('Heading 2').tagName).toBe('H2');
24
25
  });
25
26
 
27
+ describe('heading ids', () => {
28
+ // Outline's documented contract: an outline item id "should match the
29
+ // target heading element id". Markdown renders the ids that
30
+ // useOutlineFromMarkdown derives, so hash navigation resolves.
31
+ it('renders generated id attributes on headings', () => {
32
+ render(<Markdown>{'# Overview\n\ncontent\n\n# Installation'}</Markdown>);
33
+ expect(screen.getByText('Overview')).toHaveAttribute('id', 'overview');
34
+ expect(screen.getByText('Installation')).toHaveAttribute(
35
+ 'id',
36
+ 'installation',
37
+ );
38
+ });
39
+
40
+ it('disambiguates duplicate headings with numeric suffixes', () => {
41
+ render(<Markdown>{'# Setup\n\n# Setup\n\n# Setup'}</Markdown>);
42
+ const ids = screen.getAllByText('Setup').map(el => el.id);
43
+ expect(ids).toEqual(['setup', 'setup-1', 'setup-2']);
44
+ });
45
+
46
+ it('renders ids matching parseOutlineFromMarkdown for the same source', () => {
47
+ // Parity invariant: every id the outline derives must resolve to a
48
+ // rendered heading with that exact id — including slugified formatting,
49
+ // duplicate numbering, the empty-slug fallback, and code-fence decoys.
50
+ const source = [
51
+ '# **Bold** and _italic_ text',
52
+ '## Setup',
53
+ '## Setup',
54
+ '### !!!',
55
+ '```',
56
+ '# not a heading',
57
+ '```',
58
+ '## The `useState` hook',
59
+ ].join('\n\n');
60
+ const {container} = render(<Markdown>{source}</Markdown>);
61
+ const outline = parseOutlineFromMarkdown(source);
62
+ expect(outline.length).toBe(5);
63
+ for (const item of outline) {
64
+ const target = container.querySelector(`[id="${item.id}"]`);
65
+ expect(target, `no rendered heading with id "${item.id}"`).not.toBe(
66
+ null,
67
+ );
68
+ expect(target!.tagName).toMatch(/^H[1-6]$/);
69
+ expect(target!.textContent?.trim()).toBe(item.label);
70
+ }
71
+ });
72
+
73
+ it('passes the generated id to a custom heading component', () => {
74
+ const received: (string | undefined)[] = [];
75
+ render(
76
+ <Markdown
77
+ components={{
78
+ heading: ({children, id}: {children: ReactNode; id?: string}) => {
79
+ received.push(id);
80
+ return <h2 id={id}>{children}</h2>;
81
+ },
82
+ }}>
83
+ {'# Overview\n\n# Overview'}
84
+ </Markdown>,
85
+ );
86
+ expect(received).toEqual(['overview', 'overview-1']);
87
+ });
88
+
89
+ it('does not assign ids to headings nested inside blockquotes', () => {
90
+ // parseOutlineFromMarkdown only lists top-level headings. If nested
91
+ // headings consumed slugs too, duplicate numbering would drift and
92
+ // outline links would land on the wrong heading.
93
+ const source = '> # Quoted\n\n# Quoted';
94
+ const {container} = render(<Markdown>{source}</Markdown>);
95
+ const outline = parseOutlineFromMarkdown(source);
96
+ expect(outline.map(i => i.id)).toEqual(['quoted']);
97
+ const [nested, topLevel] = screen.getAllByText('Quoted');
98
+ expect(container.querySelector('blockquote')).toContainElement(nested);
99
+ expect(nested).not.toHaveAttribute('id');
100
+ expect(topLevel).toHaveAttribute('id', 'quoted');
101
+ });
102
+ });
103
+
26
104
  it('renders paragraphs as block <div> (never <p>) for composition safety', () => {
27
105
  render(<Markdown>{'Hello world'}</Markdown>);
28
106
  // Markdown paragraphs render as <div> so block-level inline content