@astryxdesign/core 0.4.7 → 0.5.0-canary.32a62fd

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 (554) 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 +13 -14
  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/Carousel/Carousel.d.ts.map +1 -1
  41. package/dist/Carousel/Carousel.js +3 -3
  42. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  43. package/dist/Chat/ChatComposerInput.js +2 -3
  44. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  45. package/dist/Chat/ChatLayout.js +3 -3
  46. package/dist/Chat/ChatMessageList.d.ts +22 -3
  47. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  48. package/dist/Chat/ChatMessageList.js +6 -3
  49. package/dist/Chat/ChatTokenizedText.d.ts +2 -0
  50. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  51. package/dist/Chat/ChatTokenizedText.js +11 -6
  52. package/dist/Chat/useChatComposerTokens.js +1 -1
  53. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  54. package/dist/CheckboxInput/CheckboxInput.js +10 -3
  55. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  56. package/dist/ClickableCard/ClickableCard.js +3 -3
  57. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  58. package/dist/CodeBlock/CodeBlock.js +15 -4
  59. package/dist/CodeBlock/highlightRanges.js +1 -1
  60. package/dist/CodeBlock/highlightStyles.js +13 -13
  61. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  62. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  63. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  64. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  65. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  66. package/dist/ContextMenu/ContextMenu.js +4 -3
  67. package/dist/DateInput/DateInput.d.ts +43 -0
  68. package/dist/DateInput/DateInput.d.ts.map +1 -1
  69. package/dist/DateInput/DateInput.js +22 -2
  70. package/dist/DateInput/NativeDateField.d.ts +10 -0
  71. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  72. package/dist/DateInput/NativeDateField.js +477 -0
  73. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  74. package/dist/DateInput/TouchDateField.js +38 -4
  75. package/dist/DateInput/index.d.ts +1 -1
  76. package/dist/DateInput/index.d.ts.map +1 -1
  77. package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
  78. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  79. package/dist/DateTimeInput/DateTimeInput.js +406 -12
  80. package/dist/DateTimeInput/index.d.ts +1 -1
  81. package/dist/DateTimeInput/index.d.ts.map +1 -1
  82. package/dist/Dialog/Dialog.d.ts +7 -1
  83. package/dist/Dialog/Dialog.d.ts.map +1 -1
  84. package/dist/Dialog/Dialog.js +89 -58
  85. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  86. package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
  87. package/dist/Field/FieldLabel.d.ts.map +1 -1
  88. package/dist/Field/FieldLabel.js +9 -1
  89. package/dist/FileInput/FileInput.d.ts.map +1 -1
  90. package/dist/FileInput/FileInput.js +3 -2
  91. package/dist/Heading/Heading.d.ts.map +1 -1
  92. package/dist/Heading/Heading.js +6 -2
  93. package/dist/HoverCard/HoverCard.d.ts +6 -0
  94. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  95. package/dist/HoverCard/HoverCard.js +52 -3
  96. package/dist/HoverCard/useHoverCard.d.ts +16 -2
  97. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  98. package/dist/HoverCard/useHoverCard.js +74 -26
  99. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  100. package/dist/Indicator/CheckboxIndicator.js +6 -2
  101. package/dist/Item/Item.d.ts.map +1 -1
  102. package/dist/Item/Item.js +4 -2
  103. package/dist/Kbd/Kbd.d.ts.map +1 -1
  104. package/dist/Kbd/Kbd.js +2 -19
  105. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  106. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  107. package/dist/Layer/LayerDepthContext.js +66 -0
  108. package/dist/Layer/index.d.ts +3 -0
  109. package/dist/Layer/index.d.ts.map +1 -1
  110. package/dist/Layer/index.js +4 -0
  111. package/dist/Layer/layerStack.d.ts +98 -0
  112. package/dist/Layer/layerStack.d.ts.map +1 -0
  113. package/dist/Layer/layerStack.js +306 -0
  114. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  115. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  116. package/dist/Layer/useLayerDismissal.js +91 -0
  117. package/dist/Lightbox/Lightbox.d.ts +1 -0
  118. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  119. package/dist/Lightbox/Lightbox.js +103 -81
  120. package/dist/Markdown/index.d.ts +1 -1
  121. package/dist/Markdown/index.d.ts.map +1 -1
  122. package/dist/Markdown/parser.d.ts +38 -1
  123. package/dist/Markdown/parser.d.ts.map +1 -1
  124. package/dist/Markdown/parser.js +177 -29
  125. package/dist/MobileNav/MobileNav.d.ts +6 -1
  126. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  127. package/dist/MobileNav/MobileNav.js +61 -36
  128. package/dist/MultiSelector/MultiSelector.d.ts +15 -1
  129. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  130. package/dist/MultiSelector/MultiSelector.js +17 -6
  131. package/dist/MultiSelector/index.d.ts +1 -1
  132. package/dist/MultiSelector/index.d.ts.map +1 -1
  133. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  134. package/dist/NavIcon/NavIcon.js +5 -1
  135. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  136. package/dist/NavMenu/NavHeadingMenu.js +3 -2
  137. package/dist/NumberInput/NumberInput.d.ts +1 -0
  138. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  139. package/dist/NumberInput/NumberInput.js +27 -37
  140. package/dist/NumberInput/numberParser.d.ts +43 -0
  141. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  142. package/dist/NumberInput/numberParser.js +293 -0
  143. package/dist/Outline/Outline.d.ts.map +1 -1
  144. package/dist/Outline/Outline.js +3 -2
  145. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  146. package/dist/OverflowList/OverflowList.js +3 -2
  147. package/dist/Overlay/Overlay.d.ts.map +1 -1
  148. package/dist/Overlay/Overlay.js +3 -2
  149. package/dist/Popover/usePopover.d.ts.map +1 -1
  150. package/dist/Popover/usePopover.js +20 -17
  151. package/dist/PowerSearch/PowerSearch.d.ts +8 -2
  152. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  153. package/dist/PowerSearch/PowerSearch.js +19 -6
  154. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
  155. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  156. package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
  157. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
  158. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  159. package/dist/PowerSearch/PowerSearchValueEditor.js +19 -9
  160. package/dist/PowerSearch/types.d.ts +2 -0
  161. package/dist/PowerSearch/types.d.ts.map +1 -1
  162. package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
  163. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  164. package/dist/PowerSearch/usePowerSearchSource.js +14 -5
  165. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  166. package/dist/ProgressBar/ProgressBar.js +18 -5
  167. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  168. package/dist/Resizable/ResizeHandle.js +3 -2
  169. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  170. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  171. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  172. package/dist/SelectableCard/SelectableCard.js +3 -3
  173. package/dist/Selector/Selector.d.ts.map +1 -1
  174. package/dist/Selector/Selector.js +5 -0
  175. package/dist/SideNav/SideNav.d.ts.map +1 -1
  176. package/dist/SideNav/SideNav.js +4 -3
  177. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  178. package/dist/SideNav/SideNavHeading.js +8 -7
  179. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  180. package/dist/SideNav/SideNavItem.js +4 -3
  181. package/dist/Slider/Slider.d.ts.map +1 -1
  182. package/dist/Slider/Slider.js +3 -3
  183. package/dist/Spinner/Spinner.d.ts +3 -3
  184. package/dist/Spinner/Spinner.d.ts.map +1 -1
  185. package/dist/Spinner/Spinner.js +130 -78
  186. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  187. package/dist/StatusDot/StatusDot.js +6 -1
  188. package/dist/Stepper/Step.d.ts +140 -0
  189. package/dist/Stepper/Step.d.ts.map +1 -0
  190. package/dist/Stepper/Step.js +1045 -0
  191. package/dist/Stepper/StepStatus.d.ts +24 -0
  192. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  193. package/dist/Stepper/StepStatus.js +1 -0
  194. package/dist/Stepper/Stepper.d.ts +93 -0
  195. package/dist/Stepper/Stepper.d.ts.map +1 -0
  196. package/dist/Stepper/Stepper.js +184 -0
  197. package/dist/Stepper/StepperContext.d.ts +41 -0
  198. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  199. package/dist/Stepper/StepperContext.js +34 -0
  200. package/dist/Stepper/index.d.ts +8 -0
  201. package/dist/Stepper/index.d.ts.map +1 -0
  202. package/dist/Stepper/index.js +7 -0
  203. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  204. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  205. package/dist/Stepper/stepper.stylex.js +20 -0
  206. package/dist/Switch/Switch.d.ts.map +1 -1
  207. package/dist/Switch/Switch.js +8 -3
  208. package/dist/TabList/Tab.d.ts +15 -2
  209. package/dist/TabList/Tab.d.ts.map +1 -1
  210. package/dist/TabList/Tab.js +32 -7
  211. package/dist/TabList/TabList.d.ts +46 -7
  212. package/dist/TabList/TabList.d.ts.map +1 -1
  213. package/dist/TabList/TabList.js +353 -23
  214. package/dist/TabList/TabListContext.d.ts +11 -1
  215. package/dist/TabList/TabListContext.d.ts.map +1 -1
  216. package/dist/TabList/TabListContext.js +11 -2
  217. package/dist/TabList/TabMenu.d.ts.map +1 -1
  218. package/dist/TabList/TabMenu.js +3 -2
  219. package/dist/TabList/index.d.ts +2 -2
  220. package/dist/TabList/index.d.ts.map +1 -1
  221. package/dist/Table/BaseTable.d.ts.map +1 -1
  222. package/dist/Table/BaseTable.js +10 -2
  223. package/dist/Table/Table.d.ts.map +1 -1
  224. package/dist/Table/Table.js +3 -6
  225. package/dist/Table/TableRow.d.ts +16 -5
  226. package/dist/Table/TableRow.d.ts.map +1 -1
  227. package/dist/Table/TableRow.js +16 -5
  228. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  229. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
  230. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  231. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  232. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  233. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  234. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  235. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  236. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  237. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  238. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  239. package/dist/Table/plugins/selection/useTableSelection.js +19 -5
  240. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  241. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  242. package/dist/Table/types.d.ts +22 -4
  243. package/dist/Table/types.d.ts.map +1 -1
  244. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  245. package/dist/Table/useBaseTablePlugins.js +5 -0
  246. package/dist/Text/Text.d.ts.map +1 -1
  247. package/dist/Text/Text.js +6 -2
  248. package/dist/TextArea/TextArea.d.ts.map +1 -1
  249. package/dist/TextArea/TextArea.js +9 -3
  250. package/dist/TextInput/TextInput.d.ts.map +1 -1
  251. package/dist/TextInput/TextInput.js +3 -2
  252. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  253. package/dist/TimeInput/TimeInput.js +3 -2
  254. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  255. package/dist/Timestamp/Timestamp.js +5 -3
  256. package/dist/Token/TokenLink.d.ts.map +1 -1
  257. package/dist/Token/TokenLink.js +2 -2
  258. package/dist/Tokenizer/Tokenizer.d.ts +3 -1
  259. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  260. package/dist/Tokenizer/Tokenizer.js +2 -0
  261. package/dist/Tooltip/Tooltip.d.ts +5 -0
  262. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  263. package/dist/Tooltip/useTooltip.d.ts +5 -0
  264. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  265. package/dist/Tooltip/useTooltip.js +39 -24
  266. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  267. package/dist/TopNav/TopNavHeading.js +5 -4
  268. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  269. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  270. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  271. package/dist/TopNav/TopNavMenu.js +4 -3
  272. package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
  273. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  274. package/dist/Typeahead/BaseTypeahead.js +68 -29
  275. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  276. package/dist/Typeahead/Typeahead.js +3 -2
  277. package/dist/astryx.css +94 -7
  278. package/dist/hooks/index.d.ts +1 -0
  279. package/dist/hooks/index.d.ts.map +1 -1
  280. package/dist/hooks/index.js +1 -0
  281. package/dist/hooks/useFocusTrap.d.ts +7 -4
  282. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  283. package/dist/hooks/useFocusTrap.js +60 -95
  284. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  285. package/dist/hooks/useHotkeys.js +3 -18
  286. package/dist/hooks/useMergedRefs.d.ts +18 -0
  287. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  288. package/dist/hooks/useMergedRefs.js +25 -0
  289. package/dist/index.d.ts +1 -0
  290. package/dist/index.d.ts.map +1 -1
  291. package/dist/index.js +1 -0
  292. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  293. package/dist/theme/derivedVarRegistry.js +24 -4
  294. package/dist/theme/syntax/tokens.d.ts +1 -1
  295. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  296. package/dist/theme/syntax/tokens.js +5 -2
  297. package/dist/utils/groupItems.d.ts +5 -1
  298. package/dist/utils/groupItems.d.ts.map +1 -1
  299. package/dist/utils/groupItems.js +9 -9
  300. package/dist/utils/index.d.ts +1 -1
  301. package/dist/utils/index.d.ts.map +1 -1
  302. package/dist/utils/isApplePlatform.d.ts +18 -0
  303. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  304. package/dist/utils/isApplePlatform.js +37 -0
  305. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  306. package/dist/utils/sharedResizeObserver.js +10 -1
  307. package/dist/utils/timeParser.d.ts +1 -1
  308. package/dist/utils/timeParser.d.ts.map +1 -1
  309. package/dist/utils/timeParser.js +26 -12
  310. package/locales/en.json +31 -7
  311. package/locales/pseudo.json +18 -0
  312. package/package.json +8 -3
  313. package/src/AppShell/AppShell.tsx +3 -2
  314. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  315. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  316. package/src/AspectRatio/AspectRatio.tsx +40 -1
  317. package/src/Avatar/Avatar.doc.mjs +14 -3
  318. package/src/Avatar/Avatar.test.tsx +97 -0
  319. package/src/Avatar/Avatar.tsx +125 -52
  320. package/src/Avatar/index.ts +2 -2
  321. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  322. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  323. package/src/AvatarGroup/AvatarGroup.tsx +15 -6
  324. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  325. package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
  326. package/src/Banner/Banner.doc.mjs +13 -11
  327. package/src/Banner/Banner.test.tsx +102 -15
  328. package/src/Banner/Banner.tsx +72 -25
  329. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  330. package/src/BottomSheet/BottomSheet.tsx +17 -4
  331. package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
  332. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  333. package/src/Button/Button.doc.mjs +22 -0
  334. package/src/Button/Button.test.tsx +13 -0
  335. package/src/Button/Button.tsx +5 -4
  336. package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
  337. package/src/ButtonGroup/ButtonGroup.test.tsx +391 -1
  338. package/src/ButtonGroup/ButtonGroup.tsx +23 -5
  339. package/src/Calendar/Calendar.doc.mjs +4 -3
  340. package/src/Calendar/Calendar.test.tsx +52 -0
  341. package/src/Calendar/Calendar.tsx +18 -15
  342. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  343. package/src/Calendar/getInitialFocusDate.ts +93 -0
  344. package/src/Carousel/Carousel.tsx +3 -2
  345. package/src/Chat/ChatComposerInput.tsx +5 -1
  346. package/src/Chat/ChatLayout.tsx +3 -2
  347. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  348. package/src/Chat/ChatMessageList.test.tsx +46 -0
  349. package/src/Chat/ChatMessageList.tsx +28 -4
  350. package/src/Chat/ChatTokenizedText.tsx +17 -10
  351. package/src/Chat/useChatComposerTokens.ts +1 -1
  352. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  353. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  354. package/src/CheckboxInput/CheckboxInput.tsx +8 -2
  355. package/src/ClickableCard/ClickableCard.tsx +3 -2
  356. package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
  357. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  358. package/src/CodeBlock/CodeBlock.tsx +20 -4
  359. package/src/CodeBlock/highlightRanges.ts +1 -1
  360. package/src/CodeBlock/highlightStyles.ts +13 -13
  361. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  362. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  363. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  364. package/src/ContextMenu/ContextMenu.tsx +4 -3
  365. package/src/DateInput/DateInput.doc.mjs +16 -0
  366. package/src/DateInput/DateInput.tsx +55 -2
  367. package/src/DateInput/DateInputTouch.test.tsx +68 -9
  368. package/src/DateInput/NativeDateField.test.tsx +565 -0
  369. package/src/DateInput/NativeDateField.tsx +623 -0
  370. package/src/DateInput/TouchDateField.tsx +38 -4
  371. package/src/DateInput/index.ts +1 -0
  372. package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
  373. package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
  374. package/src/DateTimeInput/DateTimeInput.tsx +556 -24
  375. package/src/DateTimeInput/index.ts +1 -0
  376. package/src/Dialog/Dialog.doc.mjs +8 -3
  377. package/src/Dialog/Dialog.test.tsx +261 -1
  378. package/src/Dialog/Dialog.tsx +109 -58
  379. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  380. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
  381. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
  382. package/src/Field/Field.doc.mjs +13 -2
  383. package/src/Field/FieldLabel.test.tsx +29 -0
  384. package/src/Field/FieldLabel.tsx +7 -0
  385. package/src/FileInput/FileInput.tsx +3 -2
  386. package/src/Heading/Heading.test.tsx +23 -1
  387. package/src/Heading/Heading.tsx +6 -2
  388. package/src/HoverCard/HoverCard.doc.mjs +13 -2
  389. package/src/HoverCard/HoverCard.test.tsx +101 -4
  390. package/src/HoverCard/HoverCard.tsx +71 -3
  391. package/src/HoverCard/useHoverCard.tsx +101 -33
  392. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  393. package/src/Indicator/Indicator.doc.mjs +2 -0
  394. package/src/Item/Item.tsx +5 -4
  395. package/src/Kbd/Kbd.tsx +2 -19
  396. package/src/Layer/LayerDepthContext.tsx +62 -0
  397. package/src/Layer/index.ts +9 -0
  398. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  399. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  400. package/src/Layer/layerStack.ts +362 -0
  401. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  402. package/src/Layer/useLayerDismissal.ts +173 -0
  403. package/src/Layout/Layout.doc.mjs +2 -2
  404. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  405. package/src/Lightbox/Lightbox.tsx +124 -102
  406. package/src/Link/Link.doc.mjs +39 -0
  407. package/src/Markdown/Markdown.doc.mjs +5 -0
  408. package/src/Markdown/incremental.test.ts +16 -2
  409. package/src/Markdown/index.ts +1 -0
  410. package/src/Markdown/parser.perf.test.ts +96 -1
  411. package/src/Markdown/parser.test.ts +145 -2
  412. package/src/Markdown/parser.ts +244 -29
  413. package/src/MobileNav/MobileNav.tsx +62 -36
  414. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  415. package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
  416. package/src/MultiSelector/MultiSelector.test.tsx +106 -0
  417. package/src/MultiSelector/MultiSelector.tsx +50 -6
  418. package/src/MultiSelector/index.ts +1 -0
  419. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  420. package/src/NavIcon/NavIcon.test.tsx +9 -0
  421. package/src/NavIcon/NavIcon.tsx +5 -1
  422. package/src/NavMenu/NavHeadingMenu.tsx +3 -2
  423. package/src/NumberInput/NumberInput.doc.mjs +20 -0
  424. package/src/NumberInput/NumberInput.tsx +28 -29
  425. package/src/NumberInput/numberParser.test.ts +137 -0
  426. package/src/NumberInput/numberParser.ts +346 -0
  427. package/src/Outline/Outline.tsx +3 -2
  428. package/src/OverflowList/OverflowList.tsx +3 -2
  429. package/src/Overlay/Overlay.tsx +3 -2
  430. package/src/Popover/usePopover.tsx +31 -28
  431. package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
  432. package/src/PowerSearch/PowerSearch.test.tsx +240 -1
  433. package/src/PowerSearch/PowerSearch.tsx +34 -5
  434. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +201 -0
  435. package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
  436. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +47 -1
  437. package/src/PowerSearch/PowerSearchValueEditor.tsx +15 -0
  438. package/src/PowerSearch/types.ts +2 -0
  439. package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
  440. package/src/PowerSearch/usePowerSearchSource.ts +13 -3
  441. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  442. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  443. package/src/ProgressBar/ProgressBar.tsx +28 -8
  444. package/src/Resizable/ResizeHandle.tsx +3 -2
  445. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  446. package/src/SelectableCard/SelectableCard.tsx +3 -2
  447. package/src/Selector/Selector.doc.mjs +12 -1
  448. package/src/Selector/Selector.test.tsx +45 -1
  449. package/src/Selector/Selector.tsx +11 -1
  450. package/src/SideNav/SideNav.doc.mjs +6 -6
  451. package/src/SideNav/SideNav.tsx +4 -2
  452. package/src/SideNav/SideNavHeading.tsx +12 -12
  453. package/src/SideNav/SideNavItem.tsx +4 -2
  454. package/src/Slider/Slider.tsx +3 -2
  455. package/src/Spinner/Spinner.test.tsx +147 -1
  456. package/src/Spinner/Spinner.tsx +120 -101
  457. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  458. package/src/StatusDot/StatusDot.test.tsx +9 -0
  459. package/src/StatusDot/StatusDot.tsx +7 -1
  460. package/src/Stepper/Step.doc.mjs +98 -0
  461. package/src/Stepper/Step.tsx +1638 -0
  462. package/src/Stepper/StepStatus.ts +26 -0
  463. package/src/Stepper/Stepper.doc.mjs +370 -0
  464. package/src/Stepper/Stepper.test.tsx +1024 -0
  465. package/src/Stepper/Stepper.tsx +258 -0
  466. package/src/Stepper/StepperContext.ts +71 -0
  467. package/src/Stepper/index.ts +18 -0
  468. package/src/Stepper/stepper.stylex.ts +19 -0
  469. package/src/Switch/Switch.doc.mjs +2 -0
  470. package/src/Switch/Switch.test.tsx +10 -0
  471. package/src/Switch/Switch.tsx +6 -2
  472. package/src/TabList/Tab.doc.mjs +13 -1
  473. package/src/TabList/Tab.tsx +67 -7
  474. package/src/TabList/TabList.doc.mjs +22 -6
  475. package/src/TabList/TabList.test.tsx +559 -0
  476. package/src/TabList/TabList.tsx +490 -22
  477. package/src/TabList/TabListContext.ts +13 -2
  478. package/src/TabList/TabMenu.tsx +3 -2
  479. package/src/TabList/index.ts +6 -2
  480. package/src/Table/BaseTable.tsx +12 -4
  481. package/src/Table/Table.doc.mjs +9 -2
  482. package/src/Table/Table.test.tsx +132 -14
  483. package/src/Table/Table.tsx +3 -8
  484. package/src/Table/TableBody.doc.mjs +40 -0
  485. package/src/Table/TableFooter.doc.mjs +40 -0
  486. package/src/Table/TableHeader.doc.mjs +40 -0
  487. package/src/Table/TableRow.tsx +16 -5
  488. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  489. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  490. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
  491. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  492. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  493. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  494. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  495. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  496. package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
  497. package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
  498. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  499. package/src/Table/types.ts +22 -4
  500. package/src/Table/useBaseTablePlugins.ts +5 -0
  501. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  502. package/src/Table/useTablePagination.doc.mjs +7 -0
  503. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  504. package/src/Table/useTableSelection.doc.mjs +31 -0
  505. package/src/Text/Text.test.tsx +23 -1
  506. package/src/Text/Text.tsx +6 -2
  507. package/src/TextArea/TextArea.doc.mjs +8 -2
  508. package/src/TextArea/TextArea.test.tsx +11 -0
  509. package/src/TextArea/TextArea.tsx +15 -8
  510. package/src/TextInput/TextInput.doc.mjs +10 -0
  511. package/src/TextInput/TextInput.tsx +3 -2
  512. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  513. package/src/TimeInput/TimeInput.tsx +2 -2
  514. package/src/Timestamp/Timestamp.tsx +4 -2
  515. package/src/Toast/Toast.doc.mjs +6 -0
  516. package/src/Token/TokenLink.tsx +2 -2
  517. package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
  518. package/src/Tokenizer/Tokenizer.tsx +4 -0
  519. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  520. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  521. package/src/Tooltip/Tooltip.test.tsx +32 -0
  522. package/src/Tooltip/Tooltip.tsx +5 -0
  523. package/src/Tooltip/useTooltip.tsx +47 -24
  524. package/src/TopNav/TopNavHeading.tsx +5 -4
  525. package/src/TopNav/TopNavMegaMenu.tsx +3 -2
  526. package/src/TopNav/TopNavMenu.tsx +4 -3
  527. package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
  528. package/src/Typeahead/BaseTypeahead.tsx +85 -33
  529. package/src/Typeahead/Typeahead.doc.mjs +5 -0
  530. package/src/Typeahead/Typeahead.test.tsx +49 -0
  531. package/src/Typeahead/Typeahead.tsx +3 -2
  532. package/src/hooks/index.ts +2 -0
  533. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  534. package/src/hooks/useFocusTrap.test.tsx +14 -0
  535. package/src/hooks/useFocusTrap.ts +62 -111
  536. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  537. package/src/hooks/useHotkeys.ts +3 -18
  538. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  539. package/src/hooks/useMergedRefs.test.tsx +62 -0
  540. package/src/hooks/useMergedRefs.ts +36 -0
  541. package/src/index.ts +1 -0
  542. package/src/theme/MediaTheme.doc.mjs +5 -5
  543. package/src/theme/derivedVarRegistry.test.ts +19 -3
  544. package/src/theme/derivedVarRegistry.ts +23 -4
  545. package/src/theme/generateThemeRules.test.ts +37 -0
  546. package/src/theme/syntax/tokens.ts +5 -2
  547. package/src/utils/groupItems.ts +12 -6
  548. package/src/utils/index.ts +1 -1
  549. package/src/utils/isApplePlatform.test.ts +61 -0
  550. package/src/utils/isApplePlatform.ts +37 -0
  551. package/src/utils/sharedResizeObserver.ts +10 -2
  552. package/src/utils/timeParser.test.ts +6 -1
  553. package/src/utils/timeParser.ts +35 -13
  554. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -103,6 +103,12 @@ export const docs = {
103
103
  description: 'How to display selected items in the trigger.',
104
104
  default: "'count'",
105
105
  },
106
+ {
107
+ name: 'formatValue',
108
+ type: '(items: {value: string; label: string}[]) => string',
109
+ description:
110
+ 'Formats the trigger text when triggerDisplay="count" or "labels". Receives the selected items (value plus resolved label); the count is items.length. Not used by triggerDisplay="badges".',
111
+ },
106
112
  {
107
113
  name: 'maxBadges',
108
114
  type: 'number',
@@ -207,6 +213,23 @@ export const docs = {
207
213
  description:
208
214
  'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
209
215
  },
216
+ {
217
+ name: 'startIcon',
218
+ type: 'IconType | ReactNode',
219
+ description: 'Icon displayed at the start of the selector trigger.',
220
+ },
221
+ {
222
+ name: 'hasClear',
223
+ type: 'boolean',
224
+ description: 'Shows a clear button when values are selected.',
225
+ default: 'false',
226
+ },
227
+ {
228
+ name: 'isDefaultOpen',
229
+ type: 'boolean',
230
+ description: 'Whether the dropdown starts open on mount.',
231
+ default: 'false',
232
+ },
210
233
  {
211
234
  name: 'xstyle',
212
235
  type: 'StyleXStyles',
@@ -284,6 +307,8 @@ export const docsZh = {
284
307
  placeholder: '未选择值时显示的占位文本。',
285
308
  size: '选择器的尺寸变体。',
286
309
  triggerDisplay: '在触发器中显示选中项的方式。',
310
+ formatValue:
311
+ '格式化 triggerDisplay="count" 或 "labels" 时的触发器文本。接收选中项(value 及解析后的 label),数量为 items.length。triggerDisplay="badges" 不使用此属性。',
287
312
  maxBadges:
288
313
  '显示"+N"之前的最大徽章数。仅适用于 triggerDisplay="badges"。',
289
314
  hasSelectAll: '是否显示全选复选框。',
@@ -420,6 +445,8 @@ export const docsDense = {
420
445
  variant:
421
446
  'visual trigger style: input bordered control or ghost toolbar control',
422
447
  triggerDisplay: 'how to show selected in trigger',
448
+ formatValue:
449
+ 'formats count/labels trigger text; receives selected items',
423
450
  maxBadges: 'max badges before "+N"; badges mode only',
424
451
  hasSelectAll: 'show select-all checkbox',
425
452
  selectAllLabel: 'select-all label',
@@ -128,6 +128,90 @@ describe('MultiSelector', () => {
128
128
  expect(screen.getByText('2 selected')).toBeInTheDocument();
129
129
  });
130
130
 
131
+ it('formats the count display with formatValue', () => {
132
+ render(
133
+ <MultiSelector
134
+ label="Spaces"
135
+ options={defaultOptions}
136
+ value={['Apple', 'Banana']}
137
+ onChange={() => {}}
138
+ formatValue={items => `${items.length} spaces selected`}
139
+ />,
140
+ );
141
+ expect(screen.getByText('2 spaces selected')).toBeInTheDocument();
142
+ });
143
+
144
+ it('passes selected values and resolved labels to formatValue', () => {
145
+ const formatValue = vi.fn(
146
+ (items: {value: string; label: string}[]) =>
147
+ `${items[0].label} and ${items.length - 1} more`,
148
+ );
149
+ render(
150
+ <MultiSelector
151
+ label="Fruit"
152
+ options={[
153
+ {value: 'a', label: 'Apple'},
154
+ {value: 'b', label: 'Banana'},
155
+ ]}
156
+ value={['a', 'b']}
157
+ onChange={() => {}}
158
+ formatValue={formatValue}
159
+ />,
160
+ );
161
+ expect(formatValue).toHaveBeenCalledWith([
162
+ {value: 'a', label: 'Apple'},
163
+ {value: 'b', label: 'Banana'},
164
+ ]);
165
+ expect(screen.getByText('Apple and 1 more')).toBeInTheDocument();
166
+ });
167
+
168
+ it('formats the labels display with formatValue', () => {
169
+ render(
170
+ <MultiSelector
171
+ label="Fruit"
172
+ options={defaultOptions}
173
+ value={['Apple', 'Banana', 'Orange']}
174
+ onChange={() => {}}
175
+ triggerDisplay="labels"
176
+ formatValue={items => items.map(item => item.label).join(' & ')}
177
+ />,
178
+ );
179
+ expect(screen.getByText('Apple & Banana & Orange')).toBeInTheDocument();
180
+ });
181
+
182
+ it('ignores formatValue in badges display', () => {
183
+ render(
184
+ <MultiSelector
185
+ label="Fruit"
186
+ options={defaultOptions}
187
+ value={['Apple', 'Banana']}
188
+ onChange={() => {}}
189
+ triggerDisplay="badges"
190
+ formatValue={() => 'formatted'}
191
+ />,
192
+ );
193
+ expect(screen.queryByText('formatted')).not.toBeInTheDocument();
194
+ const trigger = within(screen.getByRole('combobox'));
195
+ expect(trigger.getByText('Apple')).toBeInTheDocument();
196
+ expect(trigger.getByText('Banana')).toBeInTheDocument();
197
+ });
198
+
199
+ it('shows the placeholder rather than calling formatValue when empty', () => {
200
+ const formatValue = vi.fn(() => 'formatted');
201
+ render(
202
+ <MultiSelector
203
+ label="Fruit"
204
+ options={defaultOptions}
205
+ value={[]}
206
+ onChange={() => {}}
207
+ placeholder="Pick fruits..."
208
+ formatValue={formatValue}
209
+ />,
210
+ );
211
+ expect(screen.getByText('Pick fruits...')).toBeInTheDocument();
212
+ expect(formatValue).not.toHaveBeenCalled();
213
+ });
214
+
131
215
  it('shows labels display', () => {
132
216
  render(
133
217
  <MultiSelector
@@ -353,6 +437,7 @@ describe('MultiSelector', () => {
353
437
 
354
438
  await user.keyboard('{Tab}');
355
439
  expect(trigger).toHaveAttribute('aria-expanded', 'false');
440
+ expect(screen.getByRole('button', {name: 'Next'})).toHaveFocus();
356
441
  });
357
442
 
358
443
  it('supports keyboard navigation with ArrowDown/ArrowUp', async () => {
@@ -1981,6 +2066,27 @@ describe('MultiSelector list structure', () => {
1981
2066
  Node.DOCUMENT_POSITION_FOLLOWING,
1982
2067
  ).toBeTruthy();
1983
2068
  });
2069
+
2070
+ it('hides a standalone divider from the accessibility tree (#4994)', async () => {
2071
+ const user = userEvent.setup();
2072
+ render(
2073
+ <MultiSelector
2074
+ label="Fruit"
2075
+ options={['Apple', {type: 'divider'}, 'Banana']}
2076
+ value={[]}
2077
+ onChange={() => {}}
2078
+ />,
2079
+ );
2080
+ await user.click(screen.getByRole('combobox'));
2081
+
2082
+ // role="listbox" only permits option/group children. The divider still
2083
+ // renders role="separator" (unchanged visual/DOM), but must be excluded
2084
+ // from the accessibility tree so it never reaches the listbox's exposed
2085
+ // children (axe aria-required-children).
2086
+ const divider = document.querySelector('[role="separator"]');
2087
+ expect(divider).toBeTruthy();
2088
+ expect(divider).toHaveAttribute('aria-hidden', 'true');
2089
+ });
1984
2090
  });
1985
2091
 
1986
2092
  describe('MultiSelector search affordances', () => {
@@ -424,6 +424,11 @@ export type MultiSelectorStatusType = 'warning' | 'error' | 'success';
424
424
 
425
425
  export type {MultiSelectorStatus};
426
426
 
427
+ export interface MultiSelectorSelectedItem {
428
+ value: string;
429
+ label: string;
430
+ }
431
+
427
432
  export interface MultiSelectorProps<
428
433
  T extends MultiSelectorOptionType = MultiSelectorOptionType,
429
434
  > extends Omit<BaseProps, 'onChange' | 'defaultValue'> {
@@ -608,6 +613,17 @@ export interface MultiSelectorProps<
608
613
  */
609
614
  triggerDisplay?: 'count' | 'labels' | 'badges';
610
615
 
616
+ /**
617
+ * Formats the trigger text when triggerDisplay is 'count' or 'labels'.
618
+ * Receives the selected items (value plus resolved label, in selection
619
+ * order) and returns the full trigger text; the count is `items.length`.
620
+ * Not called when nothing is selected — the placeholder shows instead — and
621
+ * not called for triggerDisplay 'badges', which renders Badge elements
622
+ * rather than text.
623
+ * @default items => `${items.length} selected` for 'count', "A, B, C, +N" for 'labels'
624
+ */
625
+ formatValue?: (items: MultiSelectorSelectedItem[]) => string;
626
+
611
627
  /**
612
628
  * Maximum number of badges to show before showing "+N".
613
629
  * Only used when triggerDisplay is 'badges'.
@@ -711,6 +727,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
711
727
  hasSearch = false,
712
728
  searchPlaceholder: searchPlaceholderFromProps,
713
729
  triggerDisplay = 'count',
730
+ formatValue,
714
731
  maxBadges = 3,
715
732
  renderOption,
716
733
  indicatorPosition = 'start',
@@ -1107,13 +1124,18 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
1107
1124
  }, [popover.isOpen, highlightedIndex, getItemId]);
1108
1125
 
1109
1126
  // Build trigger display content
1110
- const selectedLabels = useMemo(() => {
1127
+ const selectedItems = useMemo(() => {
1111
1128
  return optimisticValue.map(v => {
1112
1129
  const item = selectableItems.find(i => i.value === v);
1113
- return item?.label ?? v;
1130
+ return {value: v, label: item?.label ?? v};
1114
1131
  });
1115
1132
  }, [optimisticValue, selectableItems]);
1116
1133
 
1134
+ const selectedLabels = useMemo(
1135
+ () => selectedItems.map(item => item.label),
1136
+ [selectedItems],
1137
+ );
1138
+
1117
1139
  const renderTriggerContent = useCallback(() => {
1118
1140
  if (optimisticValue.length === 0) {
1119
1141
  return <span {...stylex.props(styles.triggerText)}>{placeholder}</span>;
@@ -1123,7 +1145,8 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
1123
1145
  case 'count':
1124
1146
  return (
1125
1147
  <span {...stylex.props(styles.triggerText)}>
1126
- {optimisticValue.length} selected
1148
+ {formatValue?.(selectedItems) ??
1149
+ `${optimisticValue.length} selected`}
1127
1150
  </span>
1128
1151
  );
1129
1152
 
@@ -1134,7 +1157,11 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
1134
1157
  remaining > 0
1135
1158
  ? `${displayed.join(', ')}, +${remaining}`
1136
1159
  : displayed.join(', ');
1137
- return <span {...stylex.props(styles.triggerText)}>{text}</span>;
1160
+ return (
1161
+ <span {...stylex.props(styles.triggerText)}>
1162
+ {formatValue?.(selectedItems) ?? text}
1163
+ </span>
1164
+ );
1138
1165
  }
1139
1166
 
1140
1167
  case 'badges': {
@@ -1154,7 +1181,15 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
1154
1181
  );
1155
1182
  }
1156
1183
  }
1157
- }, [optimisticValue, triggerDisplay, selectedLabels, placeholder, maxBadges]);
1184
+ }, [
1185
+ optimisticValue,
1186
+ triggerDisplay,
1187
+ selectedItems,
1188
+ selectedLabels,
1189
+ placeholder,
1190
+ formatValue,
1191
+ maxBadges,
1192
+ ]);
1158
1193
 
1159
1194
  // Render search input
1160
1195
  const renderSearch = useCallback(() => {
@@ -1420,8 +1455,17 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
1420
1455
  // A standalone divider between groups would orphan itself once its
1421
1456
  // neighbors are filtered out, so skip it while searching.
1422
1457
  if (!isSearching) {
1458
+ // role="listbox" only permits option/group children; the divider
1459
+ // carries no information the options don't, so it's hidden from
1460
+ // the accessibility tree entirely rather than exposing
1461
+ // role="separator" as a disallowed listbox child (axe
1462
+ // aria-required-children).
1423
1463
  elements.push(
1424
- <Divider key={`divider-${i}`} xstyle={styles.divider} />,
1464
+ <Divider
1465
+ key={`divider-${i}`}
1466
+ aria-hidden="true"
1467
+ xstyle={styles.divider}
1468
+ />,
1425
1469
  );
1426
1470
  }
1427
1471
  } else if (isSection(option)) {
@@ -13,6 +13,7 @@ export {
13
13
  type MultiSelectorProps,
14
14
  type MultiSelectorSize,
15
15
  type MultiSelectorStatusType,
16
+ type MultiSelectorSelectedItem,
16
17
  } from './MultiSelector';
17
18
  export type {
18
19
  MultiSelectorOptionType,
@@ -22,7 +22,10 @@ export const docs = {
22
22
  ],
23
23
  theming: {
24
24
  targets: [
25
- {className: 'astryx-navicon'},
25
+ {className: 'astryx-nav-icon'},
26
+ // Still emitted beside the names above, so themes written against
27
+ // them keep working. Drop in the next major.
28
+ {className: 'astryx-navicon', deprecatedFor: 'nav-icon'},
26
29
  ],
27
30
  },
28
31
  usage: {
@@ -51,7 +54,10 @@ export const docsZh = {
51
54
  ],
52
55
  theming: {
53
56
  targets: [
54
- {className: 'astryx-navicon'},
57
+ {className: 'astryx-nav-icon'},
58
+ // Still emitted beside the names above, so themes written against
59
+ // them keep working. Drop in the next major.
60
+ {className: 'astryx-navicon', deprecatedFor: 'nav-icon'},
55
61
  ],
56
62
  },
57
63
  usage: {
@@ -30,3 +30,12 @@ describe('NavIcon', () => {
30
30
  expect(screen.getByTestId('nav-icon')).toBeInTheDocument();
31
31
  });
32
32
  });
33
+
34
+ describe('NavIcon theme target names', () => {
35
+ it('renders the deprecated class beside the current one', () => {
36
+ render(<NavIcon icon={<span>Icon</span>} data-testid="nav-icon" />);
37
+ const root = screen.getByTestId('nav-icon');
38
+ expect(root).toHaveClass('astryx-nav-icon');
39
+ expect(root).toHaveClass('astryx-navicon');
40
+ });
41
+ });
@@ -79,7 +79,11 @@ export function NavIcon({
79
79
  <span
80
80
  ref={ref}
81
81
  {...mergeProps(
82
- themeProps('navicon'),
82
+ themeProps('nav-icon', undefined, {
83
+ // `navicon` ran the compound name together; themes styling it keep
84
+ // working until the next major.
85
+ legacyNames: ['navicon'],
86
+ }),
83
87
  stylex.props(styles.base, xstyle),
84
88
  className,
85
89
  style,
@@ -15,7 +15,7 @@
15
15
  import React, {useCallback, useMemo, type ReactNode} from 'react';
16
16
  import * as stylex from '@stylexjs/stylex';
17
17
  import {spacingVars} from '../theme/tokens.stylex';
18
- import {mergeProps, mergeRefs} from '../utils';
18
+ import {mergeProps} from '../utils';
19
19
  import type {BaseProps} from '../BaseProps';
20
20
  import {useListFocus} from '../hooks/useListFocus';
21
21
  import {useTypeahead} from '../hooks/useTypeahead';
@@ -26,6 +26,7 @@ import {
26
26
  type NavHeadingMenuSize,
27
27
  } from './NavMenuContext';
28
28
 
29
+ import {useMergedRefs} from '../hooks/useMergedRefs';
29
30
  const styles = stylex.create({
30
31
  root: {
31
32
  display: 'flex',
@@ -162,7 +163,7 @@ export function NavHeadingMenu({
162
163
  return (
163
164
  <NavHeadingMenuContext value={ctx}>
164
165
  <div
165
- ref={mergeRefs(ref, listRef)}
166
+ ref={useMergedRefs(ref, listRef)}
166
167
  role="menu"
167
168
  onKeyDown={listKeyDown}
168
169
  data-testid={testId}
@@ -61,6 +61,11 @@ export const docs = {
61
61
  description:
62
62
  'Whether the field is optional (mutually exclusive with isRequired).',
63
63
  },
64
+ {
65
+ name: 'onKeyDown',
66
+ type: '(e: KeyboardEvent<HTMLInputElement>) => void',
67
+ description: 'Callback fired on keydown events on the input.',
68
+ },
64
69
  {
65
70
  name: 'isRequired',
66
71
  type: 'boolean',
@@ -237,6 +242,11 @@ export const docs = {
237
242
  description:
238
243
  'A form input for numeric values with built-in validation, min/max constraints, and step controls. Use NumberInput for quantities, measurements, percentages, and similar inputs.',
239
244
  bestPractices: [
245
+ {
246
+ guidance: true,
247
+ description:
248
+ "Let people paste formatted numbers: a pasted 1,234,234,234 is read under the field's locale and commits as 1234234234 on blur. Typing is never intercepted.",
249
+ },
240
250
  {
241
251
  guidance: true,
242
252
  description:
@@ -504,6 +514,11 @@ export const docsZh = {
504
514
  description:
505
515
  'A form input for numeric values with built-in validation, min/max constraints, and step controls. Use NumberInput for quantities, measurements, percentages, and similar inputs.',
506
516
  bestPractices: [
517
+ {
518
+ guidance: true,
519
+ description:
520
+ '可以直接粘贴带格式的数字:粘贴 1,234,234,234 会按字段所在区域设置解析,失去焦点时提交为 1234234234。输入过程中不会拦截按键。',
521
+ },
507
522
  {
508
523
  guidance: true,
509
524
  description:
@@ -573,6 +588,11 @@ export const docsDense = {
573
588
  description:
574
589
  'A form input for numeric values with built-in validation, min/max constraints, and step controls. Use NumberInput for quantities, measurements, percentages, and similar inputs.',
575
590
  bestPractices: [
591
+ {
592
+ guidance: true,
593
+ description:
594
+ "Pasted formatted numbers parse: 1,234,234,234 commits as 1234234234 under the field's locale. Typing is never intercepted.",
595
+ },
576
596
  {
577
597
  guidance: true,
578
598
  description:
@@ -9,6 +9,7 @@
9
9
  * @position Core implementation; consumed by index.ts, tested by NumberInput.test.tsx
10
10
  *
11
11
  * SYNC: When modified, update these files to stay in sync:
12
+ * - /packages/core/src/NumberInput/numberParser.ts (locale-aware parsing)
12
13
  * - /packages/core/src/NumberInput/NumberInput.doc.mjs (props table, features, implementation notes)
13
14
  * - /packages/core/src/NumberInput/NumberInput.test.tsx (tests for new/changed behavior)
14
15
  * - /packages/core/src/NumberInput/index.ts (exports if types change)
@@ -213,7 +214,9 @@ import {isImeKeyEvent, mergeProps, mergeRefs} from '../utils';
213
214
  import type {BaseProps} from '../BaseProps';
214
215
  import type {SizeValue} from '../utils/types';
215
216
  import {themeProps} from '../utils/themeProps';
216
- import {useTranslator} from '../i18n';
217
+ import {useTranslator, useLocale} from '../i18n';
218
+ import {formatEditableNumber, parseLocaleNumber} from './numberParser';
219
+ import type {Locale} from '../i18n';
217
220
 
218
221
  interface NumberInputPropsBase extends Omit<
219
222
  BaseProps,
@@ -426,7 +429,8 @@ export type NumberInputProps =
426
429
  NumberInputPropsNonClearable | NumberInputPropsClearable;
427
430
 
428
431
  /**
429
- * Parse and validate a string input as a number.
432
+ * Read the typed or pasted text as a number, then apply the field's
433
+ * constraints.
430
434
  * Returns null if the input is not a valid number or fails validation.
431
435
  */
432
436
  function parseNumberInput(
@@ -435,15 +439,16 @@ function parseNumberInput(
435
439
  min?: number | null;
436
440
  max?: number | null;
437
441
  isIntegerOnly?: boolean;
442
+ locale?: Locale;
438
443
  },
439
444
  ): number | null {
440
445
  const trimmed = input.trim();
441
- if (trimmed === '' || trimmed === '-') {
446
+ if (trimmed === '') {
442
447
  return null;
443
448
  }
444
449
 
445
- const num = Number(trimmed);
446
- if (!Number.isFinite(num)) {
450
+ const num = parseLocaleNumber(trimmed, options.locale);
451
+ if (num == null || !Number.isFinite(num)) {
447
452
  return null;
448
453
  }
449
454
 
@@ -599,6 +604,7 @@ export function NumberInput({
599
604
  ...rest
600
605
  }: NumberInputProps) {
601
606
  const t = useTranslator();
607
+ const locale = useLocale();
602
608
  const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
603
609
  const size = useSize(sizeProp, 'md');
604
610
  const id = useId();
@@ -653,6 +659,11 @@ export function NumberInput({
653
659
  inputGroup,
654
660
  );
655
661
 
662
+ const parseInput = useCallback(
663
+ (text: string) => parseNumberInput(text, {min, max, isIntegerOnly, locale}),
664
+ [isIntegerOnly, locale, max, min],
665
+ );
666
+
656
667
  const formattedValue = useMemo(() => {
657
668
  if (value == null) {
658
669
  return '';
@@ -669,16 +680,16 @@ export function NumberInput({
669
680
  if (value == null) {
670
681
  return '';
671
682
  }
672
- return isFocused ? String(value) : formattedValue;
673
- }, [formattedValue, isFocused, pendingInput, value]);
683
+ return isFocused ? formatEditableNumber(value, locale) : formattedValue;
684
+ }, [formattedValue, isFocused, locale, pendingInput, value]);
674
685
 
675
686
  // Check if current pending input is valid (for styling purposes)
676
687
  const isInputValid = useMemo(() => {
677
688
  if (pendingInput === null || !pendingInput.trim()) {
678
689
  return true;
679
690
  }
680
- return parseNumberInput(pendingInput, {min, max, isIntegerOnly}) !== null;
681
- }, [pendingInput, min, max, isIntegerOnly]);
691
+ return parseInput(pendingInput) !== null;
692
+ }, [pendingInput, parseInput]);
682
693
 
683
694
  // Handle input text change - update immediately if valid
684
695
  const handleInputChange = useCallback(
@@ -693,12 +704,12 @@ export function NumberInput({
693
704
  setPendingInput(newValue);
694
705
 
695
706
  // If the input is valid, update immediately
696
- const parsed = parseNumberInput(newValue, {min, max, isIntegerOnly});
707
+ const parsed = parseInput(newValue);
697
708
  if (parsed !== null && parsed !== value) {
698
709
  onChange(parsed);
699
710
  }
700
711
  },
701
- [value, onChange, min, max, isIntegerOnly, isDisabled, isReadOnly],
712
+ [value, onChange, parseInput, isDisabled, isReadOnly],
702
713
  );
703
714
 
704
715
  // Handle focus
@@ -721,11 +732,7 @@ export function NumberInput({
721
732
  onChange(null);
722
733
  }
723
734
  } else {
724
- const parsed = parseNumberInput(pendingInput, {
725
- min,
726
- max,
727
- isIntegerOnly,
728
- });
735
+ const parsed = parseInput(pendingInput);
729
736
  if (parsed !== null && parsed !== value) {
730
737
  onChange(parsed);
731
738
  }
@@ -737,7 +744,7 @@ export function NumberInput({
737
744
  setIsFocused(false);
738
745
  onBlur?.(e);
739
746
  },
740
- [pendingInput, value, onChange, min, max, isIntegerOnly, onBlur, hasClear],
747
+ [pendingInput, value, onChange, parseInput, onBlur, hasClear],
741
748
  );
742
749
 
743
750
  const valueForStepping = useMemo(() => {
@@ -747,10 +754,8 @@ export function NumberInput({
747
754
  if (pendingInput.trim() === '') {
748
755
  return null;
749
756
  }
750
- return (
751
- parseNumberInput(pendingInput, {min, max, isIntegerOnly}) ?? value ?? null
752
- );
753
- }, [isIntegerOnly, max, min, pendingInput, value]);
757
+ return parseInput(pendingInput) ?? value ?? null;
758
+ }, [parseInput, pendingInput, value]);
754
759
 
755
760
  const getNextValue = useCallback(
756
761
  (direction: StepDirection) =>
@@ -815,11 +820,7 @@ export function NumberInput({
815
820
  onChange(null);
816
821
  }
817
822
  } else {
818
- const parsed = parseNumberInput(pendingInput, {
819
- min,
820
- max,
821
- isIntegerOnly,
822
- });
823
+ const parsed = parseInput(pendingInput);
823
824
  if (parsed !== null && parsed !== value) {
824
825
  onChange(parsed);
825
826
  }
@@ -833,9 +834,7 @@ export function NumberInput({
833
834
  pendingInput,
834
835
  value,
835
836
  onChange,
836
- min,
837
- max,
838
- isIntegerOnly,
837
+ parseInput,
839
838
  onEnter,
840
839
  onKeyDown,
841
840
  hasClear,