@astryxdesign/core 0.3.0 → 0.4.0-canary.3112e99

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 (594) 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 +3 -0
  16. package/dist/Banner/Banner.d.ts.map +1 -1
  17. package/dist/Banner/Banner.js +32 -17
  18. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  19. package/dist/Breadcrumbs/BreadcrumbItem.js +21 -8
  20. package/dist/Breadcrumbs/index.d.ts +2 -1
  21. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  22. package/dist/Breadcrumbs/index.js +1 -0
  23. package/dist/Button/Button.d.ts.map +1 -1
  24. package/dist/Button/Button.js +12 -16
  25. package/dist/Calendar/Calendar.d.ts.map +1 -1
  26. package/dist/Calendar/Calendar.js +2 -1
  27. package/dist/Calendar/styles.d.ts +0 -2
  28. package/dist/Calendar/styles.d.ts.map +1 -1
  29. package/dist/Calendar/styles.js +0 -2
  30. package/dist/Carousel/Carousel.d.ts.map +1 -1
  31. package/dist/Carousel/Carousel.js +8 -12
  32. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  33. package/dist/Chat/ChatDictationButton.js +2 -1
  34. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  35. package/dist/Chat/ChatLayoutScrollButton.js +3 -1
  36. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  37. package/dist/Chat/ChatSendButton.js +4 -3
  38. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  39. package/dist/Chat/ChatToolCalls.js +17 -17
  40. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  41. package/dist/Chat/useTriggerMenu.js +2 -6
  42. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  43. package/dist/CheckboxInput/CheckboxInput.js +36 -125
  44. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  45. package/dist/ClickableCard/ClickableCard.js +3 -11
  46. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  47. package/dist/CodeBlock/CodeBlock.js +84 -67
  48. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  49. package/dist/Collapsible/Collapsible.js +35 -15
  50. package/dist/CommandPalette/CommandPaletteItem.d.ts +1 -1
  51. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  52. package/dist/CommandPalette/CommandPaletteItem.js +6 -3
  53. package/dist/CommandPalette/CommandPaletteList.js +1 -1
  54. package/dist/ComplexSelector/ComplexSelector.d.ts +1 -1
  55. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  56. package/dist/ComplexSelector/ComplexSelector.js +32 -31
  57. package/dist/ContextMenu/ContextMenu.d.ts +2 -2
  58. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  59. package/dist/ContextMenu/ContextMenu.js +1 -1
  60. package/dist/ContextMenu/index.d.ts +2 -1
  61. package/dist/ContextMenu/index.d.ts.map +1 -1
  62. package/dist/ContextMenu/index.js +1 -0
  63. package/dist/DateInput/DateInput.d.ts +9 -2
  64. package/dist/DateInput/DateInput.d.ts.map +1 -1
  65. package/dist/DateInput/DateInput.js +47 -33
  66. package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
  67. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  68. package/dist/DateRangeInput/DateRangeInput.js +55 -32
  69. package/dist/DateTimeInput/DateTimeInput.d.ts +9 -1
  70. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  71. package/dist/DateTimeInput/DateTimeInput.js +54 -30
  72. package/dist/Dialog/Dialog.d.ts.map +1 -1
  73. package/dist/Dialog/Dialog.js +4 -4
  74. package/dist/DropdownMenu/DropdownMenu.d.ts +33 -8
  75. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  76. package/dist/DropdownMenu/DropdownMenu.js +62 -20
  77. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +8 -11
  78. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  79. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +32 -31
  80. package/dist/DropdownMenu/DropdownMenuDivider.d.ts +25 -0
  81. package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -0
  82. package/dist/DropdownMenu/DropdownMenuDivider.js +66 -0
  83. package/dist/DropdownMenu/DropdownMenuItem.d.ts +15 -2
  84. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  85. package/dist/DropdownMenu/DropdownMenuItem.js +20 -8
  86. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -1
  87. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  88. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +10 -3
  89. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +5 -5
  90. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  91. package/dist/DropdownMenu/DropdownMenuRadioItem.js +24 -67
  92. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  93. package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -8
  94. package/dist/DropdownMenu/index.d.ts +2 -1
  95. package/dist/DropdownMenu/index.d.ts.map +1 -1
  96. package/dist/DropdownMenu/index.js +4 -0
  97. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  98. package/dist/DropdownMenu/renderDropdownItems.js +35 -27
  99. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  100. package/dist/EmptyState/EmptyState.js +9 -5
  101. package/dist/Field/InputClearButton.d.ts +16 -3
  102. package/dist/Field/InputClearButton.d.ts.map +1 -1
  103. package/dist/Field/InputClearButton.js +15 -4
  104. package/dist/FileInput/FileInput.d.ts.map +1 -1
  105. package/dist/FileInput/FileInput.js +21 -10
  106. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  107. package/dist/HoverCard/useHoverCard.js +3 -19
  108. package/dist/Indicator/CheckIndicator.d.ts +25 -0
  109. package/dist/Indicator/CheckIndicator.d.ts.map +1 -0
  110. package/dist/Indicator/CheckIndicator.js +155 -0
  111. package/dist/Indicator/CheckboxIndicator.d.ts +22 -0
  112. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -0
  113. package/dist/Indicator/CheckboxIndicator.js +173 -0
  114. package/dist/Indicator/RadioIndicator.d.ts +23 -0
  115. package/dist/Indicator/RadioIndicator.d.ts.map +1 -0
  116. package/dist/Indicator/RadioIndicator.js +137 -0
  117. package/dist/Indicator/index.d.ts +24 -0
  118. package/dist/Indicator/index.d.ts.map +1 -0
  119. package/dist/Indicator/index.js +26 -0
  120. package/dist/Indicator/indicator.markers.stylex.d.ts +16 -0
  121. package/dist/Indicator/indicator.markers.stylex.d.ts.map +1 -0
  122. package/dist/Indicator/indicator.markers.stylex.js +21 -0
  123. package/dist/Indicator/indicatorRegistry.d.ts +71 -0
  124. package/dist/Indicator/indicatorRegistry.d.ts.map +1 -0
  125. package/dist/Indicator/indicatorRegistry.js +93 -0
  126. package/dist/Indicator/types.d.ts +177 -0
  127. package/dist/Indicator/types.d.ts.map +1 -0
  128. package/dist/Indicator/types.js +1 -0
  129. package/dist/Indicator/useIndicator.d.ts +18 -0
  130. package/dist/Indicator/useIndicator.d.ts.map +1 -0
  131. package/dist/Indicator/useIndicator.js +30 -0
  132. package/dist/Item/Item.d.ts.map +1 -1
  133. package/dist/Item/Item.js +4 -8
  134. package/dist/Layer/useLayer.d.ts +14 -0
  135. package/dist/Layer/useLayer.d.ts.map +1 -1
  136. package/dist/Layer/useLayer.js +25 -2
  137. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  138. package/dist/Lightbox/Lightbox.js +80 -103
  139. package/dist/Link/Link.d.ts.map +1 -1
  140. package/dist/Link/Link.js +4 -5
  141. package/dist/MobileNav/MobileNav.js +8 -8
  142. package/dist/MoreMenu/MoreMenu.d.ts +14 -1
  143. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  144. package/dist/MoreMenu/MoreMenu.js +4 -0
  145. package/dist/MultiSelector/MultiSelector.d.ts +8 -1
  146. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  147. package/dist/MultiSelector/MultiSelector.js +119 -95
  148. package/dist/NumberInput/NumberInput.d.ts +27 -1
  149. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  150. package/dist/NumberInput/NumberInput.js +230 -42
  151. package/dist/Outline/Outline.d.ts.map +1 -1
  152. package/dist/Outline/Outline.js +2 -3
  153. package/dist/Pagination/Pagination.d.ts.map +1 -1
  154. package/dist/Pagination/Pagination.js +61 -63
  155. package/dist/Popover/Popover.d.ts.map +1 -1
  156. package/dist/Popover/Popover.js +6 -8
  157. package/dist/Popover/usePopover.d.ts +15 -0
  158. package/dist/Popover/usePopover.d.ts.map +1 -1
  159. package/dist/Popover/usePopover.js +14 -2
  160. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  161. package/dist/PowerSearch/PowerSearch.js +1 -1
  162. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  163. package/dist/PowerSearch/PowerSearchEditPopover.js +7 -0
  164. package/dist/ProgressBar/ProgressBar.d.ts +11 -4
  165. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  166. package/dist/ProgressBar/ProgressBar.js +95 -6
  167. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  168. package/dist/RadioList/RadioListItem.js +29 -84
  169. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  170. package/dist/Resizable/ResizeHandle.js +2 -3
  171. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  172. package/dist/SegmentedControl/SegmentedControlItem.js +2 -3
  173. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  174. package/dist/SelectableCard/SelectableCard.js +3 -11
  175. package/dist/Selector/Selector.d.ts +12 -1
  176. package/dist/Selector/Selector.d.ts.map +1 -1
  177. package/dist/Selector/Selector.js +222 -111
  178. package/dist/Selector/hooks.d.ts +18 -6
  179. package/dist/Selector/hooks.d.ts.map +1 -1
  180. package/dist/Selector/hooks.js +57 -40
  181. package/dist/SideNav/SideNav.d.ts.map +1 -1
  182. package/dist/SideNav/SideNav.js +1 -1
  183. package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
  184. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  185. package/dist/SideNav/SideNavCollapseButton.js +29 -14
  186. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  187. package/dist/SideNav/SideNavHeading.js +56 -20
  188. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  189. package/dist/SideNav/SideNavItem.js +28 -22
  190. package/dist/Slider/Slider.d.ts.map +1 -1
  191. package/dist/Slider/Slider.js +2 -6
  192. package/dist/Stack/stack.stylex.d.ts +3 -3
  193. package/dist/Switch/Switch.d.ts.map +1 -1
  194. package/dist/Switch/Switch.js +14 -13
  195. package/dist/TabList/Tab.d.ts.map +1 -1
  196. package/dist/TabList/Tab.js +2 -3
  197. package/dist/TabList/TabMenu.d.ts.map +1 -1
  198. package/dist/TabList/TabMenu.js +41 -19
  199. package/dist/Table/BaseTable.d.ts.map +1 -1
  200. package/dist/Table/BaseTable.js +8 -0
  201. package/dist/Table/TableRow.d.ts +1 -1
  202. package/dist/Table/TableRow.d.ts.map +1 -1
  203. package/dist/Table/TableRow.js +4 -2
  204. package/dist/Table/index.d.ts +1 -1
  205. package/dist/Table/index.d.ts.map +1 -1
  206. package/dist/Table/index.js +1 -1
  207. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
  208. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  209. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +22 -18
  210. package/dist/Table/plugins/rowExpansion/index.d.ts +1 -1
  211. package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -1
  212. package/dist/Table/plugins/rowExpansion/index.js +1 -1
  213. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +41 -76
  214. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  215. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +94 -345
  216. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  217. package/dist/Table/plugins/sortable/useTableSortable.js +23 -4
  218. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  219. package/dist/Table/plugins/tree/useTableTreeData.js +29 -33
  220. package/dist/Table/tableContextMenu.d.ts.map +1 -1
  221. package/dist/Table/tableContextMenu.js +2 -1
  222. package/dist/Table/types.d.ts +11 -0
  223. package/dist/Table/types.d.ts.map +1 -1
  224. package/dist/TextArea/TextArea.d.ts +10 -1
  225. package/dist/TextArea/TextArea.d.ts.map +1 -1
  226. package/dist/TextArea/TextArea.js +16 -6
  227. package/dist/TextInput/TextInput.d.ts +10 -1
  228. package/dist/TextInput/TextInput.d.ts.map +1 -1
  229. package/dist/TextInput/TextInput.js +13 -19
  230. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  231. package/dist/Thumbnail/Thumbnail.js +32 -26
  232. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  233. package/dist/TimeInput/TimeInput.js +14 -17
  234. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  235. package/dist/Timestamp/Timestamp.js +14 -3
  236. package/dist/Timestamp/TimestampHoverCard.d.ts.map +1 -1
  237. package/dist/Timestamp/TimestampHoverCard.js +16 -34
  238. package/dist/Timestamp/formatInstant.d.ts +11 -1
  239. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  240. package/dist/Timestamp/formatInstant.js +3 -1
  241. package/dist/Token/Token.d.ts.map +1 -1
  242. package/dist/Token/Token.js +20 -11
  243. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  244. package/dist/Tokenizer/Tokenizer.js +4 -2
  245. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  246. package/dist/Tooltip/useTooltip.js +3 -19
  247. package/dist/TopNav/TopNav.d.ts.map +1 -1
  248. package/dist/TopNav/TopNav.js +6 -5
  249. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  250. package/dist/TopNav/TopNavHeading.js +54 -16
  251. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  252. package/dist/TopNav/TopNavItem.js +3 -9
  253. package/dist/TopNav/TopNavMegaMenu.d.ts +7 -0
  254. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  255. package/dist/TopNav/TopNavMegaMenu.js +146 -60
  256. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  257. package/dist/TopNav/TopNavMegaMenuItem.js +22 -3
  258. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  259. package/dist/TopNav/TopNavMenu.js +83 -38
  260. package/dist/TreeList/TreeList.d.ts.map +1 -1
  261. package/dist/TreeList/TreeList.js +13 -0
  262. package/dist/TreeList/TreeListBranches.d.ts +1 -1
  263. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  264. package/dist/TreeList/TreeListBranches.js +14 -4
  265. package/dist/TreeList/TreeListItem.d.ts +11 -1
  266. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  267. package/dist/TreeList/TreeListItem.js +57 -30
  268. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  269. package/dist/Typeahead/BaseTypeahead.js +16 -8
  270. package/dist/astryx.css +84 -96
  271. package/dist/astryx.umd.js +56 -56
  272. package/dist/astryx.umd.js.map +4 -4
  273. package/dist/hooks/containerReveal.stylex.d.ts +61 -0
  274. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -0
  275. package/dist/hooks/containerReveal.stylex.js +63 -0
  276. package/dist/hooks/index.d.ts +3 -0
  277. package/dist/hooks/index.d.ts.map +1 -1
  278. package/dist/hooks/index.js +2 -0
  279. package/dist/hooks/useClipboard.d.ts +59 -0
  280. package/dist/hooks/useClipboard.d.ts.map +1 -0
  281. package/dist/hooks/useClipboard.js +106 -0
  282. package/dist/hooks/useContainerReveal.d.ts +14 -8
  283. package/dist/hooks/useContainerReveal.d.ts.map +1 -1
  284. package/dist/hooks/useContainerReveal.js +28 -69
  285. package/dist/hooks/useIndicatorFocusRing.d.ts +28 -0
  286. package/dist/hooks/useIndicatorFocusRing.d.ts.map +1 -0
  287. package/dist/hooks/useIndicatorFocusRing.js +96 -0
  288. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  289. package/dist/hooks/useInputStatusIcon.js +17 -4
  290. package/dist/hooks/useLongPress.d.ts.map +1 -1
  291. package/dist/hooks/useLongPress.js +12 -2
  292. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  293. package/dist/hooks/useScrollLock.js +33 -18
  294. package/dist/hooks/useStreamingText.d.ts +18 -3
  295. package/dist/hooks/useStreamingText.d.ts.map +1 -1
  296. package/dist/hooks/useStreamingText.js +47 -7
  297. package/dist/hooks/useTreeFocus.d.ts.map +1 -1
  298. package/dist/hooks/useTreeFocus.js +9 -3
  299. package/dist/hooks/useTypeahead.d.ts +3 -2
  300. package/dist/hooks/useTypeahead.d.ts.map +1 -1
  301. package/dist/hooks/useTypeahead.js +19 -7
  302. package/dist/index.d.ts +1 -0
  303. package/dist/index.d.ts.map +1 -1
  304. package/dist/index.js +1 -0
  305. package/dist/theme/defineTheme.d.ts +18 -2
  306. package/dist/theme/defineTheme.d.ts.map +1 -1
  307. package/dist/theme/defineTheme.js +10 -1
  308. package/dist/theme/derivedVarRegistry.d.ts +8 -0
  309. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  310. package/dist/theme/derivedVarRegistry.js +14 -13
  311. package/dist/theme/expandColorScale.d.ts +3 -1
  312. package/dist/theme/expandColorScale.d.ts.map +1 -1
  313. package/dist/theme/expandColorScale.js +17 -7
  314. package/dist/theme/expandTypeScale.d.ts.map +1 -1
  315. package/dist/theme/expandTypeScale.js +17 -0
  316. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  317. package/dist/theme/generateThemeRules.js +11 -0
  318. package/dist/theme/index.d.ts +2 -1
  319. package/dist/theme/index.d.ts.map +1 -1
  320. package/dist/theme/index.js +1 -1
  321. package/dist/theme/tokens.stylex.d.ts +12 -0
  322. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  323. package/dist/theme/tokens.stylex.js +23 -0
  324. package/dist/utils/focusOutline.stylex.d.ts +122 -0
  325. package/dist/utils/focusOutline.stylex.d.ts.map +1 -0
  326. package/dist/utils/focusOutline.stylex.js +143 -0
  327. package/dist/utils/focusReturn.d.ts +24 -0
  328. package/dist/utils/focusReturn.d.ts.map +1 -0
  329. package/dist/utils/focusReturn.js +29 -0
  330. package/dist/utils/index.d.ts +2 -0
  331. package/dist/utils/index.d.ts.map +1 -1
  332. package/dist/utils/index.js +6 -1
  333. package/dist/utils/mergeRefs.d.ts.map +1 -1
  334. package/dist/utils/mergeRefs.js +7 -5
  335. package/dist/utils/rtlStyles.d.ts +2 -2
  336. package/dist/utils/rtlStyles.js +2 -2
  337. package/dist/utils/themeProps.d.ts +20 -1
  338. package/dist/utils/themeProps.d.ts.map +1 -1
  339. package/dist/utils/themeProps.js +8 -2
  340. package/locales/en.json +52 -0
  341. package/locales/pseudo.json +39 -0
  342. package/package.json +8 -3
  343. package/src/AlertDialog/AlertDialog.doc.mjs +16 -3
  344. package/src/AlertDialog/AlertDialog.test.tsx +208 -1
  345. package/src/AlertDialog/AlertDialog.tsx +21 -3
  346. package/src/AppShell/AppShell.doc.mjs +11 -0
  347. package/src/AppShell/AppShell.test.tsx +139 -0
  348. package/src/AppShell/AppShell.tsx +32 -22
  349. package/src/AspectRatio/AspectRatio.doc.mjs +27 -3
  350. package/src/AspectRatio/AspectRatio.test.tsx +30 -0
  351. package/src/AspectRatio/AspectRatio.tsx +13 -0
  352. package/src/Avatar/Avatar.doc.mjs +2 -13
  353. package/src/Avatar/Avatar.test.tsx +33 -8
  354. package/src/Avatar/Avatar.tsx +52 -50
  355. package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -9
  356. package/src/Banner/Banner.test.tsx +58 -1
  357. package/src/Banner/Banner.tsx +33 -11
  358. package/src/Breadcrumbs/BreadcrumbItem.tsx +16 -6
  359. package/src/Breadcrumbs/index.ts +5 -1
  360. package/src/Button/Button.doc.mjs +2 -2
  361. package/src/Button/Button.tsx +22 -41
  362. package/src/Calendar/Calendar.tsx +2 -1
  363. package/src/Calendar/styles.ts +0 -8
  364. package/src/Carousel/Carousel.doc.mjs +3 -0
  365. package/src/Carousel/Carousel.tsx +10 -6
  366. package/src/Chat/Chat.doc.mjs +2 -0
  367. package/src/Chat/ChatDictationButton.tsx +7 -1
  368. package/src/Chat/ChatLayoutScrollButton.test.tsx +22 -0
  369. package/src/Chat/ChatLayoutScrollButton.tsx +8 -1
  370. package/src/Chat/ChatSendButton.tsx +2 -3
  371. package/src/Chat/ChatToolCalls.test.tsx +35 -0
  372. package/src/Chat/ChatToolCalls.tsx +36 -16
  373. package/src/Chat/useTriggerMenu.tsx +2 -5
  374. package/src/CheckboxInput/CheckboxInput.doc.mjs +4 -2
  375. package/src/CheckboxInput/CheckboxInput.test.tsx +120 -0
  376. package/src/CheckboxInput/CheckboxInput.tsx +45 -202
  377. package/src/ClickableCard/ClickableCard.tsx +6 -11
  378. package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
  379. package/src/CodeBlock/CodeBlock.test.tsx +91 -0
  380. package/src/CodeBlock/CodeBlock.tsx +57 -80
  381. package/src/Collapsible/Collapsible.tsx +22 -18
  382. package/src/CommandPalette/CommandPalette.test.tsx +29 -0
  383. package/src/CommandPalette/CommandPaletteItem.tsx +7 -4
  384. package/src/CommandPalette/CommandPaletteList.tsx +2 -2
  385. package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
  386. package/src/ComplexSelector/ComplexSelector.test.tsx +73 -0
  387. package/src/ComplexSelector/ComplexSelector.tsx +41 -28
  388. package/src/ContextMenu/ContextMenu.doc.mjs +1 -1
  389. package/src/ContextMenu/ContextMenu.test.tsx +41 -0
  390. package/src/ContextMenu/ContextMenu.tsx +3 -3
  391. package/src/ContextMenu/index.ts +5 -1
  392. package/src/DateInput/DateInput.doc.mjs +18 -3
  393. package/src/DateInput/DateInput.test.tsx +112 -11
  394. package/src/DateInput/DateInput.tsx +44 -25
  395. package/src/DateRangeInput/DateRangeInput.doc.mjs +10 -2
  396. package/src/DateRangeInput/DateRangeInput.test.tsx +110 -14
  397. package/src/DateRangeInput/DateRangeInput.tsx +27 -21
  398. package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -2
  399. package/src/DateTimeInput/DateTimeInput.test.tsx +154 -1
  400. package/src/DateTimeInput/DateTimeInput.tsx +58 -17
  401. package/src/Dialog/Dialog.tsx +2 -9
  402. package/src/DropdownMenu/DropdownMenu.doc.mjs +5 -9
  403. package/src/DropdownMenu/DropdownMenu.test.tsx +534 -4
  404. package/src/DropdownMenu/DropdownMenu.tsx +113 -52
  405. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +27 -30
  406. package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +34 -0
  407. package/src/DropdownMenu/DropdownMenuDivider.tsx +81 -0
  408. package/src/DropdownMenu/DropdownMenuItem.doc.mjs +39 -4
  409. package/src/DropdownMenu/DropdownMenuItem.tsx +48 -10
  410. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +2 -1
  411. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +30 -76
  412. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +25 -19
  413. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +44 -14
  414. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +1 -5
  415. package/src/DropdownMenu/index.ts +8 -1
  416. package/src/DropdownMenu/renderDropdownItems.tsx +33 -34
  417. package/src/EmptyState/EmptyState.doc.mjs +4 -0
  418. package/src/EmptyState/EmptyState.test.tsx +62 -0
  419. package/src/EmptyState/EmptyState.tsx +16 -6
  420. package/src/Field/Field.doc.mjs +1 -0
  421. package/src/Field/InputClearButton.test.tsx +117 -0
  422. package/src/Field/InputClearButton.tsx +30 -3
  423. package/src/FileInput/FileInput.tsx +21 -8
  424. package/src/HoverCard/useHoverCard.tsx +2 -23
  425. package/src/Icon/Icon.doc.mjs +2 -1
  426. package/src/Indicator/CheckIndicator.tsx +174 -0
  427. package/src/Indicator/CheckboxIndicator.tsx +257 -0
  428. package/src/Indicator/Indicator.doc.mjs +344 -0
  429. package/src/Indicator/Indicator.test.tsx +393 -0
  430. package/src/Indicator/RadioIndicator.tsx +206 -0
  431. package/src/Indicator/index.ts +46 -0
  432. package/src/Indicator/indicator.markers.stylex.ts +19 -0
  433. package/src/Indicator/indicatorRegistry.test.tsx +106 -0
  434. package/src/Indicator/indicatorRegistry.ts +120 -0
  435. package/src/Indicator/types.ts +197 -0
  436. package/src/Indicator/useIndicator.ts +39 -0
  437. package/src/Item/Item.doc.mjs +1 -1
  438. package/src/Item/Item.tsx +7 -14
  439. package/src/Layer/useLayer.doc.mjs +2 -2
  440. package/src/Layer/useLayer.test.tsx +85 -0
  441. package/src/Layer/useLayer.tsx +39 -1
  442. package/src/Lightbox/Lightbox.doc.mjs +1 -1
  443. package/src/Lightbox/Lightbox.tsx +45 -49
  444. package/src/Link/Link.tsx +4 -11
  445. package/src/MobileNav/MobileNav.tsx +3 -3
  446. package/src/MoreMenu/MoreMenu.doc.mjs +31 -0
  447. package/src/MoreMenu/MoreMenu.test.tsx +68 -1
  448. package/src/MoreMenu/MoreMenu.tsx +19 -0
  449. package/src/MultiSelector/MultiSelector.doc.mjs +16 -1
  450. package/src/MultiSelector/MultiSelector.test.tsx +259 -16
  451. package/src/MultiSelector/MultiSelector.tsx +144 -121
  452. package/src/NumberInput/NumberInput.doc.mjs +265 -50
  453. package/src/NumberInput/NumberInput.test.tsx +726 -21
  454. package/src/NumberInput/NumberInput.tsx +353 -59
  455. package/src/Outline/Outline.tsx +2 -5
  456. package/src/Pagination/Pagination.doc.mjs +1 -1
  457. package/src/Pagination/Pagination.test.tsx +22 -7
  458. package/src/Pagination/Pagination.tsx +38 -35
  459. package/src/Popover/Popover.doc.mjs +2 -0
  460. package/src/Popover/Popover.tsx +6 -7
  461. package/src/Popover/usePopover.tsx +37 -4
  462. package/src/PowerSearch/PowerSearch.tsx +1 -1
  463. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +42 -0
  464. package/src/PowerSearch/PowerSearchEditPopover.tsx +7 -0
  465. package/src/ProgressBar/ProgressBar.doc.mjs +27 -5
  466. package/src/ProgressBar/ProgressBar.test.tsx +224 -1
  467. package/src/ProgressBar/ProgressBar.tsx +126 -30
  468. package/src/RadioList/RadioList.doc.mjs +4 -2
  469. package/src/RadioList/RadioListItem.tsx +31 -130
  470. package/src/Resizable/ResizeHandle.tsx +2 -9
  471. package/src/SegmentedControl/SegmentedControlItem.tsx +2 -9
  472. package/src/SelectableCard/SelectableCard.tsx +4 -9
  473. package/src/Selector/Selector.doc.mjs +15 -4
  474. package/src/Selector/Selector.test.tsx +1234 -98
  475. package/src/Selector/Selector.tsx +254 -126
  476. package/src/Selector/hooks.ts +77 -50
  477. package/src/SideNav/SideNav.test.tsx +46 -0
  478. package/src/SideNav/SideNav.tsx +1 -0
  479. package/src/SideNav/SideNavCollapseButton.tsx +15 -10
  480. package/src/SideNav/SideNavHeading.tsx +48 -10
  481. package/src/SideNav/SideNavItem.tsx +20 -12
  482. package/src/Slider/Slider.tsx +2 -11
  483. package/src/Stack/Stack.doc.mjs +110 -0
  484. package/src/StatusDot/StatusDot.doc.mjs +12 -3
  485. package/src/Switch/Switch.test.tsx +32 -0
  486. package/src/Switch/Switch.tsx +18 -10
  487. package/src/TabList/Tab.tsx +2 -9
  488. package/src/TabList/TabMenu.tsx +14 -21
  489. package/src/Table/BaseTable.tsx +11 -0
  490. package/src/Table/Table.test.tsx +31 -0
  491. package/src/Table/TableRow.tsx +6 -0
  492. package/src/Table/index.ts +1 -4
  493. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +30 -14
  494. package/src/Table/plugins/rowExpansion/index.ts +1 -4
  495. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +125 -175
  496. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +115 -458
  497. package/src/Table/plugins/sortable/useTableSortable.tsx +2 -6
  498. package/src/Table/plugins/tree/useTableTreeData.tsx +43 -24
  499. package/src/Table/tableContextMenu.test.tsx +27 -0
  500. package/src/Table/tableContextMenu.tsx +1 -0
  501. package/src/Table/types.ts +11 -0
  502. package/src/Table/useTableGroupedRows.doc.mjs +1 -1
  503. package/src/Table/useTableRowExpansion.doc.mjs +43 -66
  504. package/src/TextArea/TextArea.doc.mjs +42 -2
  505. package/src/TextArea/TextArea.test.tsx +219 -0
  506. package/src/TextArea/TextArea.tsx +34 -7
  507. package/src/TextInput/TextInput.doc.mjs +18 -2
  508. package/src/TextInput/TextInput.test.tsx +189 -0
  509. package/src/TextInput/TextInput.tsx +25 -31
  510. package/src/Thumbnail/Thumbnail.tsx +2 -9
  511. package/src/TimeInput/TimeInput.doc.mjs +2 -2
  512. package/src/TimeInput/TimeInput.test.tsx +84 -3
  513. package/src/TimeInput/TimeInput.tsx +26 -28
  514. package/src/Timestamp/Timestamp.doc.mjs +4 -3
  515. package/src/Timestamp/Timestamp.test.tsx +91 -14
  516. package/src/Timestamp/Timestamp.tsx +14 -2
  517. package/src/Timestamp/TimestampHoverCard.tsx +13 -35
  518. package/src/Timestamp/formatInstant.ts +16 -1
  519. package/src/Token/Token.tsx +5 -28
  520. package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
  521. package/src/Tokenizer/Tokenizer.test.tsx +45 -3
  522. package/src/Tokenizer/Tokenizer.tsx +10 -2
  523. package/src/Tooltip/useTooltip.tsx +2 -23
  524. package/src/TopNav/TopNav.tsx +1 -3
  525. package/src/TopNav/TopNavHeading.tsx +42 -13
  526. package/src/TopNav/TopNavItem.tsx +3 -21
  527. package/src/TopNav/TopNavMegaMenu.doc.mjs +5 -0
  528. package/src/TopNav/TopNavMegaMenu.test.tsx +433 -33
  529. package/src/TopNav/TopNavMegaMenu.tsx +118 -53
  530. package/src/TopNav/TopNavMegaMenuItem.tsx +2 -9
  531. package/src/TopNav/TopNavMenu.tsx +34 -37
  532. package/src/TreeList/TreeList.doc.mjs +5 -0
  533. package/src/TreeList/TreeList.test.tsx +208 -8
  534. package/src/TreeList/TreeList.tsx +22 -0
  535. package/src/TreeList/TreeListBranches.tsx +25 -2
  536. package/src/TreeList/TreeListItem.tsx +89 -52
  537. package/src/Typeahead/BaseTypeahead.tsx +19 -6
  538. package/src/Typeahead/Typeahead.doc.mjs +1 -0
  539. package/src/Typeahead/Typeahead.test.tsx +76 -3
  540. package/src/hooks/containerReveal.stylex.ts +102 -0
  541. package/src/hooks/index.ts +4 -0
  542. package/src/hooks/useClipboard.doc.mjs +87 -0
  543. package/src/hooks/useClipboard.test.tsx +151 -0
  544. package/src/hooks/useClipboard.ts +135 -0
  545. package/src/hooks/useContainerReveal.doc.mjs +7 -7
  546. package/src/hooks/useContainerReveal.test.tsx +42 -62
  547. package/src/hooks/useContainerReveal.ts +36 -91
  548. package/src/hooks/useImageMode.test.ts +1 -1
  549. package/src/hooks/useIndicatorFocusRing.tsx +120 -0
  550. package/src/hooks/useInputStatusIcon.tsx +8 -8
  551. package/src/hooks/useLongPress.test.tsx +18 -0
  552. package/src/hooks/useLongPress.ts +12 -2
  553. package/src/hooks/useScrollLock.test.ts +72 -0
  554. package/src/hooks/useScrollLock.ts +51 -19
  555. package/src/hooks/useStreamingText.test.ts +46 -1
  556. package/src/hooks/useStreamingText.ts +49 -7
  557. package/src/hooks/useTreeFocus.test.tsx +50 -0
  558. package/src/hooks/useTreeFocus.ts +14 -3
  559. package/src/hooks/useTypeahead.test.tsx +150 -0
  560. package/src/hooks/useTypeahead.ts +24 -9
  561. package/src/i18n/InternationalizationProvider.doc.mjs +7 -2
  562. package/src/index.ts +1 -0
  563. package/src/theme/defineTheme.ts +27 -0
  564. package/src/theme/derivedVarRegistry.test.ts +21 -1
  565. package/src/theme/derivedVarRegistry.ts +19 -6
  566. package/src/theme/expandColorScale.test.ts +14 -0
  567. package/src/theme/expandColorScale.ts +24 -9
  568. package/src/theme/expandTypeScale.test.ts +43 -0
  569. package/src/theme/expandTypeScale.ts +17 -0
  570. package/src/theme/generateThemeRules.test.ts +78 -20
  571. package/src/theme/generateThemeRules.ts +11 -0
  572. package/src/theme/index.ts +15 -0
  573. package/src/theme/tokens.stylex.ts +18 -0
  574. package/src/theme/tokens.test.ts +37 -0
  575. package/src/utils/focusOutline.stylex.ts +177 -0
  576. package/src/utils/focusReturn.test.ts +42 -0
  577. package/src/utils/focusReturn.ts +31 -0
  578. package/src/utils/index.ts +5 -0
  579. package/src/utils/mergeRefs.test.ts +48 -0
  580. package/src/utils/mergeRefs.ts +12 -6
  581. package/src/utils/rtlStyles.ts +2 -2
  582. package/src/utils/themeProps.ts +26 -4
  583. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts +0 -9
  584. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts.map +0 -1
  585. package/dist/CheckboxInput/checkbox.markers.stylex.js +0 -14
  586. package/dist/RadioList/radio.markers.stylex.d.ts +0 -7
  587. package/dist/RadioList/radio.markers.stylex.d.ts.map +0 -1
  588. package/dist/RadioList/radio.markers.stylex.js +0 -12
  589. package/dist/hooks/containerReveal.pool.stylex.d.ts +0 -303
  590. package/dist/hooks/containerReveal.pool.stylex.d.ts.map +0 -1
  591. package/dist/hooks/containerReveal.pool.stylex.js +0 -292
  592. package/src/CheckboxInput/checkbox.markers.stylex.ts +0 -12
  593. package/src/RadioList/radio.markers.stylex.ts +0 -10
  594. 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: {
@@ -14,6 +14,7 @@ import {render, screen, fireEvent, waitFor} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {TimeInput} from './TimeInput';
16
16
  import {InputGroup, InputGroupText} from '../InputGroup';
17
+ import {InternationalizationProvider} from '../i18n';
17
18
  import type {ISOTimeString} from '../utils';
18
19
  import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
19
20
 
@@ -209,6 +210,59 @@ describe('TimeInput', () => {
209
210
  expect(screen.queryByText('Invalid time')).not.toBeInTheDocument();
210
211
  });
211
212
 
213
+ it('resolves the invalid-time announcement from the i18n catalog', () => {
214
+ render(
215
+ <InternationalizationProvider
216
+ locale="en"
217
+ overrides={{en: {'@astryx.timeInput.invalidTime': 'Ungültige Zeit'}}}>
218
+ <TimeInput label="Time" onChange={() => {}} />
219
+ </InternationalizationProvider>,
220
+ );
221
+
222
+ fireEvent.change(screen.getByRole('textbox'), {target: {value: '25:99'}});
223
+
224
+ expect(screen.getByRole('alert')).toHaveTextContent('Ungültige Zeit');
225
+ });
226
+
227
+ // Arrow-key stepping mutates a plain textbox programmatically, and screen
228
+ // readers do not announce programmatic textbox changes — the new value must
229
+ // be announced through the polite live region (WCAG 4.1.2).
230
+ it('politely announces the new time after ArrowUp stepping', async () => {
231
+ const onChange = vi.fn();
232
+ render(
233
+ <TimeInput
234
+ label="Time"
235
+ value={'14:30' as ISOTimeString}
236
+ onChange={onChange}
237
+ />,
238
+ );
239
+
240
+ fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowUp'});
241
+
242
+ expect(onChange).toHaveBeenCalledWith('14:31');
243
+ await waitFor(() => {
244
+ expect(politeRegion()).toHaveTextContent('2:31 PM');
245
+ });
246
+ });
247
+
248
+ it('politely announces the new time after ArrowDown stepping', async () => {
249
+ const onChange = vi.fn();
250
+ render(
251
+ <TimeInput
252
+ label="Time"
253
+ value={'14:30' as ISOTimeString}
254
+ onChange={onChange}
255
+ />,
256
+ );
257
+
258
+ fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowDown'});
259
+
260
+ expect(onChange).toHaveBeenCalledWith('14:29');
261
+ await waitFor(() => {
262
+ expect(politeRegion()).toHaveTextContent('2:29 PM');
263
+ });
264
+ });
265
+
212
266
  it('calls onChange on blur when input is valid', async () => {
213
267
  const user = userEvent.setup();
214
268
  const onChange = vi.fn();
@@ -572,11 +626,15 @@ describe('TimeInput', () => {
572
626
  });
573
627
  });
574
628
 
575
-
576
629
  describe('TimeInput statusVariant forwarding', () => {
577
630
  it('defaults to attached (status renders with data-variant="attached")', () => {
578
631
  const {container} = render(
579
- <TimeInput label="Start" value={undefined} onChange={() => {}} status={{type: 'error', message: 'Required'}} />,
632
+ <TimeInput
633
+ label="Start"
634
+ value={undefined}
635
+ onChange={() => {}}
636
+ status={{type: 'error', message: 'Required'}}
637
+ />,
580
638
  );
581
639
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
582
640
  'data-variant',
@@ -586,7 +644,13 @@ describe('TimeInput statusVariant forwarding', () => {
586
644
 
587
645
  it('forwards statusVariant="detached" to the underlying Field status', () => {
588
646
  const {container} = render(
589
- <TimeInput label="Start" value={undefined} onChange={() => {}} status={{type: 'error', message: 'Required'}} statusVariant="detached" />,
647
+ <TimeInput
648
+ label="Start"
649
+ value={undefined}
650
+ onChange={() => {}}
651
+ status={{type: 'error', message: 'Required'}}
652
+ statusVariant="detached"
653
+ />,
590
654
  );
591
655
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
592
656
  'data-variant',
@@ -594,3 +658,20 @@ describe('TimeInput statusVariant forwarding', () => {
594
658
  );
595
659
  });
596
660
  });
661
+
662
+ describe('TimeInput disabled theme state', () => {
663
+ it('reflects disabled on the root target so themes can gate paint on it', () => {
664
+ const {container} = render(
665
+ <TimeInput label="Time" onChange={() => {}} isDisabled />,
666
+ );
667
+ const root = container.querySelector('.astryx-time-input');
668
+ expect(root).toHaveAttribute('data-disabled', 'disabled');
669
+ expect(root).toHaveClass('disabled');
670
+ });
671
+
672
+ it('omits data-disabled when enabled, like status does', () => {
673
+ const {container} = render(<TimeInput label="Time" onChange={() => {}} />);
674
+ const root = container.querySelector('.astryx-time-input');
675
+ expect(root).not.toHaveAttribute('data-disabled');
676
+ });
677
+ });
@@ -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({
@@ -576,10 +558,25 @@ export function TimeInput({
576
558
  // Check if within range
577
559
  if (isTimeInRange(newTime, min, max)) {
578
560
  fireChange(newTime);
561
+ // Stepping programmatically rewrites a plain textbox's value, and
562
+ // screen readers do not announce programmatic textbox changes — the
563
+ // new value must be spoken explicitly or stepping is silent
564
+ // (WCAG 4.1.2).
565
+ announce(formatDisplayTime(newTime, hasSeconds));
579
566
  }
580
567
  }
581
568
  },
582
- [value, hasSeconds, increment, min, max, fireChange, isDisabled],
569
+ [
570
+ value,
571
+ hasSeconds,
572
+ increment,
573
+ min,
574
+ max,
575
+ fireChange,
576
+ isDisabled,
577
+ announce,
578
+ formatDisplayTime,
579
+ ],
583
580
  );
584
581
 
585
582
  // Handle clear button click
@@ -608,7 +605,11 @@ export function TimeInput({
608
605
  onClick={handleWrapperClick}
609
606
  onMouseUp={handleWrapperMouseUp}
610
607
  {...mergeProps(
611
- themeProps('time-input', {size, status: status?.type ?? null}),
608
+ themeProps('time-input', {
609
+ size,
610
+ status: status?.type ?? null,
611
+ disabled: isDisabled ? 'disabled' : null,
612
+ }),
612
613
  stylex.props(
613
614
  inputWrapperStyles.base,
614
615
  sizeStyles[size],
@@ -673,17 +674,14 @@ export function TimeInput({
673
674
  user would get no feedback that their entry was rejected (WCAG 3.3.1).
674
675
  */}
675
676
  <VisuallyHidden as="div" role="alert" aria-live="assertive">
676
- {!isInputValid ? 'Invalid time' : ''}
677
+ {!isInputValid ? t('@astryx.timeInput.invalidTime') : ''}
677
678
  </VisuallyHidden>
678
679
  {isBusy && <Spinner size="sm" />}
679
680
  {hasClear && value && !isDisabled && (
680
- <button
681
- type="button"
681
+ <InputClearButton
682
+ label={t('@astryx.timeInput.clearLabel', {label})}
682
683
  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>
684
+ />
687
685
  )}
688
686
  {statusIcon}
689
687
  </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.'},
@@ -408,6 +408,50 @@ describe('Timestamp', () => {
408
408
  expect(el.getAttribute('aria-label')).toBeNull();
409
409
  });
410
410
 
411
+ // Timezone abbreviations like "PST" or "GMT+2" are unexpanded abbreviations
412
+ // to a screen-reader user (WCAG 3.1.4) — the AT-facing aria-label must spell
413
+ // the timezone out in full, while visible text keeps the compact short form.
414
+ it('uses the long timezone name in the aria-label (WCAG 3.1.4)', () => {
415
+ const oneHourAgo = new Date(Date.now() - 3600 * 1000);
416
+ render(
417
+ <Timestamp
418
+ value={oneHourAgo.getTime() / 1000}
419
+ format="relative"
420
+ hasTooltip={false}
421
+ data-testid="ts"
422
+ />,
423
+ );
424
+
425
+ const longTz =
426
+ new Intl.DateTimeFormat(undefined, {timeZoneName: 'long'})
427
+ .formatToParts(oneHourAgo)
428
+ .find(p => p.type === 'timeZoneName')?.value ?? '';
429
+ expect(longTz).not.toBe('');
430
+ expect(screen.getByTestId('ts').getAttribute('aria-label')).toContain(
431
+ longTz,
432
+ );
433
+ });
434
+
435
+ it('keeps the short timezone form in visible text when isTimezoneShown', () => {
436
+ const date = new Date('2026-03-25T10:00:00Z');
437
+ render(
438
+ <Timestamp
439
+ value="2026-03-25T10:00:00Z"
440
+ format="time"
441
+ isTimezoneShown
442
+ data-testid="ts"
443
+ />,
444
+ );
445
+
446
+ const tzPart = (form: 'short' | 'long') =>
447
+ new Intl.DateTimeFormat(undefined, {timeZoneName: form})
448
+ .formatToParts(date)
449
+ .find(p => p.type === 'timeZoneName')?.value ?? '';
450
+ const text = screen.getByTestId('ts').textContent ?? '';
451
+ expect(text).toContain(tzPart('short'));
452
+ expect(text).not.toContain(tzPart('long'));
453
+ });
454
+
411
455
  // --- Input handling ---
412
456
 
413
457
  it('accepts Unix timestamp in seconds', () => {
@@ -602,15 +646,26 @@ describe('Timestamp', () => {
602
646
  );
603
647
  const el = screen.getByTestId('ts');
604
648
 
605
- // The card layer mounts inline and carries the full absolute time (the
606
- // same string as the aria-label) as its single default copyable row.
649
+ // The card layer mounts inline and carries the full absolute time in
650
+ // its visible form (short timezone abbreviation) as its single default
651
+ // copyable row. The aria-label spells the timezone out in full
652
+ // (WCAG 3.1.4), so the two strings intentionally differ — compare the
653
+ // card against an independently formatted short-form string.
607
654
  // Compare with normalized whitespace: Intl output can contain narrow
608
655
  // no-break spaces that jest-dom's matcher normalization would break on.
609
656
  const card = await screen.findByRole('dialog', {hidden: true});
610
657
  const normalize = (s: string) => s.replace(/\s+/g, ' ');
611
- expect(normalize(card.textContent ?? '')).toContain(
612
- normalize(el.getAttribute('aria-label') ?? '\0'),
613
- );
658
+ const datetime = new Date(el.getAttribute('datetime') ?? '');
659
+ const expected = new Intl.DateTimeFormat(undefined, {
660
+ year: 'numeric',
661
+ month: 'long',
662
+ day: 'numeric',
663
+ hour: 'numeric',
664
+ minute: '2-digit',
665
+ second: '2-digit',
666
+ timeZoneName: 'short',
667
+ }).format(datetime);
668
+ expect(normalize(card.textContent ?? '')).toContain(normalize(expected));
614
669
 
615
670
  // Tab onto the timestamp — the only tab stop in the document.
616
671
  await user.tab();
@@ -705,15 +760,28 @@ describe('Timestamp', () => {
705
760
  // The default card is the named details card, exactly as the configured
706
761
  // one is.
707
762
  expect(card).toHaveAttribute('aria-label', 'Timestamp details');
708
- // Exactly one row, carrying the full absolute time (the same string as
709
- // the aria-label) with its own copy button.
763
+ // Exactly one row, carrying the full absolute time in its visible form
764
+ // (short timezone abbreviation) with its own copy button. The
765
+ // aria-label spells the timezone out in full (WCAG 3.1.4), so the two
766
+ // strings intentionally differ — compare the row against an
767
+ // independently formatted short-form string.
710
768
  expect(card.querySelectorAll('dd')).toHaveLength(1);
711
769
  expect(card.querySelectorAll('button')).toHaveLength(1);
712
770
 
713
771
  const normalize = (s: string) => s.replace(/\s+/g, ' ');
714
- expect(normalize(card.textContent ?? '')).toContain(
715
- normalize(screen.getByTestId('ts').getAttribute('aria-label') ?? '\0'),
772
+ const datetime = new Date(
773
+ screen.getByTestId('ts').getAttribute('datetime') ?? '',
716
774
  );
775
+ const expected = new Intl.DateTimeFormat(undefined, {
776
+ year: 'numeric',
777
+ month: 'long',
778
+ day: 'numeric',
779
+ hour: 'numeric',
780
+ minute: '2-digit',
781
+ second: '2-digit',
782
+ timeZoneName: 'short',
783
+ }).format(datetime);
784
+ expect(normalize(card.textContent ?? '')).toContain(normalize(expected));
717
785
  });
718
786
 
719
787
  it("copies the default absolute row's value", async () => {
@@ -1171,10 +1239,14 @@ describe('Timestamp', () => {
1171
1239
  },
1172
1240
  );
1173
1241
 
1174
- it('renders the full style identically as the aria-label and as a line', () => {
1242
+ it('renders the full style as the aria-label and as a line, differing only in zone-name spelling', () => {
1175
1243
  // 'full' is the one member with no visible-text counterpart — it backs
1176
1244
  // the accessible name of a relative timestamp and the tooltip's default
1177
- // line. Those two must not drift apart either.
1245
+ // line. The two must not drift apart on anything but the zone name: the
1246
+ // aria-label spells the zone out in full for assistive tech (WCAG 3.1.4),
1247
+ // the visible line keeps the abbreviation. Comparing them after swapping
1248
+ // the abbreviation for the spelled-out form keeps this a direct
1249
+ // surface-to-surface check, so re-forking either path still fails here.
1178
1250
  render(
1179
1251
  <Timestamp
1180
1252
  value={VALUE}
@@ -1183,9 +1255,14 @@ describe('Timestamp', () => {
1183
1255
  data-testid="ts"
1184
1256
  />,
1185
1257
  );
1186
- const [line] = formatTooltipLines(new Date(VALUE), [{format: 'full'}]);
1187
- expect(line.value).toBe(
1188
- screen.getByTestId('ts').getAttribute('aria-label'),
1258
+ const date = new Date(VALUE);
1259
+ const tzPart = (form: 'short' | 'long') =>
1260
+ new Intl.DateTimeFormat(undefined, {timeZoneName: form})
1261
+ .formatToParts(date)
1262
+ .find(p => p.type === 'timeZoneName')?.value ?? '';
1263
+ const [line] = formatTooltipLines(date, [{format: 'full'}]);
1264
+ expect(screen.getByTestId('ts').getAttribute('aria-label')).toBe(
1265
+ line.value.replace(tzPart('short'), tzPart('long')),
1189
1266
  );
1190
1267
  });
1191
1268
  });
@@ -451,8 +451,14 @@ export function Timestamp({
451
451
  ? formatInstant(date, effectiveFormat, {isTimezoneShown})
452
452
  : '';
453
453
 
454
- // Full absolute text for tooltip and aria-label
454
+ // Full absolute text for the tooltip (visible — keeps the compact timezone
455
+ // abbreviation) and for the AT-facing aria-label, which spells the timezone
456
+ // out in full: abbreviations like "PST" or "GMT+2" are unexpanded
457
+ // abbreviations to a screen-reader user (WCAG 3.1.4).
455
458
  const fullAbsoluteText = isValidDate ? formatInstant(date, 'full') : '';
459
+ const ariaLabelText = isValidDate
460
+ ? formatInstant(date, 'full', {timeZoneNameStyle: 'long'})
461
+ : '';
456
462
 
457
463
  // Live updates
458
464
  useEffect(() => {
@@ -518,8 +524,14 @@ export function Timestamp({
518
524
  <time
519
525
  ref={mergeRefs(ref, timeRef)}
520
526
  dateTime={isoString}
527
+ // `ariaLabelText` is '' only for an invalid date, which bails out
528
+ // before rendering — but keep the guard local: an empty aria-label
529
+ // must be omitted entirely (not rendered as aria-label="") so AT
530
+ // falls back to reading the visible <time> content.
521
531
  aria-label={
522
- isRelativeFormat(effectiveFormat) ? fullAbsoluteText : undefined
532
+ isRelativeFormat(effectiveFormat) && ariaLabelText !== ''
533
+ ? ariaLabelText
534
+ : undefined
523
535
  }
524
536
  // The hover card is anchored here with focusTrigger="always", which
525
537
  // attaches focus listeners but does not itself make the anchor