@astryxdesign/core 0.1.9 → 0.2.0-canary.136a00f

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 (560) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/Avatar/Avatar.d.ts +42 -3
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +190 -59
  5. package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
  6. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  7. package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
  8. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  9. package/dist/AvatarGroup/AvatarGroup.js +58 -6
  10. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  11. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  12. package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
  13. package/dist/Banner/Banner.js +2 -2
  14. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  15. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
  16. package/dist/Breadcrumbs/index.d.ts +1 -0
  17. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  18. package/dist/Breadcrumbs/index.js +2 -1
  19. package/dist/Button/Button.d.ts +1 -1
  20. package/dist/Button/Button.d.ts.map +1 -1
  21. package/dist/Button/Button.js +6 -4
  22. package/dist/Calendar/Calendar.d.ts.map +1 -1
  23. package/dist/Calendar/Calendar.js +50 -9
  24. package/dist/Calendar/dayCellUtils.d.ts +4 -4
  25. package/dist/Calendar/dayCellUtils.js +2 -2
  26. package/dist/Calendar/styles.d.ts +30 -31
  27. package/dist/Calendar/styles.d.ts.map +1 -1
  28. package/dist/Calendar/styles.js +30 -31
  29. package/dist/Card/Card.js +1 -1
  30. package/dist/Carousel/Carousel.d.ts.map +1 -1
  31. package/dist/Carousel/Carousel.js +22 -12
  32. package/dist/Chat/ChatComposerInput.js +1 -1
  33. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  34. package/dist/Chat/ChatDictationButton.js +3 -1
  35. package/dist/Chat/ChatLayout.js +4 -4
  36. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  37. package/dist/Chat/ChatMessageBubble.js +8 -8
  38. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  39. package/dist/Chat/ChatToolCalls.js +10 -3
  40. package/dist/Chat/useTriggerMenu.js +2 -2
  41. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  42. package/dist/CheckboxInput/CheckboxInput.js +6 -6
  43. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  44. package/dist/CheckboxList/CheckboxListItem.js +19 -4
  45. package/dist/Citation/Citation.d.ts +22 -1
  46. package/dist/Citation/Citation.d.ts.map +1 -1
  47. package/dist/Citation/Citation.js +20 -6
  48. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  49. package/dist/CodeBlock/CodeBlock.js +16 -10
  50. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  51. package/dist/Collapsible/Collapsible.js +3 -1
  52. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  53. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  54. package/dist/CommandPalette/CommandPalette.js +42 -3
  55. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  56. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  57. package/dist/ContextMenu/ContextMenu.js +23 -5
  58. package/dist/ContextMenu/index.d.ts +1 -0
  59. package/dist/ContextMenu/index.d.ts.map +1 -1
  60. package/dist/ContextMenu/index.js +3 -1
  61. package/dist/DateInput/DateInput.d.ts +10 -2
  62. package/dist/DateInput/DateInput.d.ts.map +1 -1
  63. package/dist/DateInput/DateInput.js +33 -19
  64. package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
  65. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  66. package/dist/DateRangeInput/DateRangeInput.js +23 -20
  67. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  68. package/dist/DateTimeInput/DateTimeInput.js +23 -18
  69. package/dist/Divider/Divider.d.ts +2 -2
  70. package/dist/Divider/Divider.d.ts.map +1 -1
  71. package/dist/Divider/Divider.js +13 -0
  72. package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
  73. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  74. package/dist/DropdownMenu/DropdownMenu.js +22 -5
  75. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  76. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
  77. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  78. package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
  79. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
  80. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  81. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
  82. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
  83. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  84. package/dist/DropdownMenu/DropdownMenuRadioItem.js +5 -2
  85. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
  86. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
  87. package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
  88. package/dist/DropdownMenu/index.d.ts +10 -0
  89. package/dist/DropdownMenu/index.d.ts.map +1 -1
  90. package/dist/DropdownMenu/index.js +13 -0
  91. package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
  92. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  93. package/dist/DropdownMenu/menuItemHover.js +33 -0
  94. package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
  95. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
  96. package/dist/DropdownMenu/menuItemRoles.js +10 -1
  97. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  98. package/dist/DropdownMenu/renderDropdownItems.js +21 -6
  99. package/dist/Field/Field.d.ts +3 -1
  100. package/dist/Field/Field.d.ts.map +1 -1
  101. package/dist/Field/Field.js +4 -1
  102. package/dist/Field/FieldLabel.d.ts +2 -1
  103. package/dist/Field/FieldLabel.d.ts.map +1 -1
  104. package/dist/Field/FieldLabel.js +9 -5
  105. package/dist/Field/inputStyles.stylex.d.ts +1 -0
  106. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  107. package/dist/Field/inputStyles.stylex.js +1 -0
  108. package/dist/FieldStatus/FieldStatus.d.ts +10 -0
  109. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  110. package/dist/FieldStatus/FieldStatus.js +39 -3
  111. package/dist/FileInput/FileInput.d.ts +10 -2
  112. package/dist/FileInput/FileInput.d.ts.map +1 -1
  113. package/dist/FileInput/FileInput.js +93 -65
  114. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  115. package/dist/HoverCard/useHoverCard.js +10 -4
  116. package/dist/Icon/Icon.d.ts +15 -1
  117. package/dist/Icon/Icon.d.ts.map +1 -1
  118. package/dist/Icon/Icon.js +19 -3
  119. package/dist/Item/Item.d.ts +16 -3
  120. package/dist/Item/Item.d.ts.map +1 -1
  121. package/dist/Item/Item.js +31 -6
  122. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  123. package/dist/Layer/layerAnimations.stylex.js +10 -2
  124. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  125. package/dist/Lightbox/Lightbox.js +19 -13
  126. package/dist/List/List.d.ts.map +1 -1
  127. package/dist/List/List.js +6 -3
  128. package/dist/List/ListItem.d.ts +11 -1
  129. package/dist/List/ListItem.d.ts.map +1 -1
  130. package/dist/List/ListItem.js +2 -0
  131. package/dist/Markdown/Markdown.d.ts.map +1 -1
  132. package/dist/Markdown/Markdown.js +7 -0
  133. package/dist/MetadataList/MetadataList.d.ts +1 -1
  134. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  135. package/dist/MetadataList/MetadataList.js +4 -2
  136. package/dist/MultiSelector/MultiSelector.d.ts +9 -1
  137. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  138. package/dist/MultiSelector/MultiSelector.js +80 -42
  139. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  140. package/dist/NumberInput/NumberInput.d.ts +10 -2
  141. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  142. package/dist/NumberInput/NumberInput.js +22 -17
  143. package/dist/Outline/Outline.js +2 -2
  144. package/dist/Pagination/Pagination.d.ts.map +1 -1
  145. package/dist/Pagination/Pagination.js +11 -3
  146. package/dist/PowerSearch/PowerSearch.d.ts +9 -2
  147. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  148. package/dist/PowerSearch/PowerSearch.js +2 -0
  149. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  150. package/dist/ProgressBar/ProgressBar.js +6 -1
  151. package/dist/RadioList/RadioList.d.ts +2 -2
  152. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  153. package/dist/RadioList/RadioListItem.js +5 -5
  154. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  155. package/dist/Resizable/ResizeHandle.js +49 -19
  156. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  157. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  158. package/dist/SegmentedControl/SegmentedControlItem.js +5 -3
  159. package/dist/Selector/Selector.d.ts +8 -0
  160. package/dist/Selector/Selector.d.ts.map +1 -1
  161. package/dist/Selector/Selector.js +66 -17
  162. package/dist/SideNav/SideNav.d.ts.map +1 -1
  163. package/dist/SideNav/SideNav.js +5 -5
  164. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  165. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  166. package/dist/SideNav/SideNavItem.d.ts +1 -1
  167. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  168. package/dist/SideNav/SideNavItem.js +12 -10
  169. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  170. package/dist/Skeleton/Skeleton.js +2 -2
  171. package/dist/Slider/Slider.d.ts.map +1 -1
  172. package/dist/Slider/Slider.js +87 -34
  173. package/dist/Spinner/Spinner.d.ts +3 -2
  174. package/dist/Spinner/Spinner.d.ts.map +1 -1
  175. package/dist/Spinner/Spinner.js +11 -2
  176. package/dist/Switch/Switch.d.ts +8 -1
  177. package/dist/Switch/Switch.d.ts.map +1 -1
  178. package/dist/Switch/Switch.js +171 -91
  179. package/dist/TabList/Tab.js +2 -2
  180. package/dist/TabList/TabList.d.ts +2 -11
  181. package/dist/TabList/TabList.d.ts.map +1 -1
  182. package/dist/TabList/TabList.js +5 -9
  183. package/dist/TabList/TabListContext.d.ts +0 -5
  184. package/dist/TabList/TabListContext.d.ts.map +1 -1
  185. package/dist/TabList/TabListContext.js +0 -5
  186. package/dist/TabList/TabMenu.js +1 -1
  187. package/dist/Table/BaseTable.d.ts.map +1 -1
  188. package/dist/Table/BaseTable.js +30 -4
  189. package/dist/Table/TableCell.js +3 -3
  190. package/dist/Table/TableHeaderCell.js +3 -3
  191. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  192. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  193. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  194. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +37 -27
  195. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  196. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  197. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  198. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +15 -7
  199. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  200. package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
  201. package/dist/Table/types.d.ts +32 -0
  202. package/dist/Table/types.d.ts.map +1 -1
  203. package/dist/TextArea/TextArea.d.ts +10 -1
  204. package/dist/TextArea/TextArea.d.ts.map +1 -1
  205. package/dist/TextArea/TextArea.js +18 -19
  206. package/dist/TextInput/TextInput.d.ts +10 -2
  207. package/dist/TextInput/TextInput.d.ts.map +1 -1
  208. package/dist/TextInput/TextInput.js +20 -17
  209. package/dist/Thumbnail/Thumbnail.js +2 -2
  210. package/dist/TimeInput/TimeInput.d.ts +10 -2
  211. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  212. package/dist/TimeInput/TimeInput.js +17 -17
  213. package/dist/Timestamp/Timestamp.d.ts +31 -3
  214. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  215. package/dist/Timestamp/Timestamp.js +47 -76
  216. package/dist/Timestamp/formatInstant.d.ts +41 -0
  217. package/dist/Timestamp/formatInstant.d.ts.map +1 -0
  218. package/dist/Timestamp/formatInstant.js +177 -0
  219. package/dist/Timestamp/index.d.ts +1 -0
  220. package/dist/Timestamp/index.d.ts.map +1 -1
  221. package/dist/Timestamp/tooltipEntries.d.ts +56 -0
  222. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
  223. package/dist/Timestamp/tooltipEntries.js +163 -0
  224. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  225. package/dist/Toast/ToastViewport.js +61 -9
  226. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  227. package/dist/ToggleButton/ToggleButton.js +3 -1
  228. package/dist/Token/Token.d.ts +34 -4
  229. package/dist/Token/Token.d.ts.map +1 -1
  230. package/dist/Token/Token.js +85 -45
  231. package/dist/Token/TokenLink.d.ts +62 -0
  232. package/dist/Token/TokenLink.d.ts.map +1 -0
  233. package/dist/Token/TokenLink.js +76 -0
  234. package/dist/Token/index.d.ts +1 -1
  235. package/dist/Token/index.d.ts.map +1 -1
  236. package/dist/Tokenizer/Tokenizer.d.ts +9 -2
  237. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  238. package/dist/Tokenizer/Tokenizer.js +4 -2
  239. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  240. package/dist/Tooltip/useTooltip.js +17 -1
  241. package/dist/TopNav/TopNavItem.d.ts +3 -1
  242. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  243. package/dist/TopNav/TopNavItem.js +30 -3
  244. package/dist/TreeList/TreeList.d.ts.map +1 -1
  245. package/dist/TreeList/TreeList.js +1 -0
  246. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  247. package/dist/TreeList/TreeListBranches.js +8 -6
  248. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  249. package/dist/TreeList/TreeListItem.js +32 -14
  250. package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
  251. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  252. package/dist/Typeahead/BaseTypeahead.js +22 -11
  253. package/dist/Typeahead/Typeahead.d.ts +9 -2
  254. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  255. package/dist/Typeahead/Typeahead.js +11 -2
  256. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  257. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  258. package/dist/Typeahead/TypeaheadItem.js +20 -10
  259. package/dist/astryx.css +70 -30
  260. package/dist/astryx.umd.js +51 -51
  261. package/dist/astryx.umd.js.map +4 -4
  262. package/dist/hooks/index.d.ts +2 -0
  263. package/dist/hooks/index.d.ts.map +1 -1
  264. package/dist/hooks/index.js +1 -0
  265. package/dist/hooks/isRtlElement.d.ts +18 -0
  266. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  267. package/dist/hooks/isRtlElement.js +27 -0
  268. package/dist/hooks/useAnnounce.d.ts +3 -0
  269. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  270. package/dist/hooks/useAnnounce.js +39 -1
  271. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  272. package/dist/hooks/useFocusTrap.js +52 -11
  273. package/dist/hooks/useGridFocus.d.ts +6 -1
  274. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  275. package/dist/hooks/useGridFocus.js +12 -9
  276. package/dist/hooks/useHotkeys.d.ts +9 -0
  277. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  278. package/dist/hooks/useHotkeys.js +9 -0
  279. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  280. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  281. package/dist/hooks/useInputStatusIcon.js +158 -0
  282. package/dist/hooks/useKeyboardHint.d.ts +1 -1
  283. package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
  284. package/dist/hooks/useKeyboardHint.js +4 -2
  285. package/dist/hooks/useListFocus.d.ts +39 -1
  286. package/dist/hooks/useListFocus.d.ts.map +1 -1
  287. package/dist/hooks/useListFocus.js +54 -9
  288. package/dist/i18n/InternationalizationContext.d.ts +1 -0
  289. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  290. package/dist/i18n/InternationalizationContext.js +3 -0
  291. package/dist/i18n/InternationalizationProvider.d.ts +8 -1
  292. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  293. package/dist/i18n/InternationalizationProvider.js +5 -1
  294. package/dist/i18n/getLocaleDirection.d.ts +18 -0
  295. package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
  296. package/dist/i18n/getLocaleDirection.js +29 -0
  297. package/dist/i18n/index.d.ts +6 -0
  298. package/dist/i18n/index.d.ts.map +1 -1
  299. package/dist/i18n/index.js +7 -1
  300. package/dist/i18n/useDirection.d.ts +2 -0
  301. package/dist/i18n/useDirection.d.ts.map +1 -0
  302. package/dist/i18n/useDirection.js +27 -0
  303. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  304. package/dist/theme/derivedVarRegistry.js +13 -0
  305. package/dist/utils/index.d.ts +1 -0
  306. package/dist/utils/index.d.ts.map +1 -1
  307. package/dist/utils/index.js +2 -1
  308. package/dist/utils/plainDate.d.ts +17 -0
  309. package/dist/utils/plainDate.d.ts.map +1 -1
  310. package/dist/utils/plainDate.js +23 -4
  311. package/dist/utils/rtlStyles.d.ts +24 -0
  312. package/dist/utils/rtlStyles.d.ts.map +1 -0
  313. package/dist/utils/rtlStyles.js +27 -0
  314. package/locales/en.json +112 -0
  315. package/locales/pseudo.json +84 -0
  316. package/package.json +6 -1
  317. package/src/Avatar/Avatar.doc.mjs +50 -3
  318. package/src/Avatar/Avatar.test.tsx +218 -0
  319. package/src/Avatar/Avatar.tsx +285 -79
  320. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  321. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  322. package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
  323. package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
  324. package/src/AvatarGroup/AvatarGroup.tsx +58 -3
  325. package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
  326. package/src/Banner/Banner.tsx +6 -6
  327. package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
  328. package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
  329. package/src/Breadcrumbs/index.ts +4 -0
  330. package/src/Button/Button.doc.mjs +0 -4
  331. package/src/Button/Button.test.tsx +16 -0
  332. package/src/Button/Button.tsx +6 -4
  333. package/src/Calendar/Calendar.test.tsx +170 -20
  334. package/src/Calendar/Calendar.tsx +73 -16
  335. package/src/Calendar/dayCellUtils.test.ts +18 -18
  336. package/src/Calendar/dayCellUtils.ts +2 -2
  337. package/src/Calendar/styles.ts +33 -39
  338. package/src/Card/Card.tsx +1 -1
  339. package/src/Carousel/Carousel.tsx +25 -6
  340. package/src/Chat/ChatComposer.doc.mjs +2 -2
  341. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  342. package/src/Chat/ChatComposerInput.tsx +2 -2
  343. package/src/Chat/ChatDictationButton.tsx +7 -1
  344. package/src/Chat/ChatLayout.tsx +4 -4
  345. package/src/Chat/ChatMessageBubble.tsx +15 -10
  346. package/src/Chat/ChatSystemMessage.test.tsx +5 -0
  347. package/src/Chat/ChatToolCalls.tsx +9 -2
  348. package/src/Chat/useTriggerMenu.tsx +1 -1
  349. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  350. package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
  351. package/src/CheckboxInput/CheckboxInput.tsx +21 -6
  352. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  353. package/src/CheckboxList/CheckboxList.test.tsx +94 -3
  354. package/src/CheckboxList/CheckboxListItem.tsx +17 -10
  355. package/src/Citation/Citation.doc.mjs +4 -3
  356. package/src/Citation/Citation.test.tsx +97 -0
  357. package/src/Citation/Citation.tsx +43 -11
  358. package/src/CodeBlock/CodeBlock.test.tsx +17 -0
  359. package/src/CodeBlock/CodeBlock.tsx +38 -11
  360. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  361. package/src/Collapsible/Collapsible.test.tsx +7 -0
  362. package/src/Collapsible/Collapsible.tsx +16 -6
  363. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  364. package/src/CommandPalette/CommandPalette.tsx +41 -2
  365. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  366. package/src/ContextMenu/ContextMenu.test.tsx +59 -2
  367. package/src/ContextMenu/ContextMenu.tsx +22 -11
  368. package/src/ContextMenu/index.ts +5 -0
  369. package/src/DateInput/DateInput.doc.mjs +25 -0
  370. package/src/DateInput/DateInput.test.tsx +230 -0
  371. package/src/DateInput/DateInput.tsx +51 -29
  372. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  373. package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
  374. package/src/DateRangeInput/DateRangeInput.tsx +42 -30
  375. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  376. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  377. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  378. package/src/Divider/Divider.test.tsx +32 -8
  379. package/src/Divider/Divider.tsx +14 -1
  380. package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
  381. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  382. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
  383. package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
  384. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
  385. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
  386. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +9 -3
  387. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +20 -2
  388. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  389. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
  390. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
  391. package/src/DropdownMenu/index.ts +16 -0
  392. package/src/DropdownMenu/menuItemHover.ts +39 -0
  393. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  394. package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
  395. package/src/Field/Field.tsx +14 -9
  396. package/src/Field/FieldLabel.test.tsx +25 -0
  397. package/src/Field/FieldLabel.tsx +12 -3
  398. package/src/Field/inputStyles.stylex.ts +2 -0
  399. package/src/FieldStatus/FieldStatus.test.tsx +72 -0
  400. package/src/FieldStatus/FieldStatus.tsx +48 -2
  401. package/src/FileInput/FileInput.doc.mjs +23 -2
  402. package/src/FileInput/FileInput.test.tsx +104 -13
  403. package/src/FileInput/FileInput.tsx +106 -79
  404. package/src/HoverCard/useHoverCard.tsx +15 -3
  405. package/src/Icon/Icon.doc.mjs +13 -0
  406. package/src/Icon/Icon.test.tsx +89 -0
  407. package/src/Icon/Icon.tsx +51 -3
  408. package/src/Item/Item.doc.mjs +5 -0
  409. package/src/Item/Item.test.tsx +88 -0
  410. package/src/Item/Item.tsx +57 -11
  411. package/src/Layer/layerAnimations.stylex.ts +23 -0
  412. package/src/Lightbox/Lightbox.tsx +15 -7
  413. package/src/List/List.test.tsx +17 -29
  414. package/src/List/List.tsx +6 -1
  415. package/src/List/ListItem.doc.mjs +12 -0
  416. package/src/List/ListItem.tsx +13 -0
  417. package/src/Markdown/Markdown.test.tsx +21 -0
  418. package/src/Markdown/Markdown.tsx +4 -0
  419. package/src/MetadataList/MetadataList.test.tsx +24 -0
  420. package/src/MetadataList/MetadataList.tsx +6 -2
  421. package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
  422. package/src/MultiSelector/MultiSelector.test.tsx +402 -0
  423. package/src/MultiSelector/MultiSelector.tsx +120 -59
  424. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  425. package/src/NumberInput/NumberInput.doc.mjs +21 -0
  426. package/src/NumberInput/NumberInput.test.tsx +71 -0
  427. package/src/NumberInput/NumberInput.tsx +35 -26
  428. package/src/Outline/Outline.test.tsx +12 -12
  429. package/src/Outline/Outline.tsx +2 -2
  430. package/src/Pagination/Pagination.tsx +11 -3
  431. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  432. package/src/PowerSearch/PowerSearch.test.tsx +23 -0
  433. package/src/PowerSearch/PowerSearch.tsx +10 -1
  434. package/src/ProgressBar/ProgressBar.test.tsx +34 -0
  435. package/src/ProgressBar/ProgressBar.tsx +16 -1
  436. package/src/RadioList/RadioList.doc.mjs +6 -0
  437. package/src/RadioList/RadioList.test.tsx +26 -4
  438. package/src/RadioList/RadioList.tsx +2 -2
  439. package/src/RadioList/RadioListItem.tsx +12 -5
  440. package/src/Resizable/ResizeHandle.test.tsx +94 -0
  441. package/src/Resizable/ResizeHandle.tsx +70 -20
  442. package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
  443. package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
  444. package/src/Selector/Selector.doc.mjs +15 -0
  445. package/src/Selector/Selector.test.tsx +370 -0
  446. package/src/Selector/Selector.tsx +88 -20
  447. package/src/SideNav/SideNav.tsx +1 -8
  448. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  449. package/src/SideNav/SideNavItem.tsx +5 -3
  450. package/src/Skeleton/Skeleton.test.tsx +16 -0
  451. package/src/Skeleton/Skeleton.tsx +13 -1
  452. package/src/Slider/Slider.doc.mjs +6 -0
  453. package/src/Slider/Slider.test.tsx +240 -12
  454. package/src/Slider/Slider.tsx +96 -23
  455. package/src/Spinner/Spinner.test.tsx +10 -8
  456. package/src/Spinner/Spinner.tsx +15 -5
  457. package/src/Switch/Switch.doc.mjs +142 -42
  458. package/src/Switch/Switch.test.tsx +111 -0
  459. package/src/Switch/Switch.tsx +149 -32
  460. package/src/TabList/Tab.tsx +2 -2
  461. package/src/TabList/TabList.doc.mjs +0 -6
  462. package/src/TabList/TabList.test.tsx +3 -15
  463. package/src/TabList/TabList.tsx +6 -17
  464. package/src/TabList/TabListContext.ts +0 -6
  465. package/src/TabList/TabMenu.tsx +2 -2
  466. package/src/Table/BaseTable.tsx +34 -2
  467. package/src/Table/Table.doc.mjs +11 -0
  468. package/src/Table/Table.test.tsx +85 -0
  469. package/src/Table/TableCell.tsx +3 -3
  470. package/src/Table/TableHeaderCell.tsx +3 -3
  471. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  472. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
  473. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +27 -18
  474. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  475. package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
  476. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +38 -9
  477. package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
  478. package/src/Table/types.ts +33 -0
  479. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  480. package/src/TextArea/TextArea.doc.mjs +21 -0
  481. package/src/TextArea/TextArea.test.tsx +23 -0
  482. package/src/TextArea/TextArea.tsx +27 -26
  483. package/src/TextInput/TextInput.doc.mjs +21 -0
  484. package/src/TextInput/TextInput.test.tsx +150 -0
  485. package/src/TextInput/TextInput.tsx +28 -25
  486. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  487. package/src/Thumbnail/Thumbnail.tsx +1 -1
  488. package/src/TimeInput/TimeInput.doc.mjs +21 -0
  489. package/src/TimeInput/TimeInput.test.tsx +23 -0
  490. package/src/TimeInput/TimeInput.tsx +24 -25
  491. package/src/Timestamp/Timestamp.doc.mjs +32 -6
  492. package/src/Timestamp/Timestamp.test.tsx +371 -0
  493. package/src/Timestamp/Timestamp.tsx +96 -93
  494. package/src/Timestamp/formatInstant.ts +218 -0
  495. package/src/Timestamp/index.ts +4 -0
  496. package/src/Timestamp/tooltipEntries.test.ts +552 -0
  497. package/src/Timestamp/tooltipEntries.ts +210 -0
  498. package/src/Toast/ToastViewport.test.tsx +218 -8
  499. package/src/Toast/ToastViewport.tsx +71 -12
  500. package/src/ToggleButton/ToggleButton.test.tsx +24 -0
  501. package/src/ToggleButton/ToggleButton.tsx +19 -1
  502. package/src/Token/Token.test.tsx +166 -15
  503. package/src/Token/Token.tsx +104 -47
  504. package/src/Token/TokenLink.tsx +107 -0
  505. package/src/Token/index.ts +1 -1
  506. package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
  507. package/src/Tokenizer/Tokenizer.test.tsx +23 -0
  508. package/src/Tokenizer/Tokenizer.tsx +14 -2
  509. package/src/Tooltip/Tooltip.test.tsx +46 -0
  510. package/src/Tooltip/useTooltip.tsx +20 -0
  511. package/src/TopNav/TopNav.test.tsx +93 -2
  512. package/src/TopNav/TopNavItem.doc.mjs +3 -3
  513. package/src/TopNav/TopNavItem.tsx +35 -6
  514. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
  515. package/src/TreeList/TreeList.doc.mjs +6 -0
  516. package/src/TreeList/TreeList.test.tsx +50 -10
  517. package/src/TreeList/TreeList.tsx +5 -0
  518. package/src/TreeList/TreeListBranches.tsx +8 -6
  519. package/src/TreeList/TreeListItem.tsx +33 -11
  520. package/src/Typeahead/BaseTypeahead.tsx +42 -15
  521. package/src/Typeahead/Typeahead.doc.mjs +13 -0
  522. package/src/Typeahead/Typeahead.test.tsx +112 -0
  523. package/src/Typeahead/Typeahead.tsx +17 -1
  524. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  525. package/src/__tests__/forcedColors.ts +60 -0
  526. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  527. package/src/doc-mjs.d.ts +19 -0
  528. package/src/hooks/index.ts +6 -0
  529. package/src/hooks/isRtlElement.ts +27 -0
  530. package/src/hooks/useAnnounce.test.tsx +75 -2
  531. package/src/hooks/useAnnounce.ts +47 -1
  532. package/src/hooks/useFocusTrap.test.tsx +104 -0
  533. package/src/hooks/useFocusTrap.ts +61 -12
  534. package/src/hooks/useGridFocus.doc.mjs +3 -3
  535. package/src/hooks/useGridFocus.test.tsx +41 -0
  536. package/src/hooks/useGridFocus.ts +21 -10
  537. package/src/hooks/useHotkeys.ts +9 -0
  538. package/src/hooks/useInputStatusIcon.test.tsx +162 -0
  539. package/src/hooks/useInputStatusIcon.tsx +224 -0
  540. package/src/hooks/useKeyboardHint.test.tsx +22 -0
  541. package/src/hooks/useKeyboardHint.tsx +6 -2
  542. package/src/hooks/useListFocus.doc.mjs +25 -3
  543. package/src/hooks/useListFocus.test.tsx +153 -1
  544. package/src/hooks/useListFocus.ts +102 -9
  545. package/src/i18n/InternationalizationContext.ts +4 -0
  546. package/src/i18n/InternationalizationProvider.tsx +12 -2
  547. package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
  548. package/src/i18n/__tests__/useDirection.test.tsx +66 -0
  549. package/src/i18n/getLocaleDirection.ts +29 -0
  550. package/src/i18n/index.ts +6 -0
  551. package/src/i18n/useDirection.ts +29 -0
  552. package/src/reset.css +0 -26
  553. package/src/reset.test.ts +60 -0
  554. package/src/theme/derivedVarRegistry.test.ts +1 -0
  555. package/src/theme/derivedVarRegistry.ts +6 -0
  556. package/src/theme/generateThemeRules.test.ts +42 -0
  557. package/src/utils/index.ts +2 -0
  558. package/src/utils/plainDate.test.ts +24 -6
  559. package/src/utils/plainDate.ts +18 -4
  560. package/src/utils/rtlStyles.ts +27 -0
@@ -19,7 +19,10 @@ import {
19
19
  } from '@testing-library/react';
20
20
  import userEvent from '@testing-library/user-event';
21
21
  import {MultiSelector} from './MultiSelector';
22
+ import {Icon} from '../Icon';
22
23
  import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
24
+ import {defineTheme} from '../theme/defineTheme';
25
+ import {generateThemeCSSFlat} from '../theme/generateThemeRules';
23
26
 
24
27
  // Module-level constants to satisfy @eslint-react/no-unstable-default-props.
25
28
  const ANNOUNCE_OPTIONS = ['Apple', 'Banana', 'Orange'] as const;
@@ -507,6 +510,59 @@ describe('MultiSelector', () => {
507
510
  expect(options[0]).toHaveTextContent('Select all');
508
511
  });
509
512
 
513
+ it('select-all accessible name reflects none/partial/all selection', async () => {
514
+ const user = userEvent.setup();
515
+ const options = [
516
+ {value: 'apple', label: 'Apple'},
517
+ {value: 'banana', label: 'Banana'},
518
+ ];
519
+ const {rerender} = render(
520
+ <MultiSelector
521
+ label="Fruit"
522
+ options={options}
523
+ value={[]}
524
+ onChange={() => {}}
525
+ hasSelectAll
526
+ />,
527
+ );
528
+
529
+ await user.click(screen.getByRole('combobox'));
530
+
531
+ // None selected: plain name, not selected
532
+ let selectAll = screen.getAllByRole('option', h)[0];
533
+ expect(selectAll).not.toHaveAccessibleName(/partially selected/);
534
+ expect(selectAll).toHaveAttribute('aria-selected', 'false');
535
+
536
+ // Partial: aria-selected="mixed" is invalid on role="option", so the
537
+ // indeterminate state must be conveyed through the accessible name.
538
+ rerender(
539
+ <MultiSelector
540
+ label="Fruit"
541
+ options={options}
542
+ value={['apple']}
543
+ onChange={() => {}}
544
+ hasSelectAll
545
+ />,
546
+ );
547
+ selectAll = screen.getAllByRole('option', h)[0];
548
+ expect(selectAll).toHaveAccessibleName('Select all, partially selected');
549
+ expect(selectAll).toHaveAttribute('aria-selected', 'false');
550
+
551
+ // All selected: plain name again, selected
552
+ rerender(
553
+ <MultiSelector
554
+ label="Fruit"
555
+ options={options}
556
+ value={['apple', 'banana']}
557
+ onChange={() => {}}
558
+ hasSelectAll
559
+ />,
560
+ );
561
+ selectAll = screen.getAllByRole('option', h)[0];
562
+ expect(selectAll).not.toHaveAccessibleName(/partially selected/);
563
+ expect(selectAll).toHaveAttribute('aria-selected', 'true');
564
+ });
565
+
510
566
  it('select-all toggles via keyboard Enter', async () => {
511
567
  const user = userEvent.setup();
512
568
  const onChange = vi.fn();
@@ -565,6 +621,72 @@ describe('MultiSelector', () => {
565
621
  expect(options).toHaveLength(1);
566
622
  });
567
623
 
624
+ describe('grouped search', () => {
625
+ const GROUPED = [
626
+ {
627
+ type: 'section' as const,
628
+ title: 'Citrus',
629
+ options: [
630
+ {value: 'orange', label: 'Orange'},
631
+ {value: 'lemon', label: 'Lemon'},
632
+ ],
633
+ },
634
+ {
635
+ type: 'section' as const,
636
+ title: 'Berries',
637
+ options: [
638
+ {value: 'strawberry', label: 'Strawberry'},
639
+ {value: 'blueberry', label: 'Blueberry'},
640
+ ],
641
+ },
642
+ ];
643
+
644
+ it('keeps the group header above matching items while searching', async () => {
645
+ const user = userEvent.setup();
646
+ render(
647
+ <MultiSelector
648
+ label="Fruit"
649
+ options={GROUPED}
650
+ value={[]}
651
+ onChange={() => {}}
652
+ hasSearch
653
+ />,
654
+ );
655
+ await user.click(screen.getByRole('button', {name: 'Fruit'}));
656
+ await user.type(screen.getByRole('combobox', h), 'orange');
657
+
658
+ expect(
659
+ screen.getByRole('group', {name: 'Citrus', ...h}),
660
+ ).toBeInTheDocument();
661
+ const options = screen.getAllByRole('option', h);
662
+ expect(options).toHaveLength(1);
663
+ expect(options[0]).toHaveTextContent('Orange');
664
+ });
665
+
666
+ it('hides a group whose items have no match', async () => {
667
+ const user = userEvent.setup();
668
+ render(
669
+ <MultiSelector
670
+ label="Fruit"
671
+ options={GROUPED}
672
+ value={[]}
673
+ onChange={() => {}}
674
+ hasSearch
675
+ />,
676
+ );
677
+ await user.click(screen.getByRole('button', {name: 'Fruit'}));
678
+ await user.type(screen.getByRole('combobox', h), 'berry');
679
+
680
+ expect(
681
+ screen.getByRole('group', {name: 'Berries', ...h}),
682
+ ).toBeInTheDocument();
683
+ expect(
684
+ screen.queryByRole('group', {name: 'Citrus', ...h}),
685
+ ).not.toBeInTheDocument();
686
+ expect(screen.getAllByRole('option', h)).toHaveLength(2);
687
+ });
688
+ });
689
+
568
690
  it('PageDown/PageUp jump the highlight to the last/first filtered option', async () => {
569
691
  const user = userEvent.setup();
570
692
  render(
@@ -645,6 +767,29 @@ describe('MultiSelector', () => {
645
767
  ).toBeInTheDocument();
646
768
  });
647
769
 
770
+ it('empty-state message is not exposed as a listbox child', async () => {
771
+ const user = userEvent.setup();
772
+ render(
773
+ <MultiSelector
774
+ label="Fruit"
775
+ options={defaultOptions}
776
+ value={[]}
777
+ onChange={() => {}}
778
+ hasSearch
779
+ />,
780
+ );
781
+
782
+ await user.click(screen.getByRole('button', {name: 'Fruit'}));
783
+ await user.type(screen.getByRole('combobox', h), 'xyz');
784
+
785
+ // role="listbox" only permits option/group children — the visual
786
+ // empty-state message must be presentational (it is announced through
787
+ // the result-count live region instead).
788
+ const listbox = screen.getByRole('listbox', h);
789
+ const empty = within(listbox).getByText('No results found');
790
+ expect(empty).toHaveAttribute('role', 'presentation');
791
+ });
792
+
648
793
  describe('result announcements', () => {
649
794
  it('announces the match count politely while searching', async () => {
650
795
  const user = userEvent.setup();
@@ -1245,3 +1390,260 @@ describe('MultiSelector', () => {
1245
1390
  });
1246
1391
  });
1247
1392
  });
1393
+
1394
+ describe('MultiSelector statusVariant forwarding', () => {
1395
+ it('defaults to attached (status renders with data-variant="attached")', () => {
1396
+ const {container} = render(
1397
+ <MultiSelector
1398
+ label="Fruit"
1399
+ options={['Apple', 'Banana']}
1400
+ value={[]}
1401
+ onChange={() => {}}
1402
+ status={{type: 'error', message: 'Required'}}
1403
+ />,
1404
+ );
1405
+ expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
1406
+ 'data-variant',
1407
+ 'attached',
1408
+ );
1409
+ });
1410
+
1411
+ it('forwards statusVariant="detached" to the underlying Field status', () => {
1412
+ const {container} = render(
1413
+ <MultiSelector
1414
+ label="Fruit"
1415
+ options={['Apple', 'Banana']}
1416
+ value={[]}
1417
+ onChange={() => {}}
1418
+ status={{type: 'error', message: 'Required'}}
1419
+ statusVariant="detached"
1420
+ />,
1421
+ );
1422
+ expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
1423
+ 'data-variant',
1424
+ 'detached',
1425
+ );
1426
+ });
1427
+ });
1428
+
1429
+ describe('MultiSelector clear icon theme target', () => {
1430
+ const ICON_OPTIONS = ['Apple', 'Banana', 'Orange'];
1431
+
1432
+ // Resolve the clear glyph span (the astryx-icon element inside the clear
1433
+ // button), independent of the theme target class.
1434
+ const getClearIcon = (): HTMLElement => {
1435
+ const button = screen.getByRole('button', {name: 'Clear all Fruit'});
1436
+ const icon = button.querySelector('.astryx-icon');
1437
+ if (icon == null) {
1438
+ throw new Error('clear icon not found');
1439
+ }
1440
+ return icon as HTMLElement;
1441
+ };
1442
+
1443
+ it('renders the astryx-multi-selector-clear-icon target on the clear glyph', () => {
1444
+ render(
1445
+ <MultiSelector
1446
+ label="Fruit"
1447
+ options={ICON_OPTIONS}
1448
+ value={['Banana']}
1449
+ onChange={() => {}}
1450
+ hasClear
1451
+ />,
1452
+ );
1453
+ // The stable theme target lands on the icon element itself (not the
1454
+ // button), so a theme can restyle just this glyph (color, size, hover)
1455
+ // via `defineTheme` — a button-level target could not reach the icon's
1456
+ // own color/size.
1457
+ const icon = getClearIcon();
1458
+ expect(icon).toHaveClass('astryx-multi-selector-clear-icon');
1459
+ expect(icon).toHaveClass('astryx-icon');
1460
+ });
1461
+
1462
+ it('keeps the clear button functional alongside the target', () => {
1463
+ const onChange = vi.fn();
1464
+ render(
1465
+ <MultiSelector
1466
+ label="Fruit"
1467
+ options={ICON_OPTIONS}
1468
+ value={['Banana']}
1469
+ onChange={onChange}
1470
+ hasClear
1471
+ />,
1472
+ );
1473
+ const clear = screen.getByRole('button', {name: 'Clear all Fruit'});
1474
+ expect(clear.tagName).toBe('BUTTON');
1475
+ fireEvent.click(clear);
1476
+ expect(onChange).toHaveBeenCalledWith([]);
1477
+ });
1478
+
1479
+ it('renders the default icon (secondary color, sm size) byte-identically', () => {
1480
+ // Pixel-identical default guard: the clear glyph must carry the exact same
1481
+ // StyleX color/size classes as a standalone secondary/sm icon. The added
1482
+ // target class is purely additive — it changes nothing until a theme
1483
+ // targets it.
1484
+ render(
1485
+ <MultiSelector
1486
+ label="Fruit"
1487
+ options={ICON_OPTIONS}
1488
+ value={['Banana']}
1489
+ onChange={() => {}}
1490
+ hasClear
1491
+ />,
1492
+ );
1493
+ const icon = getClearIcon();
1494
+
1495
+ const {container: refContainer} = render(
1496
+ <Icon icon="close" size="sm" color="secondary" />,
1497
+ );
1498
+ const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
1499
+
1500
+ const styleClasses = (el: HTMLElement) =>
1501
+ el.className
1502
+ .split(' ')
1503
+ .filter(c => c !== 'astryx-multi-selector-clear-icon')
1504
+ .sort();
1505
+
1506
+ expect(styleClasses(icon)).toEqual(styleClasses(refIcon));
1507
+ });
1508
+
1509
+ it('exposes multi-selector-clear-icon so a theme reaches the icon color, size, and hover', () => {
1510
+ // jsdom cannot resolve the @layer cascade, so the DOM-class assertion above
1511
+ // (target lands on the icon element) plus this generation assertion (the
1512
+ // theme emits same-element icon rules in @layer astryx-theme) together
1513
+ // prove the seam: a same-element theme rule wins over the icon's own
1514
+ // base-layer color/size.
1515
+ const theme = defineTheme({
1516
+ name: 'multi-selector-clear-icon-test',
1517
+ components: {
1518
+ 'multi-selector-clear-icon': {
1519
+ base: {
1520
+ width: '12px',
1521
+ height: '12px',
1522
+ fontSize: '12px',
1523
+ color: 'var(--color-icon-secondary)',
1524
+ ':hover': {color: 'var(--color-icon-primary)'},
1525
+ },
1526
+ },
1527
+ },
1528
+ });
1529
+ const css = generateThemeCSSFlat(theme);
1530
+ expect(css).toContain('.astryx-multi-selector-clear-icon {');
1531
+ expect(css).toContain('width: 12px');
1532
+ expect(css).toContain('height: 12px');
1533
+ expect(css).toContain('.astryx-multi-selector-clear-icon:hover {');
1534
+ expect(css).toContain('color: var(--color-icon-primary)');
1535
+ });
1536
+ });
1537
+
1538
+ describe('MultiSelector indicator (chevron) icon theme target', () => {
1539
+ const ICON_OPTIONS = ['Apple', 'Banana', 'Orange'];
1540
+
1541
+ const getIndicatorIcon = (container: HTMLElement): HTMLElement => {
1542
+ // The chevron is the only glyph carrying the indicator target class.
1543
+ const icon = container.querySelector(
1544
+ '.astryx-multi-selector-indicator-icon',
1545
+ );
1546
+ if (icon == null) {
1547
+ throw new Error('indicator icon not found');
1548
+ }
1549
+ return icon as HTMLElement;
1550
+ };
1551
+
1552
+ it('renders the astryx-multi-selector-indicator-icon target on the chevron glyph', () => {
1553
+ const {container} = render(
1554
+ <MultiSelector
1555
+ label="Fruit"
1556
+ options={ICON_OPTIONS}
1557
+ value={[]}
1558
+ onChange={() => {}}
1559
+ />,
1560
+ );
1561
+ // The stable theme target lands on the icon element itself (not the trigger
1562
+ // button), so a theme can restyle just this glyph (color, size, hover) —
1563
+ // and each open/closed state — via `defineTheme`. A button-level target
1564
+ // could not reach the icon's own color/size.
1565
+ const icon = getIndicatorIcon(container);
1566
+ expect(icon).toHaveClass('astryx-multi-selector-indicator-icon');
1567
+ expect(icon).toHaveClass('astryx-icon');
1568
+ // Open/closed state is reflected so a theme can target each state alone.
1569
+ expect(icon).toHaveAttribute('data-state', 'collapsed');
1570
+ });
1571
+
1572
+ it('reflects the expanded state on the chevron when the popover is open', async () => {
1573
+ const user = userEvent.setup();
1574
+ const {container} = render(
1575
+ <MultiSelector
1576
+ label="Fruit"
1577
+ options={ICON_OPTIONS}
1578
+ value={[]}
1579
+ onChange={() => {}}
1580
+ />,
1581
+ );
1582
+ await user.click(screen.getByRole('combobox'));
1583
+ await waitFor(() => {
1584
+ expect(getIndicatorIcon(container)).toHaveAttribute(
1585
+ 'data-state',
1586
+ 'expanded',
1587
+ );
1588
+ });
1589
+ });
1590
+
1591
+ it('renders the default icon (inherit color, sm size) byte-identically', () => {
1592
+ // Pixel-identical default guard: the chevron glyph must carry the exact
1593
+ // same StyleX color/size classes as a standalone inherit/sm icon. The added
1594
+ // target class + data-state are purely additive — they change nothing until
1595
+ // a theme targets them.
1596
+ const {container} = render(
1597
+ <MultiSelector
1598
+ label="Fruit"
1599
+ options={ICON_OPTIONS}
1600
+ value={[]}
1601
+ onChange={() => {}}
1602
+ />,
1603
+ );
1604
+ const icon = getIndicatorIcon(container);
1605
+
1606
+ const {container: refContainer} = render(
1607
+ <Icon icon="chevronDown" size="sm" color="inherit" />,
1608
+ );
1609
+ const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
1610
+
1611
+ // Exclude the additive theme-target classes (the stable target + its
1612
+ // reflected state class) so only the StyleX color/size classes remain.
1613
+ const themeTargetClasses = new Set([
1614
+ 'astryx-multi-selector-indicator-icon',
1615
+ 'collapsed',
1616
+ 'expanded',
1617
+ ]);
1618
+ const styleClasses = (el: HTMLElement) =>
1619
+ el.className
1620
+ .split(' ')
1621
+ .filter(c => !themeTargetClasses.has(c))
1622
+ .sort();
1623
+
1624
+ expect(styleClasses(icon)).toEqual(styleClasses(refIcon));
1625
+ });
1626
+
1627
+ it('exposes multi-selector-indicator-icon so a theme reaches the icon size and per-state color', () => {
1628
+ // jsdom cannot resolve the @layer cascade, so the DOM-class assertions
1629
+ // above (target lands on the icon element) plus this generation assertion
1630
+ // (the theme emits same-element icon rules in @layer astryx-theme) together
1631
+ // prove the seam: a same-element theme rule wins over the icon's own
1632
+ // base-layer color/size.
1633
+ const theme = defineTheme({
1634
+ name: 'multi-selector-indicator-icon-test',
1635
+ components: {
1636
+ 'multi-selector-indicator-icon': {
1637
+ base: {width: '14px', height: '14px', fontSize: '14px'},
1638
+ 'state:expanded': {color: 'var(--color-icon-primary)'},
1639
+ },
1640
+ },
1641
+ });
1642
+ const css = generateThemeCSSFlat(theme);
1643
+ expect(css).toContain('.astryx-multi-selector-indicator-icon {');
1644
+ expect(css).toContain('width: 14px');
1645
+ expect(css).toContain('height: 14px');
1646
+ expect(css).toContain('.astryx-multi-selector-indicator-icon.expanded');
1647
+ expect(css).toContain('color: var(--color-icon-primary)');
1648
+ });
1649
+ });