@astryxdesign/core 0.4.5 → 0.4.6-canary.cea9ecd

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 (538) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/dist/Avatar/Avatar.d.ts +10 -5
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +139 -30
  5. package/dist/Avatar/AvatarStatusDot.d.ts +2 -1
  6. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  7. package/dist/Avatar/AvatarStatusDot.js +30 -4
  8. package/dist/Avatar/AvatarStatusLabelContext.d.ts +39 -0
  9. package/dist/Avatar/AvatarStatusLabelContext.d.ts.map +1 -0
  10. package/dist/Avatar/AvatarStatusLabelContext.js +41 -0
  11. package/dist/AvatarGroup/AvatarGroup.d.ts +3 -1
  12. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  13. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  14. package/dist/AvatarGroup/AvatarGroupOverflow.js +15 -9
  15. package/dist/Blockquote/Blockquote.d.ts +4 -3
  16. package/dist/Blockquote/Blockquote.d.ts.map +1 -1
  17. package/dist/Blockquote/Blockquote.js +9 -10
  18. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  19. package/dist/BottomSheet/BottomSheetPanel.js +21 -5
  20. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  21. package/dist/Breadcrumbs/BreadcrumbItem.js +47 -34
  22. package/dist/Button/Button.d.ts.map +1 -1
  23. package/dist/Button/Button.js +7 -7
  24. package/dist/Calendar/Calendar.d.ts.map +1 -1
  25. package/dist/Calendar/Calendar.js +21 -12
  26. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  27. package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
  28. package/dist/Calendar/styles.d.ts +2 -2
  29. package/dist/Calendar/styles.d.ts.map +1 -1
  30. package/dist/Calendar/styles.js +5 -5
  31. package/dist/Center/Center.d.ts +23 -1
  32. package/dist/Center/Center.d.ts.map +1 -1
  33. package/dist/Center/Center.js +12 -6
  34. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  35. package/dist/Chat/ChatComposer.js +3 -3
  36. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  37. package/dist/Chat/ChatComposerDrawer.js +2 -2
  38. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  39. package/dist/Chat/ChatToolCalls.js +2 -2
  40. package/dist/Chat/useChatDictation.d.ts +1 -1
  41. package/dist/Chat/useChatDictation.d.ts.map +1 -1
  42. package/dist/Chat/useSpeechRecognition.d.ts +1 -1
  43. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  44. package/dist/Chat/useSpeechRecognition.js +4 -3
  45. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  46. package/dist/Chat/useTriggerMenu.js +2 -2
  47. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  48. package/dist/CheckboxInput/CheckboxInput.js +2 -2
  49. package/dist/Citation/Citation.d.ts.map +1 -1
  50. package/dist/Citation/Citation.js +5 -5
  51. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  52. package/dist/ClickableCard/ClickableCard.js +4 -4
  53. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  54. package/dist/CodeBlock/CodeBlock.js +1 -1
  55. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  56. package/dist/Collapsible/Collapsible.js +2 -2
  57. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  58. package/dist/CommandPalette/CommandPaletteItem.js +3 -3
  59. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  60. package/dist/ComplexSelector/ComplexSelector.js +6 -6
  61. package/dist/DateInput/DateInput.d.ts +31 -2
  62. package/dist/DateInput/DateInput.d.ts.map +1 -1
  63. package/dist/DateInput/DateInput.js +90 -22
  64. package/dist/DateInput/MonthScroller.d.ts +35 -0
  65. package/dist/DateInput/MonthScroller.d.ts.map +1 -0
  66. package/dist/DateInput/MonthScroller.js +658 -0
  67. package/dist/DateInput/MonthYearWheels.d.ts +24 -0
  68. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
  69. package/dist/DateInput/MonthYearWheels.js +114 -0
  70. package/dist/DateInput/TouchDateField.d.ts +10 -0
  71. package/dist/DateInput/TouchDateField.d.ts.map +1 -0
  72. package/dist/DateInput/TouchDateField.js +810 -0
  73. package/dist/DateInput/Wheel.d.ts +41 -0
  74. package/dist/DateInput/Wheel.d.ts.map +1 -0
  75. package/dist/DateInput/Wheel.js +315 -0
  76. package/dist/DateInput/monthGeometry.d.ts +65 -0
  77. package/dist/DateInput/monthGeometry.d.ts.map +1 -0
  78. package/dist/DateInput/monthGeometry.js +98 -0
  79. package/dist/DateInput/tokens.stylex.d.ts +63 -0
  80. package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
  81. package/dist/DateInput/tokens.stylex.js +74 -0
  82. package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
  83. package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
  84. package/dist/DateInput/useOwnScrollGesture.js +202 -0
  85. package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
  86. package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
  87. package/dist/DateInput/usePointerDragScroll.js +216 -0
  88. package/dist/DateInput/useScrollSettle.d.ts +26 -0
  89. package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
  90. package/dist/DateInput/useScrollSettle.js +149 -0
  91. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  92. package/dist/DateRangeInput/DateRangeInput.js +17 -14
  93. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  94. package/dist/DateTimeInput/DateTimeInput.js +17 -14
  95. package/dist/Dialog/Dialog.d.ts.map +1 -1
  96. package/dist/Dialog/Dialog.js +3 -3
  97. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  98. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +2 -2
  99. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  100. package/dist/DropdownMenu/DropdownMenuItem.js +2 -2
  101. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  102. package/dist/DropdownMenu/DropdownMenuRadioItem.js +2 -2
  103. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  104. package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -2
  105. package/dist/Field/FieldLabel.d.ts.map +1 -1
  106. package/dist/Field/FieldLabel.js +4 -4
  107. package/dist/Field/InputClearButton.d.ts.map +1 -1
  108. package/dist/Field/InputClearButton.js +6 -0
  109. package/dist/Field/inputStyles.stylex.d.ts +1 -1
  110. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  111. package/dist/Field/inputStyles.stylex.js +5 -5
  112. package/dist/FileInput/FileInput.d.ts.map +1 -1
  113. package/dist/FileInput/FileInput.js +6 -6
  114. package/dist/HoverCard/HoverCard.d.ts +13 -3
  115. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  116. package/dist/HoverCard/HoverCard.js +2 -0
  117. package/dist/HoverCard/index.d.ts +1 -1
  118. package/dist/HoverCard/index.d.ts.map +1 -1
  119. package/dist/HoverCard/useHoverCard.d.ts +17 -2
  120. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  121. package/dist/HoverCard/useHoverCard.js +78 -9
  122. package/dist/InputGroup/InputGroup.js +1 -1
  123. package/dist/Item/Item.d.ts +9 -1
  124. package/dist/Item/Item.d.ts.map +1 -1
  125. package/dist/Item/Item.js +52 -14
  126. package/dist/Layer/index.d.ts +4 -2
  127. package/dist/Layer/index.d.ts.map +1 -1
  128. package/dist/Layer/index.js +2 -0
  129. package/dist/Layer/useLayer.d.ts.map +1 -1
  130. package/dist/Layer/useLayer.js +3 -2
  131. package/dist/Layer/useTouchTrigger.d.ts +113 -0
  132. package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
  133. package/dist/Layer/useTouchTrigger.js +241 -0
  134. package/dist/Layout/container.stylex.d.ts +4 -2
  135. package/dist/Layout/container.stylex.d.ts.map +1 -1
  136. package/dist/Layout/container.stylex.js +19 -11
  137. package/dist/Layout/index.d.ts +1 -0
  138. package/dist/Layout/index.d.ts.map +1 -1
  139. package/dist/Layout/index.js +4 -0
  140. package/dist/Layout/padding.stylex.d.ts +315 -12
  141. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  142. package/dist/Layout/padding.stylex.js +389 -12
  143. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  144. package/dist/Lightbox/Lightbox.js +5 -4
  145. package/dist/Link/Link.d.ts.map +1 -1
  146. package/dist/Link/Link.js +6 -6
  147. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  148. package/dist/MetadataList/MetadataList.js +1 -1
  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 -8
  154. package/dist/NavItem/navItemStyles.stylex.d.ts +4 -4
  155. package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
  156. package/dist/NavItem/navItemStyles.stylex.js +4 -4
  157. package/dist/NavMenu/NavHeadingMenuItem.d.ts.map +1 -1
  158. package/dist/NavMenu/NavHeadingMenuItem.js +3 -3
  159. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  160. package/dist/NumberInput/NumberInput.js +36 -8
  161. package/dist/Outline/Outline.d.ts.map +1 -1
  162. package/dist/Outline/Outline.js +3 -3
  163. package/dist/Pagination/Pagination.d.ts.map +1 -1
  164. package/dist/Pagination/Pagination.js +2 -2
  165. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  166. package/dist/PowerSearch/PowerSearch.js +11 -12
  167. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  169. package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
  170. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  171. package/dist/PowerSearch/formatFilterValue.js +23 -8
  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 +70 -40
  175. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  176. package/dist/Resizable/ResizeHandle.js +7 -7
  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 +7 -2
  182. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  183. package/dist/SelectableCard/SelectableCard.js +3 -3
  184. package/dist/Selector/Selector.d.ts +26 -1
  185. package/dist/Selector/Selector.d.ts.map +1 -1
  186. package/dist/Selector/Selector.js +93 -20
  187. package/dist/Selector/SelectorOption.d.ts +14 -1
  188. package/dist/Selector/SelectorOption.d.ts.map +1 -1
  189. package/dist/Selector/SelectorOption.js +6 -0
  190. package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
  191. package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
  192. package/dist/Selector/SelectorRowLayoutContext.js +27 -0
  193. package/dist/Selector/types.d.ts +1 -0
  194. package/dist/Selector/types.d.ts.map +1 -1
  195. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  196. package/dist/SideNav/SideNavHeading.js +4 -4
  197. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  198. package/dist/SideNav/SideNavItem.js +3 -3
  199. package/dist/Slider/Slider.d.ts.map +1 -1
  200. package/dist/Slider/Slider.js +7 -7
  201. package/dist/Stack/Stack.d.ts +23 -1
  202. package/dist/Stack/Stack.d.ts.map +1 -1
  203. package/dist/Stack/Stack.js +12 -6
  204. package/dist/Switch/Switch.d.ts.map +1 -1
  205. package/dist/Switch/Switch.js +2 -2
  206. package/dist/TabList/Tab.d.ts.map +1 -1
  207. package/dist/TabList/Tab.js +1 -1
  208. package/dist/TabList/TabMenu.d.ts.map +1 -1
  209. package/dist/TabList/TabMenu.js +3 -3
  210. package/dist/Table/TableRow.js +4 -4
  211. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  212. package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
  213. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  214. package/dist/Table/plugins/filtering/useTableFiltering.js +2 -2
  215. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  216. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +2 -2
  217. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  218. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +2 -2
  219. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  220. package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
  221. package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
  222. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  223. package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
  224. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  225. package/dist/Table/plugins/tree/useTableTreeData.js +3 -3
  226. package/dist/TextArea/TextArea.js +1 -1
  227. package/dist/TextInput/TextInput.js +1 -1
  228. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  229. package/dist/Thumbnail/Thumbnail.js +3 -3
  230. package/dist/TimeInput/TimeInput.js +2 -2
  231. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  232. package/dist/Timestamp/Timestamp.js +6 -4
  233. package/dist/Timestamp/formatInstant.d.ts +3 -2
  234. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  235. package/dist/Timestamp/formatInstant.js +8 -8
  236. package/dist/Timestamp/tooltipEntries.d.ts +2 -1
  237. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  238. package/dist/Timestamp/tooltipEntries.js +5 -3
  239. package/dist/Toast/Toast.d.ts +4 -3
  240. package/dist/Toast/Toast.d.ts.map +1 -1
  241. package/dist/Toast/Toast.js +10 -7
  242. package/dist/Token/Token.d.ts.map +1 -1
  243. package/dist/Token/Token.js +6 -6
  244. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  245. package/dist/Tokenizer/Tokenizer.js +1 -1
  246. package/dist/Tooltip/Tooltip.d.ts +16 -3
  247. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  248. package/dist/Tooltip/Tooltip.js +2 -0
  249. package/dist/Tooltip/index.d.ts +1 -1
  250. package/dist/Tooltip/index.d.ts.map +1 -1
  251. package/dist/Tooltip/useTooltip.d.ts +21 -2
  252. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  253. package/dist/Tooltip/useTooltip.js +71 -13
  254. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  255. package/dist/TopNav/TopNavHeading.js +4 -4
  256. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  257. package/dist/TopNav/TopNavItem.js +3 -3
  258. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  259. package/dist/TopNav/TopNavMegaMenu.js +2 -2
  260. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  261. package/dist/TopNav/TopNavMegaMenuItem.js +2 -2
  262. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  263. package/dist/TopNav/TopNavMenu.js +4 -4
  264. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  265. package/dist/TreeList/TreeListItem.js +7 -7
  266. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  267. package/dist/Typeahead/BaseTypeahead.js +2 -2
  268. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  269. package/dist/Typeahead/Typeahead.js +1 -1
  270. package/dist/astryx.css +124 -62
  271. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
  272. package/dist/hooks/containerReveal.stylex.js +18 -18
  273. package/dist/hooks/scrollbarGutter.d.ts +28 -0
  274. package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
  275. package/dist/hooks/scrollbarGutter.js +103 -0
  276. package/dist/hooks/useAutoMediaMode.d.ts +31 -0
  277. package/dist/hooks/useAutoMediaMode.d.ts.map +1 -0
  278. package/dist/hooks/useAutoMediaMode.js +201 -0
  279. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  280. package/dist/hooks/useInputStatusIcon.js +1 -1
  281. package/dist/hooks/useListFocus.d.ts +5 -2
  282. package/dist/hooks/useListFocus.d.ts.map +1 -1
  283. package/dist/hooks/useListFocus.js +12 -6
  284. package/dist/hooks/useScrollLock.d.ts +4 -0
  285. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  286. package/dist/hooks/useScrollLock.js +13 -1
  287. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  288. package/dist/i18n/InternationalizationContext.js +2 -0
  289. package/dist/i18n/index.d.ts +6 -0
  290. package/dist/i18n/index.d.ts.map +1 -1
  291. package/dist/i18n/index.js +6 -0
  292. package/dist/i18n/useCollator.d.ts +12 -0
  293. package/dist/i18n/useCollator.d.ts.map +1 -0
  294. package/dist/i18n/useCollator.js +40 -0
  295. package/dist/i18n/useLocale.d.ts +3 -0
  296. package/dist/i18n/useLocale.d.ts.map +1 -0
  297. package/dist/i18n/useLocale.js +31 -0
  298. package/dist/theme/MediaTheme.d.ts +25 -5
  299. package/dist/theme/MediaTheme.d.ts.map +1 -1
  300. package/dist/theme/MediaTheme.js +31 -6
  301. package/dist/theme/defineTheme.d.ts +5 -0
  302. package/dist/theme/defineTheme.d.ts.map +1 -1
  303. package/dist/theme/defineTheme.js +5 -0
  304. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  305. package/dist/theme/derivedVarRegistry.js +7 -0
  306. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  307. package/dist/theme/generateThemeRules.js +66 -5
  308. package/dist/theme/index.d.ts +1 -1
  309. package/dist/theme/index.d.ts.map +1 -1
  310. package/dist/theme/syntax/index.d.ts +6 -0
  311. package/dist/theme/syntax/index.d.ts.map +1 -1
  312. package/dist/theme/syntax/index.js +7 -2
  313. package/dist/utils/dateParser.d.ts +4 -3
  314. package/dist/utils/dateParser.d.ts.map +1 -1
  315. package/dist/utils/dateParser.js +8 -8
  316. package/dist/utils/index.d.ts +1 -1
  317. package/dist/utils/index.d.ts.map +1 -1
  318. package/dist/utils/index.js +1 -1
  319. package/dist/utils/plainDate.d.ts +5 -2
  320. package/dist/utils/plainDate.d.ts.map +1 -1
  321. package/dist/utils/plainDate.js +20 -4
  322. package/locales/en.json +28 -0
  323. package/locales/pseudo.json +21 -0
  324. package/package.json +3 -3
  325. package/src/Avatar/Avatar.doc.mjs +10 -6
  326. package/src/Avatar/Avatar.test.tsx +219 -1
  327. package/src/Avatar/Avatar.tsx +179 -37
  328. package/src/Avatar/AvatarStatusDot.tsx +30 -4
  329. package/src/Avatar/AvatarStatusLabelContext.ts +47 -0
  330. package/src/AvatarGroup/AvatarGroup.doc.mjs +10 -6
  331. package/src/AvatarGroup/AvatarGroup.test.tsx +62 -0
  332. package/src/AvatarGroup/AvatarGroup.tsx +3 -1
  333. package/src/AvatarGroup/AvatarGroupOverflow.tsx +31 -8
  334. package/src/Banner/Banner.doc.mjs +2 -0
  335. package/src/Blockquote/Blockquote.doc.mjs +30 -7
  336. package/src/Blockquote/Blockquote.test.tsx +34 -3
  337. package/src/Blockquote/Blockquote.tsx +11 -9
  338. package/src/BottomSheet/BottomSheet.doc.mjs +3 -3
  339. package/src/BottomSheet/BottomSheet.test.tsx +24 -0
  340. package/src/BottomSheet/BottomSheetPanel.test.tsx +91 -0
  341. package/src/BottomSheet/BottomSheetPanel.tsx +58 -3
  342. package/src/Breadcrumbs/BreadcrumbItem.tsx +36 -23
  343. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +26 -2
  344. package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -0
  345. package/src/Button/Button.tsx +12 -9
  346. package/src/Calendar/Calendar.tsx +15 -9
  347. package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
  348. package/src/Calendar/styles.ts +8 -5
  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 +11 -5
  353. package/src/Chat/ChatComposerDrawer.tsx +4 -1
  354. package/src/Chat/ChatToolCalls.tsx +13 -4
  355. package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
  356. package/src/Chat/useChatDictation.ts +1 -1
  357. package/src/Chat/useSpeechRecognition.ts +5 -3
  358. package/src/Chat/useTriggerMenu.tsx +4 -1
  359. package/src/CheckboxInput/CheckboxInput.tsx +5 -2
  360. package/src/Citation/Citation.test.tsx +6 -1
  361. package/src/Citation/Citation.tsx +11 -5
  362. package/src/ClickableCard/ClickableCard.tsx +7 -4
  363. package/src/CodeBlock/CodeBlock.tsx +4 -1
  364. package/src/Collapsible/Collapsible.tsx +5 -2
  365. package/src/CommandPalette/CommandPaletteItem.tsx +6 -3
  366. package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
  367. package/src/ComplexSelector/ComplexSelector.tsx +14 -7
  368. package/src/DateInput/DateInput.test.tsx +17 -1
  369. package/src/DateInput/DateInput.tsx +93 -21
  370. package/src/DateInput/DateInputTouch.test.tsx +2582 -0
  371. package/src/DateInput/MonthScroller.tsx +878 -0
  372. package/src/DateInput/MonthYearWheels.tsx +147 -0
  373. package/src/DateInput/TouchDateField.tsx +1223 -0
  374. package/src/DateInput/Wheel.tsx +473 -0
  375. package/src/DateInput/monthGeometry.ts +118 -0
  376. package/src/DateInput/tokens.stylex.ts +99 -0
  377. package/src/DateInput/useOwnScrollGesture.ts +227 -0
  378. package/src/DateInput/usePointerDragScroll.ts +220 -0
  379. package/src/DateInput/useScrollSettle.ts +164 -0
  380. package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
  381. package/src/DateRangeInput/DateRangeInput.tsx +31 -13
  382. package/src/DateTimeInput/DateTimeInput.tsx +25 -9
  383. package/src/Dialog/Dialog.test.tsx +24 -0
  384. package/src/Dialog/Dialog.tsx +3 -0
  385. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -2
  386. package/src/DropdownMenu/DropdownMenuItem.tsx +5 -2
  387. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -2
  388. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -2
  389. package/src/Field/Field.doc.mjs +2 -0
  390. package/src/Field/FieldLabel.tsx +9 -3
  391. package/src/Field/InputClearButton.test.tsx +110 -3
  392. package/src/Field/InputClearButton.tsx +38 -0
  393. package/src/Field/inputStyles.stylex.ts +17 -13
  394. package/src/FileInput/FileInput.tsx +15 -8
  395. package/src/FormLayout/FormLayout.doc.mjs +1 -1
  396. package/src/HoverCard/HoverCard.doc.mjs +18 -0
  397. package/src/HoverCard/HoverCard.test.tsx +189 -0
  398. package/src/HoverCard/HoverCard.tsx +22 -2
  399. package/src/HoverCard/index.ts +1 -0
  400. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  401. package/src/HoverCard/useHoverCard.tsx +103 -7
  402. package/src/InputGroup/InputGroup.tsx +1 -1
  403. package/src/Item/Item.doc.mjs +1 -0
  404. package/src/Item/Item.test.tsx +50 -0
  405. package/src/Item/Item.tsx +54 -6
  406. package/src/Layer/index.ts +10 -0
  407. package/src/Layer/useLayer.tsx +13 -2
  408. package/src/Layer/useTouchTrigger.test.ts +70 -0
  409. package/src/Layer/useTouchTrigger.ts +366 -0
  410. package/src/Layout/Layout.doc.mjs +18 -0
  411. package/src/Layout/container.stylex.ts +11 -3
  412. package/src/Layout/index.ts +4 -0
  413. package/src/Layout/overlayPaddingReset.test.tsx +222 -0
  414. package/src/Layout/padding.stylex.ts +192 -12
  415. package/src/Lightbox/Lightbox.tsx +11 -3
  416. package/src/Link/Link.tsx +9 -6
  417. package/src/MetadataList/MetadataList.tsx +4 -1
  418. package/src/MobileNav/MobileNav.tsx +61 -5
  419. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
  420. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
  421. package/src/MultiSelector/MultiSelector.test.tsx +1 -1
  422. package/src/MultiSelector/MultiSelector.tsx +26 -10
  423. package/src/NavItem/navItemStyles.stylex.ts +7 -4
  424. package/src/NavMenu/NavHeadingMenuItem.tsx +6 -3
  425. package/src/NumberInput/NumberInput.doc.mjs +24 -0
  426. package/src/NumberInput/NumberInput.test.tsx +138 -0
  427. package/src/NumberInput/NumberInput.tsx +47 -8
  428. package/src/Outline/Outline.tsx +5 -2
  429. package/src/Pagination/Pagination.tsx +5 -2
  430. package/src/Popover/Popover.test.tsx +27 -1
  431. package/src/PowerSearch/PowerSearch.tsx +17 -8
  432. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  433. package/src/PowerSearch/formatFilterValue.test.ts +22 -2
  434. package/src/PowerSearch/formatFilterValue.ts +31 -6
  435. package/src/RadioList/RadioList.doc.mjs +1 -1
  436. package/src/RadioList/RadioList.test.tsx +170 -2
  437. package/src/RadioList/RadioListItem.tsx +88 -53
  438. package/src/Resizable/ResizeHandle.test.tsx +22 -0
  439. package/src/Resizable/ResizeHandle.tsx +25 -7
  440. package/src/Section/Section.doc.mjs +55 -0
  441. package/src/Section/Section.test.tsx +201 -4
  442. package/src/Section/Section.tsx +69 -0
  443. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  444. package/src/SegmentedControl/SegmentedControlItem.tsx +15 -3
  445. package/src/SelectableCard/SelectableCard.tsx +6 -3
  446. package/src/Selector/Selector.doc.mjs +16 -2
  447. package/src/Selector/Selector.test.tsx +525 -1
  448. package/src/Selector/Selector.tsx +180 -25
  449. package/src/Selector/SelectorOption.doc.mjs +7 -0
  450. package/src/Selector/SelectorOption.tsx +21 -0
  451. package/src/Selector/SelectorRowLayoutContext.ts +32 -0
  452. package/src/Selector/types.ts +4 -4
  453. package/src/SideNav/SideNavHeading.tsx +14 -5
  454. package/src/SideNav/SideNavItem.tsx +9 -3
  455. package/src/Slider/Slider.tsx +25 -6
  456. package/src/Stack/Stack.doc.mjs +72 -0
  457. package/src/Stack/Stack.test.tsx +156 -0
  458. package/src/Stack/Stack.tsx +50 -8
  459. package/src/Switch/Switch.tsx +5 -2
  460. package/src/TabList/Tab.tsx +4 -1
  461. package/src/TabList/TabMenu.tsx +9 -3
  462. package/src/Table/TableRow.tsx +4 -4
  463. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +6 -2
  464. package/src/Table/plugins/filtering/useTableFiltering.tsx +4 -1
  465. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +10 -3
  466. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +6 -3
  467. package/src/Table/plugins/sortable/useTableSortable.tsx +4 -1
  468. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
  469. package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
  470. package/src/Table/plugins/tree/useTableTreeData.tsx +10 -4
  471. package/src/TextArea/TextArea.doc.mjs +1 -1
  472. package/src/TextArea/TextArea.tsx +1 -1
  473. package/src/TextInput/TextInput.tsx +1 -1
  474. package/src/Thumbnail/Thumbnail.tsx +9 -3
  475. package/src/TimeInput/TimeInput.tsx +1 -1
  476. package/src/Timestamp/Timestamp.test.tsx +27 -7
  477. package/src/Timestamp/Timestamp.tsx +8 -4
  478. package/src/Timestamp/formatInstant.ts +9 -7
  479. package/src/Timestamp/tooltipEntries.test.ts +11 -6
  480. package/src/Timestamp/tooltipEntries.ts +6 -2
  481. package/src/Toast/Toast.tsx +9 -7
  482. package/src/Token/Token.tsx +14 -5
  483. package/src/Tokenizer/Tokenizer.tsx +4 -1
  484. package/src/Tooltip/Tooltip.doc.mjs +18 -0
  485. package/src/Tooltip/Tooltip.test.tsx +254 -1
  486. package/src/Tooltip/Tooltip.tsx +22 -2
  487. package/src/Tooltip/index.ts +1 -0
  488. package/src/Tooltip/useTooltip.doc.mjs +2 -0
  489. package/src/Tooltip/useTooltip.tsx +99 -21
  490. package/src/TopNav/TopNavHeading.tsx +13 -4
  491. package/src/TopNav/TopNavItem.tsx +6 -3
  492. package/src/TopNav/TopNavMegaMenu.tsx +5 -2
  493. package/src/TopNav/TopNavMegaMenuItem.tsx +5 -2
  494. package/src/TopNav/TopNavMenu.tsx +10 -4
  495. package/src/TreeList/TreeListItem.tsx +22 -7
  496. package/src/Typeahead/BaseTypeahead.tsx +5 -2
  497. package/src/Typeahead/Typeahead.tsx +4 -1
  498. package/src/hooks/containerReveal.stylex.ts +54 -18
  499. package/src/hooks/scrollbarGutter.test.ts +167 -0
  500. package/src/hooks/scrollbarGutter.ts +121 -0
  501. package/src/hooks/useAutoMediaMode.test.ts +109 -0
  502. package/src/hooks/useAutoMediaMode.ts +233 -0
  503. package/src/hooks/useInputStatusIcon.tsx +4 -1
  504. package/src/hooks/useListFocus.doc.mjs +2 -2
  505. package/src/hooks/useListFocus.test.tsx +65 -3
  506. package/src/hooks/useListFocus.ts +15 -7
  507. package/src/hooks/useScrollLock.doc.mjs +4 -4
  508. package/src/hooks/useScrollLock.test.ts +73 -0
  509. package/src/hooks/useScrollLock.ts +14 -0
  510. package/src/i18n/InternationalizationContext.ts +2 -0
  511. package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
  512. package/src/i18n/__tests__/useCollator.test.tsx +115 -0
  513. package/src/i18n/__tests__/useLocale.test.tsx +52 -0
  514. package/src/i18n/index.ts +6 -0
  515. package/src/i18n/useCollator.doc.mjs +84 -0
  516. package/src/i18n/useCollator.ts +44 -0
  517. package/src/i18n/useLocale.doc.mjs +70 -0
  518. package/src/i18n/useLocale.ts +34 -0
  519. package/src/i18n/useTranslator.doc.mjs +1 -1
  520. package/src/reset.css +9 -2
  521. package/src/reset.test.ts +22 -0
  522. package/src/theme/MediaTheme.doc.mjs +23 -4
  523. package/src/theme/MediaTheme.dom.test.tsx +97 -0
  524. package/src/theme/MediaTheme.tsx +42 -7
  525. package/src/theme/defineTheme.test.ts +9 -3
  526. package/src/theme/defineTheme.ts +5 -0
  527. package/src/theme/derivedVarRegistry.test.ts +19 -5
  528. package/src/theme/derivedVarRegistry.ts +4 -0
  529. package/src/theme/generateThemeRules.test.ts +118 -0
  530. package/src/theme/generateThemeRules.ts +83 -5
  531. package/src/theme/index.ts +1 -1
  532. package/src/theme/syntax/index.ts +6 -2
  533. package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
  534. package/src/utils/dateParser.test.ts +20 -0
  535. package/src/utils/dateParser.ts +14 -7
  536. package/src/utils/index.ts +2 -0
  537. package/src/utils/plainDate.test.ts +6 -0
  538. package/src/utils/plainDate.ts +21 -4
@@ -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
  /**
@@ -157,13 +158,20 @@ const styles = stylex.create({
157
158
  cursor: {
158
159
  default: 'zoom-in',
159
160
  '@media (hover: hover)': 'zoom-in',
161
+ ':is(:disabled,[aria-disabled="true"])': 'default',
160
162
  },
161
163
  },
162
164
  imageWrapperZoomed: {
163
- cursor: 'grab',
165
+ cursor: {
166
+ default: 'grab',
167
+ ':is(:disabled,[aria-disabled="true"])': 'default',
168
+ },
164
169
  },
165
170
  imageWrapperDragging: {
166
- cursor: 'grabbing',
171
+ cursor: {
172
+ default: 'grabbing',
173
+ ':is(:disabled,[aria-disabled="true"])': 'default',
174
+ },
167
175
  },
168
176
  image: {
169
177
  maxWidth: '100%',
@@ -588,7 +596,7 @@ export function Lightbox({
588
596
  aria-label={currentItem.alt || t('@astryx.lightbox.mediaViewer')}
589
597
  {...mergeProps(
590
598
  themeProps('lightbox'),
591
- stylex.props(styles.dialog, xstyle),
599
+ stylex.props(styles.dialog, overlayPaddingReset.reset, xstyle),
592
600
  className,
593
601
  style,
594
602
  )}
package/src/Link/Link.tsx CHANGED
@@ -61,11 +61,14 @@ 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
  },
68
- cursor: 'pointer',
68
+ cursor: {
69
+ default: 'pointer',
70
+ ':is(:disabled,[aria-disabled="true"])': 'default',
71
+ },
69
72
  transitionProperty: 'color, text-decoration',
70
73
  transitionDuration: durationVars['--duration-fast'],
71
74
  transitionTimingFunction: easeVars['--ease-standard'],
@@ -85,7 +88,7 @@ const styles = stylex.create({
85
88
  textDecoration: 'underline',
86
89
  },
87
90
  disabled: {
88
- cursor: 'not-allowed',
91
+ cursor: 'default',
89
92
  opacity: 0.5,
90
93
  pointerEvents: 'none',
91
94
  },
@@ -103,7 +106,7 @@ const linkColorStyles = stylex.create({
103
106
  primary: {
104
107
  color: {
105
108
  default: colorVars['--color-text-primary'],
106
- ':hover': {
109
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
107
110
  '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-primary']}, ${colorVars['--color-tint-hover']} 15%)`,
108
111
  },
109
112
  },
@@ -111,7 +114,7 @@ const linkColorStyles = stylex.create({
111
114
  secondary: {
112
115
  color: {
113
116
  default: colorVars['--color-text-secondary'],
114
- ':hover': {
117
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
115
118
  '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-secondary']}, ${colorVars['--color-tint-hover']} 15%)`,
116
119
  },
117
120
  },
@@ -125,7 +128,7 @@ const linkColorStyles = stylex.create({
125
128
  accent: {
126
129
  color: {
127
130
  default: colorVars['--color-text-accent'],
128
- ':hover': {
131
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
129
132
  '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-accent']}, ${colorVars['--color-tint-hover']} 15%)`,
130
133
  },
131
134
  },
@@ -146,7 +146,10 @@ const styles = stylex.create({
146
146
  background: 'none',
147
147
  border: 'none',
148
148
  padding: `${spacingVars['--spacing-2']} 0`,
149
- cursor: 'pointer',
149
+ cursor: {
150
+ default: 'pointer',
151
+ ':is(:disabled,[aria-disabled="true"])': 'default',
152
+ },
150
153
  color: colorVars['--color-accent'],
151
154
  fontSize: typeScaleVars['--text-body-size'],
152
155
  lineHeight: typeScaleVars['--text-body-leading'],
@@ -23,6 +23,7 @@
23
23
  *
24
24
  * SYNC: When modified, update these files to stay in sync:
25
25
  * - /packages/core/src/MobileNav/index.ts (exports if types change)
26
+ * - /packages/core/src/hooks/scrollbarGutter.ts (shared scroll-lock gutter)
26
27
  * - /packages/cli/assets/templates/blocks/components/MobileNav/ (showcase blocks)
27
28
  */
28
29
 
@@ -47,7 +48,12 @@ import {Button} from '../Button';
47
48
  import {Icon} from '../Icon';
48
49
  import {Heading} from '../Heading/Heading';
49
50
  import {useAppShellMobile} from '../AppShell/AppShellMobileContext';
51
+ import {
52
+ holdScrollbarGutter,
53
+ type ScrollbarGutterHold,
54
+ } from '../hooks/scrollbarGutter';
50
55
  import {mergeProps, mergeRefs, composeEventHandlers} from '../utils';
56
+ import {overlayPaddingReset} from '../Layout/padding.stylex';
51
57
  import type {BaseProps} from '../BaseProps';
52
58
  import {themeProps} from '../utils/themeProps';
53
59
  import {useTranslator} from '../i18n';
@@ -70,7 +76,16 @@ const styles = stylex.create({
70
76
  width: '100vw',
71
77
  height: '100dvh',
72
78
  backgroundColor: 'transparent',
73
- overflow: 'hidden',
79
+ // `clip`, not `hidden`. Both clip the off-screen drawer, but `hidden` makes
80
+ // the dialog a SCROLL CONTAINER, and a scroll container in the top layer
81
+ // whose subtree holds another scroller (the drawer's content area) does not
82
+ // paint a @starting-style entry transition for its descendants in Chromium:
83
+ // the transition ticks in the CSSOM while every painted frame shows the
84
+ // end value, so the drawer appears fully open. `clip` clips without
85
+ // creating a scroll container and the slide-in paints normally. The dialog
86
+ // never scrolls anyway — its child is absolutely positioned — so nothing
87
+ // depended on it being a scroll container.
88
+ overflow: 'clip',
74
89
  overscrollBehavior: 'contain',
75
90
  // Prevent touch gestures (pull-to-refresh, background scroll) passing through
76
91
  touchAction: 'none',
@@ -112,7 +127,14 @@ const styles = stylex.create({
112
127
  },
113
128
  backdropOpen: {
114
129
  '::backdrop': {
115
- opacity: 1,
130
+ // The ::backdrop only exists once showModal() has put the dialog in the
131
+ // top layer, so its first rendered frame already has the open opacity.
132
+ // Without a starting style there is no earlier value to transition from
133
+ // and the scrim snaps in — @starting-style supplies that value.
134
+ opacity: {
135
+ default: 1,
136
+ '@starting-style': 0,
137
+ },
116
138
  },
117
139
  },
118
140
  drawer: {
@@ -143,7 +165,17 @@ const styles = stylex.create({
143
165
  },
144
166
  },
145
167
  drawerStartOpen: {
146
- transform: 'translateX(0)',
168
+ // The whole dialog is `display: none` while closed, so the drawer is not
169
+ // rendered and the open transform is the only value it has ever had — a
170
+ // transition needs a previous value to run from. @starting-style gives the
171
+ // first rendered frame the off-screen transform, so the slide-in plays.
172
+ transform: {
173
+ default: 'translateX(0)',
174
+ '@starting-style': {
175
+ default: 'translateX(-100%)',
176
+ ':is([dir="rtl"] *)': 'translateX(100%)',
177
+ },
178
+ },
147
179
  },
148
180
  drawerEnd: {
149
181
  insetInlineEnd: 0,
@@ -156,7 +188,14 @@ const styles = stylex.create({
156
188
  },
157
189
  },
158
190
  drawerEndOpen: {
159
- transform: 'translateX(0)',
191
+ // See drawerStartOpen — same starting style, mirrored edge.
192
+ transform: {
193
+ default: 'translateX(0)',
194
+ '@starting-style': {
195
+ default: 'translateX(100%)',
196
+ ':is([dir="rtl"] *)': 'translateX(-100%)',
197
+ },
198
+ },
160
199
  },
161
200
  header: {
162
201
  display: 'flex',
@@ -396,6 +435,15 @@ export function MobileNav({
396
435
 
397
436
  const dialogRef = useRef<HTMLDialogElement>(null);
398
437
  const closeTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null);
438
+ const gutterRef = useRef<ScrollbarGutterHold | null>(null);
439
+
440
+ // Gives back the gutter held open in place of the hidden scrollbar.
441
+ const releaseGutter = useCallback(() => {
442
+ if (gutterRef.current) {
443
+ gutterRef.current.release();
444
+ gutterRef.current = null;
445
+ }
446
+ }, []);
399
447
  // Resolved side — computed from trigger position when side='auto'
400
448
  const [resolvedSide, setResolvedSide] = useState<'start' | 'end'>(
401
449
  side === 'auto' ? 'end' : side,
@@ -438,6 +486,10 @@ export function MobileNav({
438
486
  }
439
487
 
440
488
  if (isOpen) {
489
+ // Taken first: every mutation below is one that can hide the scrollbar,
490
+ // and the gutter has to be measured while it is still there.
491
+ gutterRef.current ??= holdScrollbarGutter(document.documentElement);
492
+
441
493
  if (!dialog.open) {
442
494
  dialog.showModal();
443
495
  }
@@ -445,8 +497,10 @@ export function MobileNav({
445
497
  // overflow: clip avoids creating a scroll container (unlike hidden),
446
498
  // so there's no scroll bounce and no need to save/restore scroll position.
447
499
  document.documentElement.style.overflow = 'clip';
500
+ gutterRef.current.settle();
448
501
  } else if (dialog.open) {
449
502
  document.documentElement.style.overflow = '';
503
+ releaseGutter();
450
504
 
451
505
  closeTimeoutRef.current = setTimeout(() => {
452
506
  dialog.close();
@@ -459,8 +513,9 @@ export function MobileNav({
459
513
  closeTimeoutRef.current = null;
460
514
  }
461
515
  document.documentElement.style.overflow = '';
516
+ releaseGutter();
462
517
  };
463
- }, [isOpen]);
518
+ }, [isOpen, releaseGutter]);
464
519
 
465
520
  // Close the native dialog on unmount if it's still open. Inside AppShell the
466
521
  // drawer is mounted in an <Activity> that switches to mode="hidden" when the
@@ -512,6 +567,7 @@ export function MobileNav({
512
567
  themeProps('mobile-nav', {side: resolvedSide}),
513
568
  stylex.props(
514
569
  styles.dialog,
570
+ overlayPaddingReset.reset,
515
571
  isOpen && styles.open,
516
572
  styles.backdrop,
517
573
  isOpen && styles.backdropOpen,
@@ -0,0 +1,212 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file MobileNavEntryAnimation.test.tsx
5
+ * @input Uses vitest, @testing-library/react, the TypeScript compiler API
6
+ * @output Regression tests keeping the drawer's slide-in and scrim fade-in
7
+ * @position Testing; guards the open path of MobileNav.tsx
8
+ *
9
+ * The drawer used to open with no animation at all while closing smoothly.
10
+ *
11
+ * The dialog is `display: none` until `isOpen`, so nothing inside it is
12
+ * rendered while closed. React commits the open `display` and the open
13
+ * `transform` in the same pass, which means the first frame the drawer is ever
14
+ * rendered in already holds the open transform: a transition has no earlier
15
+ * value to run from and the drawer simply appears. Closing looked fine because
16
+ * both values exist by then — `display` stays in the transition with
17
+ * `allow-discrete`, so the element is still rendered as the transform animates
18
+ * out.
19
+ *
20
+ * `@starting-style` supplies that before-change style — the off-screen
21
+ * transform for the drawer, transparent for the `::backdrop`.
22
+ *
23
+ * That alone is NOT enough, and the second half is the part that is easy to
24
+ * undo by accident. The dialog used `overflow: hidden`, which makes it a
25
+ * SCROLL CONTAINER. A scroll container in the top layer whose subtree holds
26
+ * another scroller — here the drawer's own content area — does not paint a
27
+ * `@starting-style` entry transition for its descendants in Chromium: the
28
+ * transition ticks in the CSSOM (`getComputedStyle` interpolates perfectly)
29
+ * while every painted frame shows the end value. Measuring the CSSOM says
30
+ * "animating"; the screen says "snapped". `overflow: clip` clips the
31
+ * off-screen drawer exactly as `hidden` did without creating a scroll
32
+ * container, and the slide-in paints.
33
+ *
34
+ * Reproduced minimally: dialog `overflow: hidden` + a scrolling child inside
35
+ * the drawer snaps; either one alone animates.
36
+ *
37
+ * Note on scope: jsdom has no top layer, no transitions, no `@starting-style`
38
+ * evaluation and no compositor, so none of this is observable here. These
39
+ * tests pin the three declarations the behaviour rests on. Verified in
40
+ * Chromium by screencasting painted frames (not computed style) at both edges,
41
+ * LTR and RTL: open and close each paint ~60-100 distinct intermediate
42
+ * positions, and reduced motion collapses to a 10ms transition.
43
+ */
44
+
45
+ import {describe, it, expect, beforeAll} from 'vitest';
46
+ import {render, screen} from '@testing-library/react';
47
+ import {readFileSync} from 'node:fs';
48
+ import {join} from 'node:path';
49
+ import ts from 'typescript';
50
+ import {MobileNav} from './MobileNav';
51
+
52
+ // jsdom doesn't implement showModal/close on <dialog>, so we mock them
53
+ beforeAll(() => {
54
+ HTMLDialogElement.prototype.showModal =
55
+ HTMLDialogElement.prototype.showModal ||
56
+ function (this: HTMLDialogElement) {
57
+ this.setAttribute('open', '');
58
+ };
59
+ HTMLDialogElement.prototype.close =
60
+ HTMLDialogElement.prototype.close ||
61
+ function (this: HTMLDialogElement) {
62
+ this.removeAttribute('open');
63
+ };
64
+ });
65
+
66
+ /** Every CSS rule StyleX has injected into the document, as text. */
67
+ function injectedRules(): string[] {
68
+ const rules: string[] = [];
69
+ for (const sheet of Array.from(document.styleSheets)) {
70
+ let cssRules: CSSRuleList;
71
+ try {
72
+ cssRules = sheet.cssRules;
73
+ } catch {
74
+ continue;
75
+ }
76
+ for (const rule of Array.from(cssRules)) {
77
+ rules.push(rule.cssText);
78
+ }
79
+ }
80
+ return rules;
81
+ }
82
+
83
+ describe('MobileNav scrim fades in', () => {
84
+ it('gives the ::backdrop a transparent starting style', () => {
85
+ render(
86
+ <MobileNav isOpen onOpenChange={() => {}} data-testid="mobile-nav">
87
+ <span>Nav content</span>
88
+ </MobileNav>,
89
+ );
90
+
91
+ const classes = Array.from(screen.getByTestId('mobile-nav').classList);
92
+ // Without this the scrim is opaque in the frame the dialog enters the top
93
+ // layer, so it has nothing to fade from and snaps in behind the drawer.
94
+ const startingStyleForThisDialog = injectedRules().filter(
95
+ rule =>
96
+ rule.startsWith('@starting-style') &&
97
+ rule.includes('::backdrop') &&
98
+ classes.some(cls => rule.includes(`.${cls}`)),
99
+ );
100
+
101
+ expect(startingStyleForThisDialog).toHaveLength(1);
102
+ expect(startingStyleForThisDialog[0]).toMatch(/opacity:\s*0/);
103
+ });
104
+ });
105
+
106
+ // =============================================================================
107
+ // Drawer slide-in — asserted on the style definition
108
+ // =============================================================================
109
+
110
+ const SOURCE = readFileSync(join(__dirname, 'MobileNav.tsx'), 'utf8');
111
+
112
+ /**
113
+ * The object literal a `styles.<name>` key is defined with, e.g. the value of
114
+ * `drawerStartOpen` inside the file's `stylex.create({...})` call.
115
+ */
116
+ function styleDefinition(name: string): ts.ObjectLiteralExpression {
117
+ const file = ts.createSourceFile(
118
+ 'MobileNav.tsx',
119
+ SOURCE,
120
+ ts.ScriptTarget.Latest,
121
+ true,
122
+ ts.ScriptKind.TSX,
123
+ );
124
+
125
+ let found: ts.ObjectLiteralExpression | undefined;
126
+ const visit = (node: ts.Node) => {
127
+ if (
128
+ ts.isPropertyAssignment(node) &&
129
+ ts.isIdentifier(node.name) &&
130
+ node.name.text === name &&
131
+ ts.isObjectLiteralExpression(node.initializer)
132
+ ) {
133
+ found = node.initializer;
134
+ }
135
+ ts.forEachChild(node, visit);
136
+ };
137
+ visit(file);
138
+
139
+ if (!found) {
140
+ throw new Error(`No style named "${name}" in MobileNav.tsx`);
141
+ }
142
+ return found;
143
+ }
144
+
145
+ /** The value of one property of a style definition, as source text. */
146
+ function property(style: ts.ObjectLiteralExpression, key: string): string {
147
+ const prop = style.properties.find(
148
+ p =>
149
+ ts.isPropertyAssignment(p) &&
150
+ (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) &&
151
+ p.name.text === key,
152
+ );
153
+
154
+ if (!prop) {
155
+ throw new Error(`No "${key}" in ${style.getText().slice(0, 40)}…`);
156
+ }
157
+ return (prop as ts.PropertyAssignment).initializer.getText();
158
+ }
159
+
160
+ describe('MobileNav dialog does not become a scroll container', () => {
161
+ it('clips the off-screen drawer with `clip`, not `hidden`', () => {
162
+ // This is the half of the fix with no visible declaration of its own
163
+ // purpose: `hidden` looks like a pure clipping choice and clips exactly as
164
+ // well, so it is an easy "harmless tidy-up" to make. It is not harmless —
165
+ // it makes the dialog a scroll container, and the entry animation then
166
+ // ticks in the CSSOM without ever painting. See the file header.
167
+ expect(property(styleDefinition('dialog'), 'overflow')).toBe("'clip'");
168
+ });
169
+ });
170
+
171
+ describe.each([
172
+ {
173
+ name: 'drawerStartOpen',
174
+ offscreen: 'translateX(-100%)',
175
+ offscreenRtl: 'translateX(100%)',
176
+ },
177
+ {
178
+ name: 'drawerEndOpen',
179
+ offscreen: 'translateX(100%)',
180
+ offscreenRtl: 'translateX(-100%)',
181
+ },
182
+ ])('MobileNav drawer slides in ($name)', ({name, offscreen, offscreenRtl}) => {
183
+ it('opens to the on-screen transform', () => {
184
+ expect(property(styleDefinition(name), 'transform')).toContain(
185
+ 'translateX(0)',
186
+ );
187
+ });
188
+
189
+ it('starts off-screen so the open transform has something to run from', () => {
190
+ const transform = property(styleDefinition(name), 'transform');
191
+
192
+ // The whole point: the first rendered frame needs the closed transform.
193
+ // Drop this and the drawer is simply there, fully open, on frame one —
194
+ // while the close still animates, which is what made the bug look like a
195
+ // missing entry animation rather than a missing starting style.
196
+ expect(transform).toContain('@starting-style');
197
+ expect(transform).toContain(offscreen);
198
+ // Mirrored, like the closed styles it has to match: sliding in from the
199
+ // wrong edge in RTL is as broken as not sliding at all.
200
+ expect(transform).toContain(offscreenRtl);
201
+ });
202
+
203
+ it('starts from the same edge the closed style parks it at', () => {
204
+ const closed = property(
205
+ styleDefinition(name.replace('Open', '')),
206
+ 'transform',
207
+ );
208
+
209
+ expect(closed).toContain(offscreen);
210
+ expect(closed).toContain(offscreenRtl);
211
+ });
212
+ });