@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
@@ -0,0 +1,109 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file MobileNavScrollbarGutter.test.tsx
5
+ * @input Uses vitest, @testing-library/react, MobileNav, a stubbed viewport
6
+ * @output Unit tests for the scrollbar gutter MobileNav reserves while open
7
+ * @position Testing; guards MobileNav.tsx against the open-drawer page shift
8
+ *
9
+ * MobileNav clips the document to lock background scroll, which hides a
10
+ * classic scrollbar and widens the layout viewport by its width — the page
11
+ * behind the drawer jumps sideways. The clip has to be paired with holding
12
+ * that gutter open.
13
+ *
14
+ * SYNC: When MobileNav.tsx changes, update tests to match new behavior
15
+ */
16
+
17
+ import {describe, it, expect, beforeAll, afterEach} from 'vitest';
18
+ import {render, cleanup} from '@testing-library/react';
19
+ import {MobileNav} from './MobileNav';
20
+
21
+ beforeAll(() => {
22
+ // jsdom doesn't implement showModal/close on <dialog>
23
+ HTMLDialogElement.prototype.showModal =
24
+ HTMLDialogElement.prototype.showModal ||
25
+ function (this: HTMLDialogElement) {
26
+ this.setAttribute('open', '');
27
+ };
28
+ HTMLDialogElement.prototype.close =
29
+ HTMLDialogElement.prototype.close ||
30
+ function (this: HTMLDialogElement) {
31
+ this.removeAttribute('open');
32
+ };
33
+ });
34
+
35
+ /** jsdom does no layout, so both halves of the measurement are stubbed. */
36
+ function stubViewport(innerWidth: number, clientWidth: number) {
37
+ Object.defineProperty(window, 'innerWidth', {
38
+ value: innerWidth,
39
+ configurable: true,
40
+ writable: true,
41
+ });
42
+ Object.defineProperty(document.documentElement, 'clientWidth', {
43
+ value: clientWidth,
44
+ configurable: true,
45
+ });
46
+ }
47
+
48
+ const rootGutter = () => document.documentElement.style.scrollbarGutter;
49
+
50
+ describe('MobileNav scrollbar gutter', () => {
51
+ afterEach(() => {
52
+ cleanup();
53
+ document.documentElement.style.cssText = '';
54
+ // @ts-expect-error -- drop the viewport stub so jsdom's own value comes back
55
+ delete document.documentElement.clientWidth;
56
+ });
57
+
58
+ it('holds the gutter open while the drawer is open', () => {
59
+ stubViewport(1024, 1009);
60
+
61
+ const view = render(
62
+ <MobileNav isOpen={true} onOpenChange={() => {}}>
63
+ <span>Nav content</span>
64
+ </MobileNav>,
65
+ );
66
+
67
+ expect(document.documentElement.style.overflow).toBe('clip');
68
+ expect(rootGutter()).toBe('stable');
69
+
70
+ view.unmount();
71
+
72
+ expect(document.documentElement.style.overflow).toBe('');
73
+ expect(rootGutter()).toBe('');
74
+ });
75
+
76
+ it('gives the gutter back when the drawer closes', () => {
77
+ stubViewport(1024, 1009);
78
+
79
+ const view = render(
80
+ <MobileNav isOpen={true} onOpenChange={() => {}}>
81
+ <span>Nav content</span>
82
+ </MobileNav>,
83
+ );
84
+
85
+ expect(rootGutter()).toBe('stable');
86
+
87
+ view.rerender(
88
+ <MobileNav isOpen={false} onOpenChange={() => {}}>
89
+ <span>Nav content</span>
90
+ </MobileNav>,
91
+ );
92
+
93
+ expect(rootGutter()).toBe('');
94
+ });
95
+
96
+ it('holds nothing when the scrollbar is an overlay one', () => {
97
+ stubViewport(1024, 1024);
98
+
99
+ render(
100
+ <MobileNav isOpen={true} onOpenChange={() => {}}>
101
+ <span>Nav content</span>
102
+ </MobileNav>,
103
+ );
104
+
105
+ expect(document.documentElement.style.overflow).toBe('clip');
106
+ expect(rootGutter()).toBe('');
107
+ expect(document.documentElement.style.paddingRight).toBe('');
108
+ });
109
+ });
@@ -1790,7 +1790,7 @@ describe('MultiSelector clear icon theme target', () => {
1790
1790
  expect(css).toContain('.astryx-multi-selector-clear-icon {');
1791
1791
  expect(css).toContain('width: 12px');
1792
1792
  expect(css).toContain('height: 12px');
1793
- expect(css).toContain('.astryx-multi-selector-clear-icon:hover {');
1793
+ expect(css).toContain('.astryx-multi-selector-clear-icon:hover');
1794
1794
  expect(css).toContain('color: var(--color-icon-primary)');
1795
1795
  });
1796
1796
  });
@@ -103,7 +103,10 @@ const styles = stylex.create({
103
103
  fontSize: typeScaleVars['--text-label-size'],
104
104
  lineHeight: typeScaleVars['--text-label-leading'],
105
105
  color: colorVars['--color-text-primary'],
106
- cursor: 'pointer',
106
+ cursor: {
107
+ default: 'pointer',
108
+ ':is(:disabled,[aria-disabled="true"])': 'default',
109
+ },
107
110
  },
108
111
  // Trigger button — the actual combobox button, visually integrated with the container
109
112
  trigger: {
@@ -124,7 +127,10 @@ const styles = stylex.create({
124
127
  fontSize: 'inherit',
125
128
  lineHeight: 'inherit',
126
129
  color: 'inherit',
127
- cursor: 'pointer',
130
+ cursor: {
131
+ default: 'pointer',
132
+ ':is(:disabled,[aria-disabled="true"])': 'default',
133
+ },
128
134
  // The wrapper (inputWrapperStyles.base) renders the focus ring via
129
135
  // :focus-within when this button is focused, matching
130
136
  // TextInput/NumberInput/Selector. The button must not draw its own
@@ -190,16 +196,17 @@ const styles = stylex.create({
190
196
  backgroundColor: 'transparent',
191
197
  backgroundImage: {
192
198
  default: null,
193
- ':hover': {
199
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
194
200
  '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
195
201
  },
196
202
  ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
197
203
  },
198
204
  boxShadow: {
199
205
  default: 'none',
200
- ':hover:not(:focus-within)': {
201
- '@media (hover: hover)': 'none',
202
- },
206
+ ':hover:not(:focus-within):where(:not(:disabled,[aria-disabled="true"]))':
207
+ {
208
+ '@media (hover: hover)': 'none',
209
+ },
203
210
  ':focus-within': 'none',
204
211
  },
205
212
  fontWeight: fontWeightVars['--font-weight-medium'],
@@ -229,7 +236,10 @@ const styles = stylex.create({
229
236
  borderStyle: 'none',
230
237
  backgroundColor: 'transparent',
231
238
  color: 'inherit',
232
- cursor: 'pointer',
239
+ cursor: {
240
+ default: 'pointer',
241
+ ':is(:disabled,[aria-disabled="true"])': 'default',
242
+ },
233
243
  borderRadius: radiusVars['--radius-element'],
234
244
  },
235
245
 
@@ -251,7 +261,10 @@ const styles = stylex.create({
251
261
  display: 'flex',
252
262
  alignItems: 'center',
253
263
  gap: spacingVars['--spacing-2'],
254
- cursor: 'pointer',
264
+ cursor: {
265
+ default: 'pointer',
266
+ ':is(:disabled,[aria-disabled="true"])': 'default',
267
+ },
255
268
  },
256
269
 
257
270
  // Section heading. Plain secondary text, no rules — the same treatment
@@ -282,7 +295,10 @@ const styles = stylex.create({
282
295
  gap: spacingVars['--spacing-2'],
283
296
  width: '100%',
284
297
  borderRadius: radiusVars['--radius-element'],
285
- cursor: 'pointer',
298
+ cursor: {
299
+ default: 'pointer',
300
+ ':is(:disabled,[aria-disabled="true"])': 'default',
301
+ },
286
302
  // Row typography lives here, not on the label span, so a theme override on
287
303
  // the row target reaches both the fallback label and renderOption output
288
304
  // (a declaration on the span would win over the inherited row value).
@@ -301,7 +317,7 @@ const styles = stylex.create({
301
317
  itemDisabled: {
302
318
  opacity: 0.5,
303
319
  color: colorVars['--color-text-disabled'],
304
- cursor: 'not-allowed',
320
+ cursor: 'default',
305
321
  },
306
322
 
307
323
  // Decorative checkbox (non-interactive, purely visual)
@@ -65,14 +65,17 @@ export const navItemStyles = stylex.create({
65
65
  backgroundColor: 'transparent',
66
66
  color: colorVars['--color-text-primary'],
67
67
  textDecoration: 'none',
68
- cursor: 'pointer',
68
+ cursor: {
69
+ default: 'pointer',
70
+ ':is(:disabled,[aria-disabled="true"])': 'default',
71
+ },
69
72
  fontFamily: 'inherit',
70
73
  fontSize: typeScaleVars['--text-label-size'],
71
74
  fontWeight: fontWeightVars['--font-weight-normal'],
72
75
  lineHeight: typeScaleVars['--text-label-leading'],
73
76
  textAlign: 'start',
74
77
  boxSizing: 'border-box',
75
- ':hover': {
78
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
76
79
  '@media (hover: hover)': {
77
80
  backgroundColor: colorVars['--color-overlay-hover'],
78
81
  },
@@ -98,7 +101,7 @@ export const navItemStyles = stylex.create({
98
101
  '@media (forced-colors: active)': 'HighlightText',
99
102
  },
100
103
  fontWeight: fontWeightVars['--font-weight-medium'],
101
- ':hover': {
104
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
102
105
  '@media (hover: hover)': {
103
106
  backgroundColor: {
104
107
  default: colorVars['--color-neutral'],
@@ -120,7 +123,7 @@ export const navItemStyles = stylex.create({
120
123
  /** Disabled state — muted color, no interaction */
121
124
  disabled: {
122
125
  color: colorVars['--color-text-disabled'],
123
- cursor: 'not-allowed',
126
+ cursor: 'default',
124
127
  pointerEvents: 'none' as const,
125
128
  },
126
129
 
@@ -43,12 +43,15 @@ const styles = stylex.create({
43
43
  backgroundColor: {
44
44
  default: 'transparent',
45
45
  ':focus': colorVars['--color-overlay-hover'],
46
- ':hover': {
46
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
47
47
  '@media (hover: hover)': colorVars['--color-overlay-hover'],
48
48
  },
49
49
  },
50
50
  border: 'none',
51
- cursor: 'pointer',
51
+ cursor: {
52
+ default: 'pointer',
53
+ ':is(:disabled,[aria-disabled="true"])': 'default',
54
+ },
52
55
  textAlign: 'start',
53
56
  outline: 'none',
54
57
  textDecoration: 'none',
@@ -61,7 +64,7 @@ const styles = stylex.create({
61
64
  },
62
65
  disabled: {
63
66
  opacity: 0.5,
64
- cursor: 'not-allowed',
67
+ cursor: 'default',
65
68
  },
66
69
  });
67
70
 
@@ -219,6 +219,19 @@ export const docs = {
219
219
  states: ['disabled', 'readonly'],
220
220
  },
221
221
  ],
222
+ derived: [
223
+ // `padding` in any spelling — the shorthand, `paddingBlock`, or a lone
224
+ // `paddingBlockStart` — is parsed by the shared container expansion and
225
+ // emitted as normalized per-side `--astryx-number-input-padding-*`
226
+ // tokens. The wrapper and the number-stepper column both read those, so
227
+ // the column stays flush with the field edges under a themed padding.
228
+ {property: 'padding', expand: 'container'},
229
+ // Scoped to this component's own subtree: the stepper column's outer
230
+ // corners follow the field radius, so a themed `number-input`
231
+ // borderRadius has to reach the var the column reads, not just the
232
+ // wrapper's own `border-radius`.
233
+ {property: 'borderRadius', vars: ['--_field-radius']},
234
+ ],
222
235
  },
223
236
  usage: {
224
237
  description:
@@ -475,6 +488,17 @@ export const docsZh = {
475
488
  states: ['disabled', 'readonly'],
476
489
  },
477
490
  ],
491
+ derived: [
492
+ // 任何写法的 `padding`(简写、`paddingBlock`,或单独的
493
+ // `paddingBlockStart`)都由共享的 container 展开解析,并输出为规范化的
494
+ // 每侧 `--astryx-number-input-padding-*` 令牌。容器与数字步进器列都读取
495
+ // 这些令牌,因此在主题化内边距下步进器仍与字段边缘齐平。
496
+ {property: 'padding', expand: 'container'},
497
+ // 作用域限于该组件自身的子树:步进器列的外角跟随字段圆角,因此主题化的
498
+ // `number-input` borderRadius 必须传到步进器读取的变量,而不只是容器
499
+ // 自身的 `border-radius`。
500
+ {property: 'borderRadius', vars: ['--_field-radius']},
501
+ ],
478
502
  },
479
503
  usage: {
480
504
  description:
@@ -15,6 +15,8 @@ import userEvent from '@testing-library/user-event';
15
15
  import {TestIcon} from '../__tests__/TestIcon';
16
16
  import {InputGroup} from '../InputGroup';
17
17
  import {NumberInput} from './NumberInput';
18
+ import {defineTheme} from '../theme/defineTheme';
19
+ import {generateThemeCSS} from '../theme/generateThemeRules';
18
20
  import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
19
21
 
20
22
  // FieldStatus announces status messages through the persistent useAnnounce
@@ -1745,3 +1747,139 @@ describe('NumberInput readonly theme state', () => {
1745
1747
  expect(root).not.toHaveAttribute('data-readonly');
1746
1748
  });
1747
1749
  });
1750
+
1751
+ describe('NumberInput stepper padding coupling', () => {
1752
+ function generateThemeTestCSS(theme: Parameters<typeof generateThemeCSS>[0]) {
1753
+ const {prose, component} = generateThemeCSS(theme);
1754
+ return [prose, component].filter(Boolean).join('\n\n');
1755
+ }
1756
+
1757
+ // The chains the wrapper and the stepper column both read. Spelled out here
1758
+ // rather than imported so the test pins the actual token names a theme sets:
1759
+ // if the chain is renamed or a level is dropped, this fails.
1760
+ const BLOCK_START =
1761
+ 'var(--astryx-number-input-padding-block-start, var(--astryx-number-input-padding, var(--spacing-1)))';
1762
+ const BLOCK_END =
1763
+ 'var(--astryx-number-input-padding-block-end, var(--astryx-number-input-padding, var(--spacing-1)))';
1764
+
1765
+ // jsdom re-serializes a var() chain without the spaces after its commas.
1766
+ const noSpace = (value: string) => value.replace(/\s+/g, '');
1767
+
1768
+ it('reads its padding from the public number-input padding tokens', () => {
1769
+ const {container} = render(
1770
+ <NumberInput
1771
+ label="Quantity"
1772
+ value={5}
1773
+ onChange={() => {}}
1774
+ hasNumberSteppers
1775
+ />,
1776
+ );
1777
+ const root = container.querySelector('.astryx-number-input') as HTMLElement;
1778
+ // Read as physical properties: StyleX compiles the block-axis logical
1779
+ // properties to `padding-top`/`padding-bottom` (identical in every
1780
+ // horizontal writing mode). Per side, not through the shared field base's
1781
+ // `paddingBlock` shorthand, so each edge can be cancelled on its own.
1782
+ const wrapper = getComputedStyle(root);
1783
+ expect(noSpace(wrapper.paddingTop)).toBe(noSpace(BLOCK_START));
1784
+ expect(noSpace(wrapper.paddingBottom)).toBe(noSpace(BLOCK_END));
1785
+
1786
+ // The column cancels the wrapper's block padding by reading the same
1787
+ // tokens — not a hardcoded default — so it stays flush when a theme
1788
+ // changes the padding. The column is the stepper buttons' direct parent.
1789
+ const steppers = container.querySelector(
1790
+ 'button[aria-label="Increment Quantity"]',
1791
+ )?.parentElement as HTMLElement;
1792
+ const column = getComputedStyle(steppers);
1793
+ expect(noSpace(column.marginTop)).toBe(
1794
+ noSpace(`calc(-1 * ${BLOCK_START})`),
1795
+ );
1796
+ expect(noSpace(column.marginBottom)).toBe(
1797
+ noSpace(`calc(-1 * ${BLOCK_END})`),
1798
+ );
1799
+ });
1800
+
1801
+ // jsdom cannot resolve the @layer cascade, so the generated CSS is the
1802
+ // proof. Each case is a spelling of the SAME declaration: the column has to
1803
+ // track all of them, not just the one the component happened to name.
1804
+ describe('a themed padding reaches the steppers in every spelling', () => {
1805
+ it.each([
1806
+ [
1807
+ 'the padding shorthand, two values',
1808
+ {padding: '14px 20px'},
1809
+ [
1810
+ '--astryx-number-input-padding-block-start: 14px',
1811
+ '--astryx-number-input-padding-block-end: 14px',
1812
+ '--astryx-number-input-padding-inline: 20px',
1813
+ ],
1814
+ ],
1815
+ [
1816
+ 'the padding shorthand, one value',
1817
+ {padding: '10px'},
1818
+ ['--astryx-number-input-padding: 10px'],
1819
+ ],
1820
+ [
1821
+ 'the block/inline longhands',
1822
+ {paddingBlock: '10px', paddingInline: '20px'},
1823
+ [
1824
+ '--astryx-number-input-padding-block-start: 10px',
1825
+ '--astryx-number-input-padding-block-end: 10px',
1826
+ '--astryx-number-input-padding-inline: 20px',
1827
+ ],
1828
+ ],
1829
+ [
1830
+ 'a single edge longhand',
1831
+ {paddingBlockStart: '12px'},
1832
+ ['--astryx-number-input-padding-block-start: 12px'],
1833
+ ],
1834
+ [
1835
+ // A single var carrying "4px 12px" would make the column's
1836
+ // calc(-1 * …) invalid and drop the margin outright; the expansion
1837
+ // splits the two values into their own edges instead.
1838
+ 'an asymmetric block padding',
1839
+ {paddingBlock: '4px 12px'},
1840
+ [
1841
+ '--astryx-number-input-padding-block-start: 4px',
1842
+ '--astryx-number-input-padding-block-end: 12px',
1843
+ ],
1844
+ ],
1845
+ [
1846
+ // `paddingTop` is `paddingBlockStart` in every horizontal writing
1847
+ // mode, so it normalizes onto the same tokens. The physical inline
1848
+ // pair is deliberately not mapped — see generateThemeRules.
1849
+ 'the physical block longhands',
1850
+ {paddingTop: '14px', paddingBottom: '6px'},
1851
+ [
1852
+ '--astryx-number-input-padding-block-start: 14px',
1853
+ '--astryx-number-input-padding-block-end: 6px',
1854
+ ],
1855
+ ],
1856
+ ])('%s', (_label, base, expected) => {
1857
+ const theme = defineTheme({
1858
+ name: 'number-input-padding-spelling-test',
1859
+ components: {'number-input': {base}},
1860
+ });
1861
+ const css = generateThemeTestCSS(theme);
1862
+ for (const declaration of expected) {
1863
+ expect(css).toContain(declaration);
1864
+ }
1865
+ // The expansion consumes the padding: a raw declaration left on the
1866
+ // wrapper is padding the column cannot see, which is the gap itself.
1867
+ expect(css).not.toMatch(
1868
+ /^\s*padding(-block|-inline|-top|-bottom)?(-start|-end)?:/m,
1869
+ );
1870
+ });
1871
+ });
1872
+
1873
+ it('carries a themed border radius to the stepper column corners', () => {
1874
+ // The column's outer corners read --_field-radius. Emitting only
1875
+ // `border-radius` on the wrapper rounds the field and leaves the steppers
1876
+ // at the default radius, which is visible wherever the two differ.
1877
+ const theme = defineTheme({
1878
+ name: 'number-input-radius-test',
1879
+ components: {'number-input': {base: {borderRadius: '2px'}}},
1880
+ });
1881
+ const css = generateThemeTestCSS(theme);
1882
+ expect(css).toContain('--_field-radius: 2px');
1883
+ expect(css).toContain('border-radius: 2px');
1884
+ });
1885
+ });
@@ -31,7 +31,6 @@ import {
31
31
  colorVars,
32
32
  sizeVars,
33
33
  spacingVars,
34
- radiusVars,
35
34
  typographyVars,
36
35
  typeScaleVars,
37
36
  borderVars,
@@ -56,9 +55,41 @@ import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
56
55
  import {useResolvedRequired} from '../hooks/useResolvedRequired';
57
56
  import {useInputGroup} from '../InputGroup/InputGroupContext';
58
57
 
58
+ // Public padding tokens for the `number-input` theme target. A theme writes an
59
+ // ordinary `padding` (in ANY spelling — the shorthand, `paddingBlock`, or a
60
+ // single `paddingBlockStart`) and the pipeline's `container` expansion parses
61
+ // it and emits these normalized per-side tokens; the wrapper and the stepper
62
+ // column both read them, so the column tracks whatever the theme sets instead
63
+ // of assuming the default. Routing through the shared expansion rather than a
64
+ // hand-rolled property→var mapping is what makes every spelling work: a
65
+ // mapping only fires for the exact property name it names.
66
+ //
67
+ // Read order per level: `var(--astryx-…, <next level>)`, terminating at the
68
+ // shared field defaults (NOT the container default --spacing-4, which is a
69
+ // layout metric and would resize every themed field). Built as chained const
70
+ // strings — no function calls — so StyleX can statically analyze them; same
71
+ // shape as the card/section/dialog chains in Layout/container.stylex.ts.
72
+ const FIELD_PAD_BLOCK = spacingVars['--spacing-1'];
73
+ const FIELD_PAD_INLINE = spacingVars['--spacing-2'];
74
+ const padBlockAll = `var(--astryx-number-input-padding, ${FIELD_PAD_BLOCK})`;
75
+ const padInlineAll = `var(--astryx-number-input-padding, ${FIELD_PAD_INLINE})`;
76
+ const padInline = `var(--astryx-number-input-padding-inline, ${padInlineAll})`;
77
+ const padInlineStart = `var(--astryx-number-input-padding-inline-start, ${padInline})`;
78
+ const padInlineEnd = `var(--astryx-number-input-padding-inline-end, ${padInline})`;
79
+ const padBlockStart = `var(--astryx-number-input-padding-block-start, ${padBlockAll})`;
80
+ const padBlockEnd = `var(--astryx-number-input-padding-block-end, ${padBlockAll})`;
81
+
59
82
  const styles = stylex.create({
60
83
  wrapper: {
61
84
  zIndex: 1,
85
+ // Applied per side rather than through the shared field base's
86
+ // `paddingBlock`/`paddingInline` shorthands, because the stepper column
87
+ // has to cancel the block padding edge by edge — an asymmetric
88
+ // `paddingBlock: 4px 12px` needs two different negative margins.
89
+ paddingBlockStart: padBlockStart,
90
+ paddingBlockEnd: padBlockEnd,
91
+ paddingInlineStart: padInlineStart,
92
+ paddingInlineEnd: padInlineEnd,
62
93
  },
63
94
  wrapperWithNumberSteppers: {
64
95
  paddingInlineEnd: 0,
@@ -84,7 +115,7 @@ const styles = stylex.create({
84
115
  },
85
116
  },
86
117
  inputDisabled: {
87
- cursor: 'not-allowed',
118
+ cursor: 'default',
88
119
  },
89
120
  inputInvalid: {
90
121
  color: colorVars['--color-text-secondary'],
@@ -102,13 +133,18 @@ const styles = stylex.create({
102
133
  flexDirection: 'column',
103
134
  flexShrink: 0,
104
135
  width: spacingVars['--spacing-4'],
105
- marginBlock: `calc(-1 * ${spacingVars['--spacing-1']})`,
136
+ // Cancel the wrapper's block padding edge by edge so the column spans the
137
+ // field's full height. Reading the same tokens the wrapper applies is what
138
+ // keeps it flush under a themed padding — including an asymmetric one,
139
+ // where a single `marginBlock` would be wrong at one end.
140
+ marginBlockStart: `calc(-1 * ${padBlockStart})`,
141
+ marginBlockEnd: `calc(-1 * ${padBlockEnd})`,
106
142
  borderInlineStartWidth: borderVars['--border-width'],
107
143
  borderInlineStartStyle: 'solid',
108
144
  borderInlineStartColor: colorVars['--color-border-emphasized'],
109
145
  overflow: 'hidden',
110
- borderStartEndRadius: radiusVars['--radius-element'],
111
- borderEndEndRadius: radiusVars['--radius-element'],
146
+ borderStartEndRadius: 'var(--_field-radius)',
147
+ borderEndEndRadius: 'var(--_field-radius)',
112
148
  },
113
149
  numberStepperButton: {
114
150
  boxSizing: 'border-box',
@@ -125,17 +161,20 @@ const styles = stylex.create({
125
161
  backgroundColor: colorVars['--color-background-surface'],
126
162
  backgroundImage: {
127
163
  default: null,
128
- ':hover': {
164
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
129
165
  '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
130
166
  },
131
167
  ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
132
168
  },
133
- cursor: 'pointer',
169
+ cursor: {
170
+ default: 'pointer',
171
+ ':is(:disabled,[aria-disabled="true"])': 'default',
172
+ },
134
173
  outline: 'none',
135
174
  },
136
175
  numberStepperButtonDisabled: {
137
176
  color: colorVars['--color-icon-disabled'],
138
- cursor: 'not-allowed',
177
+ cursor: 'default',
139
178
  backgroundImage: 'none',
140
179
  },
141
180
  decrementButton: {
@@ -190,7 +190,10 @@ const styles = stylex.create({
190
190
  borderRadius: radiusVars['--radius-element'],
191
191
  boxSizing: 'border-box',
192
192
  color: colorVars['--color-text-secondary'],
193
- cursor: 'pointer',
193
+ cursor: {
194
+ default: 'pointer',
195
+ ':is(:disabled,[aria-disabled="true"])': 'default',
196
+ },
194
197
  display: 'flex',
195
198
  fontWeight: fontWeightVars['--font-weight-normal'],
196
199
  outline: 'none',
@@ -203,7 +206,7 @@ const styles = stylex.create({
203
206
  width: '100%',
204
207
  fontSize: typeScaleVars['--text-body-size'],
205
208
  lineHeight: typeScaleVars['--text-body-leading'],
206
- ':hover': {
209
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
207
210
  '@media (hover: hover)': {
208
211
  backgroundColor: colorVars['--color-overlay-hover'],
209
212
  color: colorVars['--color-text-primary'],
@@ -214,7 +214,10 @@ const styles = stylex.create({
214
214
  padding: 0,
215
215
  borderRadius: '50%',
216
216
  backgroundColor: colorVars['--color-neutral'],
217
- cursor: 'pointer',
217
+ cursor: {
218
+ default: 'pointer',
219
+ ':is(:disabled,[aria-disabled="true"])': 'default',
220
+ },
218
221
  transitionProperty: 'background-color',
219
222
  transitionDuration: durationVars['--duration-fast'],
220
223
  transitionTimingFunction: easeVars['--ease-standard'],
@@ -227,7 +230,7 @@ const styles = stylex.create({
227
230
  backgroundColor: colorVars['--color-accent'],
228
231
  },
229
232
  dotDisabled: {
230
- cursor: 'not-allowed',
233
+ cursor: 'default',
231
234
  opacity: 0.5,
232
235
  },
233
236
  activePage: {
@@ -2,7 +2,8 @@
2
2
 
3
3
  /**
4
4
  * @file Popover.test.tsx
5
- * @input Uses vitest, @testing-library/react, Popover component
5
+ * @input Uses vitest, @testing-library/react, Popover, Dialog,
6
+ * SegmentedControl
6
7
  * @output Unit tests for Popover component behavior
7
8
  * @position Testing; validates Popover.tsx implementation
8
9
  *
@@ -14,6 +15,7 @@ import {render, screen, fireEvent} from '@testing-library/react';
14
15
  import React, {useRef} from 'react';
15
16
  import {Popover} from './Popover';
16
17
  import {Dialog} from '../Dialog';
18
+ import {SegmentedControl, SegmentedControlItem} from '../SegmentedControl';
17
19
 
18
20
  // Store original matches to restore later
19
21
  const originalMatches = HTMLElement.prototype.matches;
@@ -306,6 +308,30 @@ describe('Popover', () => {
306
308
  expect(trigger).toHaveAttribute('aria-expanded', 'false');
307
309
  });
308
310
 
311
+ it('dismisses on Escape pressed inside a roving-focus list', () => {
312
+ render(
313
+ <Popover
314
+ content={
315
+ <SegmentedControl value="grid" onChange={() => {}} label="View">
316
+ <SegmentedControlItem value="grid" label="Grid" />
317
+ <SegmentedControlItem value="list" label="List" />
318
+ </SegmentedControl>
319
+ }
320
+ label="Test">
321
+ <button type="button">Open</button>
322
+ </Popover>,
323
+ );
324
+ const trigger = screen.getByRole('button', {name: 'Open'});
325
+ fireEvent.click(trigger);
326
+ expect(trigger).toHaveAttribute('aria-expanded', 'true');
327
+
328
+ // From the segment, so the list's own key handler runs first. jsdom has
329
+ // no popover display, so the open content still reads as hidden.
330
+ const segment = screen.getByRole('radio', {name: 'Grid', hidden: true});
331
+ fireEvent.keyDown(segment, {key: 'Escape'});
332
+ expect(trigger).toHaveAttribute('aria-expanded', 'false');
333
+ });
334
+
309
335
  it('stays open on Escape when hasEscapeDismiss is false', () => {
310
336
  render(
311
337
  <Popover