@astryxdesign/core 0.4.7 → 0.5.0-canary.1f8525f

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 (566) hide show
  1. package/CHANGELOG.md +161 -1
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +3 -2
  4. package/dist/AspectRatio/AspectRatio.d.ts +24 -0
  5. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  6. package/dist/AspectRatio/AspectRatio.js +23 -4
  7. package/dist/Avatar/Avatar.d.ts +25 -1
  8. package/dist/Avatar/Avatar.d.ts.map +1 -1
  9. package/dist/Avatar/Avatar.js +58 -19
  10. package/dist/Avatar/index.d.ts +2 -2
  11. package/dist/Avatar/index.d.ts.map +1 -1
  12. package/dist/Avatar/index.js +1 -1
  13. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  14. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  15. package/dist/AvatarGroup/AvatarGroup.js +8 -4
  16. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  17. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  19. package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
  20. package/dist/Banner/Banner.d.ts +40 -15
  21. package/dist/Banner/Banner.d.ts.map +1 -1
  22. package/dist/Banner/Banner.js +51 -18
  23. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  24. package/dist/BottomSheet/BottomSheet.js +17 -4
  25. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  26. package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
  27. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  28. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
  29. package/dist/Button/Button.d.ts.map +1 -1
  30. package/dist/Button/Button.js +5 -4
  31. package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
  32. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  33. package/dist/ButtonGroup/ButtonGroup.js +26 -7
  34. package/dist/Calendar/Calendar.d.ts +3 -1
  35. package/dist/Calendar/Calendar.d.ts.map +1 -1
  36. package/dist/Calendar/Calendar.js +14 -15
  37. package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
  38. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
  39. package/dist/Calendar/getInitialFocusDate.js +62 -0
  40. package/dist/Calendar/styles.d.ts +5 -14
  41. package/dist/Calendar/styles.d.ts.map +1 -1
  42. package/dist/Calendar/styles.js +15 -15
  43. package/dist/Carousel/Carousel.d.ts.map +1 -1
  44. package/dist/Carousel/Carousel.js +3 -3
  45. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  46. package/dist/Chat/ChatComposerInput.js +2 -3
  47. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  48. package/dist/Chat/ChatLayout.js +3 -3
  49. package/dist/Chat/ChatMessageList.d.ts +22 -3
  50. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  51. package/dist/Chat/ChatMessageList.js +6 -3
  52. package/dist/Chat/ChatTokenizedText.d.ts +2 -0
  53. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  54. package/dist/Chat/ChatTokenizedText.js +11 -6
  55. package/dist/Chat/useChatComposerTokens.js +1 -1
  56. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  57. package/dist/CheckboxInput/CheckboxInput.js +10 -3
  58. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  59. package/dist/ClickableCard/ClickableCard.js +3 -3
  60. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  61. package/dist/CodeBlock/CodeBlock.js +15 -4
  62. package/dist/CodeBlock/highlightRanges.js +1 -1
  63. package/dist/CodeBlock/highlightStyles.js +13 -13
  64. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  65. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  66. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  67. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  68. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  69. package/dist/ContextMenu/ContextMenu.js +4 -3
  70. package/dist/DateInput/DateInput.d.ts +43 -0
  71. package/dist/DateInput/DateInput.d.ts.map +1 -1
  72. package/dist/DateInput/DateInput.js +22 -2
  73. package/dist/DateInput/NativeDateField.d.ts +10 -0
  74. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  75. package/dist/DateInput/NativeDateField.js +494 -0
  76. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  77. package/dist/DateInput/TouchDateField.js +38 -4
  78. package/dist/DateInput/index.d.ts +1 -1
  79. package/dist/DateInput/index.d.ts.map +1 -1
  80. package/dist/DateInput/nativeDateSegments.d.ts +22 -0
  81. package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
  82. package/dist/DateInput/nativeDateSegments.js +111 -0
  83. package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
  84. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  85. package/dist/DateTimeInput/DateTimeInput.js +406 -12
  86. package/dist/DateTimeInput/index.d.ts +1 -1
  87. package/dist/DateTimeInput/index.d.ts.map +1 -1
  88. package/dist/Dialog/Dialog.d.ts +7 -1
  89. package/dist/Dialog/Dialog.d.ts.map +1 -1
  90. package/dist/Dialog/Dialog.js +89 -58
  91. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  92. package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
  93. package/dist/Field/FieldLabel.d.ts.map +1 -1
  94. package/dist/Field/FieldLabel.js +9 -1
  95. package/dist/FileInput/FileInput.d.ts.map +1 -1
  96. package/dist/FileInput/FileInput.js +3 -2
  97. package/dist/Heading/Heading.d.ts.map +1 -1
  98. package/dist/Heading/Heading.js +6 -2
  99. package/dist/HoverCard/HoverCard.d.ts +6 -0
  100. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  101. package/dist/HoverCard/HoverCard.js +52 -3
  102. package/dist/HoverCard/useHoverCard.d.ts +16 -2
  103. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  104. package/dist/HoverCard/useHoverCard.js +74 -26
  105. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  106. package/dist/Indicator/CheckboxIndicator.js +6 -2
  107. package/dist/Item/Item.d.ts.map +1 -1
  108. package/dist/Item/Item.js +4 -2
  109. package/dist/Kbd/Kbd.d.ts.map +1 -1
  110. package/dist/Kbd/Kbd.js +2 -19
  111. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  112. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  113. package/dist/Layer/LayerDepthContext.js +66 -0
  114. package/dist/Layer/index.d.ts +3 -0
  115. package/dist/Layer/index.d.ts.map +1 -1
  116. package/dist/Layer/index.js +4 -0
  117. package/dist/Layer/layerStack.d.ts +98 -0
  118. package/dist/Layer/layerStack.d.ts.map +1 -0
  119. package/dist/Layer/layerStack.js +306 -0
  120. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  121. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  122. package/dist/Layer/useLayerDismissal.js +91 -0
  123. package/dist/Lightbox/Lightbox.d.ts +1 -0
  124. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  125. package/dist/Lightbox/Lightbox.js +103 -81
  126. package/dist/Markdown/index.d.ts +1 -1
  127. package/dist/Markdown/index.d.ts.map +1 -1
  128. package/dist/Markdown/parser.d.ts +38 -1
  129. package/dist/Markdown/parser.d.ts.map +1 -1
  130. package/dist/Markdown/parser.js +177 -29
  131. package/dist/MobileNav/MobileNav.d.ts +6 -1
  132. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  133. package/dist/MobileNav/MobileNav.js +61 -36
  134. package/dist/MultiSelector/MultiSelector.d.ts +15 -1
  135. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  136. package/dist/MultiSelector/MultiSelector.js +17 -6
  137. package/dist/MultiSelector/index.d.ts +1 -1
  138. package/dist/MultiSelector/index.d.ts.map +1 -1
  139. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  140. package/dist/NavIcon/NavIcon.js +5 -1
  141. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  142. package/dist/NavMenu/NavHeadingMenu.js +3 -2
  143. package/dist/NumberInput/NumberInput.d.ts +1 -0
  144. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  145. package/dist/NumberInput/NumberInput.js +27 -37
  146. package/dist/NumberInput/numberParser.d.ts +51 -0
  147. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  148. package/dist/NumberInput/numberParser.js +333 -0
  149. package/dist/Outline/Outline.d.ts.map +1 -1
  150. package/dist/Outline/Outline.js +3 -2
  151. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  152. package/dist/OverflowList/OverflowList.js +3 -2
  153. package/dist/Overlay/Overlay.d.ts.map +1 -1
  154. package/dist/Overlay/Overlay.js +3 -2
  155. package/dist/Popover/usePopover.d.ts.map +1 -1
  156. package/dist/Popover/usePopover.js +20 -17
  157. package/dist/PowerSearch/PowerSearch.d.ts +8 -2
  158. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  159. package/dist/PowerSearch/PowerSearch.js +19 -6
  160. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
  161. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  162. package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
  163. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
  164. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  165. package/dist/PowerSearch/PowerSearchValueEditor.js +19 -9
  166. package/dist/PowerSearch/types.d.ts +2 -0
  167. package/dist/PowerSearch/types.d.ts.map +1 -1
  168. package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
  169. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  170. package/dist/PowerSearch/usePowerSearchSource.js +14 -5
  171. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  172. package/dist/ProgressBar/ProgressBar.js +18 -5
  173. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  174. package/dist/Resizable/ResizeHandle.js +3 -2
  175. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  176. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  177. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  178. package/dist/SelectableCard/SelectableCard.js +3 -3
  179. package/dist/Selector/Selector.d.ts.map +1 -1
  180. package/dist/Selector/Selector.js +5 -0
  181. package/dist/SideNav/SideNav.d.ts.map +1 -1
  182. package/dist/SideNav/SideNav.js +4 -3
  183. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  184. package/dist/SideNav/SideNavHeading.js +8 -7
  185. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  186. package/dist/SideNav/SideNavItem.js +4 -3
  187. package/dist/Slider/Slider.d.ts.map +1 -1
  188. package/dist/Slider/Slider.js +37 -5
  189. package/dist/Spinner/Spinner.d.ts +3 -3
  190. package/dist/Spinner/Spinner.d.ts.map +1 -1
  191. package/dist/Spinner/Spinner.js +130 -78
  192. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  193. package/dist/StatusDot/StatusDot.js +6 -1
  194. package/dist/Stepper/Step.d.ts +140 -0
  195. package/dist/Stepper/Step.d.ts.map +1 -0
  196. package/dist/Stepper/Step.js +1045 -0
  197. package/dist/Stepper/StepStatus.d.ts +24 -0
  198. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  199. package/dist/Stepper/StepStatus.js +1 -0
  200. package/dist/Stepper/Stepper.d.ts +93 -0
  201. package/dist/Stepper/Stepper.d.ts.map +1 -0
  202. package/dist/Stepper/Stepper.js +184 -0
  203. package/dist/Stepper/StepperContext.d.ts +41 -0
  204. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  205. package/dist/Stepper/StepperContext.js +34 -0
  206. package/dist/Stepper/index.d.ts +8 -0
  207. package/dist/Stepper/index.d.ts.map +1 -0
  208. package/dist/Stepper/index.js +7 -0
  209. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  210. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  211. package/dist/Stepper/stepper.stylex.js +20 -0
  212. package/dist/Switch/Switch.d.ts.map +1 -1
  213. package/dist/Switch/Switch.js +8 -3
  214. package/dist/TabList/Tab.d.ts +15 -2
  215. package/dist/TabList/Tab.d.ts.map +1 -1
  216. package/dist/TabList/Tab.js +32 -7
  217. package/dist/TabList/TabList.d.ts +46 -7
  218. package/dist/TabList/TabList.d.ts.map +1 -1
  219. package/dist/TabList/TabList.js +353 -23
  220. package/dist/TabList/TabListContext.d.ts +11 -1
  221. package/dist/TabList/TabListContext.d.ts.map +1 -1
  222. package/dist/TabList/TabListContext.js +11 -2
  223. package/dist/TabList/TabMenu.d.ts.map +1 -1
  224. package/dist/TabList/TabMenu.js +3 -2
  225. package/dist/TabList/index.d.ts +2 -2
  226. package/dist/TabList/index.d.ts.map +1 -1
  227. package/dist/Table/BaseTable.d.ts.map +1 -1
  228. package/dist/Table/BaseTable.js +10 -2
  229. package/dist/Table/Table.d.ts.map +1 -1
  230. package/dist/Table/Table.js +3 -6
  231. package/dist/Table/TableRow.d.ts +16 -5
  232. package/dist/Table/TableRow.d.ts.map +1 -1
  233. package/dist/Table/TableRow.js +16 -5
  234. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  235. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
  236. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  237. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  238. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  239. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  240. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  241. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  242. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  243. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  244. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  245. package/dist/Table/plugins/selection/useTableSelection.js +19 -5
  246. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  247. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  248. package/dist/Table/types.d.ts +22 -4
  249. package/dist/Table/types.d.ts.map +1 -1
  250. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  251. package/dist/Table/useBaseTablePlugins.js +5 -0
  252. package/dist/Text/Text.d.ts.map +1 -1
  253. package/dist/Text/Text.js +6 -2
  254. package/dist/TextArea/TextArea.d.ts.map +1 -1
  255. package/dist/TextArea/TextArea.js +9 -3
  256. package/dist/TextInput/TextInput.d.ts.map +1 -1
  257. package/dist/TextInput/TextInput.js +3 -2
  258. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  259. package/dist/TimeInput/TimeInput.js +3 -2
  260. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  261. package/dist/Timestamp/Timestamp.js +5 -3
  262. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  263. package/dist/Toast/ToastViewport.js +27 -8
  264. package/dist/Token/TokenLink.d.ts.map +1 -1
  265. package/dist/Token/TokenLink.js +2 -2
  266. package/dist/Tokenizer/Tokenizer.d.ts +3 -1
  267. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  268. package/dist/Tokenizer/Tokenizer.js +2 -0
  269. package/dist/Tooltip/Tooltip.d.ts +5 -0
  270. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  271. package/dist/Tooltip/useTooltip.d.ts +5 -0
  272. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  273. package/dist/Tooltip/useTooltip.js +39 -24
  274. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  275. package/dist/TopNav/TopNavHeading.js +5 -4
  276. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  277. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  278. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  279. package/dist/TopNav/TopNavMenu.js +4 -3
  280. package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
  281. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  282. package/dist/Typeahead/BaseTypeahead.js +68 -29
  283. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  284. package/dist/Typeahead/Typeahead.js +3 -2
  285. package/dist/astryx.css +96 -7
  286. package/dist/hooks/index.d.ts +1 -0
  287. package/dist/hooks/index.d.ts.map +1 -1
  288. package/dist/hooks/index.js +1 -0
  289. package/dist/hooks/useFocusTrap.d.ts +7 -4
  290. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  291. package/dist/hooks/useFocusTrap.js +60 -95
  292. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  293. package/dist/hooks/useHotkeys.js +3 -18
  294. package/dist/hooks/useMergedRefs.d.ts +18 -0
  295. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  296. package/dist/hooks/useMergedRefs.js +25 -0
  297. package/dist/index.d.ts +1 -0
  298. package/dist/index.d.ts.map +1 -1
  299. package/dist/index.js +1 -0
  300. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  301. package/dist/theme/derivedVarRegistry.js +24 -4
  302. package/dist/theme/syntax/tokens.d.ts +1 -1
  303. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  304. package/dist/theme/syntax/tokens.js +5 -2
  305. package/dist/utils/groupItems.d.ts +5 -1
  306. package/dist/utils/groupItems.d.ts.map +1 -1
  307. package/dist/utils/groupItems.js +9 -9
  308. package/dist/utils/index.d.ts +1 -1
  309. package/dist/utils/index.d.ts.map +1 -1
  310. package/dist/utils/isApplePlatform.d.ts +18 -0
  311. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  312. package/dist/utils/isApplePlatform.js +37 -0
  313. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  314. package/dist/utils/sharedResizeObserver.js +10 -1
  315. package/dist/utils/timeParser.d.ts +1 -1
  316. package/dist/utils/timeParser.d.ts.map +1 -1
  317. package/dist/utils/timeParser.js +26 -12
  318. package/locales/en.json +31 -7
  319. package/locales/pseudo.json +18 -0
  320. package/package.json +8 -3
  321. package/src/AppShell/AppShell.tsx +3 -2
  322. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  323. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  324. package/src/AspectRatio/AspectRatio.tsx +40 -1
  325. package/src/Avatar/Avatar.doc.mjs +14 -3
  326. package/src/Avatar/Avatar.test.tsx +97 -0
  327. package/src/Avatar/Avatar.tsx +125 -52
  328. package/src/Avatar/index.ts +2 -2
  329. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  330. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  331. package/src/AvatarGroup/AvatarGroup.tsx +15 -6
  332. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  333. package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
  334. package/src/Banner/Banner.doc.mjs +13 -11
  335. package/src/Banner/Banner.test.tsx +102 -15
  336. package/src/Banner/Banner.tsx +72 -25
  337. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  338. package/src/BottomSheet/BottomSheet.tsx +17 -4
  339. package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
  340. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  341. package/src/Button/Button.doc.mjs +22 -0
  342. package/src/Button/Button.test.tsx +13 -0
  343. package/src/Button/Button.tsx +5 -4
  344. package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
  345. package/src/ButtonGroup/ButtonGroup.test.tsx +391 -1
  346. package/src/ButtonGroup/ButtonGroup.tsx +23 -5
  347. package/src/Calendar/Calendar.doc.mjs +4 -3
  348. package/src/Calendar/Calendar.test.tsx +103 -0
  349. package/src/Calendar/Calendar.tsx +19 -16
  350. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  351. package/src/Calendar/getInitialFocusDate.ts +93 -0
  352. package/src/Calendar/styles.ts +49 -31
  353. package/src/Carousel/Carousel.tsx +3 -2
  354. package/src/Chat/ChatComposerInput.tsx +5 -1
  355. package/src/Chat/ChatLayout.tsx +3 -2
  356. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  357. package/src/Chat/ChatMessageList.test.tsx +46 -0
  358. package/src/Chat/ChatMessageList.tsx +28 -4
  359. package/src/Chat/ChatTokenizedText.tsx +17 -10
  360. package/src/Chat/useChatComposerTokens.ts +1 -1
  361. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  362. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  363. package/src/CheckboxInput/CheckboxInput.tsx +8 -2
  364. package/src/ClickableCard/ClickableCard.tsx +3 -2
  365. package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
  366. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  367. package/src/CodeBlock/CodeBlock.tsx +20 -4
  368. package/src/CodeBlock/highlightRanges.ts +1 -1
  369. package/src/CodeBlock/highlightStyles.ts +13 -13
  370. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  371. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  372. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  373. package/src/ContextMenu/ContextMenu.tsx +4 -3
  374. package/src/DateInput/DateInput.doc.mjs +16 -0
  375. package/src/DateInput/DateInput.tsx +55 -2
  376. package/src/DateInput/DateInputTouch.test.tsx +68 -9
  377. package/src/DateInput/NativeDateField.test.tsx +635 -0
  378. package/src/DateInput/NativeDateField.tsx +641 -0
  379. package/src/DateInput/TouchDateField.tsx +38 -4
  380. package/src/DateInput/index.ts +1 -0
  381. package/src/DateInput/nativeDateSegments.ts +127 -0
  382. package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
  383. package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
  384. package/src/DateTimeInput/DateTimeInput.tsx +556 -24
  385. package/src/DateTimeInput/index.ts +1 -0
  386. package/src/Dialog/Dialog.doc.mjs +8 -3
  387. package/src/Dialog/Dialog.test.tsx +261 -1
  388. package/src/Dialog/Dialog.tsx +109 -58
  389. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  390. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
  391. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
  392. package/src/Field/Field.doc.mjs +13 -2
  393. package/src/Field/FieldLabel.test.tsx +29 -0
  394. package/src/Field/FieldLabel.tsx +7 -0
  395. package/src/FileInput/FileInput.tsx +3 -2
  396. package/src/Heading/Heading.test.tsx +23 -1
  397. package/src/Heading/Heading.tsx +6 -2
  398. package/src/HoverCard/HoverCard.doc.mjs +13 -2
  399. package/src/HoverCard/HoverCard.test.tsx +101 -4
  400. package/src/HoverCard/HoverCard.tsx +71 -3
  401. package/src/HoverCard/useHoverCard.tsx +101 -33
  402. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  403. package/src/Indicator/Indicator.doc.mjs +2 -0
  404. package/src/Item/Item.tsx +5 -4
  405. package/src/Kbd/Kbd.tsx +2 -19
  406. package/src/Layer/LayerDepthContext.tsx +62 -0
  407. package/src/Layer/index.ts +9 -0
  408. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  409. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  410. package/src/Layer/layerStack.ts +362 -0
  411. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  412. package/src/Layer/useLayerDismissal.ts +173 -0
  413. package/src/Layout/Layout.doc.mjs +2 -2
  414. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  415. package/src/Lightbox/Lightbox.tsx +124 -102
  416. package/src/Link/Link.doc.mjs +39 -0
  417. package/src/Markdown/Markdown.doc.mjs +5 -0
  418. package/src/Markdown/incremental.test.ts +16 -2
  419. package/src/Markdown/index.ts +1 -0
  420. package/src/Markdown/parser.perf.test.ts +96 -1
  421. package/src/Markdown/parser.test.ts +145 -2
  422. package/src/Markdown/parser.ts +244 -29
  423. package/src/MobileNav/MobileNav.tsx +62 -36
  424. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  425. package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
  426. package/src/MultiSelector/MultiSelector.test.tsx +106 -0
  427. package/src/MultiSelector/MultiSelector.tsx +50 -6
  428. package/src/MultiSelector/index.ts +1 -0
  429. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  430. package/src/NavIcon/NavIcon.test.tsx +9 -0
  431. package/src/NavIcon/NavIcon.tsx +5 -1
  432. package/src/NavMenu/NavHeadingMenu.tsx +3 -2
  433. package/src/NumberInput/NumberInput.doc.mjs +20 -0
  434. package/src/NumberInput/NumberInput.tsx +28 -29
  435. package/src/NumberInput/numberParser.test.ts +210 -0
  436. package/src/NumberInput/numberParser.ts +386 -0
  437. package/src/Outline/Outline.tsx +3 -2
  438. package/src/OverflowList/OverflowList.tsx +3 -2
  439. package/src/Overlay/Overlay.tsx +3 -2
  440. package/src/Popover/usePopover.tsx +31 -28
  441. package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
  442. package/src/PowerSearch/PowerSearch.test.tsx +240 -1
  443. package/src/PowerSearch/PowerSearch.tsx +34 -5
  444. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +201 -0
  445. package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
  446. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +47 -1
  447. package/src/PowerSearch/PowerSearchValueEditor.tsx +15 -0
  448. package/src/PowerSearch/types.ts +2 -0
  449. package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
  450. package/src/PowerSearch/usePowerSearchSource.ts +13 -3
  451. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  452. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  453. package/src/ProgressBar/ProgressBar.tsx +28 -8
  454. package/src/Resizable/ResizeHandle.tsx +3 -2
  455. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  456. package/src/SelectableCard/SelectableCard.tsx +3 -2
  457. package/src/Selector/Selector.doc.mjs +12 -1
  458. package/src/Selector/Selector.test.tsx +45 -1
  459. package/src/Selector/Selector.tsx +11 -1
  460. package/src/SideNav/SideNav.doc.mjs +6 -6
  461. package/src/SideNav/SideNav.tsx +4 -2
  462. package/src/SideNav/SideNavHeading.tsx +12 -12
  463. package/src/SideNav/SideNavItem.tsx +4 -2
  464. package/src/Slider/Slider.test.tsx +106 -1
  465. package/src/Slider/Slider.tsx +55 -3
  466. package/src/Spinner/Spinner.test.tsx +147 -1
  467. package/src/Spinner/Spinner.tsx +120 -101
  468. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  469. package/src/StatusDot/StatusDot.test.tsx +9 -0
  470. package/src/StatusDot/StatusDot.tsx +7 -1
  471. package/src/Stepper/Step.doc.mjs +98 -0
  472. package/src/Stepper/Step.tsx +1638 -0
  473. package/src/Stepper/StepStatus.ts +26 -0
  474. package/src/Stepper/Stepper.doc.mjs +370 -0
  475. package/src/Stepper/Stepper.test.tsx +1024 -0
  476. package/src/Stepper/Stepper.tsx +258 -0
  477. package/src/Stepper/StepperContext.ts +71 -0
  478. package/src/Stepper/index.ts +18 -0
  479. package/src/Stepper/stepper.stylex.ts +19 -0
  480. package/src/Switch/Switch.doc.mjs +2 -0
  481. package/src/Switch/Switch.test.tsx +10 -0
  482. package/src/Switch/Switch.tsx +6 -2
  483. package/src/TabList/Tab.doc.mjs +13 -1
  484. package/src/TabList/Tab.tsx +67 -7
  485. package/src/TabList/TabList.doc.mjs +22 -6
  486. package/src/TabList/TabList.test.tsx +559 -0
  487. package/src/TabList/TabList.tsx +490 -22
  488. package/src/TabList/TabListContext.ts +13 -2
  489. package/src/TabList/TabMenu.tsx +3 -2
  490. package/src/TabList/index.ts +6 -2
  491. package/src/Table/BaseTable.tsx +12 -4
  492. package/src/Table/Table.doc.mjs +9 -2
  493. package/src/Table/Table.test.tsx +132 -14
  494. package/src/Table/Table.tsx +3 -8
  495. package/src/Table/TableBody.doc.mjs +40 -0
  496. package/src/Table/TableFooter.doc.mjs +40 -0
  497. package/src/Table/TableHeader.doc.mjs +40 -0
  498. package/src/Table/TableRow.tsx +16 -5
  499. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  500. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  501. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
  502. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  503. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  504. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  505. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  506. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  507. package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
  508. package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
  509. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  510. package/src/Table/types.ts +22 -4
  511. package/src/Table/useBaseTablePlugins.ts +5 -0
  512. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  513. package/src/Table/useTablePagination.doc.mjs +7 -0
  514. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  515. package/src/Table/useTableSelection.doc.mjs +31 -0
  516. package/src/Text/Text.test.tsx +23 -1
  517. package/src/Text/Text.tsx +6 -2
  518. package/src/TextArea/TextArea.doc.mjs +8 -2
  519. package/src/TextArea/TextArea.test.tsx +11 -0
  520. package/src/TextArea/TextArea.tsx +15 -8
  521. package/src/TextInput/TextInput.doc.mjs +10 -0
  522. package/src/TextInput/TextInput.tsx +3 -2
  523. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  524. package/src/TimeInput/TimeInput.tsx +2 -2
  525. package/src/Timestamp/Timestamp.tsx +4 -2
  526. package/src/Toast/Toast.doc.mjs +6 -0
  527. package/src/Toast/ToastViewport.tsx +17 -1
  528. package/src/Token/TokenLink.tsx +2 -2
  529. package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
  530. package/src/Tokenizer/Tokenizer.tsx +4 -0
  531. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  532. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  533. package/src/Tooltip/Tooltip.test.tsx +32 -0
  534. package/src/Tooltip/Tooltip.tsx +5 -0
  535. package/src/Tooltip/useTooltip.tsx +47 -24
  536. package/src/TopNav/TopNavHeading.tsx +5 -4
  537. package/src/TopNav/TopNavMegaMenu.tsx +3 -2
  538. package/src/TopNav/TopNavMenu.tsx +4 -3
  539. package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
  540. package/src/Typeahead/BaseTypeahead.tsx +85 -33
  541. package/src/Typeahead/Typeahead.doc.mjs +5 -0
  542. package/src/Typeahead/Typeahead.test.tsx +49 -0
  543. package/src/Typeahead/Typeahead.tsx +3 -2
  544. package/src/hooks/index.ts +2 -0
  545. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  546. package/src/hooks/useFocusTrap.test.tsx +14 -0
  547. package/src/hooks/useFocusTrap.ts +62 -111
  548. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  549. package/src/hooks/useHotkeys.ts +3 -18
  550. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  551. package/src/hooks/useMergedRefs.test.tsx +62 -0
  552. package/src/hooks/useMergedRefs.ts +36 -0
  553. package/src/index.ts +1 -0
  554. package/src/theme/MediaTheme.doc.mjs +5 -5
  555. package/src/theme/derivedVarRegistry.test.ts +19 -3
  556. package/src/theme/derivedVarRegistry.ts +23 -4
  557. package/src/theme/generateThemeRules.test.ts +37 -0
  558. package/src/theme/syntax/tokens.ts +5 -2
  559. package/src/utils/groupItems.ts +12 -6
  560. package/src/utils/index.ts +1 -1
  561. package/src/utils/isApplePlatform.test.ts +61 -0
  562. package/src/utils/isApplePlatform.ts +37 -0
  563. package/src/utils/sharedResizeObserver.ts +10 -2
  564. package/src/utils/timeParser.test.ts +6 -1
  565. package/src/utils/timeParser.ts +35 -13
  566. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -7,7 +7,7 @@ export const docs = {
7
7
  subComponentOf: 'Chat',
8
8
  displayName: 'Chat Message List',
9
9
  isHiddenFromOverview: true,
10
- description: `Presentational message container with density context and infinite scroll support. Provides role="log" with aria-live="polite" for accessibility. A flex spacer pushes messages to the bottom when the list isn't full.`,
10
+ description: `Presentational message container with density context and infinite scroll support. Provides role="log" with aria-live="polite" for accessibility. A flex spacer pushes messages to the bottom when the list isn't full; set align="top" to start messages at the top instead.`,
11
11
  props: [
12
12
  {
13
13
  name: 'children',
@@ -45,6 +45,12 @@ export const docs = {
45
45
  type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
46
46
  description: 'Gap between top-level message rows. Defaults to the selected density; override for LLM event streams or independent rows that need different spacing from density.',
47
47
  },
48
+ {
49
+ name: 'align',
50
+ type: "'top' | 'bottom'",
51
+ description: "Vertical alignment when the list is shorter than its container. 'bottom' fills free space with a spacer so short conversations sit above the composer; 'top' omits the spacer so messages start at the top. Only affects a non-full list; overflowing lists scroll identically, preserving auto-scroll-to-bottom.",
52
+ default: "'bottom'",
53
+ },
48
54
  {
49
55
  name: 'isStreaming',
50
56
  type: 'boolean',
@@ -65,6 +71,7 @@ export const docsZh = {
65
71
  scrollToTopAction: '用户滚动到顶部时触发的异步操作。用于加载更早的消息。',
66
72
  density: '视觉密度,通过上下文传递给子消息。',
67
73
  gap: '顶层消息行之间的间距。默认跟随密度;当 LLM 事件流等独立行需要不同间距时可覆盖。',
74
+ align: "列表内容不足一屏时的垂直对齐方式。'bottom' 用占位块填满剩余空间,让简短对话贴近输入框;'top' 省略占位块,让消息从顶部开始。仅影响未填满的列表,溢出后两种模式滚动一致,保持自动滚动到底部。",
68
75
  isStreaming: '是否有助手消息正在流式输出。标记日志为 aria-busy,让屏幕阅读器等待并在完成后一次性播报,而不是每个 token 都重复播报。',
69
76
  },
70
77
  };
@@ -80,6 +87,7 @@ export const docsDense = {
80
87
  scrollToTopAction: 'async action at scroll top; load older msgs',
81
88
  density: 'visual density; flows to children via context',
82
89
  gap: 'top-level row gap; defaults to density spacing; override for independent LLM/tool rows',
90
+ align: "'top'|'bottom' (def bottom); bottom spacer pushes short lists down, top starts at top; overflow scrolls same either way",
83
91
  isStreaming: 'assistant streaming? marks log aria-busy so SR announces the completed msg once',
84
92
  },
85
93
  };
@@ -83,4 +83,50 @@ describe('ChatMessageList', () => {
83
83
  );
84
84
  expect(screen.getByTestId('chat-list')).toBeTruthy();
85
85
  });
86
+
87
+ // With no scrollToTopAction the spacer is the only aria-hidden element in
88
+ // the list, so its presence maps 1:1 to the aria-hidden count.
89
+ it('renders the bottom spacer by default', () => {
90
+ render(
91
+ <ChatMessageList data-testid="list">
92
+ <div>msg</div>
93
+ </ChatMessageList>,
94
+ );
95
+ expect(
96
+ screen.getByTestId('list').querySelectorAll('[aria-hidden]'),
97
+ ).toHaveLength(1);
98
+ });
99
+
100
+ it('renders the bottom spacer when align="bottom"', () => {
101
+ render(
102
+ <ChatMessageList align="bottom" data-testid="list">
103
+ <div>msg</div>
104
+ </ChatMessageList>,
105
+ );
106
+ expect(
107
+ screen.getByTestId('list').querySelectorAll('[aria-hidden]'),
108
+ ).toHaveLength(1);
109
+ });
110
+
111
+ it('omits the spacer when align="top"', () => {
112
+ render(
113
+ <ChatMessageList align="top" data-testid="list">
114
+ <div>msg</div>
115
+ </ChatMessageList>,
116
+ );
117
+ expect(
118
+ screen.getByTestId('list').querySelectorAll('[aria-hidden]'),
119
+ ).toHaveLength(0);
120
+ });
121
+
122
+ it('still renders children when align="top"', () => {
123
+ render(
124
+ <ChatMessageList align="top">
125
+ <ChatMessage sender="assistant">
126
+ <ChatMessageBubble>Hello</ChatMessageBubble>
127
+ </ChatMessage>
128
+ </ChatMessageList>,
129
+ );
130
+ expect(screen.getByText('Hello')).toBeTruthy();
131
+ });
86
132
  });
@@ -10,7 +10,8 @@
10
10
  *
11
11
  * Renders a container with role="log" for chat message histories.
12
12
  * Handles density context, configurable gap, empty state,
13
- * a spacer that pushes messages to the bottom, and an infinite scroll sentinel.
13
+ * a configurable spacer (align) that pushes messages to the bottom,
14
+ * and an infinite scroll sentinel.
14
15
  *
15
16
  * Auto-scroll and the scroll-to-bottom button are owned by
16
17
  * ChatLayout. When used standalone (without a layout), the list
@@ -73,6 +74,24 @@ export interface ChatMessageListProps extends BaseProps<HTMLDivElement> {
73
74
  */
74
75
  gap?: SpacingStep;
75
76
 
77
+ /**
78
+ * Vertical alignment of messages when the list is shorter than its
79
+ * container.
80
+ *
81
+ * - `'bottom'` (default): a spacer fills the free space and pushes
82
+ * messages to the bottom, so a short conversation sits just above the
83
+ * composer — the familiar messaging-app layout.
84
+ * - `'top'`: the spacer is omitted, so messages start at the top and grow
85
+ * downward — better for document-style or log-style lists.
86
+ *
87
+ * This only changes the resting position of a non-full list. Once messages
88
+ * overflow the container the spacer collapses to zero in both modes, so
89
+ * ChatLayout auto-scroll-to-bottom behavior is identical either way.
90
+ *
91
+ * @default 'bottom'
92
+ */
93
+ align?: 'top' | 'bottom';
94
+
76
95
  /**
77
96
  * Whether an assistant message is actively streaming into the list.
78
97
  *
@@ -183,7 +202,8 @@ const gapStyles = stylex.create({
183
202
  *
184
203
  * Renders messages in a flex column with density-based spacing.
185
204
  * Override gap to tune row spacing separately from density.
186
- * A spacer pushes content to the bottom when the list isn't full.
205
+ * By default a spacer pushes content to the bottom when the list isn't full;
206
+ * set `align='top'` to start messages at the top instead.
187
207
  * Supports loading older messages via `scrollToTopAction`.
188
208
  *
189
209
  * Auto-scroll and the scroll-to-bottom button are owned by
@@ -204,6 +224,7 @@ export function ChatMessageList({
204
224
  scrollToTopAction,
205
225
  density = 'balanced',
206
226
  gap,
227
+ align = 'bottom',
207
228
  isStreaming = false,
208
229
  xstyle,
209
230
  className,
@@ -291,8 +312,11 @@ export function ChatMessageList({
291
312
  </div>
292
313
  )}
293
314
 
294
- {/* Spacer pushes messages to bottom when list isn't full */}
295
- <div {...stylex.props(styles.spacer)} aria-hidden />
315
+ {/* Spacer pushes messages to bottom when the list isn't full.
316
+ Omitted for top alignment so messages start at the top. */}
317
+ {align === 'bottom' && (
318
+ <div {...stylex.props(styles.spacer)} aria-hidden />
319
+ )}
296
320
 
297
321
  {/* Messages or empty state */}
298
322
  {hasChildren ? (
@@ -14,6 +14,8 @@
14
14
  *
15
15
  * SYNC: When modified, update:
16
16
  * - /packages/core/src/Chat/index.ts
17
+ * - /packages/core/src/Chat/ChatComposerInput.tsx (token alignment must match,
18
+ * or a token moves when the message is sent)
17
19
  * - /packages/cli/assets/templates/blocks/components/ChatTokenizedText/ (block examples)
18
20
  */
19
21
 
@@ -33,6 +35,10 @@ const styles = stylex.create({
33
35
  root: {
34
36
  display: 'inline',
35
37
  },
38
+ token: {
39
+ display: 'inline-flex',
40
+ verticalAlign: 'middle',
41
+ },
36
42
  });
37
43
 
38
44
  // =============================================================================
@@ -156,16 +162,17 @@ function renderTokens(text: string, tokens: ChatComposerToken[]): ReactNode[] {
156
162
  const token = tokenMap.get(matched);
157
163
  if (token) {
158
164
  parts.push(
159
- isCustomToken(token) ? (
160
- <span key={`${matched}-${match.index}`}>{token.render()}</span>
161
- ) : (
162
- <Badge
163
- key={`${matched}-${match.index}`}
164
- label={token.label}
165
- variant={token.variant}
166
- icon={token.icon}
167
- />
168
- ),
165
+ <span key={`${matched}-${match.index}`} {...stylex.props(styles.token)}>
166
+ {isCustomToken(token) ? (
167
+ token.render()
168
+ ) : (
169
+ <Badge
170
+ label={token.label}
171
+ variant={token.variant}
172
+ icon={token.icon}
173
+ />
174
+ )}
175
+ </span>,
169
176
  );
170
177
  }
171
178
 
@@ -120,7 +120,7 @@ export function useChatComposerTokens({
120
120
  span.setAttribute('data-astryx-token-id', id);
121
121
  span.contentEditable = 'false';
122
122
  span.style.display = 'inline-flex';
123
- span.style.verticalAlign = 'baseline';
123
+ span.style.verticalAlign = 'middle';
124
124
 
125
125
  range.deleteContents();
126
126
  range.insertNode(span);
@@ -133,6 +133,7 @@ export const docs = {
133
133
  {className: 'astryx-checkbox-input', visualProps: ['size']},
134
134
  {className: 'astryx-checkbox-indicator', visualProps: ['size'], states: ['checked', 'disabled']},
135
135
  {className: 'astryx-checkbox', visualProps: ['size'], states: ['checked', 'disabled'], deprecatedFor: 'checkbox-indicator'},
136
+ {className: 'astryx-checkbox-label'},
136
137
  ],
137
138
  },
138
139
  usage: {
@@ -209,6 +210,7 @@ export const docsZh = {
209
210
  },
210
211
  {className: 'astryx-checkbox-indicator', visualProps: ['size'], states: ['checked', 'disabled']},
211
212
  {className: 'astryx-checkbox', visualProps: ['size'], states: ['checked', 'disabled'], deprecatedFor: 'checkbox-indicator'},
213
+ {className: 'astryx-checkbox-label'},
212
214
  ],
213
215
  },
214
216
  };
@@ -719,3 +719,18 @@ describe('focus ring ownership (WCAG 2.4.7)', () => {
719
719
  expect(indicatorOf(container).style.outlineStyle).toBe('');
720
720
  });
721
721
  });
722
+
723
+ describe('label theme target', () => {
724
+ it('names its own label so a theme can style it apart from a field label', () => {
725
+ // The control knows this label shares a row with it; the label does not.
726
+ // Both classes land on the one element, so a theme reaches every label
727
+ // through `astryx-field-label` and only this kind through
728
+ // `astryx-checkbox-label`.
729
+ render(
730
+ <CheckboxInput label="Notify me" value={false} onChange={() => {}} />,
731
+ );
732
+ const label = screen.getByText('Notify me').closest('label');
733
+ expect(label).toHaveClass('astryx-field-label');
734
+ expect(label).toHaveClass('astryx-checkbox-label');
735
+ });
736
+ });
@@ -44,7 +44,7 @@ import type {IconType} from '../Icon';
44
44
  import type {InputStatus} from '../Field/types';
45
45
  import {Spinner} from '../Spinner';
46
46
  import {useTooltip} from '../Tooltip';
47
- import {mergeProps, mergeRefs} from '../utils';
47
+ import {mergeProps} from '../utils';
48
48
  import {indicatorScope} from '../Indicator/indicator.markers.stylex';
49
49
  import {useIndicatorFocusRing} from '../hooks/useIndicatorFocusRing';
50
50
  import {useResolvedRequired} from '../hooks/useResolvedRequired';
@@ -52,6 +52,7 @@ import {useIndicator} from '../Indicator';
52
52
  import {themeProps} from '../utils/themeProps';
53
53
  import {CheckboxListContext} from '../CheckboxList/CheckboxListContext';
54
54
 
55
+ import {useMergedRefs} from '../hooks/useMergedRefs';
55
56
  const styles = stylex.create({
56
57
  container: {
57
58
  display: 'flex',
@@ -409,7 +410,7 @@ export function CheckboxInput({
409
410
  {...focusProps}>
410
411
  <input
411
412
  {...rest}
412
- ref={mergeRefs(
413
+ ref={useMergedRefs(
413
414
  ref,
414
415
  indeterminateRef,
415
416
  disabledMessageTooltip.positionRef,
@@ -477,6 +478,11 @@ export function CheckboxInput({
477
478
  </div>
478
479
  <div {...stylex.props(styles.labelWrapper)}>
479
480
  <FieldLabel
481
+ // A checkbox's label shares a row with its control, unlike a form
482
+ // field's label above its input. Naming the label rather than the
483
+ // arrangement means a theme asks for the thing it wants, and the
484
+ // component that actually knows what this is says so.
485
+ {...themeProps('checkbox-label')}
480
486
  label={label}
481
487
  inputID={id}
482
488
  isLabelHidden={isLabelHidden}
@@ -39,7 +39,7 @@ import {
39
39
  easeVars,
40
40
  } from '../theme/tokens.stylex';
41
41
  import type {SizeValue, SpacingStep, Elevation} from '../utils/types';
42
- import {mergeProps, mergeRefs} from '../utils';
42
+ import {mergeProps} from '../utils';
43
43
  import {Card} from '../Card/Card';
44
44
  import type {CardVariant} from '../Card/Card';
45
45
  import {useClickableContainer} from '../hooks/useClickableContainer';
@@ -48,6 +48,7 @@ import {useLinkComponent} from '../Link/useLinkComponent';
48
48
  import {themeProps} from '../utils/themeProps';
49
49
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
50
50
 
51
+ import {useMergedRefs} from '../hooks/useMergedRefs';
51
52
  // =============================================================================
52
53
  // Styles — only the interactive layer, Card handles everything else
53
54
  // =============================================================================
@@ -297,7 +298,7 @@ export function ClickableCard({
297
298
 
298
299
  return (
299
300
  <Card
300
- ref={mergeRefs(ref, containerRef)}
301
+ ref={useMergedRefs(ref, containerRef)}
301
302
  width={width}
302
303
  height={height}
303
304
  maxWidth={maxWidth}
@@ -95,6 +95,12 @@ export const docs = {
95
95
  type: 'SyntaxThemeDefinition',
96
96
  description: 'Per-instance syntax theme override. Shorthand for wrapping the block in <SyntaxTheme theme={...}>. Accepts a preset from @astryxdesign/core/theme/syntax or a theme created with defineSyntaxTheme(). Defaults to the nearest SyntaxTheme ancestor or the theme-level syntax colors.',
97
97
  },
98
+ {
99
+ name: 'highlightMode',
100
+ type: "'auto' | 'ranges' | 'spans'",
101
+ description: 'Syntax highlighting rendering mode.',
102
+ default: "'auto'",
103
+ },
98
104
  {
99
105
  name: 'isCollapsible',
100
106
  type: 'boolean',
@@ -141,10 +147,16 @@ export const docs = {
141
147
  theming: {
142
148
  targets: [
143
149
  {className: 'astryx-code', visualProps: ['color']},
144
- {className: 'astryx-codeblock', visualProps: ['size', 'language', 'container']},
145
- {className: 'astryx-codeblock-header', visualProps: ['size', 'language', 'container']},
146
- {className: 'astryx-codeblock-title', visualProps: ['size', 'language']},
147
- {className: 'astryx-codeblock-copy-button'},
150
+ {className: 'astryx-code-block', visualProps: ['size', 'language', 'container']},
151
+ {className: 'astryx-code-block-header', visualProps: ['size', 'language', 'container']},
152
+ {className: 'astryx-code-block-title', visualProps: ['size', 'language']},
153
+ {className: 'astryx-code-block-copy-button'},
154
+ // Still emitted beside the names above, so themes written against
155
+ // them keep working. Drop in the next major.
156
+ {className: 'astryx-codeblock', visualProps: ['size', 'language', 'container'], deprecatedFor: 'code-block'},
157
+ {className: 'astryx-codeblock-header', visualProps: ['size', 'language', 'container'], deprecatedFor: 'code-block-header'},
158
+ {className: 'astryx-codeblock-title', visualProps: ['size', 'language'], deprecatedFor: 'code-block-title'},
159
+ {className: 'astryx-codeblock-copy-button', deprecatedFor: 'code-block-copy-button'},
148
160
  ],
149
161
  vars: [
150
162
  {name: '--_codeblock-gutter-width', description: 'Width of the line-number gutter, computed from the digit count of the last line so the code column starts at a stable offset.', default: '2ch', private: true},
@@ -396,3 +396,40 @@ describe('CodeBlock', () => {
396
396
  });
397
397
  });
398
398
  });
399
+
400
+ describe('CodeBlock theme target names', () => {
401
+ it('renders the deprecated classes beside the current ones', () => {
402
+ const {container} = render(
403
+ <CodeBlock
404
+ code="const x = 1;"
405
+ language="javascript"
406
+ title="example.js"
407
+ />,
408
+ );
409
+ expect(container.querySelector('.astryx-code-block')).toHaveClass(
410
+ 'astryx-codeblock',
411
+ );
412
+ expect(container.querySelector('.astryx-code-block-header')).toHaveClass(
413
+ 'astryx-codeblock-header',
414
+ );
415
+ expect(container.querySelector('.astryx-code-block-title')).toHaveClass(
416
+ 'astryx-codeblock-title',
417
+ );
418
+ expect(screen.getByRole('button', {name: 'Copy code'})).toHaveClass(
419
+ 'astryx-code-block-copy-button',
420
+ );
421
+ });
422
+
423
+ it('reaches the header and title through the current defineTheme keys', () => {
424
+ const theme = defineTheme({
425
+ name: 'code-block-header-target-test',
426
+ components: {
427
+ 'code-block-header': {base: {paddingBlock: 'var(--spacing-1)'}},
428
+ 'code-block-title': {base: {fontSize: 'var(--text-body-size)'}},
429
+ },
430
+ });
431
+ const css = generateThemeTestCSS(theme);
432
+ expect(css).toContain('.astryx-code-block-header');
433
+ expect(css).toContain('.astryx-code-block-title');
434
+ });
435
+ });
@@ -810,14 +810,20 @@ export function CodeBlock({
810
810
  void handleCopy();
811
811
  }}
812
812
  xstyle={[styles.copyButton, !showHeader && styles.copyButtonAbsolute]}
813
- {...themeProps('codeblock-copy-button')}
813
+ {...themeProps('code-block-copy-button', undefined, {
814
+ legacyNames: ['codeblock-copy-button'],
815
+ })}
814
816
  />
815
817
  ) : null;
816
818
 
817
819
  const headerEl = showHeader ? (
818
820
  <div
819
821
  {...mergeProps(
820
- themeProps('codeblock-header', {size, language, container}),
822
+ themeProps(
823
+ 'code-block-header',
824
+ {size, language, container},
825
+ {legacyNames: ['codeblock-header']},
826
+ ),
821
827
  stylex.props(
822
828
  styles.headerRow,
823
829
  hasLineNumbers ? styles.headerWithDivider : styles.headerCompact,
@@ -845,7 +851,11 @@ export function CodeBlock({
845
851
  )}>
846
852
  <span
847
853
  {...mergeProps(
848
- themeProps('codeblock-title', {size, language}),
854
+ themeProps(
855
+ 'code-block-title',
856
+ {size, language},
857
+ {legacyNames: ['codeblock-title']},
858
+ ),
849
859
  stylex.props(styles.headerTitle),
850
860
  )}>
851
861
  {canCollapse && (
@@ -917,7 +927,13 @@ export function CodeBlock({
917
927
  <pre
918
928
  ref={ref}
919
929
  {...mergeProps(
920
- themeProps('codeblock', {size, language, container}),
930
+ themeProps(
931
+ 'code-block',
932
+ {size, language, container},
933
+ // `codeblock` ran the compound name together; themes styling it keep
934
+ // working until the next major.
935
+ {legacyNames: ['codeblock']},
936
+ ),
921
937
  stylex.props(
922
938
  styles.root,
923
939
  dynamicStyles.width(widthProp),
@@ -67,7 +67,7 @@ function ensureDynamicHighlightType(tokenType: string): void {
67
67
  const name = `astryx-${tokenType}`;
68
68
  const colorVar = `var(--color-syntax-${tokenType}, currentColor)`;
69
69
  dynamicStyleSheet.insertRule(
70
- `.astryx-codeblock code::highlight(${name}), .astryx-codeeditor code::highlight(${name}) { color: ${colorVar}; }`,
70
+ `.astryx-code-block code::highlight(${name}), .astryx-codeeditor code::highlight(${name}) { color: ${colorVar}; }`,
71
71
  );
72
72
  }
73
73
 
@@ -30,31 +30,31 @@ const FALLBACK_TOKENS = `:root {\n${Object.entries(syntaxTokenDefaults)
30
30
  const HIGHLIGHT_STYLES = `
31
31
  ${FALLBACK_TOKENS}
32
32
 
33
- .astryx-codeblock code::highlight(astryx-keyword),
33
+ .astryx-code-block code::highlight(astryx-keyword),
34
34
  .astryx-codeeditor code::highlight(astryx-keyword) { color: var(--color-syntax-keyword); }
35
- .astryx-codeblock code::highlight(astryx-string),
35
+ .astryx-code-block code::highlight(astryx-string),
36
36
  .astryx-codeeditor code::highlight(astryx-string) { color: var(--color-syntax-string); }
37
- .astryx-codeblock code::highlight(astryx-comment),
37
+ .astryx-code-block code::highlight(astryx-comment),
38
38
  .astryx-codeeditor code::highlight(astryx-comment) { color: var(--color-syntax-comment); }
39
- .astryx-codeblock code::highlight(astryx-number),
39
+ .astryx-code-block code::highlight(astryx-number),
40
40
  .astryx-codeeditor code::highlight(astryx-number) { color: var(--color-syntax-number); }
41
- .astryx-codeblock code::highlight(astryx-function),
41
+ .astryx-code-block code::highlight(astryx-function),
42
42
  .astryx-codeeditor code::highlight(astryx-function) { color: var(--color-syntax-function); }
43
- .astryx-codeblock code::highlight(astryx-type),
43
+ .astryx-code-block code::highlight(astryx-type),
44
44
  .astryx-codeeditor code::highlight(astryx-type) { color: var(--color-syntax-type); }
45
- .astryx-codeblock code::highlight(astryx-tag),
45
+ .astryx-code-block code::highlight(astryx-tag),
46
46
  .astryx-codeeditor code::highlight(astryx-tag) { color: var(--color-syntax-tag); }
47
- .astryx-codeblock code::highlight(astryx-attribute),
47
+ .astryx-code-block code::highlight(astryx-attribute),
48
48
  .astryx-codeeditor code::highlight(astryx-attribute) { color: var(--color-syntax-attribute); }
49
- .astryx-codeblock code::highlight(astryx-property),
49
+ .astryx-code-block code::highlight(astryx-property),
50
50
  .astryx-codeeditor code::highlight(astryx-property) { color: var(--color-syntax-property); }
51
- .astryx-codeblock code::highlight(astryx-operator),
51
+ .astryx-code-block code::highlight(astryx-operator),
52
52
  .astryx-codeeditor code::highlight(astryx-operator) { color: var(--color-syntax-operator); }
53
- .astryx-codeblock code::highlight(astryx-constant),
53
+ .astryx-code-block code::highlight(astryx-constant),
54
54
  .astryx-codeeditor code::highlight(astryx-constant) { color: var(--color-syntax-constant); }
55
- .astryx-codeblock code::highlight(astryx-punctuation),
55
+ .astryx-code-block code::highlight(astryx-punctuation),
56
56
  .astryx-codeeditor code::highlight(astryx-punctuation) { color: var(--color-syntax-punctuation); }
57
- .astryx-codeblock code::highlight(astryx-variable),
57
+ .astryx-code-block code::highlight(astryx-variable),
58
58
  .astryx-codeeditor code::highlight(astryx-variable) { color: var(--color-syntax-variable); }
59
59
 
60
60
  /* Span-based fallback classes — used when highlightMode='spans' or
@@ -16,7 +16,7 @@ import {useCallback, useEffect, useRef, type ReactNode} from 'react';
16
16
  import * as stylex from '@stylexjs/stylex';
17
17
  import {Icon} from '../Icon';
18
18
  import {Spinner} from '../Spinner';
19
- import {mergeProps, mergeRefs} from '../utils';
19
+ import {mergeProps} from '../utils';
20
20
  import {
21
21
  colorVars,
22
22
  typeScaleVars,
@@ -29,6 +29,7 @@ import type {BaseProps} from '../BaseProps';
29
29
  import {themeProps} from '../utils/themeProps';
30
30
  import {useTranslator} from '../i18n';
31
31
 
32
+ import {useMergedRefs} from '../hooks/useMergedRefs';
32
33
  const styles = stylex.create({
33
34
  wrapper: {
34
35
  display: 'flex',
@@ -216,7 +217,7 @@ export function CommandPaletteInput({
216
217
  <Icon icon="search" size="sm" color="inherit" />
217
218
  </span>
218
219
  <input
219
- ref={mergeRefs(ref, inputRef)}
220
+ ref={useMergedRefs(ref, inputRef)}
220
221
  type="text"
221
222
  role="combobox"
222
223
  aria-expanded={ctx?.isOpen ?? true}
@@ -14,7 +14,7 @@
14
14
  import {useCallback, useEffect, useMemo, useRef, type ReactNode} from 'react';
15
15
  import * as stylex from '@stylexjs/stylex';
16
16
  import type {BaseProps} from '../BaseProps';
17
- import {mergeProps, mergeRefs} from '../utils';
17
+ import {mergeProps} from '../utils';
18
18
  import {composeEventHandlers} from '../utils/composeEventHandlers';
19
19
  import {
20
20
  colorVars,
@@ -27,6 +27,7 @@ import {useCommandPaletteContext} from './CommandPaletteContext';
27
27
  import {useDialogContext} from '../Dialog/DialogContext';
28
28
  import {themeProps} from '../utils/themeProps';
29
29
 
30
+ import {useMergedRefs} from '../hooks/useMergedRefs';
30
31
  const HOVER_HOVER = '@media (hover: hover)';
31
32
 
32
33
  const styles = stylex.create({
@@ -191,7 +192,7 @@ export function CommandPaletteItem({
191
192
 
192
193
  return (
193
194
  <div
194
- ref={mergeRefs(ref, itemRef)}
195
+ ref={useMergedRefs(ref, itemRef)}
195
196
  {...props}
196
197
  id={ctx && itemIndex >= 0 ? ctx.getItemId(itemIndex) : undefined}
197
198
  role="option"
@@ -58,6 +58,11 @@ export const docs = {
58
58
  description: 'Accessible name for the menu surface, announced when it opens.',
59
59
  default: "'Context menu'",
60
60
  },
61
+ {
62
+ name: 'onOpenChange',
63
+ type: '(isOpen: boolean) => void',
64
+ description: 'Callback fired when the menu opens or closes.',
65
+ },
61
66
  {
62
67
  name: 'isDisabled',
63
68
  type: 'boolean',
@@ -63,7 +63,7 @@ import {
63
63
  easeVars,
64
64
  shadowVars,
65
65
  } from '../theme/tokens.stylex';
66
- import {mergeProps, mergeRefs, isImeKeyEvent} from '../utils';
66
+ import {mergeProps, isImeKeyEvent} from '../utils';
67
67
  import type {BaseProps} from '../BaseProps';
68
68
  import type {StyleXStyles} from '../theme/types';
69
69
  import {themeProps} from '../utils/themeProps';
@@ -75,6 +75,7 @@ import type {
75
75
  DropdownMenuSection,
76
76
  } from '../DropdownMenu/DropdownMenu';
77
77
 
78
+ import {useMergedRefs} from '../hooks/useMergedRefs';
78
79
  const styles = stylex.create({
79
80
  // Trigger wrapper: suppress the iOS long-press callout/selection so the
80
81
  // long-press opens our context menu instead of the native text/callout UI.
@@ -467,7 +468,7 @@ export function ContextMenu({
467
468
  return (
468
469
  <>
469
470
  <div
470
- ref={mergeRefs(ref, triggerRef)}
471
+ ref={useMergedRefs(ref, triggerRef)}
471
472
  {...triggerProps}
472
473
  onContextMenu={handleContextMenu}
473
474
  {...longPressHandlers}
@@ -482,7 +483,7 @@ export function ContextMenu({
482
483
  )}>
483
484
  {children}
484
485
  <span
485
- ref={mergeRefs(cursorAnchorRef, layer.ref)}
486
+ ref={useMergedRefs(cursorAnchorRef, layer.ref)}
486
487
  aria-hidden="true"
487
488
  {...mergeProps(stylex.props(styles.cursorAnchor), {
488
489
  style: {
@@ -156,6 +156,13 @@ export const docs = {
156
156
  "How the committed date value is displayed. Named values are reused from Timestamp's format vocabulary: 'date' shows 'Mar 21, 2026', 'date_long' shows 'March 21, 2026', 'date_weekday' shows 'Wed, Mar 21, 2026', 'system_date' shows '2026-03-21'. A function receives the ISO value and returns a custom string. Applies only to the committed value, never to text being typed.",
157
157
  default: "'date_long'",
158
158
  },
159
+ {
160
+ name: 'nativePicker',
161
+ type: "'touch' | 'always' | 'never'",
162
+ description:
163
+ "Which surface draws the date picker. 'touch' (the default) hands a touch device to the browser/OS \u2014 the field becomes an input type=date and the platform draws the picker (the iOS wheel, the Android calendar dialog); 'always' does that wherever the browser supports input type=date; 'never' keeps Astryx's own pickers everywhere (the bottom-sheet picker on a finger, the calendar popover on a mouse). Use 'never' for a field that needs weekStartsOn, numberOfMonths or dateConstraints, none of which a native picker can express. format and placeholder still apply in native mode; min and max are forwarded, but a native picker may not show them (on iOS an out-of-range date can be selected and is refused on commit rather than greyed out).",
164
+ default: "'touch'",
165
+ },
159
166
  {
160
167
  name: 'width',
161
168
  type: 'SizeValue',
@@ -437,6 +444,13 @@ export const docsZh = {
437
444
  "已选日期的显示格式。命名值复用 Timestamp 的格式词汇:'date' 显示 'Mar 21, 2026','date_long' 显示 'March 21, 2026','date_weekday' 显示 'Wed, Mar 21, 2026','system_date' 显示 '2026-03-21'。函数接收 ISO 值并返回自定义字符串。仅作用于已提交的值,不影响正在输入的文本。",
438
445
  default: "'date_long'",
439
446
  },
447
+ {
448
+ name: 'nativePicker',
449
+ type: "'touch' | 'always' | 'never'",
450
+ description:
451
+ "由哪个界面绘制日期选择器。'touch'(默认)在触摸设备上交给浏览器/操作系统:字段变为 input type=date,由平台绘制选择器(iOS 滚轮、Android 日历对话框);'always' 在所有支持 input type=date 的浏览器上都这样做;'never' 始终使用 Astryx 自带的选择器(触摸设备用底部弹出选择器,鼠标设备用日历弹出层)。需要 weekStartsOn、numberOfMonths 或 dateConstraints 的字段应使用 'never',原生选择器无法表达这些。原生模式下 format 和 placeholder 仍然生效;min 和 max 会传递给原生控件,但原生选择器可能不会显示这些限制(在 iOS 上仍可选中超出范围的日期,会在提交时被拒绝,而不是变灰)。",
452
+ default: "'touch'",
453
+ },
440
454
  {
441
455
  name: 'xstyle',
442
456
  type: 'StyleXStyles',
@@ -537,6 +551,8 @@ export const docsDense = {
537
551
  weekStartsOn: 'first day of week in calendar (0=Sunday, or name e.g. "mon")',
538
552
  format:
539
553
  "committed-value display: 'date_long' (default, March 21, 2026), 'date' (Mar 21, 2026), 'date_weekday' (Wed, Mar 21, 2026), 'system_date' (2026-03-21), or (iso)=>string; reuses Timestamp vocabulary. Committed value only, not while typing.",
554
+ nativePicker:
555
+ "which surface draws the picker: 'touch' (default) = browser/OS on a coarse pointer, 'always', 'never' = Astryx's own everywhere. use 'never' for weekStartsOn/numberOfMonths/dateConstraints. format+placeholder still apply; min/max forwarded but not necessarily shown by the OS picker \u2014 refused on commit instead.",
540
556
  xstyle: 'StyleX styles for layout; must be stylex.create() value',
541
557
  },
542
558
  };