@astryxdesign/core 0.3.0 → 0.4.0-canary.41f53a0

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 (579) 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 +12 -16
  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 +32 -31
  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 +47 -33
  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 +55 -32
  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 +54 -30
  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 +177 -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 +80 -103
  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 +8 -1
  140. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  141. package/dist/MultiSelector/MultiSelector.js +119 -95
  142. package/dist/NumberInput/NumberInput.d.ts +27 -1
  143. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  144. package/dist/NumberInput/NumberInput.js +230 -42
  145. package/dist/Outline/Outline.d.ts.map +1 -1
  146. package/dist/Outline/Outline.js +2 -3
  147. package/dist/Pagination/Pagination.d.ts.map +1 -1
  148. package/dist/Pagination/Pagination.js +61 -63
  149. package/dist/Popover/Popover.d.ts.map +1 -1
  150. package/dist/Popover/Popover.js +6 -8
  151. package/dist/Popover/usePopover.d.ts +15 -0
  152. package/dist/Popover/usePopover.d.ts.map +1 -1
  153. package/dist/Popover/usePopover.js +14 -2
  154. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  155. package/dist/PowerSearch/PowerSearch.js +1 -1
  156. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  157. package/dist/PowerSearch/PowerSearchEditPopover.js +7 -0
  158. package/dist/ProgressBar/ProgressBar.d.ts +11 -4
  159. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  160. package/dist/ProgressBar/ProgressBar.js +95 -6
  161. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  162. package/dist/RadioList/RadioListItem.js +29 -84
  163. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  164. package/dist/Resizable/ResizeHandle.js +2 -3
  165. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  166. package/dist/SegmentedControl/SegmentedControlItem.js +2 -3
  167. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  168. package/dist/SelectableCard/SelectableCard.js +3 -11
  169. package/dist/Selector/Selector.d.ts +12 -1
  170. package/dist/Selector/Selector.d.ts.map +1 -1
  171. package/dist/Selector/Selector.js +222 -111
  172. package/dist/Selector/hooks.d.ts +18 -6
  173. package/dist/Selector/hooks.d.ts.map +1 -1
  174. package/dist/Selector/hooks.js +57 -40
  175. package/dist/SideNav/SideNav.d.ts.map +1 -1
  176. package/dist/SideNav/SideNav.js +1 -1
  177. package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
  178. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  179. package/dist/SideNav/SideNavCollapseButton.js +29 -14
  180. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  181. package/dist/SideNav/SideNavHeading.js +56 -20
  182. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  183. package/dist/SideNav/SideNavItem.js +28 -22
  184. package/dist/Slider/Slider.d.ts.map +1 -1
  185. package/dist/Slider/Slider.js +2 -6
  186. package/dist/Stack/stack.stylex.d.ts +3 -3
  187. package/dist/Switch/Switch.d.ts.map +1 -1
  188. package/dist/Switch/Switch.js +14 -13
  189. package/dist/TabList/Tab.d.ts.map +1 -1
  190. package/dist/TabList/Tab.js +2 -3
  191. package/dist/TabList/TabMenu.d.ts.map +1 -1
  192. package/dist/TabList/TabMenu.js +41 -19
  193. package/dist/Table/BaseTable.d.ts.map +1 -1
  194. package/dist/Table/BaseTable.js +8 -0
  195. package/dist/Table/index.d.ts +1 -1
  196. package/dist/Table/index.d.ts.map +1 -1
  197. package/dist/Table/index.js +1 -1
  198. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
  199. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  200. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +22 -18
  201. package/dist/Table/plugins/rowExpansion/index.d.ts +1 -1
  202. package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -1
  203. package/dist/Table/plugins/rowExpansion/index.js +1 -1
  204. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +41 -76
  205. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  206. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +94 -345
  207. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  208. package/dist/Table/plugins/sortable/useTableSortable.js +23 -4
  209. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  210. package/dist/Table/plugins/tree/useTableTreeData.js +29 -33
  211. package/dist/Table/tableContextMenu.d.ts.map +1 -1
  212. package/dist/Table/tableContextMenu.js +2 -1
  213. package/dist/Table/types.d.ts +11 -0
  214. package/dist/Table/types.d.ts.map +1 -1
  215. package/dist/TextArea/TextArea.d.ts +10 -1
  216. package/dist/TextArea/TextArea.d.ts.map +1 -1
  217. package/dist/TextArea/TextArea.js +16 -6
  218. package/dist/TextInput/TextInput.d.ts +10 -1
  219. package/dist/TextInput/TextInput.d.ts.map +1 -1
  220. package/dist/TextInput/TextInput.js +13 -19
  221. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  222. package/dist/Thumbnail/Thumbnail.js +32 -26
  223. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  224. package/dist/TimeInput/TimeInput.js +14 -17
  225. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  226. package/dist/Timestamp/Timestamp.js +14 -3
  227. package/dist/Timestamp/TimestampHoverCard.d.ts.map +1 -1
  228. package/dist/Timestamp/TimestampHoverCard.js +16 -34
  229. package/dist/Timestamp/formatInstant.d.ts +11 -1
  230. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  231. package/dist/Timestamp/formatInstant.js +3 -1
  232. package/dist/Token/Token.d.ts.map +1 -1
  233. package/dist/Token/Token.js +20 -11
  234. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  235. package/dist/Tokenizer/Tokenizer.js +4 -2
  236. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  237. package/dist/Tooltip/useTooltip.js +3 -19
  238. package/dist/TopNav/TopNav.d.ts.map +1 -1
  239. package/dist/TopNav/TopNav.js +6 -5
  240. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  241. package/dist/TopNav/TopNavHeading.js +54 -16
  242. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  243. package/dist/TopNav/TopNavItem.js +3 -9
  244. package/dist/TopNav/TopNavMegaMenu.d.ts +7 -0
  245. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  246. package/dist/TopNav/TopNavMegaMenu.js +146 -60
  247. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  248. package/dist/TopNav/TopNavMegaMenuItem.js +22 -3
  249. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  250. package/dist/TopNav/TopNavMenu.js +83 -38
  251. package/dist/TreeList/TreeList.d.ts.map +1 -1
  252. package/dist/TreeList/TreeList.js +13 -0
  253. package/dist/TreeList/TreeListBranches.d.ts +1 -1
  254. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  255. package/dist/TreeList/TreeListBranches.js +14 -4
  256. package/dist/TreeList/TreeListItem.d.ts +11 -1
  257. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  258. package/dist/TreeList/TreeListItem.js +57 -30
  259. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  260. package/dist/Typeahead/BaseTypeahead.js +16 -8
  261. package/dist/astryx.css +84 -96
  262. package/dist/astryx.umd.js +56 -56
  263. package/dist/astryx.umd.js.map +4 -4
  264. package/dist/hooks/containerReveal.stylex.d.ts +61 -0
  265. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -0
  266. package/dist/hooks/containerReveal.stylex.js +63 -0
  267. package/dist/hooks/index.d.ts +3 -0
  268. package/dist/hooks/index.d.ts.map +1 -1
  269. package/dist/hooks/index.js +2 -0
  270. package/dist/hooks/useClipboard.d.ts +59 -0
  271. package/dist/hooks/useClipboard.d.ts.map +1 -0
  272. package/dist/hooks/useClipboard.js +106 -0
  273. package/dist/hooks/useContainerReveal.d.ts +14 -8
  274. package/dist/hooks/useContainerReveal.d.ts.map +1 -1
  275. package/dist/hooks/useContainerReveal.js +28 -69
  276. package/dist/hooks/useIndicatorFocusRing.d.ts +28 -0
  277. package/dist/hooks/useIndicatorFocusRing.d.ts.map +1 -0
  278. package/dist/hooks/useIndicatorFocusRing.js +96 -0
  279. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  280. package/dist/hooks/useInputStatusIcon.js +17 -4
  281. package/dist/hooks/useLongPress.d.ts.map +1 -1
  282. package/dist/hooks/useLongPress.js +12 -2
  283. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  284. package/dist/hooks/useScrollLock.js +33 -18
  285. package/dist/hooks/useStreamingText.d.ts +18 -3
  286. package/dist/hooks/useStreamingText.d.ts.map +1 -1
  287. package/dist/hooks/useStreamingText.js +47 -7
  288. package/dist/hooks/useTreeFocus.d.ts.map +1 -1
  289. package/dist/hooks/useTreeFocus.js +9 -3
  290. package/dist/hooks/useTypeahead.d.ts +3 -2
  291. package/dist/hooks/useTypeahead.d.ts.map +1 -1
  292. package/dist/hooks/useTypeahead.js +19 -7
  293. package/dist/index.d.ts +1 -0
  294. package/dist/index.d.ts.map +1 -1
  295. package/dist/index.js +1 -0
  296. package/dist/theme/defineTheme.d.ts +18 -2
  297. package/dist/theme/defineTheme.d.ts.map +1 -1
  298. package/dist/theme/defineTheme.js +10 -1
  299. package/dist/theme/derivedVarRegistry.d.ts +8 -0
  300. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  301. package/dist/theme/derivedVarRegistry.js +14 -13
  302. package/dist/theme/expandColorScale.d.ts +3 -1
  303. package/dist/theme/expandColorScale.d.ts.map +1 -1
  304. package/dist/theme/expandColorScale.js +17 -7
  305. package/dist/theme/expandTypeScale.d.ts.map +1 -1
  306. package/dist/theme/expandTypeScale.js +17 -0
  307. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  308. package/dist/theme/generateThemeRules.js +11 -0
  309. package/dist/theme/index.d.ts +2 -1
  310. package/dist/theme/index.d.ts.map +1 -1
  311. package/dist/theme/index.js +1 -1
  312. package/dist/theme/tokens.stylex.d.ts +12 -0
  313. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  314. package/dist/theme/tokens.stylex.js +23 -0
  315. package/dist/utils/focusOutline.stylex.d.ts +122 -0
  316. package/dist/utils/focusOutline.stylex.d.ts.map +1 -0
  317. package/dist/utils/focusOutline.stylex.js +143 -0
  318. package/dist/utils/focusReturn.d.ts +24 -0
  319. package/dist/utils/focusReturn.d.ts.map +1 -0
  320. package/dist/utils/focusReturn.js +29 -0
  321. package/dist/utils/index.d.ts +2 -0
  322. package/dist/utils/index.d.ts.map +1 -1
  323. package/dist/utils/index.js +6 -1
  324. package/dist/utils/mergeRefs.d.ts.map +1 -1
  325. package/dist/utils/mergeRefs.js +7 -5
  326. package/dist/utils/rtlStyles.d.ts +2 -2
  327. package/dist/utils/rtlStyles.js +2 -2
  328. package/dist/utils/themeProps.d.ts +20 -1
  329. package/dist/utils/themeProps.d.ts.map +1 -1
  330. package/dist/utils/themeProps.js +8 -2
  331. package/locales/en.json +20 -0
  332. package/locales/pseudo.json +15 -0
  333. package/package.json +8 -3
  334. package/src/AlertDialog/AlertDialog.doc.mjs +16 -3
  335. package/src/AlertDialog/AlertDialog.test.tsx +208 -1
  336. package/src/AlertDialog/AlertDialog.tsx +21 -3
  337. package/src/AppShell/AppShell.doc.mjs +11 -0
  338. package/src/AppShell/AppShell.test.tsx +139 -0
  339. package/src/AppShell/AppShell.tsx +32 -22
  340. package/src/AspectRatio/AspectRatio.doc.mjs +27 -3
  341. package/src/AspectRatio/AspectRatio.test.tsx +30 -0
  342. package/src/AspectRatio/AspectRatio.tsx +13 -0
  343. package/src/Avatar/Avatar.doc.mjs +2 -13
  344. package/src/Avatar/Avatar.test.tsx +33 -8
  345. package/src/Avatar/Avatar.tsx +52 -50
  346. package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -9
  347. package/src/Banner/Banner.tsx +9 -6
  348. package/src/Breadcrumbs/BreadcrumbItem.tsx +16 -6
  349. package/src/Breadcrumbs/index.ts +5 -1
  350. package/src/Button/Button.doc.mjs +2 -2
  351. package/src/Button/Button.tsx +22 -41
  352. package/src/Calendar/Calendar.tsx +2 -1
  353. package/src/Calendar/styles.ts +0 -8
  354. package/src/Carousel/Carousel.doc.mjs +3 -0
  355. package/src/Carousel/Carousel.tsx +10 -6
  356. package/src/Chat/Chat.doc.mjs +2 -0
  357. package/src/Chat/ChatDictationButton.tsx +7 -1
  358. package/src/Chat/ChatLayoutScrollButton.test.tsx +22 -0
  359. package/src/Chat/ChatLayoutScrollButton.tsx +8 -1
  360. package/src/Chat/ChatSendButton.tsx +2 -3
  361. package/src/Chat/ChatToolCalls.test.tsx +35 -0
  362. package/src/Chat/ChatToolCalls.tsx +36 -16
  363. package/src/Chat/useTriggerMenu.tsx +2 -5
  364. package/src/CheckboxInput/CheckboxInput.doc.mjs +4 -2
  365. package/src/CheckboxInput/CheckboxInput.test.tsx +120 -0
  366. package/src/CheckboxInput/CheckboxInput.tsx +45 -202
  367. package/src/ClickableCard/ClickableCard.tsx +6 -11
  368. package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
  369. package/src/CodeBlock/CodeBlock.test.tsx +91 -0
  370. package/src/CodeBlock/CodeBlock.tsx +57 -80
  371. package/src/Collapsible/Collapsible.tsx +22 -18
  372. package/src/CommandPalette/CommandPalette.test.tsx +29 -0
  373. package/src/CommandPalette/CommandPaletteItem.tsx +7 -4
  374. package/src/CommandPalette/CommandPaletteList.tsx +2 -2
  375. package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
  376. package/src/ComplexSelector/ComplexSelector.test.tsx +73 -0
  377. package/src/ComplexSelector/ComplexSelector.tsx +41 -28
  378. package/src/ContextMenu/ContextMenu.doc.mjs +1 -1
  379. package/src/ContextMenu/ContextMenu.test.tsx +41 -0
  380. package/src/ContextMenu/ContextMenu.tsx +3 -3
  381. package/src/ContextMenu/index.ts +5 -1
  382. package/src/DateInput/DateInput.doc.mjs +18 -3
  383. package/src/DateInput/DateInput.test.tsx +112 -11
  384. package/src/DateInput/DateInput.tsx +44 -25
  385. package/src/DateRangeInput/DateRangeInput.doc.mjs +10 -2
  386. package/src/DateRangeInput/DateRangeInput.test.tsx +110 -14
  387. package/src/DateRangeInput/DateRangeInput.tsx +27 -21
  388. package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -2
  389. package/src/DateTimeInput/DateTimeInput.test.tsx +154 -1
  390. package/src/DateTimeInput/DateTimeInput.tsx +58 -17
  391. package/src/Dialog/Dialog.tsx +2 -9
  392. package/src/DropdownMenu/DropdownMenu.doc.mjs +5 -9
  393. package/src/DropdownMenu/DropdownMenu.test.tsx +534 -4
  394. package/src/DropdownMenu/DropdownMenu.tsx +113 -52
  395. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +27 -30
  396. package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +34 -0
  397. package/src/DropdownMenu/DropdownMenuDivider.tsx +81 -0
  398. package/src/DropdownMenu/DropdownMenuItem.doc.mjs +39 -4
  399. package/src/DropdownMenu/DropdownMenuItem.tsx +48 -10
  400. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +30 -76
  401. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +25 -19
  402. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +44 -14
  403. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +1 -5
  404. package/src/DropdownMenu/index.ts +8 -1
  405. package/src/DropdownMenu/renderDropdownItems.tsx +33 -34
  406. package/src/EmptyState/EmptyState.doc.mjs +4 -0
  407. package/src/EmptyState/EmptyState.test.tsx +62 -0
  408. package/src/EmptyState/EmptyState.tsx +16 -6
  409. package/src/Field/Field.doc.mjs +1 -0
  410. package/src/Field/InputClearButton.test.tsx +117 -0
  411. package/src/Field/InputClearButton.tsx +30 -3
  412. package/src/HoverCard/useHoverCard.tsx +2 -23
  413. package/src/Icon/Icon.doc.mjs +2 -1
  414. package/src/Indicator/CheckIndicator.tsx +174 -0
  415. package/src/Indicator/CheckboxIndicator.tsx +257 -0
  416. package/src/Indicator/Indicator.doc.mjs +344 -0
  417. package/src/Indicator/Indicator.test.tsx +393 -0
  418. package/src/Indicator/RadioIndicator.tsx +206 -0
  419. package/src/Indicator/index.ts +46 -0
  420. package/src/Indicator/indicator.markers.stylex.ts +19 -0
  421. package/src/Indicator/indicatorRegistry.test.tsx +106 -0
  422. package/src/Indicator/indicatorRegistry.ts +120 -0
  423. package/src/Indicator/types.ts +197 -0
  424. package/src/Indicator/useIndicator.ts +39 -0
  425. package/src/Item/Item.doc.mjs +1 -1
  426. package/src/Item/Item.tsx +7 -14
  427. package/src/Layer/useLayer.doc.mjs +2 -2
  428. package/src/Layer/useLayer.test.tsx +85 -0
  429. package/src/Layer/useLayer.tsx +39 -1
  430. package/src/Lightbox/Lightbox.doc.mjs +1 -1
  431. package/src/Lightbox/Lightbox.tsx +45 -49
  432. package/src/Link/Link.tsx +4 -11
  433. package/src/MobileNav/MobileNav.tsx +3 -3
  434. package/src/MoreMenu/MoreMenu.doc.mjs +31 -0
  435. package/src/MoreMenu/MoreMenu.test.tsx +68 -1
  436. package/src/MoreMenu/MoreMenu.tsx +19 -0
  437. package/src/MultiSelector/MultiSelector.doc.mjs +16 -1
  438. package/src/MultiSelector/MultiSelector.test.tsx +259 -16
  439. package/src/MultiSelector/MultiSelector.tsx +144 -121
  440. package/src/NumberInput/NumberInput.doc.mjs +265 -50
  441. package/src/NumberInput/NumberInput.test.tsx +726 -21
  442. package/src/NumberInput/NumberInput.tsx +353 -59
  443. package/src/Outline/Outline.tsx +2 -5
  444. package/src/Pagination/Pagination.doc.mjs +1 -1
  445. package/src/Pagination/Pagination.test.tsx +22 -7
  446. package/src/Pagination/Pagination.tsx +38 -35
  447. package/src/Popover/Popover.doc.mjs +2 -0
  448. package/src/Popover/Popover.tsx +6 -7
  449. package/src/Popover/usePopover.tsx +37 -4
  450. package/src/PowerSearch/PowerSearch.tsx +1 -1
  451. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +42 -0
  452. package/src/PowerSearch/PowerSearchEditPopover.tsx +7 -0
  453. package/src/ProgressBar/ProgressBar.doc.mjs +27 -5
  454. package/src/ProgressBar/ProgressBar.test.tsx +224 -1
  455. package/src/ProgressBar/ProgressBar.tsx +126 -30
  456. package/src/RadioList/RadioList.doc.mjs +4 -2
  457. package/src/RadioList/RadioListItem.tsx +31 -130
  458. package/src/Resizable/ResizeHandle.tsx +2 -9
  459. package/src/SegmentedControl/SegmentedControlItem.tsx +2 -9
  460. package/src/SelectableCard/SelectableCard.tsx +4 -9
  461. package/src/Selector/Selector.doc.mjs +15 -4
  462. package/src/Selector/Selector.test.tsx +1234 -98
  463. package/src/Selector/Selector.tsx +254 -126
  464. package/src/Selector/hooks.ts +77 -50
  465. package/src/SideNav/SideNav.test.tsx +46 -0
  466. package/src/SideNav/SideNav.tsx +1 -0
  467. package/src/SideNav/SideNavCollapseButton.tsx +15 -10
  468. package/src/SideNav/SideNavHeading.tsx +48 -10
  469. package/src/SideNav/SideNavItem.tsx +20 -12
  470. package/src/Slider/Slider.tsx +2 -11
  471. package/src/Stack/Stack.doc.mjs +110 -0
  472. package/src/StatusDot/StatusDot.doc.mjs +12 -3
  473. package/src/Switch/Switch.test.tsx +32 -0
  474. package/src/Switch/Switch.tsx +18 -10
  475. package/src/TabList/Tab.tsx +2 -9
  476. package/src/TabList/TabMenu.tsx +14 -21
  477. package/src/Table/BaseTable.tsx +11 -0
  478. package/src/Table/index.ts +1 -4
  479. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +30 -14
  480. package/src/Table/plugins/rowExpansion/index.ts +1 -4
  481. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +125 -175
  482. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +115 -458
  483. package/src/Table/plugins/sortable/useTableSortable.tsx +2 -6
  484. package/src/Table/plugins/tree/useTableTreeData.tsx +43 -24
  485. package/src/Table/tableContextMenu.test.tsx +27 -0
  486. package/src/Table/tableContextMenu.tsx +1 -0
  487. package/src/Table/types.ts +11 -0
  488. package/src/Table/useTableGroupedRows.doc.mjs +1 -1
  489. package/src/Table/useTableRowExpansion.doc.mjs +43 -66
  490. package/src/TextArea/TextArea.doc.mjs +42 -2
  491. package/src/TextArea/TextArea.test.tsx +219 -0
  492. package/src/TextArea/TextArea.tsx +34 -7
  493. package/src/TextInput/TextInput.doc.mjs +18 -2
  494. package/src/TextInput/TextInput.test.tsx +189 -0
  495. package/src/TextInput/TextInput.tsx +25 -31
  496. package/src/Thumbnail/Thumbnail.tsx +2 -9
  497. package/src/TimeInput/TimeInput.doc.mjs +2 -2
  498. package/src/TimeInput/TimeInput.test.tsx +84 -3
  499. package/src/TimeInput/TimeInput.tsx +26 -28
  500. package/src/Timestamp/Timestamp.doc.mjs +4 -3
  501. package/src/Timestamp/Timestamp.test.tsx +91 -14
  502. package/src/Timestamp/Timestamp.tsx +14 -2
  503. package/src/Timestamp/TimestampHoverCard.tsx +13 -35
  504. package/src/Timestamp/formatInstant.ts +16 -1
  505. package/src/Token/Token.tsx +5 -28
  506. package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
  507. package/src/Tokenizer/Tokenizer.test.tsx +45 -3
  508. package/src/Tokenizer/Tokenizer.tsx +10 -2
  509. package/src/Tooltip/useTooltip.tsx +2 -23
  510. package/src/TopNav/TopNav.tsx +1 -3
  511. package/src/TopNav/TopNavHeading.tsx +42 -13
  512. package/src/TopNav/TopNavItem.tsx +3 -21
  513. package/src/TopNav/TopNavMegaMenu.test.tsx +433 -33
  514. package/src/TopNav/TopNavMegaMenu.tsx +118 -53
  515. package/src/TopNav/TopNavMegaMenuItem.tsx +2 -9
  516. package/src/TopNav/TopNavMenu.tsx +34 -37
  517. package/src/TreeList/TreeList.doc.mjs +5 -0
  518. package/src/TreeList/TreeList.test.tsx +208 -8
  519. package/src/TreeList/TreeList.tsx +22 -0
  520. package/src/TreeList/TreeListBranches.tsx +25 -2
  521. package/src/TreeList/TreeListItem.tsx +89 -52
  522. package/src/Typeahead/BaseTypeahead.tsx +19 -6
  523. package/src/Typeahead/Typeahead.doc.mjs +1 -0
  524. package/src/Typeahead/Typeahead.test.tsx +76 -3
  525. package/src/hooks/containerReveal.stylex.ts +102 -0
  526. package/src/hooks/index.ts +4 -0
  527. package/src/hooks/useClipboard.doc.mjs +87 -0
  528. package/src/hooks/useClipboard.test.tsx +151 -0
  529. package/src/hooks/useClipboard.ts +135 -0
  530. package/src/hooks/useContainerReveal.doc.mjs +7 -7
  531. package/src/hooks/useContainerReveal.test.tsx +42 -62
  532. package/src/hooks/useContainerReveal.ts +36 -91
  533. package/src/hooks/useImageMode.test.ts +1 -1
  534. package/src/hooks/useIndicatorFocusRing.tsx +120 -0
  535. package/src/hooks/useInputStatusIcon.tsx +8 -8
  536. package/src/hooks/useLongPress.test.tsx +18 -0
  537. package/src/hooks/useLongPress.ts +12 -2
  538. package/src/hooks/useScrollLock.test.ts +72 -0
  539. package/src/hooks/useScrollLock.ts +51 -19
  540. package/src/hooks/useStreamingText.test.ts +46 -1
  541. package/src/hooks/useStreamingText.ts +49 -7
  542. package/src/hooks/useTreeFocus.test.tsx +50 -0
  543. package/src/hooks/useTreeFocus.ts +14 -3
  544. package/src/hooks/useTypeahead.test.tsx +150 -0
  545. package/src/hooks/useTypeahead.ts +24 -9
  546. package/src/i18n/InternationalizationProvider.doc.mjs +7 -2
  547. package/src/index.ts +1 -0
  548. package/src/theme/defineTheme.ts +27 -0
  549. package/src/theme/derivedVarRegistry.test.ts +21 -1
  550. package/src/theme/derivedVarRegistry.ts +19 -6
  551. package/src/theme/expandColorScale.test.ts +14 -0
  552. package/src/theme/expandColorScale.ts +24 -9
  553. package/src/theme/expandTypeScale.test.ts +43 -0
  554. package/src/theme/expandTypeScale.ts +17 -0
  555. package/src/theme/generateThemeRules.test.ts +78 -20
  556. package/src/theme/generateThemeRules.ts +11 -0
  557. package/src/theme/index.ts +15 -0
  558. package/src/theme/tokens.stylex.ts +18 -0
  559. package/src/theme/tokens.test.ts +37 -0
  560. package/src/utils/focusOutline.stylex.ts +177 -0
  561. package/src/utils/focusReturn.test.ts +42 -0
  562. package/src/utils/focusReturn.ts +31 -0
  563. package/src/utils/index.ts +5 -0
  564. package/src/utils/mergeRefs.test.ts +48 -0
  565. package/src/utils/mergeRefs.ts +12 -6
  566. package/src/utils/rtlStyles.ts +2 -2
  567. package/src/utils/themeProps.ts +26 -4
  568. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts +0 -9
  569. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts.map +0 -1
  570. package/dist/CheckboxInput/checkbox.markers.stylex.js +0 -14
  571. package/dist/RadioList/radio.markers.stylex.d.ts +0 -7
  572. package/dist/RadioList/radio.markers.stylex.d.ts.map +0 -1
  573. package/dist/RadioList/radio.markers.stylex.js +0 -12
  574. package/dist/hooks/containerReveal.pool.stylex.d.ts +0 -303
  575. package/dist/hooks/containerReveal.pool.stylex.d.ts.map +0 -1
  576. package/dist/hooks/containerReveal.pool.stylex.js +0 -292
  577. package/src/CheckboxInput/checkbox.markers.stylex.ts +0 -12
  578. package/src/RadioList/radio.markers.stylex.ts +0 -10
  579. package/src/hooks/containerReveal.pool.stylex.ts +0 -571
@@ -46,6 +46,7 @@ import {useClickableContainer} from '../hooks/useClickableContainer';
46
46
  import type {BaseProps} from '../BaseProps';
47
47
  import {useLinkComponent} from '../Link/useLinkComponent';
48
48
  import {themeProps} from '../utils/themeProps';
49
+ import {focusOutlineProps} from '../utils/focusOutline.stylex';
49
50
 
50
51
  // =============================================================================
51
52
  // Styles — only the interactive layer, Card handles everything else
@@ -57,13 +58,6 @@ const styles = stylex.create({
57
58
  cursor: 'pointer',
58
59
  textDecoration: 'none',
59
60
  color: 'inherit',
60
- outlineOffset: '2px',
61
- },
62
- focusWithin: {
63
- ':has(:focus-visible)': {
64
- outline: `2px solid ${colorVars['--color-accent']}`,
65
- outlineOffset: '2px',
66
- },
67
61
  },
68
62
  // Hover overlay — guarded by @media (hover: hover) so touch devices
69
63
  // don't show a stuck hover state. Active/pressed state works everywhere.
@@ -307,14 +301,15 @@ export function ClickableCard({
307
301
  padding={padding}
308
302
  variant={variant}
309
303
  elevation={elevation}
310
- {...mergeProps(themeProps('clickable-card', {variant}), {
311
- className: classNameProp,
304
+ {...mergeProps(
305
+ themeProps('clickable-card', {variant}),
306
+ focusOutlineProps.focusWithin(),
307
+ classNameProp,
312
308
  style,
313
- })}
309
+ )}
314
310
  xstyle={
315
311
  [
316
312
  styles.interactive,
317
- styles.focusWithin,
318
313
  hasBorder ? styles.bordered : styles.borderless,
319
314
  !isDisabled && styles.overlay,
320
315
  !isDisabled && styles.hoverOnPointer,
@@ -142,6 +142,9 @@ export const docs = {
142
142
  targets: [
143
143
  {className: 'astryx-code', visualProps: ['color']},
144
144
  {className: 'astryx-codeblock', visualProps: ['size', 'language', 'container']},
145
+ {className: 'astryx-codeblock-header', visualProps: ['size', 'language', 'container']},
146
+ {className: 'astryx-codeblock-title', visualProps: ['size', 'language']},
147
+ {className: 'astryx-codeblock-copy-button'},
145
148
  ],
146
149
  },
147
150
  usage: {
@@ -15,6 +15,13 @@ import {CodeBlock} from './CodeBlock';
15
15
  import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
16
16
  import {dracula} from '../theme/syntax';
17
17
  import {InternationalizationProvider} from '../i18n';
18
+ import {defineTheme} from '../theme/defineTheme';
19
+ import {generateThemeCSS} from '../theme/generateThemeRules';
20
+
21
+ function generateThemeTestCSS(theme: Parameters<typeof generateThemeCSS>[0]) {
22
+ const {prose, component} = generateThemeCSS(theme);
23
+ return [prose, component].filter(Boolean).join('\n\n');
24
+ }
18
25
 
19
26
  function politeRegion(): HTMLElement | null {
20
27
  return document.querySelector('[data-astryx-live-region="polite"]');
@@ -64,6 +71,30 @@ describe('CodeBlock', () => {
64
71
  expect(navigator.clipboard.writeText).toHaveBeenCalledWith('const x = 1;');
65
72
  });
66
73
 
74
+ it('renders the copy button as a themeable target with a "Copy code" tooltip', () => {
75
+ render(<CodeBlock code="const x = 1;" language="javascript" />);
76
+ const copyButton = screen.getByRole('button', {name: 'Copy code'});
77
+ // Theme seam: a design system can restyle the copy control via this class
78
+ // without turning the button off and re-implementing it.
79
+ expect(copyButton).toHaveClass('astryx-codeblock-copy-button');
80
+ // The button carries a visible "Copy code" hover/focus hint (tooltip),
81
+ // wired through aria-describedby — a bare <button> could not.
82
+ expect(copyButton).toHaveAttribute('aria-describedby');
83
+ });
84
+
85
+ it('keeps the copy button tooltip as "Copy code" after copying', async () => {
86
+ render(<CodeBlock code="const x = 1;" language="javascript" />);
87
+ fireEvent.click(screen.getByRole('button', {name: 'Copy code'}));
88
+ await act(async () => {});
89
+ // The icon flip (copy → check) is the confirmation; the tooltip text does
90
+ // not change. The accessible name still swaps to "Copied" for AT.
91
+ const copyButton = screen.getByRole('button', {name: 'Copied'});
92
+ const tooltipId = copyButton.getAttribute('aria-describedby');
93
+ expect(tooltipId).toBeTruthy();
94
+ const tooltip = document.getElementById(tooltipId as string);
95
+ expect(tooltip).toHaveTextContent('Copy code');
96
+ });
97
+
67
98
  it('announces "Copied" to a polite live region after copying', async () => {
68
99
  render(<CodeBlock code="const x = 1;" language="javascript" />);
69
100
  const copyButton = screen.getByRole('button', {name: 'Copy code'});
@@ -304,4 +335,64 @@ describe('CodeBlock', () => {
304
335
  expect(container.querySelector('[data-astryx-syntax-theme]')).toBeNull();
305
336
  expect(container.firstElementChild?.tagName).toBe('PRE');
306
337
  });
338
+
339
+ describe('header theming targets', () => {
340
+ it('puts astryx-codeblock-header on the header row when a header shows', () => {
341
+ const {container} = render(
342
+ <CodeBlock
343
+ code="const x = 1;"
344
+ language="javascript"
345
+ title="example.js"
346
+ />,
347
+ );
348
+ expect(
349
+ container.querySelector('.astryx-codeblock-header'),
350
+ ).not.toBeNull();
351
+ });
352
+
353
+ it('puts astryx-codeblock-title on the header title element', () => {
354
+ const {container} = render(
355
+ <CodeBlock
356
+ code="const x = 1;"
357
+ language="javascript"
358
+ title="example.js"
359
+ />,
360
+ );
361
+ const titleEl = container.querySelector('.astryx-codeblock-title');
362
+ expect(titleEl).not.toBeNull();
363
+ // The language label + title text live in this element.
364
+ expect(titleEl).toHaveTextContent('example.js');
365
+ });
366
+
367
+ it('renders no header targets when there is no header', () => {
368
+ // plaintext hides the language label and no title is given, so the
369
+ // header row is not rendered at all.
370
+ const {container} = render(
371
+ <CodeBlock code="const x = 1;" language="plaintext" />,
372
+ );
373
+ expect(container.querySelector('.astryx-codeblock-header')).toBeNull();
374
+ expect(container.querySelector('.astryx-codeblock-title')).toBeNull();
375
+ });
376
+
377
+ it('exposes the header and title as themeable defineTheme targets', () => {
378
+ // jsdom can't resolve the @layer cascade, so this asserts the targets are
379
+ // reachable by a theme via the sanctioned defineTheme channel — replacing
380
+ // the structural `> div:first-child > div > span` header/title selectors a
381
+ // consumer would otherwise need to restyle the header padding and title.
382
+ const theme = defineTheme({
383
+ name: 'codeblock-header-target-test',
384
+ components: {
385
+ 'codeblock-header': {
386
+ base: {paddingBlock: 'var(--spacing-1)'},
387
+ },
388
+ 'codeblock-title': {
389
+ base: {fontSize: 'var(--text-body-size)'},
390
+ },
391
+ },
392
+ });
393
+ const css = generateThemeTestCSS(theme);
394
+ expect(css).toContain('.astryx-codeblock-header');
395
+ expect(css).toContain('.astryx-codeblock-title');
396
+ });
397
+ });
307
398
  });
@@ -33,8 +33,9 @@ import {
33
33
  easeVars,
34
34
  } from '../theme/tokens.stylex';
35
35
  import {mergeProps} from '../utils';
36
- import {useAnnounce} from '../hooks/useAnnounce';
36
+ import {useClipboard} from '../hooks/useClipboard';
37
37
  import {Icon} from '../Icon';
38
+ import {IconButton} from '../IconButton';
38
39
  import {
39
40
  tokenize,
40
41
  tokenizeAsync,
@@ -45,6 +46,7 @@ import type {SyntaxToken, TokenLine} from './tokenizer';
45
46
  import {ensureHighlightStyles} from './highlightStyles';
46
47
  import {applyHighlightRangesChunked} from './highlightRanges';
47
48
  import {themeProps} from '../utils/themeProps';
49
+ import {focusOutlineProps} from '../utils/focusOutline.stylex';
48
50
  import {useTranslator} from '../i18n';
49
51
  import {SyntaxTheme, type SyntaxThemeDefinition} from '../theme/syntax';
50
52
 
@@ -198,6 +200,10 @@ const styles = stylex.create({
198
200
  },
199
201
  animationDuration: durationVars['--duration-medium'],
200
202
  animationTimingFunction: easeVars['--ease-standard'],
203
+ },
204
+ // Applied to the chevron <Icon> (via `xstyle`): the glyph is the element that
205
+ // rotates and the element a theme targets, so one selector reaches both.
206
+ collapseChevronIcon: {
201
207
  transitionProperty: 'transform',
202
208
  transitionDuration: durationVars['--duration-fast'],
203
209
  transitionTimingFunction: easeVars['--ease-standard'],
@@ -214,14 +220,6 @@ const styles = stylex.create({
214
220
  // Restore a keyboard-only focus ring with the standard token/offset so this
215
221
  // disclosure control matches the rest of the system (Collapsible, TabMenu);
216
222
  // otherwise it falls back to the inconsistent UA default outline.
217
- outline: {
218
- default: null,
219
- ':focus-visible': `2px solid ${colorVars['--color-accent']}`,
220
- },
221
- outlineOffset: {
222
- default: '0',
223
- ':focus-visible': '2px',
224
- },
225
223
  },
226
224
  code: {
227
225
  display: 'block',
@@ -303,22 +301,11 @@ const styles = stylex.create({
303
301
  fontSize: typeScaleVars['--text-code-size'],
304
302
  },
305
303
  copyButton: {
306
- display: 'inline-flex',
307
- alignItems: 'center',
308
- justifyContent: 'center',
309
- padding: spacingVars['--spacing-1'],
310
- marginInlineEnd: `calc(-1 * ${spacingVars['--spacing-2']})`,
311
- border: 'none',
312
- borderRadius: radiusVars['--radius-inner'],
313
- backgroundColor: {
314
- default: 'transparent',
315
- '@media (hover: hover)': {
316
- ':hover': colorVars['--color-overlay-hover'],
317
- },
318
- },
304
+ // The copy control is a ghost IconButton (Button owns its own padding,
305
+ // radius, and hover surface); this only tints the resting glyph to the
306
+ // muted syntax-comment colour so it blends into the header/corner. A theme
307
+ // reaches it via the `codeblock-copy-button` target on the Button.
319
308
  color: 'var(--color-syntax-comment)',
320
- cursor: 'pointer',
321
- lineHeight: 0,
322
309
  },
323
310
  copyButtonAbsolute: {
324
311
  position: 'absolute',
@@ -747,18 +734,12 @@ export function CodeBlock({
747
734
  ...props
748
735
  }: CodeBlockProps) {
749
736
  const t = useTranslator();
750
- const [copied, setCopied] = useState(false);
751
- const copyResetTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
752
- const announce = useAnnounce();
753
-
754
- // Clear a pending "copied" reset when the block unmounts.
755
- useEffect(() => {
756
- return () => {
757
- if (copyResetTimerRef.current != null) {
758
- clearTimeout(copyResetTimerRef.current);
759
- }
760
- };
761
- }, []);
737
+ // Owns the clipboard write, the transient copied flag, its reset timer, and
738
+ // the polite copy announcement (a swapped aria-label alone is not reliably
739
+ // announced) — shared with Timestamp via the same hook.
740
+ const {copy, isCopied: copied} = useClipboard({
741
+ announce: t('@astryx.codeBlock.copied'),
742
+ });
762
743
 
763
744
  const useSpans =
764
745
  highlightMode === 'spans' ||
@@ -781,26 +762,11 @@ export function CodeBlock({
781
762
  );
782
763
 
783
764
  const handleCopy = useCallback(async () => {
784
- try {
785
- await navigator.clipboard.writeText(code);
786
- setCopied(true);
787
- // Swapping the button's aria-label alone isn't reliably announced by
788
- // screen readers, so confirm the copy via a polite live region.
789
- announce(t('@astryx.codeBlock.copied'));
765
+ const didCopy = await copy(code);
766
+ if (didCopy) {
790
767
  onCopy?.();
791
- // Restart the reset timer on every copy — otherwise a rapid re-copy
792
- // is reverted early by the previous click's timer.
793
- if (copyResetTimerRef.current != null) {
794
- clearTimeout(copyResetTimerRef.current);
795
- }
796
- copyResetTimerRef.current = setTimeout(() => {
797
- copyResetTimerRef.current = null;
798
- setCopied(false);
799
- }, 2000);
800
- } catch {
801
- // Clipboard failures leave the copied state unchanged.
802
768
  }
803
- }, [code, onCopy, announce, t]);
769
+ }, [code, copy, onCopy]);
804
770
 
805
771
  const sizeStyle = size === 'sm' ? styles.sizeSm : styles.sizeMd;
806
772
  // Digits in the largest line number — sizes the gutter column width.
@@ -822,34 +788,37 @@ export function CodeBlock({
822
788
  ? {maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight}
823
789
  : undefined;
824
790
 
825
- const copyIcon = (
826
- <Icon icon={copied ? 'check' : 'copy'} size="sm" color="inherit" />
827
- );
828
-
829
791
  const copyButtonEl = hasCopyButton ? (
830
- <button
831
- type="button"
792
+ <IconButton
793
+ variant="ghost"
794
+ size="sm"
795
+ icon={<Icon icon={copied ? 'check' : 'copy'} size="sm" color="inherit" />}
796
+ // A visible "Copy" hover/focus hint via Button's built-in tooltip. It
797
+ // stays "Copy" after copying — the copy → check icon flip is the
798
+ // confirmation, not a tooltip change. The aria-label still swaps to the
799
+ // localized "Copied" for assistive tech, backed by the announcement.
800
+ tooltip={t('@astryx.codeBlock.copyCode')}
801
+ label={
802
+ copied ? t('@astryx.codeBlock.copied') : t('@astryx.codeBlock.copyCode')
803
+ }
832
804
  onClick={e => {
833
805
  // Stop propagation so copying does not toggle the collapsible header.
834
806
  e.stopPropagation();
835
807
  void handleCopy();
836
808
  }}
837
- aria-label={
838
- copied ? t('@astryx.codeBlock.copied') : t('@astryx.codeBlock.copyCode')
839
- }
840
- {...stylex.props(
841
- styles.copyButton,
842
- !showHeader && styles.copyButtonAbsolute,
843
- )}>
844
- {copyIcon}
845
- </button>
809
+ xstyle={[styles.copyButton, !showHeader && styles.copyButtonAbsolute]}
810
+ {...themeProps('codeblock-copy-button')}
811
+ />
846
812
  ) : null;
847
813
 
848
814
  const headerEl = showHeader ? (
849
815
  <div
850
- {...stylex.props(
851
- styles.headerRow,
852
- hasLineNumbers ? styles.headerWithDivider : styles.headerCompact,
816
+ {...mergeProps(
817
+ themeProps('codeblock-header', {size, language, container}),
818
+ stylex.props(
819
+ styles.headerRow,
820
+ hasLineNumbers ? styles.headerWithDivider : styles.headerCompact,
821
+ ),
853
822
  )}>
854
823
  <div
855
824
  role={canCollapse ? 'button' : undefined}
@@ -867,18 +836,26 @@ export function CodeBlock({
867
836
  }
868
837
  : undefined
869
838
  }
870
- {...stylex.props(
839
+ {...focusOutlineProps.focusVisible(
871
840
  styles.header,
872
841
  canCollapse && styles.headerCollapsible,
873
842
  )}>
874
- <span {...stylex.props(styles.headerTitle)}>
843
+ <span
844
+ {...mergeProps(
845
+ themeProps('codeblock-title', {size, language}),
846
+ stylex.props(styles.headerTitle),
847
+ )}>
875
848
  {canCollapse && (
876
- <span
877
- {...stylex.props(
878
- styles.collapseChevron,
879
- !isCollapsed && styles.collapseChevronExpanded,
880
- )}>
881
- <Icon icon="chevronRight" size="xsm" color="inherit" />
849
+ <span {...stylex.props(styles.collapseChevron)}>
850
+ <Icon
851
+ icon="chevronRight"
852
+ size="xsm"
853
+ color="inherit"
854
+ xstyle={[
855
+ styles.collapseChevronIcon,
856
+ !isCollapsed && styles.collapseChevronExpanded,
857
+ ]}
858
+ />
882
859
  </span>
883
860
  )}
884
861
  {title}
@@ -42,10 +42,11 @@ import {
42
42
 
43
43
  import {useCollapsible} from './useCollapsible';
44
44
  import {CollapsibleGroupPresentationContext} from './CollapsibleGroupContext';
45
- import {useIcon} from '../Icon';
45
+ import {Icon} from '../Icon';
46
46
  import {mergeProps} from '../utils';
47
47
  import type {BaseProps} from '../BaseProps';
48
48
  import {themeProps} from '../utils/themeProps';
49
+ import {focusOutlineProps} from '../utils/focusOutline.stylex';
49
50
 
50
51
  const styles = stylex.create({
51
52
  root: {
@@ -73,14 +74,6 @@ const styles = stylex.create({
73
74
  paddingBlock: 0,
74
75
  // `all: unset` above wipes the UA focus outline; restore a keyboard-only
75
76
  // focus ring using the standard token/offset (WCAG 2.4.7).
76
- outline: {
77
- default: null,
78
- ':focus-visible': `2px solid ${colorVars['--color-accent']}`,
79
- },
80
- outlineOffset: {
81
- default: '0',
82
- ':focus-visible': '2px',
83
- },
84
77
  },
85
78
  // Capsize: trim leading from text triggers
86
79
  triggerLabel: {
@@ -100,10 +93,17 @@ const styles = stylex.create({
100
93
  alignItems: 'center',
101
94
  justifyContent: 'center',
102
95
  flexShrink: 0,
96
+ // The chevron is sized off the trigger's own type size (--text-large-size,
97
+ // 17px), which sits between Icon's `sm` (16px) and `md` (20px) boxes.
98
+ // Pinning the box to the token keeps the glyph exactly the size it was
99
+ // when it was a bare 1em SVG inheriting the trigger's font-size, and keeps
100
+ // it tracking the trigger if a theme retunes that step.
101
+ width: typeScaleVars['--text-large-size'],
102
+ height: typeScaleVars['--text-large-size'],
103
+ fontSize: typeScaleVars['--text-large-size'],
103
104
  transitionProperty: 'transform',
104
105
  transitionDuration: durationVars['--duration-fast'],
105
106
  transitionTimingFunction: easeVars['--ease-standard'],
106
- color: colorVars['--color-icon-secondary'],
107
107
  },
108
108
  chevronOpen: {
109
109
  transform: 'rotate(180deg)',
@@ -293,8 +293,6 @@ export function Collapsible({
293
293
  const isDivided = presentation?.hasDividers ?? false;
294
294
  const density = presentation?.density ?? null;
295
295
 
296
- const chevronIcon = useIcon('chevronDown');
297
-
298
296
  // Links the trigger to the region it shows/hides so assistive tech can move
299
297
  // from the button to its controlled content (disclosure pattern).
300
298
  const contentId = useId();
@@ -327,20 +325,26 @@ export function Collapsible({
327
325
  themeProps('collapsible-trigger', {
328
326
  density: density ?? undefined,
329
327
  }),
330
- stylex.props(
328
+ focusOutlineProps.focusVisible(
331
329
  styles.trigger,
332
330
  density != null && triggerDensity[density],
333
331
  isDisabled && styles.triggerDisabled,
334
332
  ),
335
333
  )}>
336
334
  <span {...stylex.props(styles.triggerLabel)}>{trigger}</span>
337
- <span
338
- {...stylex.props(
335
+ <Icon
336
+ icon="chevronDown"
337
+ // Nearest size to the trigger's 17px type step; `chevron` re-pins the
338
+ // exact box (see the style) so the glyph does not resize.
339
+ size="sm"
340
+ // Was `--color-icon-secondary` on the old wrapper span; `secondary`
341
+ // is the same token, expressed as an Icon color.
342
+ color="secondary"
343
+ xstyle={[
339
344
  styles.chevron,
340
345
  isOpen ? styles.chevronOpen : styles.chevronClosed,
341
- )}>
342
- {chevronIcon}
343
- </span>
346
+ ]}
347
+ />
344
348
  </button>
345
349
  <div
346
350
  id={contentId}
@@ -274,6 +274,35 @@ describe('CommandPalette', () => {
274
274
  );
275
275
  });
276
276
 
277
+ it('does not move the highlight while typing in the search input', async () => {
278
+ // The palette's input already filters; letting the shared combobox
279
+ // typeahead also chase prefixes would drag the highlight — and Enter —
280
+ // onto a command the user never picked.
281
+ const gitSource = createStaticSource([
282
+ {id: 'git-add', label: 'git add'},
283
+ {id: 'git-commit', label: 'git commit'},
284
+ {id: 'git-push', label: 'git push'},
285
+ ]);
286
+ render(
287
+ <CommandPalette
288
+ isOpen={true}
289
+ onOpenChange={() => {}}
290
+ searchSource={gitSource}
291
+ />,
292
+ );
293
+
294
+ const input = screen.getByRole('combobox');
295
+ await waitFor(() =>
296
+ expect(screen.getByText('git add')).toBeInTheDocument(),
297
+ );
298
+
299
+ fireEvent.keyDown(input, {key: 'g'});
300
+ fireEvent.keyDown(input, {key: 'i'});
301
+ fireEvent.keyDown(input, {key: 't'});
302
+
303
+ expect(input).not.toHaveAttribute('aria-activedescendant');
304
+ });
305
+
277
306
  describe('screen reader announcements', () => {
278
307
  const politeRegion = () =>
279
308
  document.querySelector('[data-astryx-live-region="polite"]');
@@ -15,6 +15,7 @@ import {useCallback, useEffect, useMemo, useRef, type ReactNode} from 'react';
15
15
  import * as stylex from '@stylexjs/stylex';
16
16
  import type {BaseProps} from '../BaseProps';
17
17
  import {mergeProps, mergeRefs} from '../utils';
18
+ import {composeEventHandlers} from '../utils/composeEventHandlers';
18
19
  import {
19
20
  colorVars,
20
21
  spacingVars,
@@ -127,6 +128,8 @@ export function CommandPaletteItem({
127
128
  xstyle,
128
129
  className,
129
130
  style,
131
+ onClick: onClickProp,
132
+ onMouseEnter: onMouseEnterProp,
130
133
  ...props
131
134
  }: CommandPaletteItemProps) {
132
135
  const ctx = useCommandPaletteContext();
@@ -186,13 +189,14 @@ export function CommandPaletteItem({
186
189
  return (
187
190
  <div
188
191
  ref={mergeRefs(ref, itemRef)}
192
+ {...props}
189
193
  id={ctx && itemIndex >= 0 ? ctx.getItemId(itemIndex) : undefined}
190
194
  role="option"
191
195
  aria-selected={isSelected}
192
196
  aria-disabled={isDisabled || undefined}
193
197
  data-value={value}
194
- onClick={handleClick}
195
- onMouseEnter={handleMouseEnter}
198
+ onClick={composeEventHandlers(onClickProp, handleClick)}
199
+ onMouseEnter={composeEventHandlers(onMouseEnterProp, handleMouseEnter)}
196
200
  {...mergeProps(
197
201
  themeProps('command-palette-item'),
198
202
  stylex.props(
@@ -205,8 +209,7 @@ export function CommandPaletteItem({
205
209
  ),
206
210
  className,
207
211
  style,
208
- )}
209
- {...props}>
212
+ )}>
210
213
  {children}
211
214
  </div>
212
215
  );
@@ -87,6 +87,7 @@ export function CommandPaletteList({
87
87
  return (
88
88
  <div
89
89
  ref={ref}
90
+ {...props}
90
91
  id={ctx?.listId}
91
92
  role="listbox"
92
93
  aria-label={label}
@@ -95,8 +96,7 @@ export function CommandPaletteList({
95
96
  stylex.props(styles.list, xstyle),
96
97
  className,
97
98
  style,
98
- )}
99
- {...props}>
99
+ )}>
100
100
  {children}
101
101
  </div>
102
102
  );
@@ -24,6 +24,7 @@ export const docs = {
24
24
  className: 'astryx-complex-selector-indicator-icon',
25
25
  states: ['state'],
26
26
  },
27
+ {className: 'astryx-complex-selector-popup'},
27
28
  ],
28
29
  },
29
30
  components: [
@@ -164,6 +165,47 @@ export const docsDense = {
164
165
  category: 'Data Input',
165
166
  description:
166
167
  'Field+dialog-popover shell for rich custom selectors. Content gets value/onChange/close/state; content owns semantics. Use focus hooks and evaluate custom content against WCAG 2.2.',
168
+ usage: {
169
+ description:
170
+ 'Use when a selection needs richer custom content than a Selector row. One component: it owns field, trigger, popover, focus restore, and changeAction; the render prop owns the selector-specific accessible structure.',
171
+ bestPractices: [
172
+ {
173
+ guidance: true,
174
+ description:
175
+ 'Compose content from the right accessible structure: RadioList for a simple choice, Calendar/date inputs for dates, TreeList or a searchable list for hierarchy, a custom grid for 2D arrow navigation.',
176
+ },
177
+ {
178
+ guidance: true,
179
+ description:
180
+ 'Use the onChange helper from children; it calls both onChange and changeAction and updates optimistic busy state.',
181
+ },
182
+ {
183
+ guidance: true,
184
+ description:
185
+ 'Call close() from custom content when a selection should dismiss the popup. Keep it open for multi-step or freeform flows.',
186
+ },
187
+ {
188
+ guidance: true,
189
+ description:
190
+ 'Use Astryx focus hooks: useGridFocus for 2D grids, useTreeFocus via TreeList for hierarchies, useListFocus for custom linear collections.',
191
+ },
192
+ {
193
+ guidance: true,
194
+ description:
195
+ 'Evaluate custom content against WCAG 2.2: keyboard operation, focus visible/not obscured, names and roles, labels/instructions, target size, and contrast.',
196
+ },
197
+ {
198
+ guidance: false,
199
+ description:
200
+ 'Do not rebuild trigger ARIA, popover focus management, or changeAction handling in product code.',
201
+ },
202
+ {
203
+ guidance: false,
204
+ description:
205
+ 'Do not use ComplexSelector for a plain single-column text list; use Selector instead.',
206
+ },
207
+ ],
208
+ },
167
209
  propDescriptions: {
168
210
  label: 'Accessible field label.',
169
211
  value: 'Controlled value.',