@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
@@ -24,6 +24,7 @@ import {useIcon} from '../Icon';
24
24
  import {useChatComposerContext} from './ChatContext';
25
25
 
26
26
  import type {BaseProps} from '../BaseProps';
27
+ import {mergeProps} from '../utils';
27
28
  import {themeProps} from '../utils/themeProps';
28
29
  import {useTranslator} from '../i18n';
29
30
 
@@ -117,9 +118,7 @@ export function ChatSendButton(props: ChatSendButtonProps): ReactNode {
117
118
  isDisabled={!isStopShown && isDisabled}
118
119
  onClick={isStopShown ? onStop : handleSend}
119
120
  {...rest}
120
- {...themeProps('chat-send-button')}
121
- className={className}
122
- style={style}
121
+ {...mergeProps(themeProps('chat-send-button'), {className}, style)}
123
122
  xstyle={[styles.root, xstyle]}
124
123
  />
125
124
  );
@@ -216,4 +216,39 @@ describe('ChatToolCalls', () => {
216
216
  expect(region).toHaveTextContent('searchCode');
217
217
  expect(region).toHaveTextContent('readFile');
218
218
  });
219
+
220
+ it('compensates the grouped rows overhang on the clip boundary so the hover background is not cut off', () => {
221
+ render(
222
+ <ChatToolCalls
223
+ defaultIsExpanded={true}
224
+ calls={[
225
+ {name: 'bash', status: 'complete'},
226
+ {name: 'read', status: 'complete'},
227
+ ]}
228
+ />,
229
+ );
230
+ const regionId = screen.getByRole('button').getAttribute('aria-controls');
231
+ const groupContent = document.getElementById(regionId as string);
232
+ // groupContentInner is the overflow:hidden clip boundary required for the
233
+ // grid height animation; its direct child (`list`) pulls itself outward
234
+ // by a negative inline margin so each row's hover background can overhang
235
+ // the text column without widening the layout. Without a matching
236
+ // padding/negative-margin pair on groupContentInner itself, that overhang
237
+ // extends past the clip boundary and gets cut off (#4830) instead of
238
+ // being absorbed the same way it is for a single, unwrapped call row.
239
+ const groupContentInner = groupContent!.firstElementChild as HTMLElement;
240
+ const list = groupContentInner.firstElementChild as HTMLElement;
241
+ // jsdom's getComputedStyle doesn't resolve StyleX's generated atomic
242
+ // classes here, so assert on the classes directly instead. StyleX emits
243
+ // one atomic class per distinct property+value pair, so identical
244
+ // paddingInline/marginInline values on two elements always produce the
245
+ // exact same class names — if groupContentInner mirrors list's
246
+ // padding/margin pair, their class lists intersect on (at least) those
247
+ // two classes; if the fix is missing, groupContentInner only has its own
248
+ // unrelated overflow/minHeight classes and shares nothing with list.
249
+ const innerClasses = new Set(groupContentInner.className.split(' '));
250
+ const listClasses = new Set(list.className.split(' '));
251
+ const shared = [...listClasses].filter(c => innerClasses.has(c));
252
+ expect(shared.length).toBeGreaterThanOrEqual(2);
253
+ });
219
254
  });
@@ -134,6 +134,10 @@ const styles = stylex.create({
134
134
  width: '14px',
135
135
  height: '14px',
136
136
  color: colorVars['--color-text-disabled'],
137
+ },
138
+ // Rides on the chevron <Icon> (via `xstyle`), next to the rotation it
139
+ // animates, so one element carries both the transform and the theme target.
140
+ chevronTransition: {
137
141
  transition: {
138
142
  default: `transform ${durationVars['--duration-fast']} ${easeVars['--ease-standard']}`,
139
143
  '@media (prefers-reduced-motion: reduce)': 'none',
@@ -156,6 +160,18 @@ const styles = stylex.create({
156
160
  groupContentInner: {
157
161
  overflow: 'hidden',
158
162
  minHeight: 0,
163
+ // `list` (and, within it, each `callRowClickable` row) overhangs its own
164
+ // content box by `--spacing-1` on each inline edge via a negative margin,
165
+ // so its hover background can extend past the text column without
166
+ // widening the layout — `list`'s own matching paddingInline absorbs the
167
+ // row-level overhang, but `list`'s negative margin then overhangs *this*
168
+ // element's box by the same amount, and this is the clip boundary the
169
+ // grid height animation needs `overflow: hidden` for. Mirror the same
170
+ // padding/negative-margin pair here so that overhang is absorbed too,
171
+ // instead of clipped — matching the ungrouped single-call row, which has
172
+ // no such wrapper to clip it.
173
+ paddingInline: spacingVars['--spacing-1'],
174
+ marginInline: `calc(-1 * ${spacingVars['--spacing-1']})`,
159
175
  },
160
176
  list: {
161
177
  display: 'flex',
@@ -273,10 +289,6 @@ const styles = stylex.create({
273
289
  width: '14px',
274
290
  height: '14px',
275
291
  color: colorVars['--color-text-disabled'],
276
- transition: {
277
- default: `transform ${durationVars['--duration-fast']} ${easeVars['--ease-standard']}`,
278
- '@media (prefers-reduced-motion: reduce)': 'none',
279
- },
280
292
  marginInlineStart: 'auto',
281
293
  },
282
294
  callDetailContent: {
@@ -451,12 +463,16 @@ function CallRow({call}: {call: ChatToolCallItem}) {
451
463
  <span {...stylex.props(styles.callDuration)}>{call.duration}</span>
452
464
  )}
453
465
  {hasDetail && (
454
- <span
455
- {...stylex.props(
456
- styles.callDetailChevron,
457
- isDetailOpen && styles.chevronExpanded,
458
- )}>
459
- <Icon icon="chevronDown" size="xsm" color="inherit" />
466
+ <span {...stylex.props(styles.callDetailChevron)}>
467
+ <Icon
468
+ icon="chevronDown"
469
+ size="xsm"
470
+ color="inherit"
471
+ xstyle={[
472
+ styles.chevronTransition,
473
+ isDetailOpen && styles.chevronExpanded,
474
+ ]}
475
+ />
460
476
  </span>
461
477
  )}
462
478
  </div>
@@ -627,12 +643,16 @@ export function ChatToolCalls(props: ChatToolCallsProps) {
627
643
  </>
628
644
  )}
629
645
  </span>
630
- <span
631
- {...stylex.props(
632
- styles.chevron,
633
- isExpanded && styles.chevronExpanded,
634
- )}>
635
- <Icon icon="chevronDown" size="xsm" color="inherit" />
646
+ <span {...stylex.props(styles.chevron)}>
647
+ <Icon
648
+ icon="chevronDown"
649
+ size="xsm"
650
+ color="inherit"
651
+ xstyle={[
652
+ styles.chevronTransition,
653
+ isExpanded && styles.chevronExpanded,
654
+ ]}
655
+ />
636
656
  </span>
637
657
  </div>
638
658
 
@@ -110,10 +110,6 @@ const styles = stylex.create({
110
110
  popoverSurface: {
111
111
  minWidth: '180px',
112
112
  },
113
- popoverGap: {
114
- marginBlockStart: spacingVars['--spacing-1'],
115
- marginBlockEnd: spacingVars['--spacing-1'],
116
- },
117
113
  item: {
118
114
  boxSizing: 'border-box',
119
115
  display: 'flex',
@@ -711,7 +707,8 @@ export function useTriggerMenu(
711
707
  {
712
708
  placement: 'above',
713
709
  alignment: 'start',
714
- xstyle: [styles.popoverSurface, styles.popoverGap],
710
+ offset: spacingVars['--spacing-1'],
711
+ xstyle: styles.popoverSurface,
715
712
  },
716
713
  );
717
714
  }, [popover, listboxId, state, selectItem, getItemId, t]);
@@ -131,7 +131,8 @@ export const docs = {
131
131
  theming: {
132
132
  targets: [
133
133
  {className: 'astryx-checkbox-input', visualProps: ['size']},
134
- {className: 'astryx-checkbox', visualProps: ['size'], states: ['checked', 'disabled']},
134
+ {className: 'astryx-checkbox-indicator', visualProps: ['size'], states: ['checked', 'disabled']},
135
+ {className: 'astryx-checkbox', visualProps: ['size'], states: ['checked', 'disabled'], deprecatedFor: 'checkbox-indicator'},
135
136
  ],
136
137
  },
137
138
  usage: {
@@ -206,7 +207,8 @@ export const docsZh = {
206
207
  'size',
207
208
  ],
208
209
  },
209
- {className: 'astryx-checkbox', visualProps: ['size'], states: ['checked', 'disabled']},
210
+ {className: 'astryx-checkbox-indicator', visualProps: ['size'], states: ['checked', 'disabled']},
211
+ {className: 'astryx-checkbox', visualProps: ['size'], states: ['checked', 'disabled'], deprecatedFor: 'checkbox-indicator'},
210
212
  ],
211
213
  },
212
214
  };
@@ -13,8 +13,11 @@ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
13
13
  import {render, screen, fireEvent, waitFor} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {CheckboxInput} from './CheckboxInput';
16
+ import {Theme} from '../theme/Theme';
17
+ import {defineTheme} from '../theme/defineTheme';
16
18
  import {getForcedColorsRules} from '../__tests__/forcedColors';
17
19
  import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
20
+ import {FOCUS_OUTLINE_PARTS} from '../utils/focusOutline.stylex';
18
21
 
19
22
  afterEach(() => {
20
23
  __resetLiveRegionsForTest();
@@ -542,6 +545,38 @@ describe('CheckboxInput', () => {
542
545
  expect(data.get('terms')).toBe('on');
543
546
  });
544
547
 
548
+ it('does not block form submission when required and disabled with a disabledMessage', () => {
549
+ const {container} = render(
550
+ <form>
551
+ <CheckboxInput
552
+ label="Terms"
553
+ htmlName="terms"
554
+ value={false}
555
+ onChange={() => {}}
556
+ isRequired
557
+ isDisabled
558
+ disabledMessage="Terms are managed by your administrator"
559
+ />
560
+ </form>,
561
+ );
562
+ expect(container.querySelector('form')!.checkValidity()).toBe(true);
563
+ });
564
+
565
+ it('still blocks submission when required and unchecked but enabled', () => {
566
+ const {container} = render(
567
+ <form>
568
+ <CheckboxInput
569
+ label="Terms"
570
+ htmlName="terms"
571
+ value={false}
572
+ onChange={() => {}}
573
+ isRequired
574
+ />
575
+ </form>,
576
+ );
577
+ expect(container.querySelector('form')!.checkValidity()).toBe(false);
578
+ });
579
+
545
580
  it('is excluded from form data when disabled, even with a disabledMessage', () => {
546
581
  const {container} = render(
547
582
  <form>
@@ -599,3 +634,88 @@ describe('forced colors (WCAG 1.4.11)', () => {
599
634
  expect(getForcedColorsRules()).toContain('color: canvastext;');
600
635
  });
601
636
  });
637
+
638
+ // The control's native input is `opacity: 0`, so the visible focus indicator
639
+ // has to land on the indicator beside it — which is themeable, third-party
640
+ // code. If drawing the ring were the indicator's job, a replacement that
641
+ // simply doesn't would ship a control with no visible focus (WCAG 2.4.7), and
642
+ // that is the default: our own sample replacement destructures
643
+ // {state, size, isDisabled} and drops the rest.
644
+ //
645
+ // So the owner paints it, on the indicator's own element, at focus time. The
646
+ // shape is right because `outline` follows that element's border-radius, and
647
+ // no cooperation is required.
648
+ describe('focus ring ownership (WCAG 2.4.7)', () => {
649
+ /** What a theme author plausibly writes: state in, picture out. */
650
+ const BareIndicator = ({state}: {state: string}) => (
651
+ <span aria-hidden="true" data-testid="bare-indicator">
652
+ {state === 'checked' ? 'x' : ''}
653
+ </span>
654
+ );
655
+
656
+ const bareTheme = defineTheme({
657
+ name: 'bare-indicator-theme',
658
+ indicators: {checkbox: BareIndicator},
659
+ });
660
+
661
+ /**
662
+ * The element the ring is painted on: the indicator slot's only child — the
663
+ * indicator's own root, whatever a theme renders there.
664
+ */
665
+ const indicatorOf = (container: HTMLElement) => {
666
+ const input = container.querySelector('input[type="checkbox"]');
667
+ const slot = input?.nextElementSibling;
668
+ return slot?.firstElementChild as HTMLElement;
669
+ };
670
+
671
+ const focusInput = (container: HTMLElement) => {
672
+ const input = container.querySelector(
673
+ 'input[type="checkbox"]',
674
+ ) as HTMLInputElement;
675
+ // A keydown first, so jsdom's :focus-visible heuristic sees keyboard
676
+ // modality — the ring is deliberately keyboard-only, and a bare
677
+ // fireEvent.focus() reads as a pointer focus. Same approach as the
678
+ // TreeList focus test.
679
+ fireEvent.keyDown(document.body, {key: 'Tab'});
680
+ input.focus();
681
+ fireEvent.focus(input);
682
+ return input;
683
+ };
684
+
685
+ it('paints the ring on the built-in indicator', () => {
686
+ const {container} = render(
687
+ <CheckboxInput label="Accept" value={false} onChange={() => {}} />,
688
+ );
689
+ focusInput(container);
690
+ expect(indicatorOf(container).style.outlineStyle).toBe(
691
+ FOCUS_OUTLINE_PARTS.outlineStyle,
692
+ );
693
+ });
694
+
695
+ it('paints it on a replacement that forwards nothing', () => {
696
+ const {container} = render(
697
+ <Theme theme={bareTheme}>
698
+ <CheckboxInput label="Accept" value={false} onChange={() => {}} />
699
+ </Theme>,
700
+ );
701
+
702
+ // The replacement really took effect, and really is bare.
703
+ const replaced = screen.getByTestId('bare-indicator');
704
+ expect(replaced.className).toBe('');
705
+ // ...and it still gets a ring, because the owner drew it.
706
+ focusInput(container);
707
+ expect(replaced.style.outlineStyle).toBe(FOCUS_OUTLINE_PARTS.outlineStyle);
708
+ });
709
+
710
+ it('clears the ring on blur', () => {
711
+ const {container} = render(
712
+ <CheckboxInput label="Accept" value={false} onChange={() => {}} />,
713
+ );
714
+ const input = focusInput(container);
715
+ expect(indicatorOf(container).style.outlineStyle).toBe(
716
+ FOCUS_OUTLINE_PARTS.outlineStyle,
717
+ );
718
+ fireEvent.blur(input);
719
+ expect(indicatorOf(container).style.outlineStyle).toBe('');
720
+ });
721
+ });
@@ -21,6 +21,7 @@ import {
21
21
  useCallback,
22
22
  use,
23
23
  useOptimistic,
24
+ useRef,
24
25
  useTransition,
25
26
  type ChangeEvent,
26
27
  type FocusEvent,
@@ -31,12 +32,9 @@ import {
31
32
  colorVars,
32
33
  spacingVars,
33
34
  radiusVars,
34
- durationVars,
35
- easeVars,
36
35
  typographyVars,
37
36
  typeScaleVars,
38
37
  fontWeightVars,
39
- borderVars,
40
38
  } from '../theme/tokens.stylex';
41
39
  import type {BaseProps} from '../BaseProps';
42
40
  import type {SizeValue} from '../utils/types';
@@ -47,7 +45,9 @@ import type {InputStatus} from '../Field/types';
47
45
  import {Spinner} from '../Spinner';
48
46
  import {useTooltip} from '../Tooltip';
49
47
  import {mergeProps, mergeRefs} from '../utils';
50
- import {checkboxScope} from './checkbox.markers.stylex';
48
+ import {indicatorScope} from '../Indicator/indicator.markers.stylex';
49
+ import {useIndicatorFocusRing} from '../hooks/useIndicatorFocusRing';
50
+ import {useIndicator} from '../Indicator';
51
51
  import {themeProps} from '../utils/themeProps';
52
52
  import {CheckboxListContext} from '../CheckboxList/CheckboxListContext';
53
53
 
@@ -68,6 +68,12 @@ const styles = stylex.create({
68
68
  flexShrink: 0,
69
69
  isolation: 'isolate',
70
70
  },
71
+ // Holds only the indicator, so the focus ring has one unambiguous target.
72
+ // `display: contents` adds no box of its own — the indicator keeps whatever
73
+ // layout relationship it already had with the wrapper.
74
+ indicatorSlot: {
75
+ display: 'contents',
76
+ },
71
77
  input: {
72
78
  position: 'absolute',
73
79
  margin: 0,
@@ -79,113 +85,6 @@ const styles = stylex.create({
79
85
  inputDisabled: {
80
86
  cursor: 'not-allowed',
81
87
  },
82
- checkbox: {
83
- display: 'flex',
84
- alignItems: 'center',
85
- justifyContent: 'center',
86
- borderWidth: borderVars['--border-width'],
87
- borderStyle: 'solid',
88
- borderRadius: radiusVars['--radius-inner'],
89
- transitionProperty: 'background-color, border-color',
90
- transitionDuration: {
91
- default: durationVars['--duration-fast'],
92
- '@media (prefers-reduced-motion: reduce)': '0s',
93
- },
94
- transitionTimingFunction: easeVars['--ease-standard'],
95
- },
96
- checkboxFocus: {
97
- outline: {
98
- default: 'none',
99
- [stylex.when.ancestor(':has(:focus-visible)', checkboxScope)]:
100
- `2px solid ${colorVars['--color-accent']}`,
101
- },
102
- outlineOffset: {
103
- default: null,
104
- [stylex.when.ancestor(':has(:focus-visible)', checkboxScope)]: '2px',
105
- },
106
- },
107
- // State-dependent colors with ancestor hover behavior
108
- checkboxUnchecked: {
109
- // Foreground for the inherit-shade loading spinner (reads currentColor):
110
- // brand accent on the light surface fill.
111
- color: colorVars['--color-accent'],
112
- borderColor: {
113
- default: colorVars['--color-border-emphasized'],
114
- [stylex.when.ancestor(':hover', checkboxScope)]: {
115
- '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-border-emphasized']}, ${colorVars['--color-tint-hover']} 20%)`,
116
- },
117
- },
118
- backgroundColor: {
119
- default: colorVars['--color-background-surface'],
120
- [stylex.when.ancestor(':hover', checkboxScope)]: {
121
- '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-background-surface']}, ${colorVars['--color-tint-hover']} 5%)`,
122
- },
123
- },
124
- },
125
- checkboxChecked: {
126
- // Foreground for the inherit-shade loading spinner (reads currentColor):
127
- // on-accent color against the accent fill.
128
- color: colorVars['--color-on-accent'],
129
- borderColor: {
130
- default: colorVars['--color-accent'],
131
- [stylex.when.ancestor(':hover', checkboxScope)]: {
132
- '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-accent']}, ${colorVars['--color-tint-hover']} 15%)`,
133
- },
134
- },
135
- backgroundColor: {
136
- default: colorVars['--color-accent'],
137
- [stylex.when.ancestor(':hover', checkboxScope)]: {
138
- '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-accent']}, ${colorVars['--color-tint-hover']} 15%)`,
139
- },
140
- },
141
- },
142
- checkboxDisabled: {
143
- opacity: 0.5,
144
- borderColor: {
145
- default: colorVars['--color-border'],
146
- [stylex.when.ancestor(':hover', checkboxScope)]: {
147
- '@media (hover: hover)': colorVars['--color-border'],
148
- },
149
- },
150
- },
151
- checkboxDisabledUnchecked: {
152
- backgroundColor: {
153
- default: colorVars['--color-background-muted'],
154
- [stylex.when.ancestor(':hover', checkboxScope)]: {
155
- '@media (hover: hover)': colorVars['--color-background-muted'],
156
- },
157
- },
158
- },
159
- checkmark: {
160
- display: 'none',
161
- color: {
162
- default: colorVars['--color-on-accent'],
163
- // Forced colors (Windows High Contrast) does not reliably force an SVG
164
- // stroke painted with currentColor, so the check stays the same white as
165
- // the flattened (Canvas) box fill — a white check on a white box.
166
- // CanvasText keeps it perceivable on the Canvas box, matching the
167
- // indeterminate mark (WCAG 1.4.11).
168
- '@media (forced-colors: active)': 'CanvasText',
169
- },
170
- },
171
- checkmarkVisible: {
172
- display: 'block',
173
- },
174
- indeterminateMark: {
175
- display: 'none',
176
- backgroundColor: {
177
- default: colorVars['--color-on-accent'],
178
- // Forced colors (Windows High Contrast) strips painted backgrounds,
179
- // which would make the indeterminate bar invisible; CanvasText keeps it
180
- // perceivable on the Canvas box fill (WCAG 1.4.11). The checkmark carries
181
- // the matching CanvasText treatment on its own style.
182
- '@media (forced-colors: active)': 'CanvasText',
183
- },
184
- borderRadius: radiusVars['--radius-full'],
185
- },
186
- indeterminateMarkVisible: {
187
- display: 'block',
188
- },
189
88
  labelWrapper: {
190
89
  display: 'flex',
191
90
  flexDirection: 'column',
@@ -211,39 +110,6 @@ const wrapperSizeStyles = stylex.create({
211
110
  },
212
111
  });
213
112
 
214
- const checkboxSizeStyles = stylex.create({
215
- sm: {
216
- width: 20,
217
- height: 20,
218
- },
219
- md: {
220
- width: 24,
221
- height: 24,
222
- },
223
- });
224
-
225
- const checkmarkSizeStyles = stylex.create({
226
- sm: {
227
- width: 12,
228
- height: 12,
229
- },
230
- md: {
231
- width: 14,
232
- height: 14,
233
- },
234
- });
235
-
236
- const indeterminateSizeStyles = stylex.create({
237
- sm: {
238
- width: 10,
239
- height: 2,
240
- },
241
- md: {
242
- width: 12,
243
- height: 2,
244
- },
245
- });
246
-
247
113
  export type CheckboxInputSize = keyof typeof wrapperSizeStyles;
248
114
 
249
115
  export interface CheckboxInputProps extends Omit<BaseProps, 'onChange'> {
@@ -443,9 +309,17 @@ export function CheckboxInput({
443
309
  isEnabled: showsDisabledMessage,
444
310
  });
445
311
 
312
+ // The checkbox visual is an indicator: a theme can restyle it through the
313
+ // `checkbox` target or replace the component outright.
314
+ const CheckboxControl = useIndicator('checkbox');
315
+ // The ring is drawn on the indicator itself: the native input is
316
+ // `opacity: 0`, and only the indicator's own element can shape the outline
317
+ // to match it. See useIndicatorFocusRing.
318
+ const indicatorRef = useRef<HTMLSpanElement>(null);
319
+ const {focusProps} = useIndicatorFocusRing(indicatorRef, isDisabled);
320
+
446
321
  const isIndeterminate = optimisticValue === 'indeterminate';
447
322
  const isChecked = optimisticValue === true;
448
- const isCheckedOrIndeterminate = isChecked || isIndeterminate;
449
323
 
450
324
  // Sync the native indeterminate DOM property (can't be set via JSX
451
325
  // attribute). On a native checkbox this is the authoritative way to expose
@@ -498,9 +372,13 @@ export function CheckboxInput({
498
372
  {...stylex.props(
499
373
  styles.container,
500
374
  isLabelHidden && styles.containerLabelHidden,
501
- !isDisabled && checkboxScope,
375
+ // Hover and focus reach the checkbox visual through this ancestor
376
+ // marker rather than props, so the whole row drives it.
377
+ !isDisabled && indicatorScope,
502
378
  )}>
503
- <div {...stylex.props(styles.checkboxWrapper, wrapperSizeStyles[size])}>
379
+ <div
380
+ {...stylex.props(styles.checkboxWrapper, wrapperSizeStyles[size])}
381
+ {...focusProps}>
504
382
  <input
505
383
  {...rest}
506
384
  ref={mergeRefs(
@@ -520,6 +398,7 @@ export function CheckboxInput({
520
398
  // still blocked by the isDisabled guard in onChange below.
521
399
  disabled={isDisabled && !isFocusableDisabled}
522
400
  aria-disabled={isFocusableDisabled ? 'true' : undefined}
401
+ form={isFocusableDisabled ? '' : undefined}
523
402
  readOnly={isReadOnly}
524
403
  required={isRequired}
525
404
  onChange={e => {
@@ -547,61 +426,25 @@ export function CheckboxInput({
547
426
  isDisabled && styles.inputDisabled,
548
427
  )}
549
428
  />
550
- <div
551
- aria-hidden="true"
552
- {...mergeProps(
553
- themeProps('checkbox', {
554
- size,
555
- checked: isChecked
556
- ? 'checked'
557
- : isIndeterminate
558
- ? 'indeterminate'
559
- : null,
560
- disabled: isDisabled ? 'disabled' : null,
561
- }),
562
- stylex.props(
563
- styles.checkbox,
564
- checkboxSizeStyles[size],
565
- !isDisabled && styles.checkboxFocus,
566
- isCheckedOrIndeterminate
567
- ? styles.checkboxChecked
568
- : styles.checkboxUnchecked,
569
- isDisabled && styles.checkboxDisabled,
570
- isDisabled &&
571
- !isCheckedOrIndeterminate &&
572
- styles.checkboxDisabledUnchecked,
573
- ),
574
- )}>
575
- {isBusy ? (
576
- <Spinner size="sm" shade="inherit" />
577
- ) : (
578
- <>
579
- <svg
580
- viewBox="0 0 10 10"
581
- {...stylex.props(
582
- styles.checkmark,
583
- checkmarkSizeStyles[size],
584
- isChecked && styles.checkmarkVisible,
585
- )}>
586
- <path
587
- d="M8.5 2.5L4 7.5L1.5 5"
588
- stroke="currentColor"
589
- strokeWidth="1.5"
590
- fill="none"
591
- strokeLinecap="round"
592
- strokeLinejoin="round"
593
- />
594
- </svg>
595
- <div
596
- {...stylex.props(
597
- styles.indeterminateMark,
598
- indeterminateSizeStyles[size],
599
- isIndeterminate && styles.indeterminateMarkVisible,
600
- )}
601
- />
602
- </>
603
- )}
604
- </div>
429
+ {/*
430
+ * A container holding ONLY the indicator, so the focus ring has an
431
+ * unambiguous target whatever a theme renders. `display: contents`
432
+ * keeps it out of layout entirely.
433
+ */}
434
+ <span ref={indicatorRef} {...stylex.props(styles.indicatorSlot)}>
435
+ <CheckboxControl
436
+ state={
437
+ isIndeterminate
438
+ ? 'indeterminate'
439
+ : isChecked
440
+ ? 'checked'
441
+ : 'unchecked'
442
+ }
443
+ size={size}
444
+ isDisabled={isDisabled}>
445
+ {isBusy ? <Spinner size="sm" shade="inherit" /> : null}
446
+ </CheckboxControl>
447
+ </span>
605
448
  </div>
606
449
  <div {...stylex.props(styles.labelWrapper)}>
607
450
  <FieldLabel