@astryxdesign/core 0.1.6 → 0.1.7-canary.0a6de96

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 (521) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +2 -0
  3. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  4. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  5. package/dist/AlertDialog/AlertDialog.js +4 -1
  6. package/dist/AppShell/AppShell.d.ts.map +1 -1
  7. package/dist/AppShell/AppShell.js +3 -1
  8. package/dist/AvatarGroup/AvatarGroup.d.ts +1 -1
  9. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  10. package/dist/AvatarGroup/AvatarGroup.js +4 -1
  11. package/dist/Banner/Banner.d.ts.map +1 -1
  12. package/dist/Banner/Banner.js +8 -6
  13. package/dist/Breadcrumbs/Breadcrumbs.d.ts +1 -1
  14. package/dist/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
  15. package/dist/Breadcrumbs/Breadcrumbs.js +4 -1
  16. package/dist/Button/Button.d.ts +10 -2
  17. package/dist/Button/Button.d.ts.map +1 -1
  18. package/dist/Button/Button.js +49 -6
  19. package/dist/ButtonGroup/ButtonGroup.d.ts +20 -5
  20. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  21. package/dist/ButtonGroup/ButtonGroup.js +27 -11
  22. package/dist/Calendar/Calendar.d.ts.map +1 -1
  23. package/dist/Calendar/Calendar.js +29 -7
  24. package/dist/Carousel/Carousel.d.ts +1 -1
  25. package/dist/Carousel/Carousel.d.ts.map +1 -1
  26. package/dist/Carousel/Carousel.js +8 -5
  27. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  28. package/dist/Chat/ChatComposer.js +4 -1
  29. package/dist/Chat/ChatComposerDrawer.d.ts +1 -1
  30. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  31. package/dist/Chat/ChatComposerDrawer.js +9 -2
  32. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  33. package/dist/Chat/ChatComposerInput.js +6 -2
  34. package/dist/Chat/ChatLayout.d.ts +1 -11
  35. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  36. package/dist/Chat/ChatLayout.js +6 -4
  37. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  38. package/dist/Chat/ChatLayoutScrollButton.js +4 -2
  39. package/dist/Chat/ChatMessage.d.ts +1 -1
  40. package/dist/Chat/ChatMessage.d.ts.map +1 -1
  41. package/dist/Chat/ChatMessage.js +8 -2
  42. package/dist/Chat/ChatMessageBubble.d.ts +1 -1
  43. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  44. package/dist/Chat/ChatMessageBubble.js +3 -1
  45. package/dist/Chat/ChatMessageList.d.ts +1 -1
  46. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  47. package/dist/Chat/ChatMessageList.js +3 -1
  48. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  49. package/dist/Chat/ChatMessageMetadata.js +13 -8
  50. package/dist/Chat/ChatPastedTextToken.d.ts.map +1 -1
  51. package/dist/Chat/ChatPastedTextToken.js +3 -1
  52. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  53. package/dist/Chat/ChatSendButton.js +3 -1
  54. package/dist/Chat/index.d.ts +1 -1
  55. package/dist/Chat/index.d.ts.map +1 -1
  56. package/dist/Chat/useChatStreamScroll.d.ts +12 -1
  57. package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
  58. package/dist/Chat/useChatStreamScroll.js +43 -6
  59. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  60. package/dist/Chat/useSpeechRecognition.js +4 -2
  61. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  62. package/dist/Chat/useTriggerMenu.js +4 -2
  63. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  64. package/dist/CheckboxInput/CheckboxInput.js +4 -2
  65. package/dist/CheckboxList/CheckboxList.d.ts +1 -1
  66. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  67. package/dist/CheckboxList/CheckboxList.js +3 -1
  68. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  69. package/dist/CheckboxList/CheckboxListItem.js +3 -1
  70. package/dist/Citation/Citation.d.ts.map +1 -1
  71. package/dist/Citation/Citation.js +10 -2
  72. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  73. package/dist/CodeBlock/CodeBlock.js +71 -53
  74. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  75. package/dist/Collapsible/Collapsible.js +8 -1
  76. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  77. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  78. package/dist/CommandPalette/CommandPalette.js +8 -3
  79. package/dist/CommandPalette/CommandPaletteInput.d.ts +1 -1
  80. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  81. package/dist/CommandPalette/CommandPaletteInput.js +4 -1
  82. package/dist/CommandPalette/CommandPaletteList.d.ts +1 -1
  83. package/dist/CommandPalette/CommandPaletteList.d.ts.map +1 -1
  84. package/dist/CommandPalette/CommandPaletteList.js +4 -1
  85. package/dist/ContextMenu/ContextMenu.d.ts +1 -1
  86. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  87. package/dist/ContextMenu/ContextMenu.js +8 -4
  88. package/dist/ContextMenu/index.d.ts +3 -0
  89. package/dist/ContextMenu/index.d.ts.map +1 -1
  90. package/dist/ContextMenu/index.js +7 -1
  91. package/dist/DateInput/DateInput.d.ts +1 -1
  92. package/dist/DateInput/DateInput.d.ts.map +1 -1
  93. package/dist/DateInput/DateInput.js +10 -5
  94. package/dist/DateRangeInput/DateRangeInput.d.ts +1 -1
  95. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  96. package/dist/DateRangeInput/DateRangeInput.js +11 -6
  97. package/dist/DateTimeInput/DateTimeInput.d.ts +1 -1
  98. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  99. package/dist/DateTimeInput/DateTimeInput.js +15 -7
  100. package/dist/Dialog/Dialog.d.ts.map +1 -1
  101. package/dist/Dialog/Dialog.js +15 -12
  102. package/dist/Dialog/DialogHeader.d.ts +1 -1
  103. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  104. package/dist/Dialog/DialogHeader.js +7 -3
  105. package/dist/DropdownMenu/DropdownMenu.d.ts +1 -1
  106. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  107. package/dist/DropdownMenu/DropdownMenu.js +19 -9
  108. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +89 -0
  109. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
  110. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +170 -0
  111. package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -1
  112. package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
  113. package/dist/DropdownMenu/DropdownMenuContext.js +18 -0
  114. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +69 -0
  115. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
  116. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +70 -0
  117. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +69 -0
  118. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -0
  119. package/dist/DropdownMenu/DropdownMenuRadioItem.js +178 -0
  120. package/dist/DropdownMenu/index.d.ts +5 -1
  121. package/dist/DropdownMenu/index.d.ts.map +1 -1
  122. package/dist/DropdownMenu/index.js +10 -1
  123. package/dist/DropdownMenu/menuItemRoles.d.ts +13 -0
  124. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -0
  125. package/dist/DropdownMenu/menuItemRoles.js +15 -0
  126. package/dist/EmptyState/EmptyState.d.ts +4 -1
  127. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  128. package/dist/FileInput/FileInput.d.ts.map +1 -1
  129. package/dist/FileInput/FileInput.js +11 -1
  130. package/dist/Icon/Icon.d.ts +17 -12
  131. package/dist/Icon/Icon.d.ts.map +1 -1
  132. package/dist/Icon/Icon.js +28 -20
  133. package/dist/Kbd/Kbd.js +1 -1
  134. package/dist/Layer/useLayer.d.ts +10 -0
  135. package/dist/Layer/useLayer.d.ts.map +1 -1
  136. package/dist/Layer/useLayer.js +23 -1
  137. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  138. package/dist/Lightbox/Lightbox.js +6 -4
  139. package/dist/Link/Link.d.ts +5 -1
  140. package/dist/Link/Link.d.ts.map +1 -1
  141. package/dist/Link/Link.js +32 -1
  142. package/dist/Markdown/Markdown.d.ts.map +1 -1
  143. package/dist/Markdown/Markdown.js +10 -8
  144. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  145. package/dist/MobileNav/MobileNav.js +4 -2
  146. package/dist/MobileNav/MobileNavToggle.d.ts +1 -1
  147. package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
  148. package/dist/MobileNav/MobileNavToggle.js +4 -1
  149. package/dist/MoreMenu/MoreMenu.d.ts +1 -1
  150. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  151. package/dist/MoreMenu/MoreMenu.js +4 -1
  152. package/dist/MultiSelector/MultiSelector.d.ts +1 -1
  153. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  154. package/dist/MultiSelector/MultiSelector.js +13 -6
  155. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  156. package/dist/NumberInput/NumberInput.js +5 -1
  157. package/dist/Outline/Outline.d.ts +1 -1
  158. package/dist/Outline/Outline.d.ts.map +1 -1
  159. package/dist/Outline/Outline.js +4 -1
  160. package/dist/Pagination/Pagination.d.ts +1 -1
  161. package/dist/Pagination/Pagination.d.ts.map +1 -1
  162. package/dist/Pagination/Pagination.js +38 -11
  163. package/dist/Popover/usePopover.d.ts.map +1 -1
  164. package/dist/Popover/usePopover.js +4 -1
  165. package/dist/PowerSearch/PowerSearch.d.ts +1 -1
  166. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  167. package/dist/PowerSearch/PowerSearch.js +22 -12
  168. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +1 -1
  169. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  170. package/dist/PowerSearch/PowerSearchEditPopover.js +26 -20
  171. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  172. package/dist/PowerSearch/PowerSearchToken.js +7 -3
  173. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  174. package/dist/PowerSearch/PowerSearchValueEditor.js +34 -21
  175. package/dist/PowerSearch/formatFilterValue.d.ts +2 -1
  176. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  177. package/dist/PowerSearch/formatFilterValue.js +19 -9
  178. package/dist/PowerSearch/index.d.ts +2 -1
  179. package/dist/PowerSearch/index.d.ts.map +1 -1
  180. package/dist/PowerSearch/index.js +1 -0
  181. package/dist/PowerSearch/resolveOperatorLabel.d.ts +23 -0
  182. package/dist/PowerSearch/resolveOperatorLabel.d.ts.map +1 -0
  183. package/dist/PowerSearch/resolveOperatorLabel.js +28 -0
  184. package/dist/PowerSearch/types.d.ts +28 -2
  185. package/dist/PowerSearch/types.d.ts.map +1 -1
  186. package/dist/PowerSearch/usePowerSearchConfig.d.ts.map +1 -1
  187. package/dist/PowerSearch/usePowerSearchConfig.js +27 -27
  188. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  189. package/dist/PowerSearch/usePowerSearchSource.js +15 -8
  190. package/dist/Resizable/ResizeHandle.d.ts +1 -1
  191. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  192. package/dist/Resizable/ResizeHandle.js +4 -1
  193. package/dist/Selector/Selector.d.ts.map +1 -1
  194. package/dist/Selector/Selector.js +52 -14
  195. package/dist/SideNav/SideNav.d.ts.map +1 -1
  196. package/dist/SideNav/SideNav.js +4 -2
  197. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  198. package/dist/SideNav/SideNavCollapseButton.js +3 -1
  199. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  200. package/dist/SideNav/SideNavHeading.js +5 -3
  201. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  202. package/dist/SideNav/SideNavItem.js +7 -1
  203. package/dist/Switch/Switch.d.ts.map +1 -1
  204. package/dist/Switch/Switch.js +4 -2
  205. package/dist/TabList/TabList.d.ts +1 -1
  206. package/dist/TabList/TabList.d.ts.map +1 -1
  207. package/dist/TabList/TabList.js +4 -1
  208. package/dist/Table/BaseTable.d.ts.map +1 -1
  209. package/dist/Table/BaseTable.js +29 -16
  210. package/dist/Table/Table.d.ts.map +1 -1
  211. package/dist/Table/Table.js +5 -3
  212. package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
  213. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  214. package/dist/Table/plugins/filtering/useTableFiltering.js +56 -19
  215. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
  216. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  217. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +12 -5
  218. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  219. package/dist/Table/plugins/pagination/useTablePagination.js +6 -3
  220. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  221. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +8 -6
  222. package/dist/Table/plugins/rowIndex/useTableRowIndex.d.ts +1 -1
  223. package/dist/Table/plugins/rowIndex/useTableRowIndex.js +1 -1
  224. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  225. package/dist/Table/plugins/selection/useTableSelection.js +5 -2
  226. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  227. package/dist/Table/plugins/sortable/useTableSortable.js +6 -4
  228. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +2 -2
  229. package/dist/Table/types.d.ts +17 -10
  230. package/dist/Table/types.d.ts.map +1 -1
  231. package/dist/TextInput/TextInput.d.ts.map +1 -1
  232. package/dist/TextInput/TextInput.js +5 -1
  233. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  234. package/dist/Thumbnail/Thumbnail.js +8 -2
  235. package/dist/TimeInput/TimeInput.d.ts +1 -1
  236. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  237. package/dist/TimeInput/TimeInput.js +7 -2
  238. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  239. package/dist/Timestamp/Timestamp.js +18 -3
  240. package/dist/Toast/Toast.d.ts.map +1 -1
  241. package/dist/Toast/Toast.js +3 -1
  242. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  243. package/dist/Toast/ToastViewport.js +3 -1
  244. package/dist/Token/Token.d.ts.map +1 -1
  245. package/dist/Token/Token.js +8 -2
  246. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  247. package/dist/Tokenizer/Tokenizer.js +3 -1
  248. package/dist/TopNav/TopNav.d.ts +2 -1
  249. package/dist/TopNav/TopNav.d.ts.map +1 -1
  250. package/dist/TopNav/TopNav.js +4 -1
  251. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  252. package/dist/TopNav/TopNavHeading.js +5 -3
  253. package/dist/TreeList/TreeList.d.ts.map +1 -1
  254. package/dist/TreeList/TreeList.js +5 -1
  255. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  256. package/dist/TreeList/TreeListItem.js +7 -1
  257. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  258. package/dist/Typeahead/BaseTypeahead.js +8 -4
  259. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  260. package/dist/Typeahead/Typeahead.js +3 -1
  261. package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
  262. package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
  263. package/dist/VisuallyHidden/VisuallyHidden.js +1 -0
  264. package/dist/astryx.css +35 -3
  265. package/dist/astryx.umd.js +62 -60
  266. package/dist/astryx.umd.js.map +4 -4
  267. package/dist/authoring/doc.d.ts +145 -0
  268. package/dist/authoring/doc.d.ts.map +1 -0
  269. package/dist/authoring/doc.js +100 -0
  270. package/dist/authoring/index.d.ts +29 -0
  271. package/dist/authoring/index.d.ts.map +1 -0
  272. package/dist/authoring/index.js +28 -0
  273. package/dist/authoring/integration.d.ts +35 -0
  274. package/dist/authoring/integration.d.ts.map +1 -0
  275. package/dist/authoring/integration.js +30 -0
  276. package/dist/authoring/template.d.ts +66 -0
  277. package/dist/authoring/template.d.ts.map +1 -0
  278. package/dist/authoring/template.js +55 -0
  279. package/dist/config.d.ts +80 -0
  280. package/dist/config.d.ts.map +1 -0
  281. package/dist/config.js +40 -0
  282. package/dist/docs-types.d.ts +13 -4
  283. package/dist/docs-types.d.ts.map +1 -1
  284. package/dist/i18n/InternationalizationContext.d.ts +12 -0
  285. package/dist/i18n/InternationalizationContext.d.ts.map +1 -0
  286. package/dist/i18n/InternationalizationContext.js +29 -0
  287. package/dist/i18n/InternationalizationProvider.d.ts +61 -0
  288. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -0
  289. package/dist/i18n/InternationalizationProvider.js +44 -0
  290. package/dist/i18n/index.d.ts +24 -0
  291. package/dist/i18n/index.d.ts.map +1 -0
  292. package/dist/i18n/index.js +21 -0
  293. package/dist/i18n/resolve.d.ts +22 -0
  294. package/dist/i18n/resolve.d.ts.map +1 -0
  295. package/dist/i18n/resolve.js +141 -0
  296. package/dist/i18n/translator.d.ts +25 -0
  297. package/dist/i18n/translator.d.ts.map +1 -0
  298. package/dist/i18n/translator.js +1 -0
  299. package/dist/i18n/types.d.ts +47 -0
  300. package/dist/i18n/types.d.ts.map +1 -0
  301. package/dist/i18n/types.js +1 -0
  302. package/dist/i18n/useTranslator.d.ts +15 -0
  303. package/dist/i18n/useTranslator.d.ts.map +1 -0
  304. package/dist/i18n/useTranslator.js +39 -0
  305. package/dist/index.d.ts +1 -0
  306. package/dist/index.d.ts.map +1 -1
  307. package/dist/index.js +3 -0
  308. package/dist/theme/hct.d.ts +0 -1
  309. package/dist/theme/hct.d.ts.map +1 -1
  310. package/dist/theme/hct.js +0 -3
  311. package/dist/utils/color.d.ts +13 -1
  312. package/dist/utils/color.d.ts.map +1 -1
  313. package/dist/utils/color.js +23 -1
  314. package/dist/utils/index.d.ts +1 -1
  315. package/dist/utils/index.d.ts.map +1 -1
  316. package/dist/utils/index.js +1 -1
  317. package/locales/en.json +746 -0
  318. package/locales/pseudo.json +560 -0
  319. package/package.json +23 -2
  320. package/src/AlertDialog/AlertDialog.doc.mjs +5 -0
  321. package/src/AlertDialog/AlertDialog.tsx +4 -1
  322. package/src/AppShell/AppShell.doc.mjs +8 -2
  323. package/src/AppShell/AppShell.tsx +3 -1
  324. package/src/AvatarGroup/AvatarGroup.tsx +4 -1
  325. package/src/Banner/Banner.tsx +10 -5
  326. package/src/Breadcrumbs/Breadcrumbs.tsx +4 -1
  327. package/src/Button/Button.doc.mjs +8 -0
  328. package/src/Button/Button.test.tsx +27 -0
  329. package/src/Button/Button.tsx +51 -5
  330. package/src/ButtonGroup/ButtonGroup.test.tsx +386 -2
  331. package/src/ButtonGroup/ButtonGroup.tsx +27 -11
  332. package/src/Calendar/Calendar.test.tsx +103 -2
  333. package/src/Calendar/Calendar.tsx +29 -6
  334. package/src/Card/Card.doc.mjs +3 -3
  335. package/src/Carousel/Carousel.tsx +10 -7
  336. package/src/Chat/ChatComposer.tsx +5 -1
  337. package/src/Chat/ChatComposerDrawer.tsx +9 -2
  338. package/src/Chat/ChatComposerInput.tsx +10 -4
  339. package/src/Chat/ChatLayout.test.tsx +127 -2
  340. package/src/Chat/ChatLayout.tsx +5 -12
  341. package/src/Chat/ChatLayoutScrollButton.tsx +4 -2
  342. package/src/Chat/ChatMessage.tsx +5 -1
  343. package/src/Chat/ChatMessageBubble.tsx +2 -0
  344. package/src/Chat/ChatMessageList.doc.mjs +1 -1
  345. package/src/Chat/ChatMessageList.tsx +2 -0
  346. package/src/Chat/ChatMessageMetadata.tsx +15 -9
  347. package/src/Chat/ChatPastedTextToken.tsx +3 -1
  348. package/src/Chat/ChatSendButton.tsx +3 -1
  349. package/src/Chat/ChatToolCalls.doc.mjs +1 -1
  350. package/src/Chat/index.ts +1 -0
  351. package/src/Chat/useChatStreamScroll.test.tsx +168 -0
  352. package/src/Chat/useChatStreamScroll.ts +67 -11
  353. package/src/Chat/useSpeechRecognition.ts +11 -2
  354. package/src/Chat/useTriggerMenu.tsx +4 -2
  355. package/src/CheckboxInput/CheckboxInput.test.tsx +16 -0
  356. package/src/CheckboxInput/CheckboxInput.tsx +4 -2
  357. package/src/CheckboxList/CheckboxList.doc.mjs +6 -1
  358. package/src/CheckboxList/CheckboxList.tsx +2 -0
  359. package/src/CheckboxList/CheckboxListItem.tsx +7 -1
  360. package/src/Citation/Citation.tsx +4 -2
  361. package/src/ClickableCard/ClickableCard.doc.mjs +1 -1
  362. package/src/CodeBlock/CodeBlock.tsx +91 -40
  363. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  364. package/src/Collapsible/Collapsible.test.tsx +6 -0
  365. package/src/Collapsible/Collapsible.tsx +19 -4
  366. package/src/CommandPalette/CommandPalette.tsx +10 -3
  367. package/src/CommandPalette/CommandPaletteInput.test.tsx +1 -1
  368. package/src/CommandPalette/CommandPaletteInput.tsx +5 -1
  369. package/src/CommandPalette/CommandPaletteList.tsx +4 -1
  370. package/src/ContextMenu/ContextMenu.test.tsx +75 -1
  371. package/src/ContextMenu/ContextMenu.tsx +14 -6
  372. package/src/ContextMenu/index.ts +15 -0
  373. package/src/DateInput/DateInput.doc.mjs +2 -2
  374. package/src/DateInput/DateInput.test.tsx +17 -5
  375. package/src/DateInput/DateInput.tsx +13 -5
  376. package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
  377. package/src/DateRangeInput/DateRangeInput.tsx +14 -6
  378. package/src/DateTimeInput/DateTimeInput.doc.mjs +2 -2
  379. package/src/DateTimeInput/DateTimeInput.tsx +17 -7
  380. package/src/Dialog/Dialog.tsx +11 -15
  381. package/src/Dialog/DialogHeader.tsx +7 -3
  382. package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
  383. package/src/DropdownMenu/DropdownMenu.tsx +23 -14
  384. package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
  385. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +237 -0
  386. package/src/DropdownMenu/DropdownMenuContext.tsx +29 -1
  387. package/src/DropdownMenu/DropdownMenuItem.doc.mjs +6 -0
  388. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +80 -0
  389. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +119 -0
  390. package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +80 -0
  391. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +232 -0
  392. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +163 -0
  393. package/src/DropdownMenu/index.ts +23 -3
  394. package/src/DropdownMenu/menuItemRoles.ts +22 -0
  395. package/src/EmptyState/EmptyState.doc.mjs +3 -3
  396. package/src/EmptyState/EmptyState.tsx +4 -1
  397. package/src/Field/Field.doc.mjs +2 -2
  398. package/src/FileInput/FileInput.test.tsx +40 -1
  399. package/src/FileInput/FileInput.tsx +12 -1
  400. package/src/Grid/Grid.doc.mjs +5 -5
  401. package/src/Icon/Icon.test.tsx +46 -0
  402. package/src/Icon/Icon.tsx +37 -24
  403. package/src/InputGroup/InputGroup.doc.mjs +1 -1
  404. package/src/Kbd/Kbd.test.tsx +26 -0
  405. package/src/Kbd/Kbd.tsx +1 -1
  406. package/src/Layer/useLayer.doc.mjs +8 -5
  407. package/src/Layer/useLayer.test.tsx +136 -1
  408. package/src/Layer/useLayer.tsx +34 -2
  409. package/src/Lightbox/Lightbox.doc.mjs +7 -2
  410. package/src/Lightbox/Lightbox.tsx +6 -4
  411. package/src/Link/Link.test.tsx +74 -2
  412. package/src/Link/Link.tsx +48 -1
  413. package/src/Markdown/Markdown.tsx +12 -4
  414. package/src/MobileNav/MobileNav.tsx +4 -2
  415. package/src/MobileNav/MobileNavToggle.tsx +5 -3
  416. package/src/MoreMenu/MoreMenu.tsx +4 -1
  417. package/src/MultiSelector/MultiSelector.tsx +14 -5
  418. package/src/NumberInput/NumberInput.tsx +3 -1
  419. package/src/Outline/Outline.tsx +4 -1
  420. package/src/OverflowList/OverflowList.doc.mjs +2 -2
  421. package/src/Pagination/Pagination.tsx +35 -12
  422. package/src/Popover/usePopover.tsx +6 -1
  423. package/src/PowerSearch/PowerSearch.doc.mjs +9 -4
  424. package/src/PowerSearch/PowerSearch.tsx +22 -10
  425. package/src/PowerSearch/PowerSearchEditPopover.tsx +27 -20
  426. package/src/PowerSearch/PowerSearchToken.tsx +17 -6
  427. package/src/PowerSearch/PowerSearchValueEditor.tsx +34 -21
  428. package/src/PowerSearch/formatFilterValue.test.ts +282 -0
  429. package/src/PowerSearch/formatFilterValue.ts +21 -8
  430. package/src/PowerSearch/index.ts +5 -0
  431. package/src/PowerSearch/resolveOperatorLabel.ts +34 -0
  432. package/src/PowerSearch/types.ts +33 -9
  433. package/src/PowerSearch/usePowerSearchConfig.ts +59 -27
  434. package/src/PowerSearch/usePowerSearchSource.ts +17 -8
  435. package/src/RadioList/RadioList.doc.mjs +1 -1
  436. package/src/Resizable/ResizeHandle.tsx +4 -1
  437. package/src/Section/Section.doc.mjs +4 -4
  438. package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
  439. package/src/Selector/Selector.doc.mjs +6 -3
  440. package/src/Selector/Selector.test.tsx +114 -6
  441. package/src/Selector/Selector.tsx +68 -17
  442. package/src/SideNav/SideNav.tsx +4 -2
  443. package/src/SideNav/SideNavCollapseButton.tsx +3 -1
  444. package/src/SideNav/SideNavHeading.tsx +5 -3
  445. package/src/SideNav/SideNavItem.tsx +3 -1
  446. package/src/Slider/Slider.doc.mjs +2 -2
  447. package/src/Stack/Stack.doc.mjs +10 -10
  448. package/src/Switch/Switch.doc.mjs +2 -2
  449. package/src/Switch/Switch.test.tsx +16 -0
  450. package/src/Switch/Switch.tsx +4 -2
  451. package/src/TabList/TabList.tsx +4 -1
  452. package/src/Table/BaseTable.tsx +36 -19
  453. package/src/Table/Table.test.tsx +132 -1
  454. package/src/Table/Table.tsx +6 -4
  455. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +1 -1
  456. package/src/Table/plugins/filtering/useTableFiltering.tsx +31 -30
  457. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +7 -5
  458. package/src/Table/plugins/pagination/useTablePagination.tsx +4 -1
  459. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -8
  460. package/src/Table/plugins/rowIndex/useTableRowIndex.tsx +1 -1
  461. package/src/Table/plugins/selection/useTableSelection.tsx +6 -7
  462. package/src/Table/plugins/sortable/useTableSortable.tsx +8 -5
  463. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +4 -4
  464. package/src/Table/types.ts +18 -12
  465. package/src/Table/useTableFiltering.doc.mjs +2 -2
  466. package/src/Table/useTableGroupedRows.doc.mjs +3 -3
  467. package/src/Table/useTableSortable.doc.mjs +11 -11
  468. package/src/Text/Text.doc.mjs +2 -2
  469. package/src/TextInput/TextInput.tsx +3 -1
  470. package/src/Thumbnail/Thumbnail.tsx +4 -2
  471. package/src/TimeInput/TimeInput.doc.mjs +2 -2
  472. package/src/TimeInput/TimeInput.tsx +6 -2
  473. package/src/Timestamp/Timestamp.doc.mjs +4 -4
  474. package/src/Timestamp/Timestamp.test.tsx +120 -7
  475. package/src/Timestamp/Timestamp.tsx +21 -1
  476. package/src/Toast/Toast.tsx +3 -1
  477. package/src/Toast/ToastViewport.tsx +3 -1
  478. package/src/Token/Token.tsx +4 -2
  479. package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
  480. package/src/Tokenizer/Tokenizer.tsx +4 -4
  481. package/src/Toolbar/Toolbar.doc.mjs +1 -1
  482. package/src/TopNav/TopNav.doc.mjs +1 -0
  483. package/src/TopNav/TopNav.test.tsx +30 -0
  484. package/src/TopNav/TopNav.tsx +6 -4
  485. package/src/TopNav/TopNavHeading.tsx +5 -3
  486. package/src/TreeList/TreeList.tsx +5 -1
  487. package/src/TreeList/TreeListItem.tsx +6 -1
  488. package/src/Typeahead/BaseTypeahead.tsx +11 -4
  489. package/src/Typeahead/Typeahead.doc.mjs +1 -1
  490. package/src/Typeahead/Typeahead.tsx +3 -1
  491. package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
  492. package/src/authoring/doc.ts +166 -0
  493. package/src/authoring/index.test.ts +52 -0
  494. package/src/authoring/index.ts +50 -0
  495. package/src/authoring/integration.ts +42 -0
  496. package/src/authoring/template.ts +74 -0
  497. package/src/config.test.ts +16 -0
  498. package/src/config.ts +92 -0
  499. package/src/docPropLiterals.test.ts +938 -0
  500. package/src/docs-types.ts +15 -10
  501. package/src/i18n/InternationalizationContext.ts +39 -0
  502. package/src/i18n/InternationalizationProvider.doc.mjs +72 -0
  503. package/src/i18n/InternationalizationProvider.tsx +82 -0
  504. package/src/i18n/__tests__/e2e-pagination.test.tsx +172 -0
  505. package/src/i18n/__tests__/e2e-powersearch.test.tsx +130 -0
  506. package/src/i18n/__tests__/resolve.test.ts +284 -0
  507. package/src/i18n/index.ts +32 -0
  508. package/src/i18n/resolve.ts +165 -0
  509. package/src/i18n/translator.ts +31 -0
  510. package/src/i18n/types.ts +53 -0
  511. package/src/i18n/useTranslator.doc.mjs +46 -0
  512. package/src/i18n/useTranslator.ts +50 -0
  513. package/src/index.ts +3 -0
  514. package/src/theme/hct.ts +0 -4
  515. package/src/utils/color.test.ts +101 -1
  516. package/src/utils/color.ts +23 -1
  517. package/src/utils/index.ts +8 -1
  518. package/dist/NavItem/index.d.ts +0 -9
  519. package/dist/NavItem/index.d.ts.map +0 -1
  520. package/dist/NavItem/index.js +0 -10
  521. package/src/NavItem/index.ts +0 -11
@@ -0,0 +1,232 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file DropdownMenuRadioItem.tsx
7
+ * @input React, stylex, Item + Icon + DropdownMenu context + tokens from core
8
+ * @output DropdownMenuRadioItem — a single option in a radio group.
9
+ * @position Sub-component; must be used inside a DropdownMenuRadioGroup.
10
+ *
11
+ * A menu item representing one option in a single-select group
12
+ * (role="menuitemradio"). The row owns the role and aria-checked; there is no
13
+ * nested native <input> (per the WAI-ARIA menuitemradio pattern). Selection
14
+ * state + onChange come from DropdownMenuRadioGroupContext. Keyboard nav +
15
+ * Enter/Space activation come from the parent DropdownMenu.
16
+ *
17
+ * The round radio visual (circle + center dot) is decorative (aria-hidden) —
18
+ * the row owns the checked state. Its size is derived from the menu's item size
19
+ * and it swaps to the inline-end of the row on coarse-pointer (touch) devices
20
+ * via CSS `order`. The dot is a shaped element, not an icon (a filled circle
21
+ * has no registry glyph).
22
+ */
23
+
24
+ import {useCallback, type ReactNode} from 'react';
25
+ import * as stylex from '@stylexjs/stylex';
26
+ import {renderIconSlot, type IconType} from '../Icon';
27
+ import {Item} from '../Item';
28
+ import {useDropdownMenuContext} from './DropdownMenuContext';
29
+ import {
30
+ colorVars,
31
+ spacingVars,
32
+ durationVars,
33
+ easeVars,
34
+ borderVars,
35
+ } from '../theme/tokens.stylex';
36
+ import {mergeProps, themeProps} from '../utils';
37
+ import type {BaseProps} from '../BaseProps';
38
+ import {useDropdownMenuRadioGroupContext} from './DropdownMenuContext';
39
+
40
+ const styles = stylex.create({
41
+ root: {
42
+ width: '100%',
43
+ borderRadius: `max(0px, calc(var(--_dropdown-menu-radius, ${spacingVars['--spacing-2']}) - var(--_dropdown-menu-padding, ${spacingVars['--spacing-1']})))`,
44
+ color: colorVars['--color-text-primary'],
45
+ backgroundColor: {
46
+ default: 'transparent',
47
+ ':focus': colorVars['--color-overlay-hover'],
48
+ ':hover': colorVars['--color-overlay-hover'],
49
+ },
50
+ cursor: 'pointer',
51
+ outline: 'none',
52
+ },
53
+ disabled: {
54
+ opacity: 0.5,
55
+ cursor: 'not-allowed',
56
+ },
57
+ // Rendered in Item's `marker` slot as a raw flex child. On touch it moves to
58
+ // the inline-end of the row via `order`.
59
+ circle: {
60
+ display: 'flex',
61
+ alignItems: 'center',
62
+ justifyContent: 'center',
63
+ flexShrink: 0,
64
+ boxSizing: 'border-box',
65
+ borderWidth: borderVars['--border-width'],
66
+ borderStyle: 'solid',
67
+ borderRadius: '50%',
68
+ transitionProperty: 'background-color, border-color',
69
+ transitionDuration: {
70
+ default: durationVars['--duration-fast'],
71
+ '@media (prefers-reduced-motion: reduce)': '0s',
72
+ },
73
+ transitionTimingFunction: easeVars['--ease-standard'],
74
+ order: {
75
+ default: 0,
76
+ '@media (pointer: coarse)': 1,
77
+ },
78
+ marginInlineStart: {
79
+ default: 0,
80
+ '@media (pointer: coarse)': 'auto',
81
+ },
82
+ },
83
+ unchecked: {
84
+ borderColor: colorVars['--color-border-emphasized'],
85
+ backgroundColor: colorVars['--color-background-surface'],
86
+ },
87
+ checked: {
88
+ borderColor: colorVars['--color-accent'],
89
+ backgroundColor: colorVars['--color-accent'],
90
+ },
91
+ dot: {
92
+ borderRadius: '50%',
93
+ backgroundColor: colorVars['--color-on-accent'],
94
+ },
95
+ });
96
+
97
+ const circleSizeStyles = stylex.create({
98
+ sm: {width: 18, height: 18},
99
+ md: {width: 22, height: 22},
100
+ });
101
+
102
+ const dotSizeStyles = stylex.create({
103
+ sm: {width: 6, height: 6},
104
+ md: {width: 8, height: 8},
105
+ });
106
+
107
+ export interface DropdownMenuRadioItemProps extends Omit<
108
+ BaseProps,
109
+ 'role' | 'aria-checked' | 'tabIndex'
110
+ > {
111
+ /**
112
+ * The value this item represents within its group. The group's `value`
113
+ * matches against this to determine the checked state.
114
+ */
115
+ value: string;
116
+ /**
117
+ * Primary label text identifying the option.
118
+ */
119
+ label: ReactNode;
120
+ /**
121
+ * Secondary description text displayed below the label.
122
+ */
123
+ description?: ReactNode;
124
+ /**
125
+ * Icon to display before the label. Accepts a semantic icon name (see
126
+ * `npx astryx docs icons`) or a rendered node.
127
+ */
128
+ icon?: ReactNode | IconType;
129
+ /**
130
+ * Whether this individual radio item is disabled. Disabled items stay
131
+ * focusable (via `aria-disabled`) so they remain discoverable by keyboard
132
+ * and assistive technology, but selection is blocked.
133
+ * @default false
134
+ */
135
+ isDisabled?: boolean;
136
+ /**
137
+ * Content to render after the label and description, such as a badge or
138
+ * metadata.
139
+ */
140
+ endContent?: ReactNode;
141
+ }
142
+
143
+ /**
144
+ * A single option in a DropdownMenuRadioGroup (role="menuitemradio").
145
+ *
146
+ * @example
147
+ * ```
148
+ * <DropdownMenuRadioGroup value={sort} onChange={setSort} aria-label="Sort by">
149
+ * <DropdownMenuRadioItem value="newest" label="Newest" />
150
+ * <DropdownMenuRadioItem value="oldest" label="Oldest" icon="clock" />
151
+ * </DropdownMenuRadioGroup>
152
+ * ```
153
+ */
154
+ export function DropdownMenuRadioItem({
155
+ value,
156
+ label,
157
+ description,
158
+ icon,
159
+ isDisabled = false,
160
+ endContent,
161
+ xstyle,
162
+ className,
163
+ style,
164
+ ...rest
165
+ }: DropdownMenuRadioItemProps) {
166
+ const menuCtx = useDropdownMenuContext();
167
+ const groupCtx = useDropdownMenuRadioGroupContext();
168
+ if (!groupCtx) {
169
+ throw new Error(
170
+ 'DropdownMenuRadioItem must be used within a DropdownMenuRadioGroup',
171
+ );
172
+ }
173
+ const menuSize = menuCtx?.menuSize ?? 'md';
174
+ const controlSize = menuSize === 'sm' ? 'sm' : 'md';
175
+ const isChecked = groupCtx.value === value;
176
+
177
+ const handleClick = useCallback(() => {
178
+ if (isDisabled) {
179
+ return;
180
+ }
181
+ groupCtx.onChange(value);
182
+ if (groupCtx.hasCloseOnSelect) {
183
+ menuCtx?.closeMenu();
184
+ }
185
+ }, [isDisabled, groupCtx, value, menuCtx]);
186
+
187
+ return (
188
+ <Item
189
+ {...rest}
190
+ role="menuitemradio"
191
+ aria-checked={isChecked}
192
+ tabIndex={isDisabled ? undefined : -1}
193
+ marker={
194
+ <span
195
+ aria-hidden="true"
196
+ {...mergeProps(
197
+ themeProps('dropdown-menu-radio', {
198
+ size: controlSize,
199
+ checked: isChecked ? 'checked' : null,
200
+ disabled: isDisabled ? 'disabled' : null,
201
+ }),
202
+ stylex.props(
203
+ styles.circle,
204
+ circleSizeStyles[controlSize],
205
+ isChecked ? styles.checked : styles.unchecked,
206
+ ),
207
+ )}>
208
+ {isChecked && (
209
+ <span {...stylex.props(styles.dot, dotSizeStyles[controlSize])} />
210
+ )}
211
+ </span>
212
+ }
213
+ startContent={
214
+ icon
215
+ ? renderIconSlot(icon, {size: 'sm', color: 'secondary'})
216
+ : undefined
217
+ }
218
+ label={label}
219
+ description={description}
220
+ endContent={endContent}
221
+ onClick={handleClick}
222
+ isDisabled={isDisabled}
223
+ xstyle={[styles.root, isDisabled && styles.disabled, xstyle]}
224
+ {...mergeProps(themeProps('dropdown-menu-item', {size: menuSize}), {
225
+ className,
226
+ style,
227
+ })}
228
+ />
229
+ );
230
+ }
231
+
232
+ DropdownMenuRadioItem.displayName = 'DropdownMenuRadioItem';
@@ -0,0 +1,163 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file DropdownMenuSelectable.test.tsx
5
+ * @input vitest, @testing-library/react, DropdownMenu + selectable items
6
+ * @output Unit tests for DropdownMenuCheckboxItem / RadioGroup / RadioItem (#3829)
7
+ */
8
+
9
+ import {describe, it, expect, vi, beforeEach} from 'vitest';
10
+ import {render, screen} from '@testing-library/react';
11
+ import userEvent from '@testing-library/user-event';
12
+ import {DropdownMenu} from './DropdownMenu';
13
+ import {DropdownMenuCheckboxItem} from './DropdownMenuCheckboxItem';
14
+ import {DropdownMenuRadioGroup} from './DropdownMenuRadioGroup';
15
+ import {DropdownMenuRadioItem} from './DropdownMenuRadioItem';
16
+
17
+ beforeEach(() => {
18
+ HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
19
+ this.setAttribute('popover-open', '');
20
+ const event = new Event('toggle', {bubbles: false});
21
+ Object.defineProperty(event, 'newState', {value: 'open'});
22
+ this.dispatchEvent(event);
23
+ });
24
+ HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
25
+ this.removeAttribute('popover-open');
26
+ const event = new Event('toggle', {bubbles: false});
27
+ Object.defineProperty(event, 'newState', {value: 'closed'});
28
+ this.dispatchEvent(event);
29
+ });
30
+ const originalMatches = HTMLElement.prototype.matches;
31
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
+ (HTMLElement.prototype as any).matches = function (
33
+ selector: string,
34
+ ): boolean {
35
+ if (selector === ':popover-open') {
36
+ return this.hasAttribute('popover-open');
37
+ }
38
+ return originalMatches.call(this, selector);
39
+ };
40
+ });
41
+
42
+ describe('DropdownMenuCheckboxItem', () => {
43
+ it('renders role menuitemcheckbox and reflects checked state', async () => {
44
+ const user = userEvent.setup();
45
+ render(
46
+ <DropdownMenu button={{label: 'View'}}>
47
+ <DropdownMenuCheckboxItem label="Show archived" value={true} />
48
+ </DropdownMenu>,
49
+ );
50
+ await user.click(screen.getByRole('button', {name: /View/}));
51
+ expect(
52
+ screen.getByRole('menuitemcheckbox', {
53
+ name: /Show archived/,
54
+ hidden: true,
55
+ }),
56
+ ).toHaveAttribute('aria-checked', 'true');
57
+ });
58
+
59
+ it('calls onChange with the toggled value on click', async () => {
60
+ const user = userEvent.setup();
61
+ const onChangeSpy = vi.fn();
62
+ render(
63
+ <DropdownMenu button={{label: 'View'}}>
64
+ <DropdownMenuCheckboxItem
65
+ label="Show archived"
66
+ value={false}
67
+ onChange={onChangeSpy}
68
+ />
69
+ </DropdownMenu>,
70
+ );
71
+ await user.click(screen.getByRole('button', {name: /View/}));
72
+ await user.click(
73
+ screen.getByRole('menuitemcheckbox', {
74
+ name: /Show archived/,
75
+ hidden: true,
76
+ }),
77
+ );
78
+ expect(onChangeSpy).toHaveBeenCalledWith(true);
79
+ });
80
+
81
+ it('does not toggle when disabled', async () => {
82
+ const user = userEvent.setup();
83
+ const onChangeSpy = vi.fn();
84
+ render(
85
+ <DropdownMenu button={{label: 'View'}}>
86
+ <DropdownMenuCheckboxItem
87
+ label="Show archived"
88
+ value={false}
89
+ onChange={onChangeSpy}
90
+ isDisabled
91
+ />
92
+ </DropdownMenu>,
93
+ );
94
+ await user.click(screen.getByRole('button', {name: /View/}));
95
+ const item = screen.getByRole('menuitemcheckbox', {
96
+ name: /Show archived/,
97
+ hidden: true,
98
+ });
99
+ expect(item).toHaveAttribute('aria-disabled', 'true');
100
+ await user.click(item);
101
+ expect(onChangeSpy).not.toHaveBeenCalled();
102
+ });
103
+ });
104
+
105
+ describe('DropdownMenuRadioGroup / RadioItem', () => {
106
+ it('renders a named group with radios reflecting the selected value', async () => {
107
+ const user = userEvent.setup();
108
+ render(
109
+ <DropdownMenu button={{label: 'Sort'}}>
110
+ <DropdownMenuRadioGroup
111
+ value="newest"
112
+ onChange={() => {}}
113
+ aria-label="Sort by">
114
+ <DropdownMenuRadioItem value="newest" label="Newest" />
115
+ <DropdownMenuRadioItem value="oldest" label="Oldest" />
116
+ </DropdownMenuRadioGroup>
117
+ </DropdownMenu>,
118
+ );
119
+ await user.click(screen.getByRole('button', {name: /Sort/}));
120
+ expect(
121
+ screen.getByRole('menuitemradio', {name: 'Newest', hidden: true}),
122
+ ).toHaveAttribute('aria-checked', 'true');
123
+ expect(
124
+ screen.getByRole('menuitemradio', {name: 'Oldest', hidden: true}),
125
+ ).toHaveAttribute('aria-checked', 'false');
126
+ expect(
127
+ screen.getByRole('group', {name: 'Sort by', hidden: true}),
128
+ ).toBeInTheDocument();
129
+ });
130
+
131
+ it('calls onChange with the selected value', async () => {
132
+ const user = userEvent.setup();
133
+ const onChange = vi.fn();
134
+ render(
135
+ <DropdownMenu button={{label: 'Sort'}}>
136
+ <DropdownMenuRadioGroup
137
+ value="newest"
138
+ onChange={onChange}
139
+ aria-label="Sort by">
140
+ <DropdownMenuRadioItem value="newest" label="Newest" />
141
+ <DropdownMenuRadioItem value="oldest" label="Oldest" />
142
+ </DropdownMenuRadioGroup>
143
+ </DropdownMenu>,
144
+ );
145
+ await user.click(screen.getByRole('button', {name: /Sort/}));
146
+ await user.click(
147
+ screen.getByRole('menuitemradio', {name: 'Oldest', hidden: true}),
148
+ );
149
+ expect(onChange).toHaveBeenCalledWith('oldest');
150
+ });
151
+
152
+ it('throws when a radio item is used outside a group', () => {
153
+ const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
154
+ expect(() =>
155
+ render(
156
+ <DropdownMenu button={{label: 'Sort'}}>
157
+ <DropdownMenuRadioItem value="x" label="X" />
158
+ </DropdownMenu>,
159
+ ),
160
+ ).toThrow(/DropdownMenuRadioGroup/);
161
+ spy.mockRestore();
162
+ });
163
+ });
@@ -18,7 +18,27 @@ export {
18
18
  type DropdownMenuOption,
19
19
  } from './DropdownMenu';
20
20
 
21
+ export {DropdownMenuItem, type DropdownMenuItemProps} from './DropdownMenuItem';
22
+
23
+ // Selectable items — checkbox (independent) and radio (single-select group).
24
+ export {
25
+ DropdownMenuCheckboxItem,
26
+ type DropdownMenuCheckboxItemProps,
27
+ } from './DropdownMenuCheckboxItem';
28
+ export {
29
+ DropdownMenuRadioGroup,
30
+ type DropdownMenuRadioGroupProps,
31
+ } from './DropdownMenuRadioGroup';
32
+ export {
33
+ DropdownMenuRadioItem,
34
+ type DropdownMenuRadioItemProps,
35
+ } from './DropdownMenuRadioItem';
36
+
37
+ // Menu-coordination context — public so consumers can build custom menu items
38
+ // that read the menu size / close the menu.
21
39
  export {
22
- DropdownMenuItem,
23
- type DropdownMenuItemProps,
24
- } from './DropdownMenuItem';
40
+ DropdownMenuContext,
41
+ useDropdownMenuContext,
42
+ type DropdownMenuContextValue,
43
+ type DropdownMenuSize,
44
+ } from './DropdownMenuContext';
@@ -0,0 +1,22 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file menuItemRoles.ts
5
+ * @output Shared menu-item role set + focus selector.
6
+ * @position Internal; used by DropdownMenu and ContextMenu so their
7
+ * roving-focus, typeahead, and Enter/Space activation stay in sync.
8
+ *
9
+ * Includes the selectable items (menuitemradio/menuitemcheckbox) alongside
10
+ * plain menuitem so checkbox/radio rows are reachable by arrow keys, typeahead,
11
+ * and Enter/Space — not just role="menuitem".
12
+ */
13
+
14
+ export const MENU_ITEM_ROLES: ReadonlySet<string> = new Set([
15
+ 'menuitem',
16
+ 'menuitemradio',
17
+ 'menuitemcheckbox',
18
+ ]);
19
+
20
+ export const MENU_ITEM_SELECTOR: string = [...MENU_ITEM_ROLES]
21
+ .map(role => `[role="${role}"]:not([aria-disabled="true"])`)
22
+ .join(',');
@@ -39,7 +39,7 @@ export const docs = {
39
39
  name: 'headingLevel',
40
40
  type: '1 | 2 | 3 | 4 | 5 | 6',
41
41
  description:
42
- 'Controls the rendered HTML heading tag (h1-h6) to fit the document outline.',
42
+ 'Controls only the rendered HTML heading tag (h1-h6) so the title fits the document outline. This is a semantic change for accessibility and does not change the visual size of the title, which stays fixed regardless of level.',
43
43
  default: '3',
44
44
  },
45
45
  {
@@ -121,7 +121,7 @@ export const docsZh = {
121
121
  name: 'headingLevel',
122
122
  type: '1 | 2 | 3 | 4 | 5 | 6',
123
123
  description:
124
- '控制渲染的 HTML 标题标签(h1-h6),以适配文档大纲。',
124
+ '仅控制渲染的 HTML 标题标签(h1-h6),使标题适配文档大纲。这是用于无障碍的语义变化,不会改变标题的视觉大小,标题大小始终固定,与级别无关。',
125
125
  default: '3',
126
126
  },
127
127
  {
@@ -173,7 +173,7 @@ export const docsDense = {
173
173
  },
174
174
  propDescriptions: {
175
175
  title: 'Primary msg rendered as heading (h1-h6) inside empty state.',
176
- headingLevel: 'Controls HTML heading tag (h1-h6) for document outline.',
176
+ headingLevel: 'Controls only HTML heading tag (h1-h6) for document outline; does not change visual title size.',
177
177
  description: 'Optional secondary text w/ additional context below title.',
178
178
  icon: 'Optional icon/illustration above title; rendered decorative (aria-hidden="true").',
179
179
  actions: 'Optional action buttons below description; horizontal by default, vertical when isCompact.',
@@ -105,7 +105,10 @@ export interface EmptyStateProps extends BaseProps<HTMLDivElement> {
105
105
  actions?: ReactNode;
106
106
  /**
107
107
  * Semantic heading level for the title element.
108
- * Controls the rendered HTML tag (h1–h6) to fit the document outline.
108
+ * Controls only the rendered HTML tag (h1–h6) so the title fits the
109
+ * document outline. This is a semantic change for accessibility and does
110
+ * not change the visual size of the title, which stays fixed regardless
111
+ * of level.
109
112
  * @default 3
110
113
  */
111
114
  headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
@@ -104,8 +104,8 @@ export const docs = {
104
104
  },
105
105
  {
106
106
  name: 'status',
107
- type: 'FieldStatus',
108
- description: 'Status indicator with type and optional message. When message is set, displays a colored status box.',
107
+ type: "{type: 'warning' | 'error' | 'success', message?: string, messageID?: string}",
108
+ description: 'Status indicator with type and optional message. When message is set, displays a colored status box. messageID is for wiring aria-describedby on the input.',
109
109
  },
110
110
  {
111
111
  name: 'statusVariant',
@@ -10,7 +10,13 @@
10
10
  */
11
11
 
12
12
  import {describe, it, expect, vi, afterEach, beforeEach} from 'vitest';
13
- import {render, screen, fireEvent, waitFor} from '@testing-library/react';
13
+ import {
14
+ render,
15
+ screen,
16
+ fireEvent,
17
+ createEvent,
18
+ waitFor,
19
+ } from '@testing-library/react';
14
20
  import userEvent from '@testing-library/user-event';
15
21
  import {FileInput} from './FileInput';
16
22
  import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
@@ -588,6 +594,39 @@ describe('FileInput', () => {
588
594
  expect(screen.getByText('Choose file')).toBeInTheDocument();
589
595
  });
590
596
 
597
+ it('keeps the drag-over state while dragging over the dropzone children', () => {
598
+ render(
599
+ <FileInput
600
+ label="Upload"
601
+ value={null}
602
+ onChange={() => {}}
603
+ mode="dropzone"
604
+ />,
605
+ );
606
+ const dropzone = screen.getByRole('button', {name: 'Upload'});
607
+ fireEvent.dragEnter(dropzone);
608
+ expect(screen.getByText('Drop files here')).toBeInTheDocument();
609
+
610
+ // Moving from the container onto one of its own children fires a
611
+ // dragleave on the container with the child as relatedTarget — the
612
+ // highlight must not flicker off while still inside the dropzone.
613
+ // (jsdom's DragEvent init drops relatedTarget, so set it directly.)
614
+ const child = screen.getByText('Drop files here');
615
+ const leaveToChild = createEvent.dragLeave(dropzone);
616
+ Object.defineProperty(leaveToChild, 'relatedTarget', {value: child});
617
+ fireEvent(dropzone, leaveToChild);
618
+ expect(screen.getByText('Drop files here')).toBeInTheDocument();
619
+
620
+ // Actually leaving the dropzone ends the drag-over state.
621
+ const leaveToOutside = createEvent.dragLeave(dropzone);
622
+ Object.defineProperty(leaveToOutside, 'relatedTarget', {
623
+ value: document.body,
624
+ });
625
+ fireEvent(dropzone, leaveToOutside);
626
+ expect(screen.queryByText('Drop files here')).not.toBeInTheDocument();
627
+ expect(screen.getByText('Choose file')).toBeInTheDocument();
628
+ });
629
+
591
630
  it('displays file name in dropzone mode', () => {
592
631
  const file = createFile('doc.pdf', 100, 'application/pdf');
593
632
  render(
@@ -55,6 +55,7 @@ import {mergeProps, mergeRefs} from '../utils';
55
55
  import type {BaseProps} from '../BaseProps';
56
56
  import type {SizeValue} from '../utils/types';
57
57
  import {themeProps} from '../utils/themeProps';
58
+ import {useTranslator} from '../i18n';
58
59
 
59
60
  function formatFileSize(bytes: number): string {
60
61
  if (bytes < 1024) {
@@ -425,6 +426,7 @@ export function FileInput({
425
426
  ref,
426
427
  ...rest
427
428
  }: FileInputProps) {
429
+ const t = useTranslator();
428
430
  const id = useId();
429
431
  const descriptionID = useId();
430
432
  const statusMessageID = useId();
@@ -607,6 +609,15 @@ export function FileInput({
607
609
  const handleDragLeave = useCallback((e: DragEvent) => {
608
610
  e.preventDefault();
609
611
  e.stopPropagation();
612
+ // Moving over the dropzone's own children (icon, text) fires dragleave on
613
+ // the container too — only a leave that actually exits the dropzone ends
614
+ // the drag-over state, otherwise the highlight flickers mid-drag.
615
+ if (
616
+ e.relatedTarget instanceof Node &&
617
+ e.currentTarget.contains(e.relatedTarget)
618
+ ) {
619
+ return;
620
+ }
610
621
  setIsDragOver(false);
611
622
  }, []);
612
623
 
@@ -774,7 +785,7 @@ export function FileInput({
774
785
  />
775
786
  {isDropzone ? renderDropzoneContent() : renderCompactContent()}
776
787
  {hasFiles && !isDisabled && !isLoading && (
777
- <InputClearButton label={`Clear ${label}`} onClick={handleClear} />
788
+ <InputClearButton label={t('@astryx.fileInput.clearLabel', {label})} onClick={handleClear} />
778
789
  )}
779
790
  </div>
780
791
  <div
@@ -60,28 +60,28 @@ export const docs = {
60
60
  },
61
61
  {
62
62
  name: 'gap',
63
- type: 'SpacingStep',
63
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
64
64
  description: 'Spacing between all items.',
65
65
  },
66
66
  {
67
67
  name: 'rowGap',
68
- type: 'SpacingStep',
68
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
69
69
  description: 'Row spacing; overrides `gap` for the row axis.',
70
70
  },
71
71
  {
72
72
  name: 'columnGap',
73
- type: 'SpacingStep',
73
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
74
74
  description: 'Column spacing; overrides `gap` for the column axis.',
75
75
  },
76
76
  {
77
77
  name: 'align',
78
- type: 'GridAlignment',
78
+ type: "'start' | 'center' | 'end' | 'stretch'",
79
79
  description: 'Vertical alignment of items.',
80
80
  default: "'stretch'",
81
81
  },
82
82
  {
83
83
  name: 'justify',
84
- type: 'GridAlignment',
84
+ type: "'start' | 'center' | 'end' | 'stretch'",
85
85
  description: 'Horizontal alignment of items.',
86
86
  default: "'stretch'",
87
87
  },
@@ -96,6 +96,52 @@ describe('Icon', () => {
96
96
  expect(screen.getByTestId('icon')).toBeInTheDocument();
97
97
  });
98
98
 
99
+ it('sizes component-mode icons in rem so they scale with root font-size', () => {
100
+ const sizes = {
101
+ xsm: '0.75rem',
102
+ sm: '1rem',
103
+ md: '1.25rem',
104
+ lg: '1.5rem',
105
+ } as const;
106
+ for (const [size, expected] of Object.entries(sizes)) {
107
+ const {unmount} = render(
108
+ <Icon
109
+ icon={TestIcon}
110
+ size={size as keyof typeof sizes}
111
+ data-testid="icon"
112
+ />,
113
+ );
114
+ const style = getComputedStyle(screen.getByTestId('icon'));
115
+ expect(style.width).toBe(expected);
116
+ expect(style.height).toBe(expected);
117
+ unmount();
118
+ }
119
+ });
120
+
121
+ it('sizes registry (string-mode) icons in rem, including fontSize', () => {
122
+ const sizes = {
123
+ xsm: '0.75rem',
124
+ sm: '1rem',
125
+ md: '1.25rem',
126
+ lg: '1.5rem',
127
+ } as const;
128
+ for (const [size, expected] of Object.entries(sizes)) {
129
+ const {unmount} = render(
130
+ <Icon
131
+ icon="check"
132
+ size={size as keyof typeof sizes}
133
+ data-testid="icon"
134
+ />,
135
+ );
136
+ const style = getComputedStyle(screen.getByTestId('icon'));
137
+ expect(style.width).toBe(expected);
138
+ expect(style.height).toBe(expected);
139
+ // fontSize is expressed in rem so 1em-based registry icons scale too.
140
+ expect(style.fontSize).toBe(expected);
141
+ unmount();
142
+ }
143
+ });
144
+
99
145
  it('forwards ref correctly', () => {
100
146
  const ref = vi.fn();
101
147
  render(<Icon icon={TestIcon} ref={ref} />);