@astryxdesign/core 0.1.9 → 0.2.0-canary.068bda9

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 (601) 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 +435 -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 +24 -0
  92. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  93. package/dist/DropdownMenu/menuItemHover.js +34 -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 +51 -5
  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/Heading/Heading.d.ts.map +1 -1
  115. package/dist/Heading/Heading.js +3 -2
  116. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  117. package/dist/HoverCard/useHoverCard.js +10 -4
  118. package/dist/Icon/Icon.d.ts +15 -1
  119. package/dist/Icon/Icon.d.ts.map +1 -1
  120. package/dist/Icon/Icon.js +19 -3
  121. package/dist/Item/Item.d.ts +16 -3
  122. package/dist/Item/Item.d.ts.map +1 -1
  123. package/dist/Item/Item.js +31 -6
  124. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  125. package/dist/Layer/layerAnimations.stylex.js +10 -2
  126. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  127. package/dist/Lightbox/Lightbox.js +34 -15
  128. package/dist/List/List.d.ts.map +1 -1
  129. package/dist/List/List.js +6 -3
  130. package/dist/List/ListItem.d.ts +11 -1
  131. package/dist/List/ListItem.d.ts.map +1 -1
  132. package/dist/List/ListItem.js +2 -0
  133. package/dist/Markdown/Markdown.d.ts.map +1 -1
  134. package/dist/Markdown/Markdown.js +7 -0
  135. package/dist/MetadataList/MetadataList.d.ts +1 -1
  136. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  137. package/dist/MetadataList/MetadataList.js +4 -2
  138. package/dist/MultiSelector/MultiSelector.d.ts +9 -1
  139. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  140. package/dist/MultiSelector/MultiSelector.js +81 -43
  141. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  142. package/dist/NumberInput/NumberInput.d.ts +10 -2
  143. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  144. package/dist/NumberInput/NumberInput.js +22 -17
  145. package/dist/Outline/Outline.js +2 -2
  146. package/dist/Pagination/Pagination.d.ts.map +1 -1
  147. package/dist/Pagination/Pagination.js +11 -3
  148. package/dist/PowerSearch/PowerSearch.d.ts +9 -2
  149. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  150. package/dist/PowerSearch/PowerSearch.js +2 -0
  151. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  152. package/dist/ProgressBar/ProgressBar.js +6 -1
  153. package/dist/RadioList/RadioList.d.ts +2 -2
  154. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  155. package/dist/RadioList/RadioListItem.js +5 -5
  156. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  157. package/dist/Resizable/ResizeHandle.js +49 -19
  158. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  159. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  160. package/dist/SegmentedControl/SegmentedControlItem.js +5 -3
  161. package/dist/Selector/Selector.d.ts +8 -0
  162. package/dist/Selector/Selector.d.ts.map +1 -1
  163. package/dist/Selector/Selector.js +66 -17
  164. package/dist/SideNav/SideNav.d.ts.map +1 -1
  165. package/dist/SideNav/SideNav.js +5 -5
  166. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  167. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  168. package/dist/SideNav/SideNavItem.d.ts +1 -1
  169. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  170. package/dist/SideNav/SideNavItem.js +12 -10
  171. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  172. package/dist/Skeleton/Skeleton.js +2 -2
  173. package/dist/Slider/Slider.d.ts.map +1 -1
  174. package/dist/Slider/Slider.js +87 -34
  175. package/dist/Spinner/Spinner.d.ts +3 -2
  176. package/dist/Spinner/Spinner.d.ts.map +1 -1
  177. package/dist/Spinner/Spinner.js +11 -2
  178. package/dist/Switch/Switch.d.ts +8 -1
  179. package/dist/Switch/Switch.d.ts.map +1 -1
  180. package/dist/Switch/Switch.js +171 -91
  181. package/dist/TabList/Tab.js +2 -2
  182. package/dist/TabList/TabList.d.ts +2 -11
  183. package/dist/TabList/TabList.d.ts.map +1 -1
  184. package/dist/TabList/TabList.js +5 -9
  185. package/dist/TabList/TabListContext.d.ts +0 -5
  186. package/dist/TabList/TabListContext.d.ts.map +1 -1
  187. package/dist/TabList/TabListContext.js +0 -5
  188. package/dist/TabList/TabMenu.js +1 -1
  189. package/dist/Table/BaseTable.d.ts.map +1 -1
  190. package/dist/Table/BaseTable.js +30 -4
  191. package/dist/Table/TableCell.js +3 -3
  192. package/dist/Table/TableHeaderCell.js +3 -3
  193. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  194. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  195. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  196. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +37 -27
  197. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  198. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  199. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  200. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +15 -7
  201. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  202. package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
  203. package/dist/Table/types.d.ts +32 -0
  204. package/dist/Table/types.d.ts.map +1 -1
  205. package/dist/Text/Text.d.ts +10 -1
  206. package/dist/Text/Text.d.ts.map +1 -1
  207. package/dist/Text/Text.js +25 -2
  208. package/dist/Text/index.d.ts +2 -2
  209. package/dist/Text/index.d.ts.map +1 -1
  210. package/dist/TextArea/TextArea.d.ts +10 -1
  211. package/dist/TextArea/TextArea.d.ts.map +1 -1
  212. package/dist/TextArea/TextArea.js +119 -52
  213. package/dist/TextInput/TextInput.d.ts +10 -2
  214. package/dist/TextInput/TextInput.d.ts.map +1 -1
  215. package/dist/TextInput/TextInput.js +20 -17
  216. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  217. package/dist/Thumbnail/Thumbnail.js +51 -45
  218. package/dist/TimeInput/TimeInput.d.ts +10 -2
  219. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  220. package/dist/TimeInput/TimeInput.js +17 -17
  221. package/dist/Timestamp/Timestamp.d.ts +31 -3
  222. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  223. package/dist/Timestamp/Timestamp.js +48 -77
  224. package/dist/Timestamp/formatInstant.d.ts +41 -0
  225. package/dist/Timestamp/formatInstant.d.ts.map +1 -0
  226. package/dist/Timestamp/formatInstant.js +177 -0
  227. package/dist/Timestamp/index.d.ts +1 -0
  228. package/dist/Timestamp/index.d.ts.map +1 -1
  229. package/dist/Timestamp/tooltipEntries.d.ts +56 -0
  230. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
  231. package/dist/Timestamp/tooltipEntries.js +163 -0
  232. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  233. package/dist/Toast/ToastViewport.js +61 -9
  234. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  235. package/dist/ToggleButton/ToggleButton.js +3 -1
  236. package/dist/Token/Token.d.ts +34 -4
  237. package/dist/Token/Token.d.ts.map +1 -1
  238. package/dist/Token/Token.js +85 -45
  239. package/dist/Token/TokenLink.d.ts +62 -0
  240. package/dist/Token/TokenLink.d.ts.map +1 -0
  241. package/dist/Token/TokenLink.js +76 -0
  242. package/dist/Token/index.d.ts +1 -1
  243. package/dist/Token/index.d.ts.map +1 -1
  244. package/dist/Tokenizer/Tokenizer.d.ts +9 -2
  245. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  246. package/dist/Tokenizer/Tokenizer.js +4 -2
  247. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  248. package/dist/Tooltip/useTooltip.js +17 -1
  249. package/dist/TopNav/TopNavItem.d.ts +3 -1
  250. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  251. package/dist/TopNav/TopNavItem.js +30 -3
  252. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  253. package/dist/TopNav/TopNavMegaMenu.js +9 -3
  254. package/dist/TreeList/TreeList.d.ts.map +1 -1
  255. package/dist/TreeList/TreeList.js +1 -0
  256. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  257. package/dist/TreeList/TreeListBranches.js +8 -6
  258. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  259. package/dist/TreeList/TreeListItem.js +32 -14
  260. package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
  261. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  262. package/dist/Typeahead/BaseTypeahead.js +22 -11
  263. package/dist/Typeahead/Typeahead.d.ts +9 -2
  264. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  265. package/dist/Typeahead/Typeahead.js +11 -2
  266. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  267. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  268. package/dist/Typeahead/TypeaheadItem.js +20 -10
  269. package/dist/astryx.css +114 -35
  270. package/dist/astryx.umd.js +50 -50
  271. package/dist/astryx.umd.js.map +4 -4
  272. package/dist/hooks/containerReveal.pool.stylex.d.ts +281 -0
  273. package/dist/hooks/containerReveal.pool.stylex.d.ts.map +1 -0
  274. package/dist/hooks/containerReveal.pool.stylex.js +281 -0
  275. package/dist/hooks/index.d.ts +4 -0
  276. package/dist/hooks/index.d.ts.map +1 -1
  277. package/dist/hooks/index.js +3 -1
  278. package/dist/hooks/isRtlElement.d.ts +18 -0
  279. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  280. package/dist/hooks/isRtlElement.js +27 -0
  281. package/dist/hooks/useAnnounce.d.ts +3 -0
  282. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  283. package/dist/hooks/useAnnounce.js +39 -1
  284. package/dist/hooks/useContainerReveal.d.ts +83 -0
  285. package/dist/hooks/useContainerReveal.d.ts.map +1 -0
  286. package/dist/hooks/useContainerReveal.js +123 -0
  287. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  288. package/dist/hooks/useFocusTrap.js +52 -11
  289. package/dist/hooks/useGridFocus.d.ts +6 -1
  290. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  291. package/dist/hooks/useGridFocus.js +12 -9
  292. package/dist/hooks/useHotkeys.d.ts +9 -0
  293. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  294. package/dist/hooks/useHotkeys.js +9 -0
  295. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  296. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  297. package/dist/hooks/useInputStatusIcon.js +169 -0
  298. package/dist/hooks/useKeyboardHint.d.ts +1 -1
  299. package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
  300. package/dist/hooks/useKeyboardHint.js +4 -2
  301. package/dist/hooks/useListFocus.d.ts +39 -1
  302. package/dist/hooks/useListFocus.d.ts.map +1 -1
  303. package/dist/hooks/useListFocus.js +54 -9
  304. package/dist/i18n/InternationalizationContext.d.ts +1 -0
  305. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  306. package/dist/i18n/InternationalizationContext.js +3 -0
  307. package/dist/i18n/InternationalizationProvider.d.ts +8 -1
  308. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  309. package/dist/i18n/InternationalizationProvider.js +5 -1
  310. package/dist/i18n/getLocaleDirection.d.ts +18 -0
  311. package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
  312. package/dist/i18n/getLocaleDirection.js +29 -0
  313. package/dist/i18n/index.d.ts +6 -0
  314. package/dist/i18n/index.d.ts.map +1 -1
  315. package/dist/i18n/index.js +7 -1
  316. package/dist/i18n/useDirection.d.ts +2 -0
  317. package/dist/i18n/useDirection.d.ts.map +1 -0
  318. package/dist/i18n/useDirection.js +27 -0
  319. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  320. package/dist/theme/derivedVarRegistry.js +13 -0
  321. package/dist/theme/index.d.ts +3 -3
  322. package/dist/theme/index.d.ts.map +1 -1
  323. package/dist/theme/types.d.ts +39 -2
  324. package/dist/theme/types.d.ts.map +1 -1
  325. package/dist/utils/index.d.ts +1 -0
  326. package/dist/utils/index.d.ts.map +1 -1
  327. package/dist/utils/index.js +2 -1
  328. package/dist/utils/plainDate.d.ts +17 -0
  329. package/dist/utils/plainDate.d.ts.map +1 -1
  330. package/dist/utils/plainDate.js +23 -4
  331. package/dist/utils/rtlStyles.d.ts +24 -0
  332. package/dist/utils/rtlStyles.d.ts.map +1 -0
  333. package/dist/utils/rtlStyles.js +27 -0
  334. package/locales/en.json +120 -0
  335. package/locales/pseudo.json +90 -0
  336. package/package.json +7 -2
  337. package/src/Avatar/Avatar.doc.mjs +50 -3
  338. package/src/Avatar/Avatar.test.tsx +218 -0
  339. package/src/Avatar/Avatar.tsx +285 -79
  340. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  341. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  342. package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
  343. package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
  344. package/src/AvatarGroup/AvatarGroup.tsx +58 -3
  345. package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
  346. package/src/Banner/Banner.tsx +6 -6
  347. package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
  348. package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
  349. package/src/Breadcrumbs/index.ts +4 -0
  350. package/src/Button/Button.doc.mjs +0 -4
  351. package/src/Button/Button.test.tsx +16 -0
  352. package/src/Button/Button.tsx +6 -4
  353. package/src/Calendar/Calendar.test.tsx +170 -20
  354. package/src/Calendar/Calendar.tsx +73 -16
  355. package/src/Calendar/dayCellUtils.test.ts +18 -18
  356. package/src/Calendar/dayCellUtils.ts +2 -2
  357. package/src/Calendar/styles.ts +33 -39
  358. package/src/Card/Card.tsx +1 -1
  359. package/src/Carousel/Carousel.tsx +25 -6
  360. package/src/Chat/ChatComposer.doc.mjs +2 -2
  361. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  362. package/src/Chat/ChatComposerInput.tsx +2 -2
  363. package/src/Chat/ChatDictationButton.tsx +7 -1
  364. package/src/Chat/ChatLayout.tsx +4 -4
  365. package/src/Chat/ChatMessageBubble.tsx +15 -10
  366. package/src/Chat/ChatSystemMessage.test.tsx +5 -0
  367. package/src/Chat/ChatToolCalls.tsx +9 -2
  368. package/src/Chat/useTriggerMenu.tsx +1 -1
  369. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  370. package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
  371. package/src/CheckboxInput/CheckboxInput.tsx +21 -6
  372. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  373. package/src/CheckboxList/CheckboxList.test.tsx +94 -3
  374. package/src/CheckboxList/CheckboxListItem.tsx +17 -10
  375. package/src/Citation/Citation.doc.mjs +4 -3
  376. package/src/Citation/Citation.test.tsx +97 -0
  377. package/src/Citation/Citation.tsx +43 -11
  378. package/src/CodeBlock/CodeBlock.test.tsx +17 -0
  379. package/src/CodeBlock/CodeBlock.tsx +38 -11
  380. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  381. package/src/Collapsible/Collapsible.test.tsx +7 -0
  382. package/src/Collapsible/Collapsible.tsx +16 -6
  383. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  384. package/src/CommandPalette/CommandPalette.tsx +41 -2
  385. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  386. package/src/ContextMenu/ContextMenu.test.tsx +59 -2
  387. package/src/ContextMenu/ContextMenu.tsx +22 -11
  388. package/src/ContextMenu/index.ts +5 -0
  389. package/src/DateInput/DateInput.doc.mjs +25 -0
  390. package/src/DateInput/DateInput.test.tsx +230 -0
  391. package/src/DateInput/DateInput.tsx +51 -29
  392. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  393. package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
  394. package/src/DateRangeInput/DateRangeInput.tsx +42 -30
  395. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  396. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  397. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  398. package/src/Divider/Divider.test.tsx +32 -8
  399. package/src/Divider/Divider.tsx +14 -1
  400. package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
  401. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  402. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
  403. package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
  404. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
  405. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
  406. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +9 -3
  407. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +20 -2
  408. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  409. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +663 -0
  410. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +561 -0
  411. package/src/DropdownMenu/index.ts +16 -0
  412. package/src/DropdownMenu/menuItemHover.ts +40 -0
  413. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  414. package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
  415. package/src/Field/Field.doc.mjs +4 -0
  416. package/src/Field/Field.tsx +14 -9
  417. package/src/Field/FieldLabel.test.tsx +25 -0
  418. package/src/Field/FieldLabel.tsx +12 -3
  419. package/src/Field/inputStyles.stylex.ts +2 -0
  420. package/src/FieldStatus/FieldStatus.doc.mjs +1 -0
  421. package/src/FieldStatus/FieldStatus.test.tsx +133 -0
  422. package/src/FieldStatus/FieldStatus.tsx +61 -4
  423. package/src/FileInput/FileInput.doc.mjs +23 -2
  424. package/src/FileInput/FileInput.test.tsx +104 -13
  425. package/src/FileInput/FileInput.tsx +106 -79
  426. package/src/Heading/Heading.tsx +2 -1
  427. package/src/HoverCard/useHoverCard.tsx +15 -3
  428. package/src/Icon/Icon.doc.mjs +13 -0
  429. package/src/Icon/Icon.test.tsx +89 -0
  430. package/src/Icon/Icon.tsx +51 -3
  431. package/src/Item/Item.doc.mjs +5 -0
  432. package/src/Item/Item.test.tsx +88 -0
  433. package/src/Item/Item.tsx +57 -11
  434. package/src/Layer/layerAnimations.stylex.ts +23 -0
  435. package/src/Lightbox/Lightbox.test.tsx +33 -0
  436. package/src/Lightbox/Lightbox.tsx +30 -10
  437. package/src/List/List.test.tsx +17 -29
  438. package/src/List/List.tsx +6 -1
  439. package/src/List/ListItem.doc.mjs +12 -0
  440. package/src/List/ListItem.tsx +13 -0
  441. package/src/Markdown/Markdown.test.tsx +21 -0
  442. package/src/Markdown/Markdown.tsx +4 -0
  443. package/src/MetadataList/MetadataList.test.tsx +24 -0
  444. package/src/MetadataList/MetadataList.tsx +6 -2
  445. package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
  446. package/src/MultiSelector/MultiSelector.test.tsx +402 -0
  447. package/src/MultiSelector/MultiSelector.tsx +126 -64
  448. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  449. package/src/NumberInput/NumberInput.doc.mjs +21 -0
  450. package/src/NumberInput/NumberInput.test.tsx +71 -0
  451. package/src/NumberInput/NumberInput.tsx +35 -26
  452. package/src/Outline/Outline.test.tsx +12 -12
  453. package/src/Outline/Outline.tsx +2 -2
  454. package/src/Pagination/Pagination.tsx +11 -3
  455. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  456. package/src/PowerSearch/PowerSearch.test.tsx +23 -0
  457. package/src/PowerSearch/PowerSearch.tsx +10 -1
  458. package/src/ProgressBar/ProgressBar.test.tsx +34 -0
  459. package/src/ProgressBar/ProgressBar.tsx +16 -1
  460. package/src/RadioList/RadioList.doc.mjs +6 -0
  461. package/src/RadioList/RadioList.test.tsx +26 -4
  462. package/src/RadioList/RadioList.tsx +2 -2
  463. package/src/RadioList/RadioListItem.tsx +12 -5
  464. package/src/Resizable/ResizeHandle.test.tsx +94 -0
  465. package/src/Resizable/ResizeHandle.tsx +70 -20
  466. package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
  467. package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
  468. package/src/Selector/Selector.doc.mjs +15 -0
  469. package/src/Selector/Selector.test.tsx +370 -0
  470. package/src/Selector/Selector.tsx +88 -20
  471. package/src/SideNav/SideNav.tsx +1 -8
  472. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  473. package/src/SideNav/SideNavItem.tsx +5 -3
  474. package/src/Skeleton/Skeleton.test.tsx +16 -0
  475. package/src/Skeleton/Skeleton.tsx +13 -1
  476. package/src/Slider/Slider.doc.mjs +6 -0
  477. package/src/Slider/Slider.test.tsx +240 -12
  478. package/src/Slider/Slider.tsx +96 -23
  479. package/src/Spinner/Spinner.test.tsx +10 -8
  480. package/src/Spinner/Spinner.tsx +15 -5
  481. package/src/Switch/Switch.doc.mjs +142 -42
  482. package/src/Switch/Switch.test.tsx +111 -0
  483. package/src/Switch/Switch.tsx +149 -32
  484. package/src/TabList/Tab.tsx +2 -2
  485. package/src/TabList/TabList.doc.mjs +0 -6
  486. package/src/TabList/TabList.test.tsx +3 -15
  487. package/src/TabList/TabList.tsx +6 -17
  488. package/src/TabList/TabListContext.ts +0 -6
  489. package/src/TabList/TabMenu.tsx +2 -2
  490. package/src/Table/BaseTable.tsx +34 -2
  491. package/src/Table/Table.doc.mjs +11 -0
  492. package/src/Table/Table.test.tsx +85 -0
  493. package/src/Table/TableCell.tsx +3 -3
  494. package/src/Table/TableHeaderCell.tsx +3 -3
  495. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  496. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
  497. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +27 -18
  498. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  499. package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
  500. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +38 -9
  501. package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
  502. package/src/Table/types.ts +33 -0
  503. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  504. package/src/Text/Heading.doc.mjs +3 -3
  505. package/src/Text/Text.doc.mjs +1 -1
  506. package/src/Text/Text.test.tsx +42 -0
  507. package/src/Text/Text.tsx +25 -1
  508. package/src/Text/index.ts +2 -6
  509. package/src/TextArea/TextArea.doc.mjs +23 -2
  510. package/src/TextArea/TextArea.test.tsx +132 -4
  511. package/src/TextArea/TextArea.tsx +161 -67
  512. package/src/TextInput/TextInput.doc.mjs +21 -0
  513. package/src/TextInput/TextInput.test.tsx +150 -0
  514. package/src/TextInput/TextInput.tsx +28 -25
  515. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  516. package/src/Thumbnail/Thumbnail.test.tsx +24 -1
  517. package/src/Thumbnail/Thumbnail.tsx +28 -35
  518. package/src/TimeInput/TimeInput.doc.mjs +21 -0
  519. package/src/TimeInput/TimeInput.test.tsx +23 -0
  520. package/src/TimeInput/TimeInput.tsx +24 -25
  521. package/src/Timestamp/Timestamp.doc.mjs +32 -6
  522. package/src/Timestamp/Timestamp.test.tsx +371 -0
  523. package/src/Timestamp/Timestamp.tsx +96 -93
  524. package/src/Timestamp/formatInstant.ts +218 -0
  525. package/src/Timestamp/index.ts +4 -0
  526. package/src/Timestamp/tooltipEntries.test.ts +552 -0
  527. package/src/Timestamp/tooltipEntries.ts +210 -0
  528. package/src/Toast/ToastViewport.test.tsx +218 -8
  529. package/src/Toast/ToastViewport.tsx +71 -12
  530. package/src/ToggleButton/ToggleButton.test.tsx +24 -0
  531. package/src/ToggleButton/ToggleButton.tsx +19 -1
  532. package/src/Token/Token.test.tsx +166 -15
  533. package/src/Token/Token.tsx +104 -47
  534. package/src/Token/TokenLink.tsx +107 -0
  535. package/src/Token/index.ts +1 -1
  536. package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
  537. package/src/Tokenizer/Tokenizer.test.tsx +23 -0
  538. package/src/Tokenizer/Tokenizer.tsx +14 -2
  539. package/src/Tooltip/Tooltip.test.tsx +46 -0
  540. package/src/Tooltip/useTooltip.tsx +20 -0
  541. package/src/TopNav/TopNav.test.tsx +93 -2
  542. package/src/TopNav/TopNavItem.doc.mjs +3 -3
  543. package/src/TopNav/TopNavItem.tsx +35 -6
  544. package/src/TopNav/TopNavMegaMenu.tsx +26 -2
  545. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
  546. package/src/TreeList/TreeList.doc.mjs +6 -0
  547. package/src/TreeList/TreeList.test.tsx +50 -10
  548. package/src/TreeList/TreeList.tsx +5 -0
  549. package/src/TreeList/TreeListBranches.tsx +8 -6
  550. package/src/TreeList/TreeListItem.tsx +33 -11
  551. package/src/Typeahead/BaseTypeahead.tsx +42 -15
  552. package/src/Typeahead/Typeahead.doc.mjs +13 -0
  553. package/src/Typeahead/Typeahead.test.tsx +112 -0
  554. package/src/Typeahead/Typeahead.tsx +17 -1
  555. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  556. package/src/__tests__/babelPluginAddExtensions.test.ts +190 -0
  557. package/src/__tests__/forcedColors.ts +60 -0
  558. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  559. package/src/doc-mjs.d.ts +19 -0
  560. package/src/hooks/containerReveal.pool.stylex.ts +464 -0
  561. package/src/hooks/index.ts +13 -0
  562. package/src/hooks/isRtlElement.ts +27 -0
  563. package/src/hooks/useAnnounce.test.tsx +75 -2
  564. package/src/hooks/useAnnounce.ts +47 -1
  565. package/src/hooks/useContainerReveal.test.tsx +116 -0
  566. package/src/hooks/useContainerReveal.ts +180 -0
  567. package/src/hooks/useFocusTrap.test.tsx +104 -0
  568. package/src/hooks/useFocusTrap.ts +61 -12
  569. package/src/hooks/useGridFocus.doc.mjs +3 -3
  570. package/src/hooks/useGridFocus.test.tsx +41 -0
  571. package/src/hooks/useGridFocus.ts +21 -10
  572. package/src/hooks/useHotkeys.ts +9 -0
  573. package/src/hooks/useInputStatusIcon.test.tsx +221 -0
  574. package/src/hooks/useInputStatusIcon.tsx +235 -0
  575. package/src/hooks/useKeyboardHint.test.tsx +22 -0
  576. package/src/hooks/useKeyboardHint.tsx +6 -2
  577. package/src/hooks/useListFocus.doc.mjs +25 -3
  578. package/src/hooks/useListFocus.test.tsx +153 -1
  579. package/src/hooks/useListFocus.ts +102 -9
  580. package/src/i18n/InternationalizationContext.ts +4 -0
  581. package/src/i18n/InternationalizationProvider.tsx +12 -2
  582. package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
  583. package/src/i18n/__tests__/useDirection.test.tsx +66 -0
  584. package/src/i18n/getLocaleDirection.ts +29 -0
  585. package/src/i18n/index.ts +6 -0
  586. package/src/i18n/useDirection.ts +29 -0
  587. package/src/reset.css +0 -26
  588. package/src/reset.test.ts +60 -0
  589. package/src/theme/derivedVarRegistry.test.ts +1 -0
  590. package/src/theme/derivedVarRegistry.ts +6 -0
  591. package/src/theme/generateThemeRules.test.ts +42 -0
  592. package/src/theme/index.ts +4 -8
  593. package/src/theme/types.ts +43 -13
  594. package/src/utils/index.ts +2 -0
  595. package/src/utils/plainDate.test.ts +24 -6
  596. package/src/utils/plainDate.ts +18 -4
  597. package/src/utils/rtlStyles.ts +27 -0
  598. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +0 -9
  599. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +0 -1
  600. package/dist/Thumbnail/thumbnail.markers.stylex.js +0 -14
  601. package/src/Thumbnail/thumbnail.markers.stylex.ts +0 -12
@@ -19,6 +19,9 @@ import userEvent from '@testing-library/user-event';
19
19
  import {getButton, queryButton} from '../__tests__/fastRoleQueries';
20
20
  import {DateRangeInput} from './DateRangeInput';
21
21
  import type {DateRange} from './DateRangeInput';
22
+ import {Icon} from '../Icon';
23
+ import {defineTheme} from '../theme/defineTheme';
24
+ import {generateThemeCSSFlat} from '../theme/generateThemeRules';
22
25
 
23
26
  describe('DateRangeInput', () => {
24
27
  it('renders with label', () => {
@@ -471,3 +474,140 @@ describe('DateRangeInput', () => {
471
474
  });
472
475
  });
473
476
  });
477
+
478
+ describe('DateRangeInput statusVariant forwarding', () => {
479
+ it('defaults to attached (status renders with data-variant="attached")', () => {
480
+ const {container} = render(
481
+ <DateRangeInput
482
+ label="Range"
483
+ value={null}
484
+ onChange={() => {}}
485
+ status={{type: 'error', message: 'Required'}}
486
+ />,
487
+ );
488
+ expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
489
+ 'data-variant',
490
+ 'attached',
491
+ );
492
+ });
493
+
494
+ it('forwards statusVariant="detached" to the underlying Field status', () => {
495
+ const {container} = render(
496
+ <DateRangeInput
497
+ label="Range"
498
+ value={null}
499
+ onChange={() => {}}
500
+ status={{type: 'error', message: 'Required'}}
501
+ statusVariant="detached"
502
+ />,
503
+ );
504
+ expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
505
+ 'data-variant',
506
+ 'detached',
507
+ );
508
+ });
509
+ });
510
+
511
+ describe('DateRangeInput icon theme targets', () => {
512
+ const RANGE: DateRange = {start: '2026-03-15', end: '2026-03-22'};
513
+
514
+ // Resolve a glyph span (the astryx-icon element) inside a given button,
515
+ // independent of the theme target class.
516
+ const iconIn = (button: HTMLElement): HTMLElement => {
517
+ const icon = button.querySelector('.astryx-icon');
518
+ if (icon == null) {
519
+ throw new Error('icon not found');
520
+ }
521
+ return icon as HTMLElement;
522
+ };
523
+
524
+ it('renders astryx-date-range-input-clear-icon on the clear glyph', () => {
525
+ render(
526
+ <DateRangeInput
527
+ label="Range"
528
+ value={RANGE}
529
+ onChange={() => {}}
530
+ hasClear
531
+ />,
532
+ );
533
+ // The stable target lands on the icon element itself (not the button), so a
534
+ // theme can restyle just this glyph (color, size, hover) via defineTheme —
535
+ // a button-level target could not reach the icon's own color/size.
536
+ const icon = iconIn(getButton('Clear Range'));
537
+ expect(icon).toHaveClass('astryx-date-range-input-clear-icon');
538
+ expect(icon).toHaveClass('astryx-icon');
539
+ });
540
+
541
+ it('renders astryx-date-range-input-toggle-icon on the calendar-toggle glyph, reflecting state', () => {
542
+ render(<DateRangeInput label="Range" value={null} onChange={() => {}} />);
543
+ const icon = iconIn(getButton('Open calendar'));
544
+ expect(icon).toHaveClass('astryx-date-range-input-toggle-icon');
545
+ expect(icon).toHaveClass('astryx-icon');
546
+ // Closed by default → data-state="collapsed".
547
+ expect(icon).toHaveAttribute('data-state', 'collapsed');
548
+ });
549
+
550
+ it('renders the default icons (secondary color, sm size) byte-identically', () => {
551
+ // Pixel-identical default guard: the glyphs must carry the exact same
552
+ // StyleX color/size classes as a standalone secondary/sm icon. The added
553
+ // target class is purely additive — it changes nothing until a theme
554
+ // targets it.
555
+ render(
556
+ <DateRangeInput
557
+ label="Range"
558
+ value={RANGE}
559
+ onChange={() => {}}
560
+ hasClear
561
+ />,
562
+ );
563
+ const clearIcon = iconIn(getButton('Clear Range'));
564
+
565
+ const {container: refContainer} = render(
566
+ <Icon icon="close" size="sm" color="secondary" />,
567
+ );
568
+ const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
569
+
570
+ const styleClasses = (el: HTMLElement) =>
571
+ el.className
572
+ .split(' ')
573
+ .filter(
574
+ c =>
575
+ c !== 'astryx-date-range-input-clear-icon' &&
576
+ c !== 'astryx-date-range-input-toggle-icon',
577
+ )
578
+ .sort();
579
+
580
+ expect(styleClasses(clearIcon)).toEqual(styleClasses(refIcon));
581
+ });
582
+
583
+ it('exposes the icon targets so a theme reaches icon color, size, and hover', () => {
584
+ // jsdom cannot resolve the @layer cascade, so the DOM-class assertions
585
+ // above (targets land on the icon elements) plus this generation assertion
586
+ // (the theme emits same-element icon rules in @layer astryx-theme) together
587
+ // prove the seam: a same-element theme rule wins over the icon's own
588
+ // base-layer color/size.
589
+ const theme = defineTheme({
590
+ name: 'date-range-input-icon-test',
591
+ components: {
592
+ 'date-range-input-clear-icon': {
593
+ base: {
594
+ width: '12px',
595
+ height: '12px',
596
+ fontSize: '12px',
597
+ color: 'var(--color-icon-secondary)',
598
+ ':hover': {color: 'var(--color-icon-primary)'},
599
+ },
600
+ },
601
+ 'date-range-input-toggle-icon': {
602
+ base: {width: '14px', height: '14px', fontSize: '14px'},
603
+ },
604
+ },
605
+ });
606
+ const css = generateThemeCSSFlat(theme);
607
+ expect(css).toContain('.astryx-date-range-input-clear-icon');
608
+ expect(css).toContain('.astryx-date-range-input-toggle-icon');
609
+ expect(css).toContain(':hover');
610
+ expect(css).toContain('12px');
611
+ expect(css).toContain('14px');
612
+ });
613
+ });
@@ -25,7 +25,6 @@ import {
25
25
  DATE_FORMAT_SHORT,
26
26
  DATE_FORMAT_SHORT_WITH_YEAR,
27
27
  } from '../utils/plainDate';
28
- import type {IconName} from '../Icon';
29
28
  import {
30
29
  colorVars,
31
30
  sizeVars,
@@ -38,11 +37,11 @@ import {
38
37
  import {
39
38
  Field,
40
39
  type InputStatus,
41
- type InputStatusType,
42
40
  inputWrapperStyles,
43
41
  inputStatusBorderStyles,
44
42
  inputStatusHoverShadowStyles,
45
43
  inputStatusFocusWithinStyles,
44
+ type FieldStatusVariant,
46
45
  } from '../Field';
47
46
  import {Icon} from '../Icon';
48
47
  import {Spinner} from '../Spinner';
@@ -53,6 +52,7 @@ import {mergeProps} from '../utils';
53
52
  import type {BaseProps} from '../BaseProps';
54
53
  import type {SizeValue} from '../utils/types';
55
54
  import {useSize} from '../SizeContext/SizeContext';
55
+ import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
56
56
  import {themeProps} from '../utils/themeProps';
57
57
  import {useTranslator} from '../i18n';
58
58
 
@@ -127,9 +127,9 @@ const styles = stylex.create({
127
127
  flexDirection: 'column',
128
128
  gap: spacingVars['--spacing-1'],
129
129
  padding: spacingVars['--spacing-3'],
130
- borderRightWidth: borderVars['--border-width'],
131
- borderRightStyle: 'solid',
132
- borderRightColor: colorVars['--color-border-emphasized'],
130
+ borderInlineEndWidth: borderVars['--border-width'],
131
+ borderInlineEndStyle: 'solid',
132
+ borderInlineEndColor: colorVars['--color-border-emphasized'],
133
133
  minWidth: 140,
134
134
  },
135
135
  presetButton: {
@@ -330,6 +330,14 @@ export interface DateRangeInputProps extends Omit<
330
330
  * Status indicator for the input.
331
331
  */
332
332
  status?: InputStatus;
333
+ /**
334
+ * How the status message is placed relative to the input.
335
+ * - 'attached': message overlaps directly below the input (bordered treatment)
336
+ * - 'detached': message floats below as a separate element with spacing
337
+ * - 'tooltip': no message box; the status icon becomes a focusable info-tip button that reveals the message on hover, keyboard focus, or tap
338
+ * @default 'attached'
339
+ */
340
+ statusVariant?: FieldStatusVariant;
333
341
 
334
342
  /**
335
343
  * Width of the field. Numbers are treated as pixels, strings are used as-is
@@ -385,6 +393,7 @@ export function DateRangeInput({
385
393
  placeholder: placeholderFromProps,
386
394
  size: sizeProp,
387
395
  status,
396
+ statusVariant = 'attached',
388
397
  labelTooltip,
389
398
  numberOfMonths = 2,
390
399
  width,
@@ -422,25 +431,19 @@ export function DateRangeInput({
422
431
  isEnabled: showsDisabledMessage,
423
432
  });
424
433
 
425
- const statusIconMap: Record<InputStatusType, IconName> = {
426
- warning: 'warning',
427
- error: 'error',
428
- success: 'success',
429
- };
430
-
431
- const statusIconColorMap: Record<
432
- InputStatusType,
433
- 'warning' | 'error' | 'success'
434
- > = {
435
- warning: 'warning',
436
- error: 'error',
437
- success: 'success',
438
- };
434
+ const {statusIcon, describedBy: statusTooltipDescribedBy} =
435
+ useInputStatusIcon({
436
+ status,
437
+ statusVariant,
438
+ });
439
439
 
440
440
  const ariaDescribedBy =
441
441
  [
442
442
  description ? descriptionID : null,
443
- status?.message ? statusMessageID : null,
443
+ statusVariant !== 'tooltip' && status?.message ? statusMessageID : null,
444
+ // The tooltip variant renders no message box; describe the input by the
445
+ // tooltip's content instead so the status is still announced.
446
+ statusTooltipDescribedBy,
444
447
  showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
445
448
  ]
446
449
  .filter(Boolean)
@@ -529,6 +532,7 @@ export function DateRangeInput({
529
532
  }
530
533
  : undefined
531
534
  }
535
+ statusVariant={statusVariant}
532
536
  labelTooltip={labelTooltip}
533
537
  width={width}>
534
538
  <div
@@ -550,7 +554,9 @@ export function DateRangeInput({
550
554
  sizeStyles[size],
551
555
  isEffectivelyDisabled && inputWrapperStyles.disabled,
552
556
  status && inputStatusBorderStyles[status.type],
553
- status && inputStatusHoverShadowStyles[status.type],
557
+ status &&
558
+ !isEffectivelyDisabled &&
559
+ inputStatusHoverShadowStyles[status.type],
554
560
  status && inputStatusFocusWithinStyles[status.type],
555
561
  xstyle,
556
562
  ),
@@ -571,7 +577,14 @@ export function DateRangeInput({
571
577
  styles.iconButton,
572
578
  isEffectivelyDisabled && styles.iconButtonDisabled,
573
579
  )}>
574
- <Icon icon="calendar" size="sm" color="secondary" />
580
+ <Icon
581
+ icon="calendar"
582
+ size="sm"
583
+ color="secondary"
584
+ {...themeProps('date-range-input-toggle-icon', {
585
+ state: popover.isOpen ? 'expanded' : 'collapsed',
586
+ })}
587
+ />
575
588
  </button>
576
589
  <button
577
590
  ref={ref}
@@ -604,17 +617,16 @@ export function DateRangeInput({
604
617
  onClick={handleClear}
605
618
  aria-label={t('@astryx.dateInput.clear', {label})}
606
619
  {...stylex.props(styles.iconButton)}>
607
- <Icon icon="close" size="sm" color="secondary" />
620
+ <Icon
621
+ icon="close"
622
+ size="sm"
623
+ color="secondary"
624
+ {...themeProps('date-range-input-clear-icon')}
625
+ />
608
626
  </button>
609
627
  )}
610
628
  {isBusy && <Spinner size="sm" />}
611
- {status && (
612
- <Icon
613
- icon={statusIconMap[status.type]}
614
- size="md"
615
- color={statusIconColorMap[status.type]}
616
- />
617
- )}
629
+ {statusIcon}
618
630
  </div>
619
631
  {popover.render(
620
632
  <div {...stylex.props(styles.popoverLayout)}>
@@ -173,6 +173,12 @@ export const docs = {
173
173
  description: 'Number of months displayed simultaneously in the calendar.',
174
174
  default: '1',
175
175
  },
176
+ {
177
+ name: 'width',
178
+ type: 'SizeValue',
179
+ description:
180
+ 'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
181
+ },
176
182
  {
177
183
  name: 'xstyle',
178
184
  type: 'StyleXStyles',
@@ -183,6 +189,14 @@ export const docs = {
183
189
  theming: {
184
190
  targets: [
185
191
  {className: 'astryx-date-time-input', visualProps: ['size', 'status']},
192
+ {
193
+ className: 'astryx-date-time-input-date-segment',
194
+ visualProps: ['size', 'status'],
195
+ },
196
+ {
197
+ className: 'astryx-date-time-input-time-segment',
198
+ visualProps: ['size', 'status'],
199
+ },
186
200
  ],
187
201
  },
188
202
  usage: {
@@ -469,11 +483,18 @@ export const docsZh = {
469
483
  description:
470
484
  '用于布局自定义的 StyleX 样式。必须是 stylex.create() 的值。',
471
485
  },
472
-
473
486
  ],
474
487
  theming: {
475
488
  targets: [
476
489
  {className: 'astryx-date-time-input', visualProps: ['size', 'status']},
490
+ {
491
+ className: 'astryx-date-time-input-date-segment',
492
+ visualProps: ['size', 'status'],
493
+ },
494
+ {
495
+ className: 'astryx-date-time-input-time-segment',
496
+ visualProps: ['size', 'status'],
497
+ },
477
498
  ],
478
499
  },
479
500
  };
@@ -15,6 +15,8 @@ import userEvent from '@testing-library/user-event';
15
15
  import {getButton, queryButton} from '../__tests__/fastRoleQueries';
16
16
  import {DateTimeInput} from './DateTimeInput';
17
17
  import type {ISODateTimeString} from './DateTimeInput';
18
+ import {defineTheme} from '../theme/defineTheme';
19
+ import {generateThemeCSSFlat} from '../theme/generateThemeRules';
18
20
 
19
21
  describe('DateTimeInput', () => {
20
22
  it('renders with label', () => {
@@ -814,4 +816,114 @@ describe('DateTimeInput', () => {
814
816
  expect(onChange.mock.calls[0][0]).toContain('14:31');
815
817
  });
816
818
  });
819
+ // ===========================================================================
820
+ // Segment theme targets (#4075)
821
+ // ===========================================================================
822
+
823
+ describe('segment theme targets', () => {
824
+ // The root only publishes `astryx-date-time-input`; the date and time
825
+ // wrappers were anonymous nodes carrying hashed atomic classes only, so a
826
+ // theme that restyles input geometry through the text-input/date-input/
827
+ // time-input targets could not reach them and DateTimeInput rendered
828
+ // shorter than every other input under that theme.
829
+
830
+ it('renders the date segment target on the date wrapper', () => {
831
+ render(<DateTimeInput label="Meeting" onChange={() => {}} />);
832
+ const wrapper = screen
833
+ .getByLabelText('Meeting')
834
+ .closest('.astryx-date-time-input-date-segment');
835
+
836
+ expect(wrapper).not.toBeNull();
837
+ // The wrapper is the input's own container, not an ancestor further up.
838
+ expect(wrapper).toBe(screen.getByLabelText('Meeting').parentElement);
839
+ });
840
+
841
+ it('renders the time segment target on the time wrapper', () => {
842
+ render(<DateTimeInput label="Meeting" onChange={() => {}} />);
843
+ const wrapper = screen
844
+ .getByLabelText('Meeting time')
845
+ .closest('.astryx-date-time-input-time-segment');
846
+
847
+ expect(wrapper).not.toBeNull();
848
+ expect(wrapper).toBe(screen.getByLabelText('Meeting time').parentElement);
849
+ });
850
+
851
+ it('reflects size on both segments so themes can restyle geometry', () => {
852
+ render(<DateTimeInput label="Meeting" size="lg" onChange={() => {}} />);
853
+
854
+ const date = screen
855
+ .getByLabelText('Meeting')
856
+ .closest('.astryx-date-time-input-date-segment');
857
+ const time = screen
858
+ .getByLabelText('Meeting time')
859
+ .closest('.astryx-date-time-input-time-segment');
860
+
861
+ expect(date).toHaveAttribute('data-size', 'lg');
862
+ expect(date).toHaveClass('lg');
863
+ expect(time).toHaveAttribute('data-size', 'lg');
864
+ expect(time).toHaveClass('lg');
865
+ });
866
+
867
+ it('reflects status on both segments, mirroring the root', () => {
868
+ render(
869
+ <DateTimeInput
870
+ label="Meeting"
871
+ status={{type: 'error', message: 'Required'}}
872
+ onChange={() => {}}
873
+ />,
874
+ );
875
+
876
+ const date = screen
877
+ .getByLabelText('Meeting')
878
+ .closest('.astryx-date-time-input-date-segment');
879
+ const time = screen
880
+ .getByLabelText('Meeting time')
881
+ .closest('.astryx-date-time-input-time-segment');
882
+
883
+ expect(date).toHaveAttribute('data-status', 'error');
884
+ expect(time).toHaveAttribute('data-status', 'error');
885
+ });
886
+
887
+ it('omits data-status when there is no status, like the root does', () => {
888
+ render(<DateTimeInput label="Meeting" onChange={() => {}} />);
889
+
890
+ const date = screen
891
+ .getByLabelText('Meeting')
892
+ .closest('.astryx-date-time-input-date-segment');
893
+
894
+ expect(date).not.toHaveAttribute('data-status');
895
+ });
896
+
897
+ it('keeps the root target intact', () => {
898
+ const {container} = render(
899
+ <DateTimeInput label="Meeting" onChange={() => {}} />,
900
+ );
901
+ // Additive change — the existing root target still renders.
902
+ expect(container.querySelector('.astryx-date-time-input')).not.toBeNull();
903
+ });
904
+
905
+ it('exposes both segments as themeable defineTheme targets', () => {
906
+ // jsdom cannot resolve the @layer cascade, so the generated CSS is what
907
+ // proves a theme can actually reach these nodes.
908
+ const theme = defineTheme({
909
+ name: 'date-time-input-segments-test',
910
+ components: {
911
+ 'date-time-input-date-segment': {
912
+ base: {blockSize: 'var(--size-element-lg)'},
913
+ lg: {paddingInline: 'var(--spacing-4)'},
914
+ },
915
+ 'date-time-input-time-segment': {
916
+ base: {blockSize: 'var(--size-element-lg)'},
917
+ },
918
+ },
919
+ });
920
+ const css = generateThemeCSSFlat(theme);
921
+
922
+ expect(css).toContain('.astryx-date-time-input-date-segment {');
923
+ expect(css).toContain('.astryx-date-time-input-date-segment.lg');
924
+ expect(css).toContain('.astryx-date-time-input-time-segment {');
925
+ expect(css).toContain('block-size: var(--size-element-lg)');
926
+ expect(css).toContain('padding-inline: var(--spacing-4)');
927
+ });
928
+ });
817
929
  });
@@ -27,7 +27,6 @@ import {
27
27
  type KeyboardEvent,
28
28
  } from 'react';
29
29
  import * as stylex from '@stylexjs/stylex';
30
- import type {IconName} from '../Icon';
31
30
  import {
32
31
  colorVars,
33
32
  sizeVars,
@@ -40,7 +39,6 @@ import {
40
39
  import {
41
40
  Field,
42
41
  type InputStatus,
43
- type InputStatusType,
44
42
  inputWrapperStyles,
45
43
  inputStatusBorderStyles,
46
44
  inputStatusHoverShadowStyles,
@@ -54,6 +52,7 @@ import {useCalendarConstraints} from '../Calendar/hooks';
54
52
  import {usePopover} from '../Popover';
55
53
  import {useTooltip} from '../Tooltip';
56
54
  import {useInputContainer} from '../hooks/useInputContainer';
55
+ import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
57
56
  import {
58
57
  type ISOTimeString,
59
58
  parseDateInput,
@@ -470,25 +469,21 @@ export function DateTimeInput({
470
469
  isEnabled: showsDisabledMessage,
471
470
  });
472
471
 
473
- const statusIconMap: Record<InputStatusType, IconName> = {
474
- warning: 'warning',
475
- error: 'error',
476
- success: 'success',
477
- };
478
-
479
- const statusIconColorMap: Record<
480
- InputStatusType,
481
- 'warning' | 'error' | 'success'
482
- > = {
483
- warning: 'warning',
484
- error: 'error',
485
- success: 'success',
486
- };
472
+ // DateTimeInput fixes its status presentation to the detached message box,
473
+ // so the shared helper suppresses the on-field icon (the message box carries
474
+ // its own leading glyph). Routed through the helper for consistency with the
475
+ // rest of the bordered input family.
476
+ const {statusIcon, describedBy: statusTooltipDescribedBy} =
477
+ useInputStatusIcon({
478
+ status,
479
+ statusVariant: 'detached',
480
+ });
487
481
 
488
482
  const ariaDescribedBy =
489
483
  [
490
484
  description ? descriptionID : null,
491
485
  status?.message ? statusMessageID : null,
486
+ statusTooltipDescribedBy,
492
487
  showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
493
488
  ]
494
489
  .filter(Boolean)
@@ -890,14 +885,22 @@ export function DateTimeInput({
890
885
  {/* Date input */}
891
886
  <div
892
887
  ref={popover.triggerRef}
893
- {...stylex.props(
894
- inputWrapperStyles.base,
895
- sizeStyles[size],
896
- styles.dateWrapper,
897
- isEffectivelyDisabled && inputWrapperStyles.disabled,
898
- status && inputStatusBorderStyles[status.type],
899
- status && inputStatusHoverShadowStyles[status.type],
900
- status && inputStatusFocusWithinStyles[status.type],
888
+ {...mergeProps(
889
+ themeProps('date-time-input-date-segment', {
890
+ size,
891
+ status: status?.type ?? null,
892
+ }),
893
+ stylex.props(
894
+ inputWrapperStyles.base,
895
+ sizeStyles[size],
896
+ styles.dateWrapper,
897
+ isEffectivelyDisabled && inputWrapperStyles.disabled,
898
+ status && inputStatusBorderStyles[status.type],
899
+ status &&
900
+ !isEffectivelyDisabled &&
901
+ inputStatusHoverShadowStyles[status.type],
902
+ status && inputStatusFocusWithinStyles[status.type],
903
+ ),
901
904
  )}>
902
905
  <button
903
906
  type="button"
@@ -968,13 +971,7 @@ export function DateTimeInput({
968
971
  </button>
969
972
  )}
970
973
  {isBusy && <Spinner size="sm" />}
971
- {status && (
972
- <Icon
973
- icon={statusIconMap[status.type]}
974
- size="md"
975
- color={statusIconColorMap[status.type]}
976
- />
977
- )}
974
+ {statusIcon}
978
975
  </div>
979
976
 
980
977
  {/* Time input */}
@@ -982,14 +979,22 @@ export function DateTimeInput({
982
979
  ref={timeContainerRef}
983
980
  onClick={handleTimeWrapperClick}
984
981
  onMouseUp={handleTimeWrapperMouseUp}
985
- {...stylex.props(
986
- inputWrapperStyles.base,
987
- sizeStyles[size],
988
- styles.timeWrapper,
989
- isEffectivelyDisabled && inputWrapperStyles.disabled,
990
- status && inputStatusBorderStyles[status.type],
991
- status && inputStatusHoverShadowStyles[status.type],
992
- status && inputStatusFocusWithinStyles[status.type],
982
+ {...mergeProps(
983
+ themeProps('date-time-input-time-segment', {
984
+ size,
985
+ status: status?.type ?? null,
986
+ }),
987
+ stylex.props(
988
+ inputWrapperStyles.base,
989
+ sizeStyles[size],
990
+ styles.timeWrapper,
991
+ isEffectivelyDisabled && inputWrapperStyles.disabled,
992
+ status && inputStatusBorderStyles[status.type],
993
+ status &&
994
+ !isEffectivelyDisabled &&
995
+ inputStatusHoverShadowStyles[status.type],
996
+ status && inputStatusFocusWithinStyles[status.type],
997
+ ),
993
998
  )}>
994
999
  <div {...stylex.props(styles.icon)}>
995
1000
  <Icon icon="clock" size="sm" color="secondary" />
@@ -89,25 +89,49 @@ describe('Divider', () => {
89
89
 
90
90
  it('renders vertical divider with label', () => {
91
91
  render(
92
- <Divider
93
- orientation="vertical"
94
- label="Vertical"
95
- data-testid="divider"
96
- />,
92
+ <Divider orientation="vertical" label="Vertical" data-testid="divider" />,
97
93
  );
98
94
  const divider = screen.getByTestId('divider');
99
95
  expect(divider).toHaveAttribute('aria-orientation', 'vertical');
100
96
  expect(screen.getByText('Vertical')).toBeInTheDocument();
101
97
  });
102
98
 
103
- it('renders astryx-* class names for theme targeting', () => {
99
+ it('exposes the label as the accessible name of the separator', () => {
100
+ render(<Divider label="Section" data-testid="divider" />);
101
+ const divider = screen.getByTestId('divider');
102
+ expect(divider).toHaveAttribute('aria-labelledby');
103
+ expect(divider).toHaveAccessibleName('Section');
104
+ });
105
+
106
+ it('names the separator from a ReactNode label via aria-labelledby', () => {
107
+ render(<Divider label={<span>Custom</span>} data-testid="divider" />);
108
+ expect(screen.getByTestId('divider')).toHaveAccessibleName('Custom');
109
+ });
110
+
111
+ it('does not set aria-labelledby without a label', () => {
112
+ render(<Divider data-testid="divider" />);
113
+ expect(screen.getByTestId('divider')).not.toHaveAttribute(
114
+ 'aria-labelledby',
115
+ );
116
+ });
117
+
118
+ it('prefers an explicit aria-label over the rendered label', () => {
104
119
  render(
105
120
  <Divider
106
- variant="strong"
107
- orientation="vertical"
121
+ label="Section"
122
+ aria-label="Custom name"
108
123
  data-testid="divider"
109
124
  />,
110
125
  );
126
+ const divider = screen.getByTestId('divider');
127
+ expect(divider).toHaveAccessibleName('Custom name');
128
+ expect(divider).not.toHaveAttribute('aria-labelledby');
129
+ });
130
+
131
+ it('renders astryx-* class names for theme targeting', () => {
132
+ render(
133
+ <Divider variant="strong" orientation="vertical" data-testid="divider" />,
134
+ );
111
135
  const root = screen.getByTestId('divider');
112
136
  expect(root.className).toContain('astryx-divider');
113
137
  expect(root.className).toContain('strong');