@astryxdesign/core 0.3.0 → 0.4.0

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 (551) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/dist/AlertDialog/AlertDialog.d.ts +10 -2
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +22 -3
  5. package/dist/AppShell/AppShell.d.ts +2 -2
  6. package/dist/AppShell/AppShell.d.ts.map +1 -1
  7. package/dist/AppShell/AppShell.js +40 -9
  8. package/dist/AspectRatio/AspectRatio.d.ts +13 -0
  9. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  10. package/dist/AspectRatio/AspectRatio.js +9 -0
  11. package/dist/Avatar/Avatar.d.ts.map +1 -1
  12. package/dist/Avatar/Avatar.js +33 -20
  13. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  14. package/dist/AvatarGroup/AvatarGroupOverflow.js +2 -3
  15. package/dist/Banner/Banner.d.ts.map +1 -1
  16. package/dist/Banner/Banner.js +15 -14
  17. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  18. package/dist/Breadcrumbs/BreadcrumbItem.js +21 -8
  19. package/dist/Breadcrumbs/index.d.ts +2 -1
  20. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  21. package/dist/Breadcrumbs/index.js +1 -0
  22. package/dist/Button/Button.d.ts.map +1 -1
  23. package/dist/Button/Button.js +11 -15
  24. package/dist/Calendar/Calendar.d.ts.map +1 -1
  25. package/dist/Calendar/Calendar.js +2 -1
  26. package/dist/Calendar/styles.d.ts +0 -2
  27. package/dist/Calendar/styles.d.ts.map +1 -1
  28. package/dist/Calendar/styles.js +0 -2
  29. package/dist/Carousel/Carousel.d.ts.map +1 -1
  30. package/dist/Carousel/Carousel.js +8 -12
  31. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  32. package/dist/Chat/ChatDictationButton.js +2 -1
  33. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  34. package/dist/Chat/ChatLayoutScrollButton.js +3 -1
  35. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  36. package/dist/Chat/ChatSendButton.js +4 -3
  37. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  38. package/dist/Chat/ChatToolCalls.js +17 -17
  39. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  40. package/dist/Chat/useTriggerMenu.js +2 -6
  41. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  42. package/dist/CheckboxInput/CheckboxInput.js +36 -125
  43. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  44. package/dist/ClickableCard/ClickableCard.js +3 -11
  45. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  46. package/dist/CodeBlock/CodeBlock.js +84 -67
  47. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  48. package/dist/Collapsible/Collapsible.js +35 -15
  49. package/dist/CommandPalette/CommandPaletteItem.d.ts +1 -1
  50. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  51. package/dist/CommandPalette/CommandPaletteItem.js +6 -3
  52. package/dist/CommandPalette/CommandPaletteList.js +1 -1
  53. package/dist/ComplexSelector/ComplexSelector.d.ts +1 -1
  54. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  55. package/dist/ComplexSelector/ComplexSelector.js +35 -33
  56. package/dist/ContextMenu/ContextMenu.d.ts +2 -2
  57. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  58. package/dist/ContextMenu/ContextMenu.js +1 -1
  59. package/dist/ContextMenu/index.d.ts +2 -1
  60. package/dist/ContextMenu/index.d.ts.map +1 -1
  61. package/dist/ContextMenu/index.js +1 -0
  62. package/dist/DateInput/DateInput.d.ts +9 -2
  63. package/dist/DateInput/DateInput.d.ts.map +1 -1
  64. package/dist/DateInput/DateInput.js +24 -23
  65. package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
  66. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  67. package/dist/DateRangeInput/DateRangeInput.js +11 -16
  68. package/dist/DateTimeInput/DateTimeInput.d.ts +9 -1
  69. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  70. package/dist/DateTimeInput/DateTimeInput.js +22 -17
  71. package/dist/Dialog/Dialog.d.ts.map +1 -1
  72. package/dist/Dialog/Dialog.js +4 -4
  73. package/dist/DropdownMenu/DropdownMenu.d.ts +33 -8
  74. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  75. package/dist/DropdownMenu/DropdownMenu.js +62 -20
  76. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +8 -11
  77. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  78. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +32 -31
  79. package/dist/DropdownMenu/DropdownMenuDivider.d.ts +25 -0
  80. package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -0
  81. package/dist/DropdownMenu/DropdownMenuDivider.js +66 -0
  82. package/dist/DropdownMenu/DropdownMenuItem.d.ts +15 -2
  83. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  84. package/dist/DropdownMenu/DropdownMenuItem.js +20 -8
  85. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +5 -5
  86. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  87. package/dist/DropdownMenu/DropdownMenuRadioItem.js +24 -67
  88. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  89. package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -8
  90. package/dist/DropdownMenu/index.d.ts +2 -1
  91. package/dist/DropdownMenu/index.d.ts.map +1 -1
  92. package/dist/DropdownMenu/index.js +4 -0
  93. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  94. package/dist/DropdownMenu/renderDropdownItems.js +35 -27
  95. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  96. package/dist/EmptyState/EmptyState.js +9 -5
  97. package/dist/Field/InputClearButton.d.ts +16 -3
  98. package/dist/Field/InputClearButton.d.ts.map +1 -1
  99. package/dist/Field/InputClearButton.js +15 -4
  100. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  101. package/dist/HoverCard/useHoverCard.js +3 -19
  102. package/dist/Indicator/CheckIndicator.d.ts +25 -0
  103. package/dist/Indicator/CheckIndicator.d.ts.map +1 -0
  104. package/dist/Indicator/CheckIndicator.js +155 -0
  105. package/dist/Indicator/CheckboxIndicator.d.ts +22 -0
  106. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -0
  107. package/dist/Indicator/CheckboxIndicator.js +173 -0
  108. package/dist/Indicator/RadioIndicator.d.ts +23 -0
  109. package/dist/Indicator/RadioIndicator.d.ts.map +1 -0
  110. package/dist/Indicator/RadioIndicator.js +137 -0
  111. package/dist/Indicator/index.d.ts +24 -0
  112. package/dist/Indicator/index.d.ts.map +1 -0
  113. package/dist/Indicator/index.js +26 -0
  114. package/dist/Indicator/indicator.markers.stylex.d.ts +16 -0
  115. package/dist/Indicator/indicator.markers.stylex.d.ts.map +1 -0
  116. package/dist/Indicator/indicator.markers.stylex.js +21 -0
  117. package/dist/Indicator/indicatorRegistry.d.ts +71 -0
  118. package/dist/Indicator/indicatorRegistry.d.ts.map +1 -0
  119. package/dist/Indicator/indicatorRegistry.js +93 -0
  120. package/dist/Indicator/types.d.ts +167 -0
  121. package/dist/Indicator/types.d.ts.map +1 -0
  122. package/dist/Indicator/types.js +1 -0
  123. package/dist/Indicator/useIndicator.d.ts +18 -0
  124. package/dist/Indicator/useIndicator.d.ts.map +1 -0
  125. package/dist/Indicator/useIndicator.js +30 -0
  126. package/dist/Item/Item.d.ts.map +1 -1
  127. package/dist/Item/Item.js +4 -8
  128. package/dist/Layer/useLayer.d.ts +14 -0
  129. package/dist/Layer/useLayer.d.ts.map +1 -1
  130. package/dist/Layer/useLayer.js +25 -2
  131. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  132. package/dist/Lightbox/Lightbox.js +56 -53
  133. package/dist/Link/Link.d.ts.map +1 -1
  134. package/dist/Link/Link.js +4 -5
  135. package/dist/MobileNav/MobileNav.js +8 -8
  136. package/dist/MoreMenu/MoreMenu.d.ts +14 -1
  137. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  138. package/dist/MoreMenu/MoreMenu.js +4 -0
  139. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  140. package/dist/MultiSelector/MultiSelector.js +78 -75
  141. package/dist/NumberInput/NumberInput.d.ts +27 -1
  142. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  143. package/dist/NumberInput/NumberInput.js +230 -42
  144. package/dist/Outline/Outline.d.ts.map +1 -1
  145. package/dist/Outline/Outline.js +2 -3
  146. package/dist/Pagination/Pagination.d.ts.map +1 -1
  147. package/dist/Pagination/Pagination.js +61 -63
  148. package/dist/Popover/Popover.d.ts.map +1 -1
  149. package/dist/Popover/Popover.js +6 -8
  150. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  151. package/dist/PowerSearch/PowerSearch.js +1 -1
  152. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  153. package/dist/PowerSearch/PowerSearchEditPopover.js +7 -0
  154. package/dist/ProgressBar/ProgressBar.d.ts +11 -4
  155. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  156. package/dist/ProgressBar/ProgressBar.js +96 -6
  157. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  158. package/dist/RadioList/RadioListItem.js +29 -84
  159. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  160. package/dist/Resizable/ResizeHandle.js +2 -3
  161. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  162. package/dist/SegmentedControl/SegmentedControlItem.js +2 -3
  163. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  164. package/dist/SelectableCard/SelectableCard.js +3 -11
  165. package/dist/Selector/Selector.d.ts +2 -1
  166. package/dist/Selector/Selector.d.ts.map +1 -1
  167. package/dist/Selector/Selector.js +164 -94
  168. package/dist/Selector/hooks.d.ts +18 -6
  169. package/dist/Selector/hooks.d.ts.map +1 -1
  170. package/dist/Selector/hooks.js +57 -40
  171. package/dist/SideNav/SideNav.d.ts.map +1 -1
  172. package/dist/SideNav/SideNav.js +1 -1
  173. package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
  174. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  175. package/dist/SideNav/SideNavCollapseButton.js +29 -14
  176. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  177. package/dist/SideNav/SideNavHeading.js +56 -20
  178. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  179. package/dist/SideNav/SideNavItem.js +28 -22
  180. package/dist/Stack/stack.stylex.d.ts +3 -3
  181. package/dist/Switch/Switch.js +11 -10
  182. package/dist/TabList/Tab.d.ts.map +1 -1
  183. package/dist/TabList/Tab.js +2 -3
  184. package/dist/TabList/TabMenu.d.ts.map +1 -1
  185. package/dist/TabList/TabMenu.js +41 -19
  186. package/dist/Table/BaseTable.d.ts.map +1 -1
  187. package/dist/Table/BaseTable.js +8 -0
  188. package/dist/Table/index.d.ts +1 -1
  189. package/dist/Table/index.d.ts.map +1 -1
  190. package/dist/Table/index.js +1 -1
  191. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
  192. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  193. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +22 -18
  194. package/dist/Table/plugins/rowExpansion/index.d.ts +1 -1
  195. package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -1
  196. package/dist/Table/plugins/rowExpansion/index.js +1 -1
  197. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +41 -76
  198. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  199. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +94 -345
  200. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  201. package/dist/Table/plugins/sortable/useTableSortable.js +23 -4
  202. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  203. package/dist/Table/plugins/tree/useTableTreeData.js +29 -33
  204. package/dist/Table/tableContextMenu.d.ts.map +1 -1
  205. package/dist/Table/tableContextMenu.js +2 -1
  206. package/dist/Table/types.d.ts +11 -0
  207. package/dist/Table/types.d.ts.map +1 -1
  208. package/dist/TextArea/TextArea.d.ts +10 -1
  209. package/dist/TextArea/TextArea.d.ts.map +1 -1
  210. package/dist/TextArea/TextArea.js +16 -6
  211. package/dist/TextInput/TextInput.d.ts +10 -1
  212. package/dist/TextInput/TextInput.d.ts.map +1 -1
  213. package/dist/TextInput/TextInput.js +13 -19
  214. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  215. package/dist/Thumbnail/Thumbnail.js +32 -26
  216. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  217. package/dist/TimeInput/TimeInput.js +7 -15
  218. package/dist/Timestamp/TimestampHoverCard.d.ts.map +1 -1
  219. package/dist/Timestamp/TimestampHoverCard.js +16 -34
  220. package/dist/Token/Token.d.ts.map +1 -1
  221. package/dist/Token/Token.js +20 -11
  222. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  223. package/dist/Tokenizer/Tokenizer.js +4 -2
  224. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  225. package/dist/Tooltip/useTooltip.js +3 -19
  226. package/dist/TopNav/TopNav.d.ts.map +1 -1
  227. package/dist/TopNav/TopNav.js +6 -5
  228. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  229. package/dist/TopNav/TopNavHeading.js +54 -16
  230. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  231. package/dist/TopNav/TopNavItem.js +3 -9
  232. package/dist/TopNav/TopNavMegaMenu.d.ts +7 -0
  233. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  234. package/dist/TopNav/TopNavMegaMenu.js +146 -60
  235. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  236. package/dist/TopNav/TopNavMegaMenuItem.js +22 -3
  237. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  238. package/dist/TopNav/TopNavMenu.js +83 -38
  239. package/dist/TreeList/TreeList.d.ts.map +1 -1
  240. package/dist/TreeList/TreeList.js +13 -0
  241. package/dist/TreeList/TreeListBranches.d.ts +1 -1
  242. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  243. package/dist/TreeList/TreeListBranches.js +14 -4
  244. package/dist/TreeList/TreeListItem.d.ts +11 -1
  245. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  246. package/dist/TreeList/TreeListItem.js +57 -30
  247. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  248. package/dist/Typeahead/BaseTypeahead.js +16 -8
  249. package/dist/astryx.css +74 -85
  250. package/dist/astryx.umd.js +56 -56
  251. package/dist/astryx.umd.js.map +4 -4
  252. package/dist/hooks/containerReveal.stylex.d.ts +61 -0
  253. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -0
  254. package/dist/hooks/containerReveal.stylex.js +63 -0
  255. package/dist/hooks/index.d.ts +3 -0
  256. package/dist/hooks/index.d.ts.map +1 -1
  257. package/dist/hooks/index.js +2 -0
  258. package/dist/hooks/useClipboard.d.ts +59 -0
  259. package/dist/hooks/useClipboard.d.ts.map +1 -0
  260. package/dist/hooks/useClipboard.js +106 -0
  261. package/dist/hooks/useContainerReveal.d.ts +14 -8
  262. package/dist/hooks/useContainerReveal.d.ts.map +1 -1
  263. package/dist/hooks/useContainerReveal.js +28 -69
  264. package/dist/hooks/useIndicatorFocusRing.d.ts +28 -0
  265. package/dist/hooks/useIndicatorFocusRing.d.ts.map +1 -0
  266. package/dist/hooks/useIndicatorFocusRing.js +96 -0
  267. package/dist/hooks/useLongPress.d.ts.map +1 -1
  268. package/dist/hooks/useLongPress.js +12 -2
  269. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  270. package/dist/hooks/useScrollLock.js +33 -18
  271. package/dist/hooks/useStreamingText.d.ts +18 -3
  272. package/dist/hooks/useStreamingText.d.ts.map +1 -1
  273. package/dist/hooks/useStreamingText.js +47 -7
  274. package/dist/hooks/useTreeFocus.d.ts.map +1 -1
  275. package/dist/hooks/useTreeFocus.js +9 -3
  276. package/dist/hooks/useTypeahead.d.ts +3 -2
  277. package/dist/hooks/useTypeahead.d.ts.map +1 -1
  278. package/dist/hooks/useTypeahead.js +19 -7
  279. package/dist/index.d.ts +1 -0
  280. package/dist/index.d.ts.map +1 -1
  281. package/dist/index.js +1 -0
  282. package/dist/theme/defineTheme.d.ts +16 -0
  283. package/dist/theme/defineTheme.d.ts.map +1 -1
  284. package/dist/theme/defineTheme.js +8 -0
  285. package/dist/theme/derivedVarRegistry.d.ts +8 -0
  286. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  287. package/dist/theme/derivedVarRegistry.js +14 -13
  288. package/dist/theme/expandColorScale.d.ts +3 -1
  289. package/dist/theme/expandColorScale.d.ts.map +1 -1
  290. package/dist/theme/expandColorScale.js +17 -7
  291. package/dist/theme/expandTypeScale.d.ts.map +1 -1
  292. package/dist/theme/expandTypeScale.js +17 -0
  293. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  294. package/dist/theme/generateThemeRules.js +11 -0
  295. package/dist/theme/index.d.ts +1 -0
  296. package/dist/theme/index.d.ts.map +1 -1
  297. package/dist/utils/focusOutline.stylex.d.ts +107 -0
  298. package/dist/utils/focusOutline.stylex.d.ts.map +1 -0
  299. package/dist/utils/focusOutline.stylex.js +130 -0
  300. package/dist/utils/focusReturn.d.ts +24 -0
  301. package/dist/utils/focusReturn.d.ts.map +1 -0
  302. package/dist/utils/focusReturn.js +29 -0
  303. package/dist/utils/index.d.ts +1 -0
  304. package/dist/utils/index.d.ts.map +1 -1
  305. package/dist/utils/index.js +1 -0
  306. package/dist/utils/mergeRefs.d.ts.map +1 -1
  307. package/dist/utils/mergeRefs.js +7 -5
  308. package/dist/utils/rtlStyles.d.ts +2 -2
  309. package/dist/utils/rtlStyles.js +2 -2
  310. package/dist/utils/themeProps.d.ts +20 -1
  311. package/dist/utils/themeProps.d.ts.map +1 -1
  312. package/dist/utils/themeProps.js +8 -2
  313. package/locales/en.json +12 -0
  314. package/locales/pseudo.json +9 -0
  315. package/package.json +7 -2
  316. package/src/AlertDialog/AlertDialog.doc.mjs +16 -3
  317. package/src/AlertDialog/AlertDialog.test.tsx +208 -1
  318. package/src/AlertDialog/AlertDialog.tsx +21 -3
  319. package/src/AppShell/AppShell.doc.mjs +11 -0
  320. package/src/AppShell/AppShell.test.tsx +139 -0
  321. package/src/AppShell/AppShell.tsx +32 -22
  322. package/src/AspectRatio/AspectRatio.doc.mjs +27 -3
  323. package/src/AspectRatio/AspectRatio.test.tsx +30 -0
  324. package/src/AspectRatio/AspectRatio.tsx +13 -0
  325. package/src/Avatar/Avatar.doc.mjs +2 -13
  326. package/src/Avatar/Avatar.test.tsx +33 -8
  327. package/src/Avatar/Avatar.tsx +52 -50
  328. package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -9
  329. package/src/Banner/Banner.tsx +9 -6
  330. package/src/Breadcrumbs/BreadcrumbItem.tsx +16 -6
  331. package/src/Breadcrumbs/index.ts +5 -1
  332. package/src/Button/Button.tsx +21 -41
  333. package/src/Calendar/Calendar.tsx +2 -1
  334. package/src/Calendar/styles.ts +0 -8
  335. package/src/Carousel/Carousel.doc.mjs +3 -0
  336. package/src/Carousel/Carousel.tsx +10 -6
  337. package/src/Chat/Chat.doc.mjs +2 -0
  338. package/src/Chat/ChatDictationButton.tsx +7 -1
  339. package/src/Chat/ChatLayoutScrollButton.test.tsx +22 -0
  340. package/src/Chat/ChatLayoutScrollButton.tsx +8 -1
  341. package/src/Chat/ChatSendButton.tsx +2 -3
  342. package/src/Chat/ChatToolCalls.test.tsx +35 -0
  343. package/src/Chat/ChatToolCalls.tsx +36 -16
  344. package/src/Chat/useTriggerMenu.tsx +2 -5
  345. package/src/CheckboxInput/CheckboxInput.doc.mjs +4 -2
  346. package/src/CheckboxInput/CheckboxInput.test.tsx +115 -0
  347. package/src/CheckboxInput/CheckboxInput.tsx +45 -202
  348. package/src/ClickableCard/ClickableCard.tsx +6 -11
  349. package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
  350. package/src/CodeBlock/CodeBlock.test.tsx +91 -0
  351. package/src/CodeBlock/CodeBlock.tsx +57 -80
  352. package/src/Collapsible/Collapsible.tsx +22 -18
  353. package/src/CommandPalette/CommandPalette.test.tsx +29 -0
  354. package/src/CommandPalette/CommandPaletteItem.tsx +7 -4
  355. package/src/CommandPalette/CommandPaletteList.tsx +2 -2
  356. package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
  357. package/src/ComplexSelector/ComplexSelector.test.tsx +64 -0
  358. package/src/ComplexSelector/ComplexSelector.tsx +46 -29
  359. package/src/ContextMenu/ContextMenu.doc.mjs +1 -1
  360. package/src/ContextMenu/ContextMenu.test.tsx +41 -0
  361. package/src/ContextMenu/ContextMenu.tsx +3 -3
  362. package/src/ContextMenu/index.ts +5 -1
  363. package/src/DateInput/DateInput.doc.mjs +18 -3
  364. package/src/DateInput/DateInput.test.tsx +93 -11
  365. package/src/DateInput/DateInput.tsx +41 -19
  366. package/src/DateRangeInput/DateRangeInput.doc.mjs +10 -2
  367. package/src/DateRangeInput/DateRangeInput.test.tsx +110 -14
  368. package/src/DateRangeInput/DateRangeInput.tsx +24 -12
  369. package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -2
  370. package/src/DateTimeInput/DateTimeInput.test.tsx +75 -0
  371. package/src/DateTimeInput/DateTimeInput.tsx +35 -8
  372. package/src/Dialog/Dialog.tsx +2 -9
  373. package/src/DropdownMenu/DropdownMenu.doc.mjs +5 -9
  374. package/src/DropdownMenu/DropdownMenu.test.tsx +534 -4
  375. package/src/DropdownMenu/DropdownMenu.tsx +113 -52
  376. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +27 -30
  377. package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +34 -0
  378. package/src/DropdownMenu/DropdownMenuDivider.tsx +81 -0
  379. package/src/DropdownMenu/DropdownMenuItem.doc.mjs +39 -4
  380. package/src/DropdownMenu/DropdownMenuItem.tsx +48 -10
  381. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +30 -76
  382. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +25 -19
  383. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +44 -14
  384. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +1 -5
  385. package/src/DropdownMenu/index.ts +8 -1
  386. package/src/DropdownMenu/renderDropdownItems.tsx +33 -34
  387. package/src/EmptyState/EmptyState.doc.mjs +4 -0
  388. package/src/EmptyState/EmptyState.test.tsx +62 -0
  389. package/src/EmptyState/EmptyState.tsx +16 -6
  390. package/src/Field/Field.doc.mjs +1 -0
  391. package/src/Field/InputClearButton.test.tsx +117 -0
  392. package/src/Field/InputClearButton.tsx +30 -3
  393. package/src/HoverCard/useHoverCard.tsx +2 -23
  394. package/src/Icon/Icon.doc.mjs +2 -1
  395. package/src/Indicator/CheckIndicator.tsx +174 -0
  396. package/src/Indicator/CheckboxIndicator.tsx +257 -0
  397. package/src/Indicator/Indicator.doc.mjs +344 -0
  398. package/src/Indicator/Indicator.test.tsx +393 -0
  399. package/src/Indicator/RadioIndicator.tsx +206 -0
  400. package/src/Indicator/index.ts +45 -0
  401. package/src/Indicator/indicator.markers.stylex.ts +19 -0
  402. package/src/Indicator/indicatorRegistry.test.tsx +106 -0
  403. package/src/Indicator/indicatorRegistry.ts +120 -0
  404. package/src/Indicator/types.ts +186 -0
  405. package/src/Indicator/useIndicator.ts +39 -0
  406. package/src/Item/Item.doc.mjs +1 -1
  407. package/src/Item/Item.tsx +7 -14
  408. package/src/Layer/useLayer.doc.mjs +2 -2
  409. package/src/Layer/useLayer.test.tsx +85 -0
  410. package/src/Layer/useLayer.tsx +39 -1
  411. package/src/Lightbox/Lightbox.doc.mjs +1 -1
  412. package/src/Lightbox/Lightbox.tsx +43 -38
  413. package/src/Link/Link.tsx +4 -11
  414. package/src/MobileNav/MobileNav.tsx +3 -3
  415. package/src/MoreMenu/MoreMenu.doc.mjs +31 -0
  416. package/src/MoreMenu/MoreMenu.test.tsx +68 -1
  417. package/src/MoreMenu/MoreMenu.tsx +19 -0
  418. package/src/MultiSelector/MultiSelector.doc.mjs +9 -1
  419. package/src/MultiSelector/MultiSelector.test.tsx +255 -16
  420. package/src/MultiSelector/MultiSelector.tsx +103 -99
  421. package/src/NumberInput/NumberInput.doc.mjs +265 -50
  422. package/src/NumberInput/NumberInput.test.tsx +726 -21
  423. package/src/NumberInput/NumberInput.tsx +353 -59
  424. package/src/Outline/Outline.tsx +2 -5
  425. package/src/Pagination/Pagination.doc.mjs +1 -1
  426. package/src/Pagination/Pagination.test.tsx +22 -7
  427. package/src/Pagination/Pagination.tsx +38 -35
  428. package/src/Popover/Popover.tsx +6 -7
  429. package/src/PowerSearch/PowerSearch.tsx +1 -1
  430. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +42 -0
  431. package/src/PowerSearch/PowerSearchEditPopover.tsx +7 -0
  432. package/src/ProgressBar/ProgressBar.doc.mjs +27 -5
  433. package/src/ProgressBar/ProgressBar.test.tsx +224 -1
  434. package/src/ProgressBar/ProgressBar.tsx +124 -22
  435. package/src/RadioList/RadioList.doc.mjs +4 -2
  436. package/src/RadioList/RadioListItem.tsx +31 -130
  437. package/src/Resizable/ResizeHandle.tsx +2 -9
  438. package/src/SegmentedControl/SegmentedControlItem.tsx +2 -9
  439. package/src/SelectableCard/SelectableCard.tsx +4 -9
  440. package/src/Selector/Selector.doc.mjs +7 -4
  441. package/src/Selector/Selector.test.tsx +935 -25
  442. package/src/Selector/Selector.tsx +189 -106
  443. package/src/Selector/hooks.ts +77 -50
  444. package/src/SideNav/SideNav.test.tsx +46 -0
  445. package/src/SideNav/SideNav.tsx +1 -0
  446. package/src/SideNav/SideNavCollapseButton.tsx +15 -10
  447. package/src/SideNav/SideNavHeading.tsx +48 -10
  448. package/src/SideNav/SideNavItem.tsx +20 -12
  449. package/src/Stack/Stack.doc.mjs +110 -0
  450. package/src/StatusDot/StatusDot.doc.mjs +12 -3
  451. package/src/Switch/Switch.test.tsx +32 -0
  452. package/src/Switch/Switch.tsx +8 -8
  453. package/src/TabList/Tab.tsx +2 -9
  454. package/src/TabList/TabMenu.tsx +14 -21
  455. package/src/Table/BaseTable.tsx +11 -0
  456. package/src/Table/index.ts +1 -4
  457. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +30 -14
  458. package/src/Table/plugins/rowExpansion/index.ts +1 -4
  459. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +125 -175
  460. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +115 -458
  461. package/src/Table/plugins/sortable/useTableSortable.tsx +2 -6
  462. package/src/Table/plugins/tree/useTableTreeData.tsx +43 -24
  463. package/src/Table/tableContextMenu.test.tsx +27 -0
  464. package/src/Table/tableContextMenu.tsx +1 -0
  465. package/src/Table/types.ts +11 -0
  466. package/src/Table/useTableGroupedRows.doc.mjs +1 -1
  467. package/src/Table/useTableRowExpansion.doc.mjs +43 -66
  468. package/src/TextArea/TextArea.doc.mjs +42 -2
  469. package/src/TextArea/TextArea.test.tsx +219 -0
  470. package/src/TextArea/TextArea.tsx +34 -7
  471. package/src/TextInput/TextInput.doc.mjs +18 -2
  472. package/src/TextInput/TextInput.test.tsx +189 -0
  473. package/src/TextInput/TextInput.tsx +25 -31
  474. package/src/Thumbnail/Thumbnail.tsx +2 -9
  475. package/src/TimeInput/TimeInput.doc.mjs +2 -2
  476. package/src/TimeInput/TimeInput.test.tsx +30 -3
  477. package/src/TimeInput/TimeInput.tsx +9 -26
  478. package/src/Timestamp/Timestamp.doc.mjs +4 -3
  479. package/src/Timestamp/TimestampHoverCard.tsx +13 -35
  480. package/src/Token/Token.tsx +5 -28
  481. package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
  482. package/src/Tokenizer/Tokenizer.test.tsx +45 -3
  483. package/src/Tokenizer/Tokenizer.tsx +10 -2
  484. package/src/Tooltip/useTooltip.tsx +2 -23
  485. package/src/TopNav/TopNav.tsx +1 -3
  486. package/src/TopNav/TopNavHeading.tsx +42 -13
  487. package/src/TopNav/TopNavItem.tsx +3 -21
  488. package/src/TopNav/TopNavMegaMenu.test.tsx +433 -33
  489. package/src/TopNav/TopNavMegaMenu.tsx +118 -53
  490. package/src/TopNav/TopNavMegaMenuItem.tsx +2 -9
  491. package/src/TopNav/TopNavMenu.tsx +34 -37
  492. package/src/TreeList/TreeList.doc.mjs +5 -0
  493. package/src/TreeList/TreeList.test.tsx +206 -7
  494. package/src/TreeList/TreeList.tsx +22 -0
  495. package/src/TreeList/TreeListBranches.tsx +25 -2
  496. package/src/TreeList/TreeListItem.tsx +89 -52
  497. package/src/Typeahead/BaseTypeahead.tsx +19 -6
  498. package/src/Typeahead/Typeahead.doc.mjs +1 -0
  499. package/src/Typeahead/Typeahead.test.tsx +76 -3
  500. package/src/hooks/containerReveal.stylex.ts +102 -0
  501. package/src/hooks/index.ts +4 -0
  502. package/src/hooks/useClipboard.doc.mjs +87 -0
  503. package/src/hooks/useClipboard.test.tsx +151 -0
  504. package/src/hooks/useClipboard.ts +135 -0
  505. package/src/hooks/useContainerReveal.doc.mjs +7 -7
  506. package/src/hooks/useContainerReveal.test.tsx +42 -62
  507. package/src/hooks/useContainerReveal.ts +36 -91
  508. package/src/hooks/useImageMode.test.ts +1 -1
  509. package/src/hooks/useIndicatorFocusRing.tsx +120 -0
  510. package/src/hooks/useLongPress.test.tsx +18 -0
  511. package/src/hooks/useLongPress.ts +12 -2
  512. package/src/hooks/useScrollLock.test.ts +72 -0
  513. package/src/hooks/useScrollLock.ts +51 -19
  514. package/src/hooks/useStreamingText.test.ts +46 -1
  515. package/src/hooks/useStreamingText.ts +49 -7
  516. package/src/hooks/useTreeFocus.test.tsx +50 -0
  517. package/src/hooks/useTreeFocus.ts +14 -3
  518. package/src/hooks/useTypeahead.test.tsx +150 -0
  519. package/src/hooks/useTypeahead.ts +24 -9
  520. package/src/i18n/InternationalizationProvider.doc.mjs +7 -2
  521. package/src/index.ts +1 -0
  522. package/src/theme/defineTheme.ts +24 -0
  523. package/src/theme/derivedVarRegistry.test.ts +21 -1
  524. package/src/theme/derivedVarRegistry.ts +19 -6
  525. package/src/theme/expandColorScale.test.ts +14 -0
  526. package/src/theme/expandColorScale.ts +24 -9
  527. package/src/theme/expandTypeScale.test.ts +43 -0
  528. package/src/theme/expandTypeScale.ts +17 -0
  529. package/src/theme/generateThemeRules.test.ts +61 -20
  530. package/src/theme/generateThemeRules.ts +11 -0
  531. package/src/theme/index.ts +13 -0
  532. package/src/utils/focusOutline.stylex.ts +163 -0
  533. package/src/utils/focusReturn.test.ts +42 -0
  534. package/src/utils/focusReturn.ts +31 -0
  535. package/src/utils/index.ts +1 -0
  536. package/src/utils/mergeRefs.test.ts +48 -0
  537. package/src/utils/mergeRefs.ts +12 -6
  538. package/src/utils/rtlStyles.ts +2 -2
  539. package/src/utils/themeProps.ts +26 -4
  540. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts +0 -9
  541. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts.map +0 -1
  542. package/dist/CheckboxInput/checkbox.markers.stylex.js +0 -14
  543. package/dist/RadioList/radio.markers.stylex.d.ts +0 -7
  544. package/dist/RadioList/radio.markers.stylex.d.ts.map +0 -1
  545. package/dist/RadioList/radio.markers.stylex.js +0 -12
  546. package/dist/hooks/containerReveal.pool.stylex.d.ts +0 -303
  547. package/dist/hooks/containerReveal.pool.stylex.d.ts.map +0 -1
  548. package/dist/hooks/containerReveal.pool.stylex.js +0 -292
  549. package/src/CheckboxInput/checkbox.markers.stylex.ts +0 -12
  550. package/src/RadioList/radio.markers.stylex.ts +0 -10
  551. package/src/hooks/containerReveal.pool.stylex.ts +0 -571
@@ -30,13 +30,12 @@ import * as stylex from '@stylexjs/stylex';
30
30
  import {
31
31
  colorVars,
32
32
  sizeVars,
33
- radiusVars,
34
33
  typographyVars,
35
34
  typeScaleVars,
36
- borderVars,
37
35
  } from '../theme/tokens.stylex';
38
36
  import {
39
37
  Field,
38
+ InputClearButton,
40
39
  type InputStatus,
41
40
  inputWrapperStyles,
42
41
  inputStatusBorderStyles,
@@ -44,30 +43,13 @@ import {
44
43
  inputStatusFocusWithinStyles,
45
44
  type FieldStatusVariant,
46
45
  } from '../Field';
47
- import {Icon, renderIconSlot, type IconType} from '../Icon';
46
+ import {renderIconSlot, type IconType} from '../Icon';
48
47
  import {Spinner} from '../Spinner';
49
48
  import {useTooltip} from '../Tooltip';
50
49
  import {VisuallyHidden} from '../VisuallyHidden';
51
50
  import {getInputARIA} from '../utils';
52
51
 
53
52
  const styles = stylex.create({
54
- clearButton: {
55
- display: 'flex',
56
- alignItems: 'center',
57
- justifyContent: 'center',
58
- padding: 0,
59
- margin: 0,
60
- borderWidth: 0,
61
- borderStyle: 'none',
62
- backgroundColor: 'transparent',
63
- cursor: 'pointer',
64
- borderRadius: radiusVars['--radius-element'],
65
- outline: {
66
- default: 'none',
67
- ':focus-visible': `${borderVars['--border-width']} solid ${colorVars['--color-accent']}`,
68
- },
69
- outlineOffset: 1,
70
- },
71
53
  input: {
72
54
  display: 'block',
73
55
  flex: 1,
@@ -166,6 +148,15 @@ export interface TextInputProps extends Omit<
166
148
  * @default false
167
149
  */
168
150
  isDisabled?: boolean;
151
+ /**
152
+ * Whether the input is read-only.
153
+ * The value is shown at full opacity and still submits with the form, but
154
+ * cannot be edited. Unlike `isDisabled`, a read-only input is not dimmed and
155
+ * stays in the tab order — use it for a value the user should see and send
156
+ * but not change. `isDisabled` takes precedence when both are set.
157
+ * @default false
158
+ */
159
+ isReadOnly?: boolean;
169
160
  /**
170
161
  * Explains why the input is disabled. When set together with `isDisabled`,
171
162
  * the input shows a tooltip with this text on hover and keyboard focus, and
@@ -285,6 +276,7 @@ export function TextInput({
285
276
  isOptional = false,
286
277
  isRequired = false,
287
278
  isDisabled = false,
279
+ isReadOnly = false,
288
280
  disabledMessage,
289
281
  startIcon,
290
282
  status,
@@ -365,7 +357,7 @@ export function TextInput({
365
357
  // Value can't change while showing a disabled message (the field is
366
358
  // read-only and non-native-disabled), but guard the handler too so the
367
359
  // optimistic value and callbacks never fire.
368
- if (isDisabled) {
360
+ if (isDisabled || isReadOnly) {
369
361
  return;
370
362
  }
371
363
  const newValue = e.target.value;
@@ -404,7 +396,12 @@ export function TextInput({
404
396
  onClick={handleWrapperClick}
405
397
  onMouseUp={handleWrapperMouseUp}
406
398
  {...mergeProps(
407
- themeProps('text-input', {size, status: status?.type ?? null}),
399
+ themeProps('text-input', {
400
+ size,
401
+ status: status?.type ?? null,
402
+ disabled: isDisabled ? 'disabled' : null,
403
+ readonly: isReadOnly ? 'readonly' : null,
404
+ }),
408
405
  stylex.props(
409
406
  inputWrapperStyles.base,
410
407
  sizeStyles[size],
@@ -424,7 +421,7 @@ export function TextInput({
424
421
  {...rest}
425
422
  ref={mergeRefs(ref, inputRef)}
426
423
  id={id}
427
- name={htmlName}
424
+ name={isDisabled ? undefined : htmlName}
428
425
  type={type}
429
426
  value={optimisticValue}
430
427
  onChange={handleChange}
@@ -444,7 +441,7 @@ export function TextInput({
444
441
  // keep the value from changing.
445
442
  disabled={isDisabled && !showsDisabledMessage}
446
443
  aria-disabled={showsDisabledMessage ? 'true' : undefined}
447
- readOnly={showsDisabledMessage || undefined}
444
+ readOnly={isReadOnly || showsDisabledMessage || undefined}
448
445
  autoFocus={hasAutoFocus}
449
446
  data-autofocus={hasAutoFocus || undefined}
450
447
  aria-describedby={ariaDescribedBy}
@@ -454,14 +451,11 @@ export function TextInput({
454
451
  aria-labelledby={ariaLabelledBy}
455
452
  {...stylex.props(styles.input, isDisabled && styles.inputDisabled)}
456
453
  />
457
- {hasClear && value !== '' && !isDisabled && (
458
- <button
459
- type="button"
454
+ {hasClear && value !== '' && !isDisabled && !isReadOnly && (
455
+ <InputClearButton
456
+ label={t('@astryx.textInput.clearLabel', {label})}
460
457
  onClick={handleClear}
461
- aria-label={t('@astryx.textInput.clearLabel', {label})}
462
- {...stylex.props(styles.clearButton)}>
463
- <Icon icon="close" size="sm" color="secondary" />
464
- </button>
458
+ />
465
459
  )}
466
460
  {isBusy && <Spinner size="sm" />}
467
461
  {statusIcon}
@@ -44,6 +44,7 @@ import {useContainerReveal} from '../hooks/useContainerReveal';
44
44
  import type {BaseProps} from '../BaseProps';
45
45
  import {mergeProps} from '../utils';
46
46
  import {themeProps} from '../utils/themeProps';
47
+ import {focusOutlineProps} from '../utils/focusOutline.stylex';
47
48
  import {useTranslator} from '../i18n';
48
49
 
49
50
  export interface ThumbnailProps extends BaseProps<HTMLDivElement> {
@@ -159,14 +160,6 @@ const styles = stylex.create({
159
160
  },
160
161
  interactive: {
161
162
  cursor: 'pointer',
162
- outline: {
163
- default: null,
164
- ':has(:focus-visible)': `2px solid ${colorVars['--color-accent']}`,
165
- },
166
- outlineOffset: {
167
- default: '0',
168
- ':has(:focus-visible)': '2px',
169
- },
170
163
  },
171
164
  // Hover/pressed overlay — the exact same treatment as ClickableCard and
172
165
  // SelectableCard. A transparent `::after` tints on hover/press instead of
@@ -402,7 +395,7 @@ export function Thumbnail({
402
395
  {...props}>
403
396
  <div
404
397
  {...mergeProps(
405
- stylex.props(
398
+ focusOutlineProps.focusWithin(
406
399
  styles.imageContainer,
407
400
  isInteractive && styles.interactive,
408
401
  isInteractive && styles.overlay,
@@ -257,7 +257,7 @@ export const docs = {
257
257
  ],
258
258
  theming: {
259
259
  targets: [
260
- {className: 'astryx-time-input', visualProps: ['size', 'status']},
260
+ {className: 'astryx-time-input', visualProps: ['size', 'status'], states: ['disabled']},
261
261
  ],
262
262
  },
263
263
  };
@@ -406,7 +406,7 @@ export const docsZh = {
406
406
  ],
407
407
  theming: {
408
408
  targets: [
409
- {className: 'astryx-time-input', visualProps: ['size', 'status']},
409
+ {className: 'astryx-time-input', visualProps: ['size', 'status'], states: ['disabled']},
410
410
  ],
411
411
  },
412
412
  usage: {
@@ -572,11 +572,15 @@ describe('TimeInput', () => {
572
572
  });
573
573
  });
574
574
 
575
-
576
575
  describe('TimeInput statusVariant forwarding', () => {
577
576
  it('defaults to attached (status renders with data-variant="attached")', () => {
578
577
  const {container} = render(
579
- <TimeInput label="Start" value={undefined} onChange={() => {}} status={{type: 'error', message: 'Required'}} />,
578
+ <TimeInput
579
+ label="Start"
580
+ value={undefined}
581
+ onChange={() => {}}
582
+ status={{type: 'error', message: 'Required'}}
583
+ />,
580
584
  );
581
585
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
582
586
  'data-variant',
@@ -586,7 +590,13 @@ describe('TimeInput statusVariant forwarding', () => {
586
590
 
587
591
  it('forwards statusVariant="detached" to the underlying Field status', () => {
588
592
  const {container} = render(
589
- <TimeInput label="Start" value={undefined} onChange={() => {}} status={{type: 'error', message: 'Required'}} statusVariant="detached" />,
593
+ <TimeInput
594
+ label="Start"
595
+ value={undefined}
596
+ onChange={() => {}}
597
+ status={{type: 'error', message: 'Required'}}
598
+ statusVariant="detached"
599
+ />,
590
600
  );
591
601
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
592
602
  'data-variant',
@@ -594,3 +604,20 @@ describe('TimeInput statusVariant forwarding', () => {
594
604
  );
595
605
  });
596
606
  });
607
+
608
+ describe('TimeInput disabled theme state', () => {
609
+ it('reflects disabled on the root target so themes can gate paint on it', () => {
610
+ const {container} = render(
611
+ <TimeInput label="Time" onChange={() => {}} isDisabled />,
612
+ );
613
+ const root = container.querySelector('.astryx-time-input');
614
+ expect(root).toHaveAttribute('data-disabled', 'disabled');
615
+ expect(root).toHaveClass('disabled');
616
+ });
617
+
618
+ it('omits data-disabled when enabled, like status does', () => {
619
+ const {container} = render(<TimeInput label="Time" onChange={() => {}} />);
620
+ const root = container.querySelector('.astryx-time-input');
621
+ expect(root).not.toHaveAttribute('data-disabled');
622
+ });
623
+ });
@@ -32,13 +32,12 @@ import * as stylex from '@stylexjs/stylex';
32
32
  import {
33
33
  colorVars,
34
34
  sizeVars,
35
- radiusVars,
36
35
  typographyVars,
37
36
  typeScaleVars,
38
- borderVars,
39
37
  } from '../theme/tokens.stylex';
40
38
  import {
41
39
  Field,
40
+ InputClearButton,
42
41
  type InputStatus,
43
42
  inputWrapperStyles,
44
43
  inputStatusBorderStyles,
@@ -106,23 +105,6 @@ const styles = stylex.create({
106
105
  inputInvalid: {
107
106
  color: colorVars['--color-text-secondary'],
108
107
  },
109
- clearButton: {
110
- display: 'flex',
111
- alignItems: 'center',
112
- justifyContent: 'center',
113
- padding: 0,
114
- margin: 0,
115
- borderWidth: 0,
116
- borderStyle: 'none',
117
- backgroundColor: 'transparent',
118
- cursor: 'pointer',
119
- borderRadius: radiusVars['--radius-element'],
120
- outline: {
121
- default: 'none',
122
- ':focus-visible': `${borderVars['--border-width']} solid ${colorVars['--color-accent']}`,
123
- },
124
- outlineOffset: 1,
125
- },
126
108
  });
127
109
 
128
110
  const sizeStyles = stylex.create({
@@ -608,7 +590,11 @@ export function TimeInput({
608
590
  onClick={handleWrapperClick}
609
591
  onMouseUp={handleWrapperMouseUp}
610
592
  {...mergeProps(
611
- themeProps('time-input', {size, status: status?.type ?? null}),
593
+ themeProps('time-input', {
594
+ size,
595
+ status: status?.type ?? null,
596
+ disabled: isDisabled ? 'disabled' : null,
597
+ }),
612
598
  stylex.props(
613
599
  inputWrapperStyles.base,
614
600
  sizeStyles[size],
@@ -677,13 +663,10 @@ export function TimeInput({
677
663
  </VisuallyHidden>
678
664
  {isBusy && <Spinner size="sm" />}
679
665
  {hasClear && value && !isDisabled && (
680
- <button
681
- type="button"
666
+ <InputClearButton
667
+ label={t('@astryx.timeInput.clearLabel', {label})}
682
668
  onClick={handleClear}
683
- aria-label={t('@astryx.timeInput.clearLabel', {label})}
684
- {...stylex.props(styles.clearButton)}>
685
- <Icon icon="close" size="sm" color="secondary" />
686
- </button>
669
+ />
687
670
  )}
688
671
  {statusIcon}
689
672
  </div>
@@ -49,7 +49,7 @@ export const docs = {
49
49
  name: 'tooltipEntries',
50
50
  type: 'ReadonlyArray<{timezoneID?: string; format?: TimestampTooltipFormat; label?: string; isCopyable?: boolean}>',
51
51
  description:
52
- "Lines to show on hover, so one instant can be read and optionally copied in several time zones and/or formats at once. Each entry is one line, in the order given. Omit timezoneID (or pass 'local') for the viewer's own zone; format defaults to the full absolute style and also accepts 'full' alongside every non-relative TimestampFormat. Rows are read-only unless they set isCopyable (default false); copyable rows show a copy button in a dedicated trailing action column so buttons align, and the column is only present when some row is copyable. With no entries the card shows a single default row with the full absolute time, which is copyable. Configuring entries also attaches the surface to absolute formats, which otherwise have none.",
52
+ "Lines to show on hover, so one instant can be read (and optionally copied) in several time zones and/or formats at once. Each entry is one line, in the order given. Omit timezoneID (or pass 'local') for the viewer's own zone; format defaults to the full absolute style and also accepts 'full' alongside every non-relative TimestampFormat. Rows are read-only unless they set isCopyable (default false); copyable rows show a copy button in a dedicated trailing action column so buttons align, and the column is only present when some row is copyable. With no entries the card shows a single default row with the full absolute time, which is copyable. Configuring entries also attaches the surface to absolute formats, which otherwise have none.",
53
53
  },
54
54
  {
55
55
  name: 'isTimezoneShown',
@@ -104,7 +104,7 @@ export const docs = {
104
104
  {guidance: true, description: 'Use tooltipEntries when readers must compare zones, such as an incident log where the reader\'s time and the event\'s origin zone both matter.'},
105
105
  {guidance: true, description: 'Label every entry once a tooltip shows more than one zone; a bare abbreviation is not always recognizable (Tokyo renders as "GMT+9", not "JST").'},
106
106
  {guidance: true, description: 'Use isLive for active dashboards or real-time feeds so the relative time stays accurate without a page refresh.'},
107
- {guidance: true, description: 'Reach for tooltipEntries when readers need to grab an exact value an incident log or deploy record where someone pastes the UTC time or Unix seconds elsewhere; configuring entries turns the hover into copy-to-clipboard rows.'},
107
+ {guidance: true, description: 'Reach for tooltipEntries when readers need to grab an exact value: an incident log or deploy record where someone pastes the UTC time or Unix seconds elsewhere; configuring entries turns the hover into copy-to-clipboard rows.'},
108
108
  {guidance: false, description: 'Don\'t display raw Unix timestamps or ISO strings to users; always pass them through Timestamp to get a human-readable format.'},
109
109
  {guidance: false, description: 'Avoid system_date or system_time formats in user-facing UI; they are meant for developer tools, logs, and machine-readable contexts.'},
110
110
  {guidance: false, description: 'Don\'t disable the hover card on relative timestamps; users expect to hover for the full date when they see "3 hours ago".'},
@@ -147,7 +147,7 @@ export const docsZh = {
147
147
  {guidance: true, description: 'Use tooltipEntries when readers must compare zones, such as an incident log where the reader\'s time and the event\'s origin zone both matter.'},
148
148
  {guidance: true, description: 'Label every entry once a tooltip shows more than one zone; a bare abbreviation is not always recognizable (Tokyo renders as "GMT+9", not "JST").'},
149
149
  {guidance: true, description: 'Use isLive for active dashboards or real-time feeds so the relative time stays accurate without a page refresh.'},
150
- {guidance: true, description: 'Reach for tooltipEntries when readers need to grab an exact value an incident log or deploy record where someone pastes the UTC time or Unix seconds elsewhere; configuring entries turns the hover into copy-to-clipboard rows.'},
150
+ {guidance: true, description: 'Reach for tooltipEntries when readers need to grab an exact value: an incident log or deploy record where someone pastes the UTC time or Unix seconds elsewhere; configuring entries turns the hover into copy-to-clipboard rows.'},
151
151
  {guidance: false, description: 'Don\'t display raw Unix timestamps or ISO strings to users; always pass them through Timestamp to get a human-readable format.'},
152
152
  {guidance: false, description: 'Avoid system_date or system_time formats in user-facing UI; they are meant for developer tools, logs, and machine-readable contexts.'},
153
153
  {guidance: false, description: 'Don\'t disable the hover card on relative timestamps; users expect to hover for the full date when they see "3 hours ago".'},
@@ -176,6 +176,7 @@ export const docsDense = {
176
176
  {guidance: true, description: 'tooltipEntries to compare zones when the reader time and event zone both matter.'},
177
177
  {guidance: true, description: 'Label each entry once a tooltip shows more than one zone; a bare abbreviation is not always recognizable (Tokyo renders "GMT+9", not "JST").'},
178
178
  {guidance: true, description: 'isLive for dashboards so relative time stays current.'},
179
+ {guidance: true, description: 'tooltipEntries when readers must grab an exact value: an incident log or deploy record where someone pastes the UTC time or Unix seconds; entries turn the hover into copy-to-clipboard rows.'},
179
180
  {guidance: false, description: 'Don\'t show raw Unix timestamps or ISO strings; always use Timestamp.'},
180
181
  {guidance: false, description: 'Avoid system_* formats in user-facing UI; those are for dev tools and logs.'},
181
182
  {guidance: false, description: 'Don\'t disable the hover card on relative timestamps; users expect the full date on hover.'},
@@ -24,12 +24,12 @@
24
24
  */
25
25
 
26
26
  import type {ReactNode} from 'react';
27
- import {useCallback, useEffect, useRef, useState} from 'react';
27
+ import {useCallback} from 'react';
28
28
  import * as stylex from '@stylexjs/stylex';
29
29
  import {HoverCard} from '../HoverCard';
30
30
  import {IconButton} from '../IconButton';
31
31
  import {Icon} from '../Icon';
32
- import {useAnnounce} from '../hooks/useAnnounce';
32
+ import {useClipboard} from '../hooks/useClipboard';
33
33
  import {useTranslator} from '../i18n';
34
34
  import {themeProps} from '../utils/themeProps';
35
35
  import {
@@ -108,7 +108,9 @@ const COPY_FEEDBACK_MS = 1500;
108
108
  * The per-row copy affordance: a compact ghost `IconButton` that writes the
109
109
  * row's value to the clipboard, flips `copy` → `check` for a moment, and
110
110
  * announces the copy to a polite live region (a swapped aria-label alone
111
- * isn't reliably announced). A clipboard rejection is a silent no-op.
111
+ * isn't reliably announced). A clipboard rejection is a silent no-op. The
112
+ * clipboard write, copied flag, reset timer, and announcement are owned by
113
+ * `useClipboard` — shared with CodeBlock's built-in copy button.
112
114
  *
113
115
  * Kept as its own component so its state/timer/effect only exist for rows that
114
116
  * actually opt into copying — read-only rows render no button and carry none
@@ -116,36 +118,14 @@ const COPY_FEEDBACK_MS = 1500;
116
118
  */
117
119
  function CopyButton({value}: {value: string}) {
118
120
  const t = useTranslator();
119
- const announce = useAnnounce();
120
- const [copied, setCopied] = useState(false);
121
- const resetTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
121
+ const {copy, isCopied: copied} = useClipboard({
122
+ announce: t('@astryx.timestamp.copied'),
123
+ resetAfterMs: COPY_FEEDBACK_MS,
124
+ });
122
125
 
123
- useEffect(() => {
124
- return () => {
125
- if (resetTimerRef.current != null) {
126
- clearTimeout(resetTimerRef.current);
127
- }
128
- };
129
- }, []);
130
-
131
- const handleCopy = useCallback(async () => {
132
- try {
133
- await navigator.clipboard.writeText(value);
134
- setCopied(true);
135
- announce(t('@astryx.timestamp.copied'));
136
- // Restart the reset timer on every copy so a rapid re-copy isn't
137
- // reverted early by the previous click's timer.
138
- if (resetTimerRef.current != null) {
139
- clearTimeout(resetTimerRef.current);
140
- }
141
- resetTimerRef.current = setTimeout(() => {
142
- resetTimerRef.current = null;
143
- setCopied(false);
144
- }, COPY_FEEDBACK_MS);
145
- } catch {
146
- // Clipboard failures leave the copied state unchanged.
147
- }
148
- }, [value, announce, t]);
126
+ const handleCopy = useCallback(() => {
127
+ void copy(value);
128
+ }, [copy, value]);
149
129
 
150
130
  return (
151
131
  <IconButton
@@ -163,9 +143,7 @@ function CopyButton({value}: {value: string}) {
163
143
  ? t('@astryx.timestamp.copied')
164
144
  : t('@astryx.timestamp.copyValue', {value})
165
145
  }
166
- onClick={() => {
167
- void handleCopy();
168
- }}
146
+ onClick={handleCopy}
169
147
  {...themeProps('timestamp-copy-button')}
170
148
  />
171
149
  );
@@ -36,6 +36,7 @@ import {useInteractiveRole} from '../hooks/useInteractiveRole';
36
36
  import {TokenLink} from './TokenLink';
37
37
  import type {BaseProps} from '../BaseProps';
38
38
  import {themeProps} from '../utils/themeProps';
39
+ import {focusOutlineProps} from '../utils/focusOutline.stylex';
39
40
  import {useTranslator} from '../i18n';
40
41
  import type {TokenColorMap} from './index';
41
42
 
@@ -146,14 +147,6 @@ const styles = stylex.create({
146
147
  },
147
148
  ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
148
149
  },
149
- outline: {
150
- default: null,
151
- ':focus-visible': `2px solid ${colorVars['--color-accent']}`,
152
- },
153
- outlineOffset: {
154
- default: '0',
155
- ':focus-visible': '2px',
156
- },
157
150
  },
158
151
  disabled: {
159
152
  cursor: 'not-allowed',
@@ -180,16 +173,6 @@ const styles = stylex.create({
180
173
  overflow: 'hidden',
181
174
  minWidth: 0,
182
175
  },
183
- focusVisibleOutline: {
184
- outline: {
185
- default: null,
186
- ':has(:focus-visible)': `2px solid ${colorVars['--color-accent']}`,
187
- },
188
- outlineOffset: {
189
- default: '0',
190
- ':has(:focus-visible)': '2px',
191
- },
192
- },
193
176
  removeButton: {
194
177
  all: 'unset',
195
178
  display: 'inline-flex',
@@ -203,10 +186,6 @@ const styles = stylex.create({
203
186
  width: '16px',
204
187
  height: '16px',
205
188
  color: 'inherit',
206
- outline: {
207
- default: null,
208
- ':focus-visible': `2px solid ${colorVars['--color-accent']}`,
209
- },
210
189
  '::after': {
211
190
  content: '""',
212
191
  position: 'absolute',
@@ -337,7 +316,7 @@ export function Token({
337
316
  onRemove(e);
338
317
  }}
339
318
  disabled={isDisabled}
340
- {...stylex.props(styles.removeButton)}>
319
+ {...focusOutlineProps.focusVisible(styles.removeButton)}>
341
320
  <Icon icon="close" size="xsm" color="inherit" />
342
321
  </button>
343
322
  );
@@ -370,7 +349,7 @@ export function Token({
370
349
  {...sharedProps}
371
350
  {...mergeProps(
372
351
  themeProps('token', {color, size}),
373
- stylex.props(
352
+ focusOutlineProps.focusVisible(
374
353
  styles.base,
375
354
  sizeStyles[size],
376
355
  colorStyles[color],
@@ -415,12 +394,11 @@ export function Token({
415
394
  {...sharedProps}
416
395
  {...mergeProps(
417
396
  themeProps('token', {color, size}),
418
- stylex.props(
397
+ focusOutlineProps.focusWithin(
419
398
  styles.base,
420
399
  sizeStyles[size],
421
400
  colorStyles[color],
422
401
  styles.interactive,
423
- styles.focusVisibleOutline,
424
402
  isDisabled && styles.disabled,
425
403
  xstyle,
426
404
  ),
@@ -447,12 +425,11 @@ export function Token({
447
425
  {...sharedProps}
448
426
  {...mergeProps(
449
427
  themeProps('token', {color, size}),
450
- stylex.props(
428
+ focusOutlineProps.focusWithin(
451
429
  styles.base,
452
430
  sizeStyles[size],
453
431
  colorStyles[color],
454
432
  styles.interactive,
455
- styles.focusVisibleOutline,
456
433
  isDisabled && styles.disabled,
457
434
  xstyle,
458
435
  ),
@@ -210,7 +210,7 @@ export const docs = {
210
210
  ],
211
211
  theming: {
212
212
  targets: [
213
- {className: 'astryx-tokenizer', visualProps: ['size', 'status']},
213
+ {className: 'astryx-tokenizer', visualProps: ['size', 'status'], states: ['disabled']},
214
214
  ],
215
215
  },
216
216
  usage: {
@@ -424,7 +424,7 @@ export const docsZh = {
424
424
  ],
425
425
  theming: {
426
426
  targets: [
427
- {className: 'astryx-tokenizer', visualProps: ['size', 'status']},
427
+ {className: 'astryx-tokenizer', visualProps: ['size', 'status'], states: ['disabled']},
428
428
  ],
429
429
  },
430
430
  usage: {
@@ -1137,11 +1137,16 @@ describe('Tokenizer', () => {
1137
1137
  });
1138
1138
  });
1139
1139
 
1140
-
1141
1140
  describe('Tokenizer statusVariant forwarding', () => {
1142
1141
  it('defaults to attached (status renders with data-variant="attached")', () => {
1143
1142
  const {container} = render(
1144
- <Tokenizer label="Members" searchSource={userSource} value={[]} onChange={() => {}} status={{type: 'error', message: 'Required'}} />,
1143
+ <Tokenizer
1144
+ label="Members"
1145
+ searchSource={userSource}
1146
+ value={[]}
1147
+ onChange={() => {}}
1148
+ status={{type: 'error', message: 'Required'}}
1149
+ />,
1145
1150
  );
1146
1151
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
1147
1152
  'data-variant',
@@ -1151,7 +1156,14 @@ describe('Tokenizer statusVariant forwarding', () => {
1151
1156
 
1152
1157
  it('forwards statusVariant="detached" to the underlying Field status', () => {
1153
1158
  const {container} = render(
1154
- <Tokenizer label="Members" searchSource={userSource} value={[]} onChange={() => {}} status={{type: 'error', message: 'Required'}} statusVariant="detached" />,
1159
+ <Tokenizer
1160
+ label="Members"
1161
+ searchSource={userSource}
1162
+ value={[]}
1163
+ onChange={() => {}}
1164
+ status={{type: 'error', message: 'Required'}}
1165
+ statusVariant="detached"
1166
+ />,
1155
1167
  );
1156
1168
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
1157
1169
  'data-variant',
@@ -1159,3 +1171,33 @@ describe('Tokenizer statusVariant forwarding', () => {
1159
1171
  );
1160
1172
  });
1161
1173
  });
1174
+
1175
+ describe('Tokenizer disabled theme state', () => {
1176
+ it('reflects disabled on the root target so themes can gate paint on it', () => {
1177
+ const {container} = render(
1178
+ <Tokenizer
1179
+ label="Members"
1180
+ searchSource={userSource}
1181
+ value={[]}
1182
+ onChange={() => {}}
1183
+ isDisabled
1184
+ />,
1185
+ );
1186
+ const root = container.querySelector('.astryx-tokenizer');
1187
+ expect(root).toHaveAttribute('data-disabled', 'disabled');
1188
+ expect(root).toHaveClass('disabled');
1189
+ });
1190
+
1191
+ it('omits data-disabled when enabled, like status does', () => {
1192
+ const {container} = render(
1193
+ <Tokenizer
1194
+ label="Members"
1195
+ searchSource={userSource}
1196
+ value={[]}
1197
+ onChange={() => {}}
1198
+ />,
1199
+ );
1200
+ const root = container.querySelector('.astryx-tokenizer');
1201
+ expect(root).not.toHaveAttribute('data-disabled');
1202
+ });
1203
+ });
@@ -730,7 +730,11 @@ export function Tokenizer<T extends SearchableItem>({
730
730
  onBlurCapture={handleBlurCapture}
731
731
  data-testid={testId}
732
732
  {...mergeProps(
733
- themeProps('tokenizer', {size, status: status?.type}),
733
+ themeProps('tokenizer', {
734
+ size,
735
+ status: status?.type,
736
+ disabled: isDisabled ? 'disabled' : null,
737
+ }),
734
738
  stylex.props(
735
739
  inputWrapperStyles.base,
736
740
  styles.wrapper,
@@ -828,7 +832,11 @@ export function Tokenizer<T extends SearchableItem>({
828
832
  ref={placeholderRef}
829
833
  onClick={handleWrapperClick}
830
834
  {...mergeProps(
831
- themeProps('tokenizer', {size, status: status?.type}),
835
+ themeProps('tokenizer', {
836
+ size,
837
+ status: status?.type,
838
+ disabled: isDisabled ? 'disabled' : null,
839
+ }),
832
840
  stylex.props(
833
841
  inputWrapperStyles.base,
834
842
  styles.wrapper,