@astryxdesign/core 0.1.8 → 0.1.9

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 (487) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +6 -2
  4. package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
  5. package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
  6. package/dist/Avatar/Avatar.d.ts +18 -2
  7. package/dist/Avatar/Avatar.d.ts.map +1 -1
  8. package/dist/Avatar/Avatar.js +63 -7
  9. package/dist/Avatar/AvatarStatusDot.d.ts +33 -5
  10. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  11. package/dist/Avatar/AvatarStatusDot.js +144 -19
  12. package/dist/Banner/Banner.d.ts +9 -1
  13. package/dist/Banner/Banner.d.ts.map +1 -1
  14. package/dist/Banner/Banner.js +31 -2
  15. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
  16. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  17. package/dist/Breadcrumbs/BreadcrumbItem.js +208 -6
  18. package/dist/Breadcrumbs/index.d.ts +5 -0
  19. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  20. package/dist/Breadcrumbs/index.js +9 -1
  21. package/dist/Button/Button.d.ts +8 -2
  22. package/dist/Button/Button.d.ts.map +1 -1
  23. package/dist/Button/Button.js +31 -2
  24. package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
  25. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  26. package/dist/ButtonGroup/ButtonGroup.js +30 -1
  27. package/dist/Calendar/Calendar.d.ts.map +1 -1
  28. package/dist/Calendar/Calendar.js +30 -2
  29. package/dist/Calendar/dayCellUtils.js +1 -1
  30. package/dist/Card/Card.d.ts +8 -2
  31. package/dist/Card/Card.d.ts.map +1 -1
  32. package/dist/Card/Card.js +28 -2
  33. package/dist/Carousel/Carousel.d.ts +4 -1
  34. package/dist/Carousel/Carousel.d.ts.map +1 -1
  35. package/dist/Carousel/Carousel.js +24 -4
  36. package/dist/Chat/ChatComposer.d.ts +8 -0
  37. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  38. package/dist/Chat/ChatComposer.js +46 -7
  39. package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
  40. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  41. package/dist/Chat/ChatComposerDrawer.js +11 -1
  42. package/dist/Chat/ChatComposerInput.d.ts +20 -3
  43. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  44. package/dist/Chat/ChatComposerInput.js +35 -3
  45. package/dist/Chat/ChatContext.d.ts +33 -0
  46. package/dist/Chat/ChatContext.d.ts.map +1 -1
  47. package/dist/Chat/ChatContext.js +16 -2
  48. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  49. package/dist/Chat/ChatDictationButton.js +1 -1
  50. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  51. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  52. package/dist/Chat/ChatLayoutScrollButton.js +4 -4
  53. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  54. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  55. package/dist/Chat/ChatSendButton.js +7 -1
  56. package/dist/Chat/ChatToolCalls.d.ts +5 -1
  57. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  58. package/dist/Chat/ChatToolCalls.js +18 -9
  59. package/dist/Chat/index.d.ts +2 -1
  60. package/dist/Chat/index.d.ts.map +1 -1
  61. package/dist/Chat/index.js +1 -1
  62. package/dist/Chat/useChatStreamScroll.d.ts +2 -1
  63. package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
  64. package/dist/Chat/useChatStreamScroll.js +22 -8
  65. package/dist/Chat/useSpeechRecognition.d.ts +0 -1
  66. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  67. package/dist/Chat/useSpeechRecognition.js +1 -1
  68. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  69. package/dist/CheckboxInput/CheckboxInput.js +1 -1
  70. package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
  71. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  72. package/dist/CheckboxList/CheckboxListItem.js +11 -1
  73. package/dist/ClickableCard/ClickableCard.d.ts +9 -2
  74. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  75. package/dist/ClickableCard/ClickableCard.js +5 -2
  76. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  77. package/dist/CodeBlock/CodeBlock.js +8 -1
  78. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  79. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  80. package/dist/CommandPalette/CommandPalette.js +3 -1
  81. package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
  82. package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
  83. package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
  84. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  85. package/dist/CommandPalette/CommandPaletteInput.js +6 -1
  86. package/dist/DateInput/DateInput.d.ts +47 -1
  87. package/dist/DateInput/DateInput.d.ts.map +1 -1
  88. package/dist/DateInput/DateInput.js +26 -2
  89. package/dist/DateInput/index.d.ts +1 -1
  90. package/dist/DateInput/index.d.ts.map +1 -1
  91. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  92. package/dist/DateTimeInput/DateTimeInput.js +10 -1
  93. package/dist/Dialog/Dialog.d.ts +3 -0
  94. package/dist/Dialog/Dialog.d.ts.map +1 -1
  95. package/dist/Dialog/Dialog.js +57 -6
  96. package/dist/Dialog/DialogContext.d.ts +7 -0
  97. package/dist/Dialog/DialogContext.d.ts.map +1 -1
  98. package/dist/Dialog/DialogContext.js +2 -2
  99. package/dist/Dialog/DialogHeader.d.ts +5 -2
  100. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  101. package/dist/Dialog/DialogHeader.js +6 -1
  102. package/dist/Divider/Divider.js +1 -1
  103. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
  104. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  105. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +1 -2
  106. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
  107. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  108. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
  109. package/dist/Field/Field.d.ts.map +1 -1
  110. package/dist/Field/Field.js +2 -3
  111. package/dist/Field/FieldLabel.d.ts +1 -1
  112. package/dist/Field/FieldLabel.d.ts.map +1 -1
  113. package/dist/Field/FieldLabel.js +42 -15
  114. package/dist/FieldStatus/FieldStatus.d.ts +8 -0
  115. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  116. package/dist/FieldStatus/FieldStatus.js +22 -4
  117. package/dist/FileInput/FileInput.d.ts.map +1 -1
  118. package/dist/FileInput/FileInput.js +10 -2
  119. package/dist/HoverCard/HoverCard.d.ts +9 -1
  120. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  121. package/dist/HoverCard/HoverCard.js +2 -0
  122. package/dist/HoverCard/useHoverCard.d.ts +8 -0
  123. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  124. package/dist/HoverCard/useHoverCard.js +7 -2
  125. package/dist/Icon/Icon.d.ts +7 -2
  126. package/dist/Icon/Icon.d.ts.map +1 -1
  127. package/dist/Item/Item.d.ts +6 -1
  128. package/dist/Item/Item.d.ts.map +1 -1
  129. package/dist/Item/Item.js +22 -1
  130. package/dist/Layer/useLayer.d.ts +6 -0
  131. package/dist/Layer/useLayer.d.ts.map +1 -1
  132. package/dist/Layer/useLayer.js +2 -0
  133. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  134. package/dist/MobileNav/MobileNav.js +6 -1
  135. package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
  136. package/dist/MobileNav/MobileNavToggle.js +4 -0
  137. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  138. package/dist/MultiSelector/MultiSelector.js +39 -12
  139. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  140. package/dist/MultiSelector/hooks.js +16 -0
  141. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  142. package/dist/Outline/Outline.d.ts +0 -1
  143. package/dist/Outline/Outline.d.ts.map +1 -1
  144. package/dist/Outline/Outline.js +0 -1
  145. package/dist/OverflowList/OverflowList.d.ts +20 -3
  146. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  147. package/dist/OverflowList/OverflowList.js +29 -4
  148. package/dist/Popover/Popover.d.ts.map +1 -1
  149. package/dist/Popover/Popover.js +3 -2
  150. package/dist/Popover/usePopover.d.ts.map +1 -1
  151. package/dist/Popover/usePopover.js +3 -9
  152. package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
  153. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  154. package/dist/SelectableCard/SelectableCard.d.ts +9 -2
  155. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  156. package/dist/SelectableCard/SelectableCard.js +16 -13
  157. package/dist/Selector/Selector.d.ts.map +1 -1
  158. package/dist/Selector/Selector.js +4 -2
  159. package/dist/Selector/hooks.d.ts.map +1 -1
  160. package/dist/Selector/hooks.js +16 -0
  161. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  162. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  163. package/dist/SideNav/SideNavHeading.js +21 -8
  164. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  165. package/dist/Slider/Slider.d.ts.map +1 -1
  166. package/dist/Slider/Slider.js +19 -2
  167. package/dist/Stack/stack.stylex.d.ts +9 -9
  168. package/dist/Table/BaseTable.d.ts.map +1 -1
  169. package/dist/Table/BaseTable.js +3 -2
  170. package/dist/Table/index.d.ts +2 -0
  171. package/dist/Table/index.d.ts.map +1 -1
  172. package/dist/Table/index.js +1 -0
  173. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  174. package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
  175. package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
  176. package/dist/Table/plugins/rowStatus/index.js +3 -0
  177. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
  178. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
  179. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
  180. package/dist/Table/plugins/selection/useTableSelection.d.ts +13 -0
  181. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  182. package/dist/Table/plugins/selection/useTableSelection.js +4 -1
  183. package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
  184. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  185. package/dist/Table/plugins/tree/useTableTreeData.js +87 -0
  186. package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
  187. package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
  188. package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
  189. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  190. package/dist/Table/useBaseTablePlugins.js +5 -3
  191. package/dist/Thumbnail/Thumbnail.d.ts +26 -5
  192. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  193. package/dist/Thumbnail/Thumbnail.js +97 -54
  194. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
  195. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
  196. package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
  197. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  198. package/dist/TimeInput/TimeInput.js +15 -4
  199. package/dist/Timestamp/Timestamp.d.ts +3 -1
  200. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  201. package/dist/Timestamp/Timestamp.js +8 -6
  202. package/dist/Toast/useToast.d.ts.map +1 -1
  203. package/dist/Toast/useToast.js +2 -5
  204. package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
  205. package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
  206. package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
  207. package/dist/Tokenizer/Tokenizer.d.ts +1 -1
  208. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  209. package/dist/Tokenizer/Tokenizer.js +16 -4
  210. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  211. package/dist/TopNav/TopNavHeading.js +18 -8
  212. package/dist/TopNav/TopNavMegaMenu.js +10 -4
  213. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
  214. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
  215. package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
  216. package/dist/TopNav/TopNavMenu.d.ts +2 -1
  217. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  218. package/dist/TopNav/TopNavMenu.js +68 -6
  219. package/dist/TreeList/TreeList.d.ts +12 -3
  220. package/dist/TreeList/TreeList.d.ts.map +1 -1
  221. package/dist/TreeList/TreeList.js +2 -0
  222. package/dist/TreeList/TreeListBranches.d.ts +5 -0
  223. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  224. package/dist/TreeList/TreeListBranches.js +10 -4
  225. package/dist/TreeList/TreeListItem.d.ts +8 -2
  226. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  227. package/dist/TreeList/TreeListItem.js +27 -7
  228. package/dist/TreeList/TreeListTypes.d.ts +25 -1
  229. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  230. package/dist/TreeList/index.d.ts +2 -2
  231. package/dist/TreeList/index.d.ts.map +1 -1
  232. package/dist/astryx.css +28 -18
  233. package/dist/astryx.umd.js +51 -51
  234. package/dist/astryx.umd.js.map +4 -4
  235. package/dist/authoring/doc.d.ts.map +1 -1
  236. package/dist/docs-types.d.ts +8 -0
  237. package/dist/docs-types.d.ts.map +1 -1
  238. package/dist/hooks/computeOverflow.d.ts +47 -0
  239. package/dist/hooks/computeOverflow.d.ts.map +1 -0
  240. package/dist/hooks/computeOverflow.js +213 -0
  241. package/dist/hooks/index.d.ts +1 -0
  242. package/dist/hooks/index.d.ts.map +1 -1
  243. package/dist/hooks/index.js +2 -1
  244. package/dist/hooks/useDevWarning.d.ts +18 -0
  245. package/dist/hooks/useDevWarning.d.ts.map +1 -0
  246. package/dist/hooks/useDevWarning.js +49 -0
  247. package/dist/hooks/useOverflow.d.ts +19 -0
  248. package/dist/hooks/useOverflow.d.ts.map +1 -1
  249. package/dist/hooks/useOverflow.js +36 -25
  250. package/dist/i18n/resolve.d.ts.map +1 -1
  251. package/dist/i18n/resolve.js +7 -18
  252. package/dist/theme/Theme.d.ts.map +1 -1
  253. package/dist/theme/Theme.js +2 -7
  254. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  255. package/dist/theme/generateThemeRules.js +51 -0
  256. package/dist/theme/hct.d.ts +0 -1
  257. package/dist/theme/hct.d.ts.map +1 -1
  258. package/dist/theme/hct.js +1 -1
  259. package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
  260. package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
  261. package/dist/utils/devWarning.d.ts +42 -0
  262. package/dist/utils/devWarning.d.ts.map +1 -0
  263. package/dist/utils/devWarning.js +88 -0
  264. package/dist/utils/index.d.ts +3 -1
  265. package/dist/utils/index.d.ts.map +1 -1
  266. package/dist/utils/index.js +3 -2
  267. package/dist/utils/plainDate.d.ts +30 -0
  268. package/dist/utils/plainDate.d.ts.map +1 -1
  269. package/dist/utils/plainDate.js +53 -0
  270. package/dist/utils/types.d.ts +13 -0
  271. package/dist/utils/types.d.ts.map +1 -1
  272. package/locales/en.json +24 -0
  273. package/locales/fr-FR.json +14 -0
  274. package/locales/pseudo.json +18 -0
  275. package/package.json +1 -1
  276. package/src/AppShell/AppShell.tsx +6 -0
  277. package/src/AppShell/AppShellMobileContext.tsx +8 -0
  278. package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
  279. package/src/Avatar/Avatar.doc.mjs +15 -3
  280. package/src/Avatar/Avatar.test.tsx +156 -1
  281. package/src/Avatar/Avatar.tsx +96 -4
  282. package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
  283. package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
  284. package/src/Avatar/AvatarStatusDot.tsx +178 -21
  285. package/src/Banner/Banner.doc.mjs +9 -0
  286. package/src/Banner/Banner.test.tsx +30 -0
  287. package/src/Banner/Banner.tsx +47 -3
  288. package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
  289. package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
  290. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
  291. package/src/Breadcrumbs/Breadcrumbs.test.tsx +284 -2
  292. package/src/Breadcrumbs/index.ts +27 -0
  293. package/src/Button/Button.doc.mjs +9 -0
  294. package/src/Button/Button.test.tsx +49 -0
  295. package/src/Button/Button.tsx +25 -1
  296. package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
  297. package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
  298. package/src/ButtonGroup/ButtonGroup.tsx +32 -0
  299. package/src/Calendar/Calendar.doc.mjs +12 -1
  300. package/src/Calendar/Calendar.test.tsx +193 -0
  301. package/src/Calendar/Calendar.tsx +38 -16
  302. package/src/Calendar/dayCellUtils.test.ts +5 -0
  303. package/src/Calendar/dayCellUtils.ts +1 -1
  304. package/src/Card/Card.doc.mjs +9 -0
  305. package/src/Card/Card.test.tsx +21 -3
  306. package/src/Card/Card.tsx +35 -2
  307. package/src/Carousel/Carousel.doc.mjs +1 -0
  308. package/src/Carousel/Carousel.test.tsx +53 -0
  309. package/src/Carousel/Carousel.tsx +34 -4
  310. package/src/Chat/ChatComposer.doc.mjs +12 -3
  311. package/src/Chat/ChatComposer.test.tsx +115 -0
  312. package/src/Chat/ChatComposer.tsx +73 -9
  313. package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
  314. package/src/Chat/ChatComposerDrawer.tsx +11 -1
  315. package/src/Chat/ChatComposerInput.doc.mjs +7 -0
  316. package/src/Chat/ChatComposerInput.test.tsx +103 -0
  317. package/src/Chat/ChatComposerInput.tsx +49 -3
  318. package/src/Chat/ChatContext.tsx +37 -10
  319. package/src/Chat/ChatDictationButton.tsx +4 -1
  320. package/src/Chat/ChatLayout.tsx +3 -1
  321. package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
  322. package/src/Chat/ChatMessageMetadata.tsx +1 -2
  323. package/src/Chat/ChatSendButton.tsx +11 -1
  324. package/src/Chat/ChatToolCalls.test.tsx +64 -0
  325. package/src/Chat/ChatToolCalls.tsx +25 -4
  326. package/src/Chat/index.ts +5 -1
  327. package/src/Chat/useChatStreamScroll.test.tsx +49 -0
  328. package/src/Chat/useChatStreamScroll.ts +27 -10
  329. package/src/Chat/useSpeechRecognition.ts +1 -1
  330. package/src/Chat/useTriggerMenu.tsx +3 -1
  331. package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
  332. package/src/CheckboxInput/CheckboxInput.tsx +1 -1
  333. package/src/CheckboxList/CheckboxList.test.tsx +81 -3
  334. package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
  335. package/src/CheckboxList/CheckboxListItem.tsx +41 -5
  336. package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
  337. package/src/ClickableCard/ClickableCard.test.tsx +34 -0
  338. package/src/ClickableCard/ClickableCard.tsx +13 -3
  339. package/src/CodeBlock/CodeBlock.test.tsx +56 -0
  340. package/src/CodeBlock/CodeBlock.tsx +9 -1
  341. package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
  342. package/src/CommandPalette/CommandPalette.tsx +3 -1
  343. package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
  344. package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
  345. package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
  346. package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
  347. package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
  348. package/src/ContextMenu/ContextMenu.test.tsx +193 -0
  349. package/src/DateInput/DateInput.doc.mjs +16 -0
  350. package/src/DateInput/DateInput.test.tsx +108 -0
  351. package/src/DateInput/DateInput.tsx +68 -3
  352. package/src/DateInput/index.ts +1 -0
  353. package/src/DateTimeInput/DateTimeInput.test.tsx +35 -0
  354. package/src/DateTimeInput/DateTimeInput.tsx +14 -2
  355. package/src/Dialog/Dialog.doc.mjs +2 -2
  356. package/src/Dialog/Dialog.test.tsx +77 -4
  357. package/src/Dialog/Dialog.tsx +89 -5
  358. package/src/Dialog/DialogContext.ts +9 -2
  359. package/src/Dialog/DialogHeader.doc.mjs +2 -2
  360. package/src/Dialog/DialogHeader.tsx +9 -2
  361. package/src/Divider/Divider.tsx +2 -2
  362. package/src/DropdownMenu/DropdownMenu.test.tsx +169 -0
  363. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +1 -2
  364. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
  365. package/src/Field/Field.test.tsx +57 -12
  366. package/src/Field/Field.tsx +6 -5
  367. package/src/Field/FieldLabel.tsx +8 -0
  368. package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
  369. package/src/FieldStatus/FieldStatus.test.tsx +78 -40
  370. package/src/FieldStatus/FieldStatus.tsx +22 -4
  371. package/src/FileInput/FileInput.test.tsx +52 -3
  372. package/src/FileInput/FileInput.tsx +13 -2
  373. package/src/HoverCard/HoverCard.doc.mjs +13 -0
  374. package/src/HoverCard/HoverCard.test.tsx +21 -2
  375. package/src/HoverCard/HoverCard.tsx +11 -0
  376. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  377. package/src/HoverCard/useHoverCard.tsx +24 -2
  378. package/src/Icon/Icon.doc.mjs +3 -2
  379. package/src/Icon/Icon.tsx +7 -2
  380. package/src/IconButton/IconButton.doc.mjs +8 -0
  381. package/src/IconButton/IconButton.test.tsx +15 -18
  382. package/src/Item/Item.test.tsx +40 -18
  383. package/src/Item/Item.tsx +38 -2
  384. package/src/Layer/useLayer.tsx +8 -0
  385. package/src/List/List.test.tsx +9 -8
  386. package/src/MobileNav/MobileNav.tsx +12 -1
  387. package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
  388. package/src/MobileNav/MobileNavToggle.tsx +9 -1
  389. package/src/MultiSelector/MultiSelector.doc.mjs +4 -2
  390. package/src/MultiSelector/MultiSelector.test.tsx +172 -3
  391. package/src/MultiSelector/MultiSelector.tsx +55 -12
  392. package/src/MultiSelector/hooks.ts +17 -0
  393. package/src/NumberInput/NumberInput.test.tsx +11 -7
  394. package/src/NumberInput/NumberInput.tsx +1 -2
  395. package/src/Outline/Outline.tsx +0 -1
  396. package/src/OverflowList/OverflowList.doc.mjs +39 -6
  397. package/src/OverflowList/OverflowList.test.tsx +111 -0
  398. package/src/OverflowList/OverflowList.tsx +48 -8
  399. package/src/Popover/Popover.tsx +7 -4
  400. package/src/Popover/usePopover.tsx +9 -13
  401. package/src/PowerSearch/PowerSearch.doc.mjs +14 -0
  402. package/src/PowerSearch/PowerSearch.test.tsx +20 -0
  403. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
  404. package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
  405. package/src/PowerSearch/usePowerSearchSource.ts +1 -2
  406. package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
  407. package/src/SelectableCard/SelectableCard.test.tsx +46 -4
  408. package/src/SelectableCard/SelectableCard.tsx +29 -16
  409. package/src/Selector/Selector.test.tsx +69 -0
  410. package/src/Selector/Selector.tsx +5 -1
  411. package/src/Selector/hooks.ts +17 -0
  412. package/src/SideNav/SideNav.test.tsx +119 -3
  413. package/src/SideNav/SideNavCollapseButton.tsx +6 -1
  414. package/src/SideNav/SideNavHeading.tsx +24 -8
  415. package/src/SideNav/SideNavItem.tsx +5 -1
  416. package/src/Slider/Slider.test.tsx +75 -2
  417. package/src/Slider/Slider.tsx +21 -5
  418. package/src/Switch/Switch.test.tsx +32 -1
  419. package/src/Table/BaseTable.tsx +3 -5
  420. package/src/Table/index.ts +5 -0
  421. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
  422. package/src/Table/plugins/rowStatus/index.ts +7 -0
  423. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
  424. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
  425. package/src/Table/plugins/selection/useTableSelection.test.tsx +16 -0
  426. package/src/Table/plugins/selection/useTableSelection.tsx +19 -1
  427. package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
  428. package/src/Table/plugins/tree/useTableTreeData.tsx +128 -1
  429. package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
  430. package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
  431. package/src/Table/useBaseTablePlugins.ts +10 -6
  432. package/src/Table/useTableRowStatus.doc.mjs +30 -0
  433. package/src/Table/useTableSelection.doc.mjs +65 -14
  434. package/src/Table/useTableTreeData.doc.mjs +29 -0
  435. package/src/Table/useTableTreeState.doc.mjs +2 -2
  436. package/src/TextArea/TextArea.test.tsx +9 -1
  437. package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
  438. package/src/Thumbnail/Thumbnail.test.tsx +98 -7
  439. package/src/Thumbnail/Thumbnail.tsx +141 -41
  440. package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
  441. package/src/TimeInput/TimeInput.test.tsx +76 -1
  442. package/src/TimeInput/TimeInput.tsx +19 -6
  443. package/src/Timestamp/Timestamp.doc.mjs +4 -4
  444. package/src/Timestamp/Timestamp.test.tsx +32 -0
  445. package/src/Timestamp/Timestamp.tsx +28 -8
  446. package/src/Toast/useToast.tsx +7 -8
  447. package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
  448. package/src/Tokenizer/Tokenizer.doc.mjs +15 -1
  449. package/src/Tokenizer/Tokenizer.test.tsx +183 -2
  450. package/src/Tokenizer/Tokenizer.tsx +16 -4
  451. package/src/TopNav/TopNav.test.tsx +125 -1
  452. package/src/TopNav/TopNavHeading.tsx +24 -8
  453. package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
  454. package/src/TopNav/TopNavMegaMenu.tsx +10 -4
  455. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
  456. package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
  457. package/src/TopNav/TopNavMenu.test.tsx +118 -4
  458. package/src/TopNav/TopNavMenu.tsx +83 -5
  459. package/src/TreeList/TreeList.doc.mjs +22 -0
  460. package/src/TreeList/TreeList.test.tsx +232 -0
  461. package/src/TreeList/TreeList.tsx +18 -2
  462. package/src/TreeList/TreeListBranches.tsx +16 -2
  463. package/src/TreeList/TreeListItem.tsx +51 -11
  464. package/src/TreeList/TreeListTypes.ts +27 -1
  465. package/src/TreeList/index.ts +2 -2
  466. package/src/authoring/doc.ts +1 -3
  467. package/src/docs-types.ts +5 -0
  468. package/src/hooks/computeOverflow.test.ts +422 -0
  469. package/src/hooks/computeOverflow.ts +290 -0
  470. package/src/hooks/index.ts +2 -0
  471. package/src/hooks/useDevWarning.test.tsx +45 -0
  472. package/src/hooks/useDevWarning.ts +54 -0
  473. package/src/hooks/useOverflow.test.ts +96 -4
  474. package/src/hooks/useOverflow.ts +74 -33
  475. package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
  476. package/src/i18n/resolve.ts +9 -21
  477. package/src/theme/Theme.tsx +11 -14
  478. package/src/theme/generateThemeRules.test.ts +65 -0
  479. package/src/theme/generateThemeRules.ts +56 -0
  480. package/src/theme/hct.ts +1 -1
  481. package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
  482. package/src/utils/devWarning.test.ts +56 -0
  483. package/src/utils/devWarning.ts +102 -0
  484. package/src/utils/index.ts +6 -0
  485. package/src/utils/plainDate.test.ts +22 -0
  486. package/src/utils/plainDate.ts +61 -0
  487. package/src/utils/types.ts +14 -0
@@ -634,3 +634,107 @@ describe('useTableTreeState — semantics edges', () => {
634
634
  expect(ids(result.current.visibleData)).toEqual(['src', 'readme']);
635
635
  });
636
636
  });
637
+
638
+ // =============================================================================
639
+ // isAllExpanded (drives the header expand-all control)
640
+ // =============================================================================
641
+
642
+ describe('useTableTreeState: isAllExpanded', () => {
643
+ it('reports false when nothing is expanded', () => {
644
+ const {result} = renderHook(() =>
645
+ useTableTreeState({data: fileTree, idKey: 'id'}),
646
+ );
647
+
648
+ expect(result.current.isAllExpanded).toBe(false);
649
+ });
650
+
651
+ it('reports true only when every expandable row is expanded', () => {
652
+ const {result} = renderHook(() =>
653
+ useTableTreeState({data: fileTree, idKey: 'id'}),
654
+ );
655
+
656
+ act(() => {
657
+ result.current.expandAll();
658
+ });
659
+
660
+ expect(result.current.isAllExpanded).toBe(true);
661
+ });
662
+
663
+ it("reports 'indeterminate' when some but not all expandable rows are expanded", () => {
664
+ const {result} = renderHook(() =>
665
+ useTableTreeState({
666
+ data: fileTree,
667
+ idKey: 'id',
668
+ defaultExpandedIds: ['src'],
669
+ }),
670
+ );
671
+
672
+ // 'src' and 'components' are both expandable; only 'src' is expanded.
673
+ expect(result.current.isAllExpanded).toBe('indeterminate');
674
+ });
675
+
676
+ it('returns to false after collapseAll', () => {
677
+ const {result} = renderHook(() =>
678
+ useTableTreeState({
679
+ data: fileTree,
680
+ idKey: 'id',
681
+ defaultExpandedIds: ['src', 'components'],
682
+ }),
683
+ );
684
+
685
+ act(() => {
686
+ result.current.collapseAll();
687
+ });
688
+
689
+ expect(result.current.isAllExpanded).toBe(false);
690
+ });
691
+
692
+ it('reports false for flat data (no expandable rows)', () => {
693
+ const flat: FileRow[] = [
694
+ {id: 'a', name: 'A', size: 1},
695
+ {id: 'b', name: 'B', size: 2},
696
+ ];
697
+ const {result} = renderHook(() =>
698
+ useTableTreeState({data: flat, idKey: 'id'}),
699
+ );
700
+
701
+ expect(result.current.isAllExpanded).toBe(false);
702
+ });
703
+
704
+ it('ignores expanded ids that match no expandable row when aggregating', () => {
705
+ // 'readme' is a leaf (not expandable) and 'ghost' matches nothing; neither
706
+ // should count toward the expandable total, so an all-expandable set that
707
+ // omits them still reads as fully expanded.
708
+ const {result} = renderHook(() =>
709
+ useTableTreeState({
710
+ data: fileTree,
711
+ idKey: 'id',
712
+ defaultExpandedIds: ['src', 'components', 'readme', 'ghost'],
713
+ }),
714
+ );
715
+
716
+ expect(result.current.isAllExpanded).toBe(true);
717
+ });
718
+
719
+ it('exposes the aggregate state and expand/collapse handlers through treeConfig', () => {
720
+ const {result} = renderHook(() =>
721
+ useTableTreeState({data: fileTree, idKey: 'id'}),
722
+ );
723
+
724
+ // The headless plugin reads everything it needs to render the header
725
+ // expand-all control from treeConfig, not from the state hook directly.
726
+ expect(result.current.treeConfig.isAllExpanded).toBe(false);
727
+
728
+ act(() => {
729
+ result.current.treeConfig.onExpandAll?.();
730
+ });
731
+ expect(result.current.isAllExpanded).toBe(true);
732
+ expect(result.current.treeConfig.isAllExpanded).toBe(true);
733
+
734
+ act(() => {
735
+ result.current.treeConfig.onCollapseAll?.();
736
+ });
737
+ expect(result.current.isAllExpanded).toBe(false);
738
+ expect(result.current.treeConfig.isAllExpanded).toBe(false);
739
+ });
740
+ });
@@ -74,6 +74,12 @@ export interface UseTableTreeStateResult<T extends Record<string, unknown>> {
74
74
  treeConfig: UseTableTreeDataConfig<T>;
75
75
  /** The current expanded row ids. */
76
76
  expandedIds: ReadonlySet<string>;
77
+ /**
78
+ * Aggregate expansion state across every expandable row: `true` when all are
79
+ * expanded, `false` when none are, `'indeterminate'` when some but not all
80
+ * are. Drives the header expand-all control. Reports `false` for flat data.
81
+ */
82
+ isAllExpanded: boolean | 'indeterminate';
77
83
  /** Expand every expandable row in the tree. */
78
84
  expandAll: () => void;
79
85
  /** Collapse every row. */
@@ -211,6 +217,25 @@ export function useTableTreeState<T extends Record<string, unknown>>(
211
217
 
212
218
  const hasExpandableRows = allExpandableIds.length > 0;
213
219
 
220
+ // Aggregate state for the header expand-all control. Only expandable ids
221
+ // count toward the total, so expanded ids that match a leaf or no row at
222
+ // all never skew the tally.
223
+ const isAllExpanded: boolean | 'indeterminate' = useMemo(() => {
224
+ if (!hasExpandableRows) {
225
+ return false;
226
+ }
227
+ const expandedCount = allExpandableIds.filter(id =>
228
+ expandedIds.has(id),
229
+ ).length;
230
+ if (expandedCount === 0) {
231
+ return false;
232
+ }
233
+ if (expandedCount === allExpandableIds.length) {
234
+ return true;
235
+ }
236
+ return 'indeterminate';
237
+ }, [hasExpandableRows, allExpandableIds, expandedIds]);
238
+
214
239
  const onToggleItem = useCallback(
215
240
  (item: T) => {
216
241
  const id = getId(item);
@@ -243,11 +268,30 @@ export function useTableTreeState<T extends Record<string, unknown>>(
243
268
  getRowMeta,
244
269
  onToggleItem,
245
270
  hasExpandableRows,
271
+ isAllExpanded,
272
+ onExpandAll: expandAll,
273
+ onCollapseAll: collapseAll,
246
274
  indent,
247
275
  treeColumnKey,
248
276
  }),
249
- [getRowMeta, onToggleItem, hasExpandableRows, indent, treeColumnKey],
277
+ [
278
+ getRowMeta,
279
+ onToggleItem,
280
+ hasExpandableRows,
281
+ isAllExpanded,
282
+ expandAll,
283
+ collapseAll,
284
+ indent,
285
+ treeColumnKey,
286
+ ],
250
287
  );
251
288
 
252
- return {visibleData, treeConfig, expandedIds, expandAll, collapseAll};
289
+ return {
290
+ visibleData,
291
+ treeConfig,
292
+ expandedIds,
293
+ isAllExpanded,
294
+ expandAll,
295
+ collapseAll,
296
+ };
253
297
  }
@@ -38,6 +38,7 @@
38
38
 
39
39
  import {useRef} from 'react';
40
40
  import type {TablePlugin} from './types';
41
+ import {devWarn} from '../utils/devWarning';
41
42
 
42
43
  // ======================================================================// Canonical Plugin Order
43
44
  // ======================================================================
@@ -112,8 +113,9 @@ function validatePlugin<T extends Record<string, unknown>>(
112
113
  // Warn about unknown keys (likely misspelled transform names)
113
114
  for (const key of keys) {
114
115
  if (!VALID_TRANSFORM_KEYS.has(key)) {
115
- console.warn(
116
- `[Table] Plugin "${name}" has unknown key "${key}". ` +
116
+ devWarn(
117
+ 'Table',
118
+ `Plugin "${name}" has unknown key "${key}". ` +
117
119
  `Valid keys: ${[...VALID_TRANSFORM_KEYS].join(', ')}. ` +
118
120
  `This key will be ignored.`,
119
121
  );
@@ -125,8 +127,9 @@ function validatePlugin<T extends Record<string, unknown>>(
125
127
  if (VALID_TRANSFORM_KEYS.has(key)) {
126
128
  const value = (plugin as Record<string, unknown>)[key];
127
129
  if (value != null && typeof value !== 'function') {
128
- console.warn(
129
- `[Table] Plugin "${name}" has non-function value for "${key}" ` +
130
+ devWarn(
131
+ 'Table',
132
+ `Plugin "${name}" has non-function value for "${key}" ` +
130
133
  `(got ${typeof value}). Transform will be skipped.`,
131
134
  );
132
135
  }
@@ -140,8 +143,9 @@ function validatePlugin<T extends Record<string, unknown>>(
140
143
  typeof (plugin as Record<string, unknown>)[key] === 'function',
141
144
  );
142
145
  if (!hasTransforms) {
143
- console.warn(
144
- `[Table] Plugin "${name}" has no transform methods. ` +
146
+ devWarn(
147
+ 'Table',
148
+ `Plugin "${name}" has no transform methods. ` +
145
149
  `It will be included in the pipeline but won't do anything.`,
146
150
  );
147
151
  }
@@ -0,0 +1,30 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../docs-types').ComponentDoc} */
4
+
5
+ export const docs = {
6
+ name: 'useTableRowStatus',
7
+ subComponentOf: 'Table',
8
+ displayName: 'useTableRowStatus',
9
+ description:
10
+ 'Hook that returns a TablePlugin which prepends a narrow column signaling per-row status: a colored status dot by default, or an icon when provided (shape + color is more accessible than color alone). getStatus maps a row to a semantic color (mapped to a theme token) or raw CSS color, an optional icon, and a required accessible label (shown in a tooltip on hover and announced to assistive technology, so status is never color-only); return null for no indicator. Memoize getStatus with useCallback for a stable plugin identity.',
11
+ props: [
12
+ {
13
+ name: 'getStatus',
14
+ type: "(item: T) => { color: 'accent' | 'success' | 'error' | 'warning' | 'red' | 'orange' | 'green' | 'yellow' | 'blue' | 'gray' | string; icon?: IconName; label: string } | null",
15
+ description:
16
+ 'Derive the status indicator for a row: a semantic color (accent, success, error, warning, red, orange, green, yellow, blue, gray — mapped to a theme token) or a raw CSS color as an escape hatch; an optional icon to signal status by shape instead of the dot (recommended when multiple statuses coexist; valid names: close, chevronDown, chevronLeft, chevronRight, check, success, error, warning, info, calendar, clock, externalLink, menu, moreHorizontal, search, arrowUp, arrowDown, arrowsUpDown, funnel, eyeSlash, viewColumns, copy, checkDouble, wrench, stop, microphone); and a required accessible label (announced via role="img" and shown in a tooltip on hover, so a status is never conveyed by color alone). Return null for rows with no status. Memoize with useCallback for a stable plugin identity.',
17
+ required: true,
18
+ },
19
+ ],
20
+ };
21
+
22
+ /** @type {import('../docs-types').TranslationDoc} */
23
+ export const docsDense = {
24
+ description:
25
+ 'Returns a TablePlugin that prepends a narrow per-row status column: a colored dot, or an icon when provided (shape + color beats color alone for a11y). getStatus maps a row to {color, icon?, label} or null. color is a semantic name (success/error/warning/etc.) mapped to a theme token, or a raw CSS color. label is required (tooltip + accessible name). Memoize getStatus with useCallback.',
26
+ propDescriptions: {
27
+ getStatus:
28
+ 'Map a row to {color, icon?, label} or null. color = semantic status name (mapped to a token) or raw CSS; icon = shape signifier (a11y); label = required accessible name (tooltip + role="img"). Memoize with useCallback.',
29
+ },
30
+ };
@@ -6,7 +6,8 @@ export const docs = {
6
6
  name: 'useTableSelection',
7
7
  subComponentOf: 'Table',
8
8
  displayName: 'useTableSelection',
9
- description: 'Hook that returns a TablePlugin implementing row selection with checkboxes, select-all, and aria-selected. Uses React Context for independent checkbox re-renders.',
9
+ description:
10
+ 'Hook that returns a TablePlugin implementing row selection with checkboxes, select-all, and aria-selected. Uses React Context for independent checkbox re-renders.',
10
11
  props: [
11
12
  {
12
13
  name: 'getIsItemSelected',
@@ -17,7 +18,8 @@ export const docs = {
17
18
  {
18
19
  name: 'onSelectItem',
19
20
  type: '(event: {item: T; isSelected: boolean}) => void',
20
- description: 'Called when a row checkbox is toggled. isSelected is the new desired state.',
21
+ description:
22
+ 'Called when a row checkbox is toggled. isSelected is the new desired state.',
21
23
  required: true,
22
24
  },
23
25
  {
@@ -29,33 +31,67 @@ export const docs = {
29
31
  {
30
32
  name: 'getIsAllSelected',
31
33
  type: '() => boolean',
32
- description: 'Returns whether all selectable items are currently selected.',
34
+ description:
35
+ 'Returns whether all selectable items are currently selected.',
33
36
  required: true,
34
37
  },
35
38
  {
36
39
  name: 'getIsIndeterminate',
37
40
  type: '() => boolean',
38
- description: 'Returns whether selection is partial (some but not all). Renders the select-all checkbox in indeterminate state.',
41
+ description:
42
+ 'Returns whether selection is partial (some but not all). Renders the select-all checkbox in indeterminate state.',
39
43
  },
40
44
  {
41
45
  name: 'getIsItemSelectable',
42
46
  type: '(item: T) => boolean',
43
- description: 'Returns whether a row should show a checkbox. Non-selectable rows render nothing in the selection cell.',
47
+ description:
48
+ 'Returns whether a row should show a checkbox. Non-selectable rows render nothing in the selection cell.',
44
49
  default: '() => true',
45
50
  },
46
51
  {
47
52
  name: 'getIsItemEnabled',
48
53
  type: '(item: T) => boolean',
49
- description: 'Returns whether a row checkbox is interactive. Disabled rows show a disabled checkbox.',
54
+ description:
55
+ 'Returns whether a row checkbox is interactive. Disabled rows show a disabled checkbox.',
50
56
  default: '() => true',
51
57
  },
58
+ {
59
+ name: 'getRowLabel',
60
+ type: '(item: T) => string',
61
+ description:
62
+ 'Derives a human-readable identity for a row; the row checkbox\'s hidden label becomes `Select ${getRowLabel(item)}` so screen readers announce which row each checkbox selects. Falls back to "Select row" when omitted.',
63
+ },
64
+ ],
65
+ examples: [
66
+ {
67
+ label: 'Accessible per-row checkbox names',
68
+ code: `
69
+ const selectionPlugin = useTableSelection({
70
+ getIsItemSelected: item => selectedIds.has(item.id),
71
+ onSelectItem: ({item, isSelected}) => toggle(item.id, isSelected),
72
+ onSelectAll: ({isAllSelected}) => selectAll(isAllSelected),
73
+ getIsAllSelected: () => selectedIds.size === users.length,
74
+ // Screen readers announce "Select Alice", "Select Bob", ...
75
+ // instead of an undifferentiated "Select row" for every checkbox.
76
+ getRowLabel: item => item.name,
77
+ });
78
+
79
+ <Table
80
+ data={users}
81
+ columns={columns}
82
+ idKey="id"
83
+ plugins={{selection: selectionPlugin}}
84
+ />;
85
+ `,
86
+ },
52
87
  ],
53
88
  };
54
89
 
55
90
  export const docsZh = {
56
91
  name: 'useTableSelection',
57
92
  displayName: 'useTableSelection',
58
- description: '返回 TablePlugin 的 Hook,实现带复选框、全选和 aria-selected 的行选择功能。使用 React Context 实现独立的复选框重新渲染。',
93
+ description:
94
+ '返回 TablePlugin 的 Hook,实现带复选框、全选和 aria-selected 的行选择功能。使用 React Context 实现独立的复选框重新渲染。',
59
95
  props: [
60
96
  {
61
97
  name: 'getIsItemSelected',
@@ -84,12 +120,14 @@ export const docsZh = {
84
120
  {
85
121
  name: 'getIsIndeterminate',
86
122
  type: '() => boolean',
87
- description: '返回选择是否为部分选中(部分但非全部)。将全选复选框渲染为不确定状态。',
123
+ description:
124
+ '返回选择是否为部分选中(部分但非全部)。将全选复选框渲染为不确定状态。',
88
125
  },
89
126
  {
90
127
  name: 'getIsItemSelectable',
91
128
  type: '(item: T) => boolean',
92
- description: '返回行是否应显示复选框。不可选择的行在选择单元格中不渲染任何内容。',
129
+ description:
130
+ '返回行是否应显示复选框。不可选择的行在选择单元格中不渲染任何内容。',
93
131
  default: '() => true',
94
132
  },
95
133
  {
@@ -98,20 +136,33 @@ export const docsZh = {
98
136
  description: '返回行复选框是否可交互。禁用的行显示禁用状态的复选框。',
99
137
  default: '() => true',
100
138
  },
139
+ {
140
+ name: 'getRowLabel',
141
+ type: '(item: T) => string',
142
+ description:
143
+ '为行派生人类可读的标识;行复选框的隐藏标签变为 `Select ${getRowLabel(item)}`,让屏幕阅读器播报每个复选框选择的是哪一行。省略时回退为 "Select row"。',
144
+ },
101
145
  ],
102
146
  };
103
147
 
104
148
  export const docsDense = {
105
149
  name: 'useTableSelection',
106
150
  displayName: 'useTableSelection',
107
- description: 'Hook returning TablePlugin for row selection w/ checkboxes, select-all, aria-selected. Uses React Context for independent checkbox re-renders.',
151
+ description:
152
+ 'Hook returning TablePlugin for row selection w/ checkboxes, select-all, aria-selected. Uses React Context for independent checkbox re-renders.',
108
153
  propDescriptions: {
109
154
  getIsItemSelected: 'Returns whether item is selected.',
110
- onSelectItem: 'Called on row checkbox toggle; isSelected = new desired state.',
155
+ onSelectItem:
156
+ 'Called on row checkbox toggle; isSelected = new desired state.',
111
157
  onSelectAll: 'Called on select-all header checkbox toggle.',
112
158
  getIsAllSelected: 'Returns whether all selectable items are selected.',
113
- getIsIndeterminate: 'Returns partial selection state; renders indeterminate checkbox.',
114
- getIsItemSelectable: 'Returns whether row shows checkbox; non-selectable rows render nothing.',
115
- getIsItemEnabled: 'Returns whether row checkbox is interactive; disabled rows show disabled checkbox.',
159
+ getIsIndeterminate:
160
+ 'Returns partial selection state; renders indeterminate checkbox.',
161
+ getIsItemSelectable:
162
+ 'Returns whether row shows checkbox; non-selectable rows render nothing.',
163
+ getIsItemEnabled:
164
+ 'Returns whether row checkbox is interactive; disabled rows show disabled checkbox.',
165
+ getRowLabel:
166
+ 'Derives row identity for the checkbox\'s hidden label: `Select ${getRowLabel(item)}`. Falls back to "Select row" when omitted.',
116
167
  },
117
168
  };
@@ -29,6 +29,29 @@ export const docs = {
29
29
  'Whether any row in the dataset is expandable. When false the plugin is a no-op: no expanders, no indent, no tree ARIA.',
30
30
  required: true,
31
31
  },
32
+ {
33
+ name: 'hasExpandAllControl',
34
+ type: 'boolean',
35
+ description:
36
+ 'Show an expand-all/collapse-all toggle in the tree column header. Requires isAllExpanded plus onExpandAll/onCollapseAll (all supplied by useTableTreeState).',
37
+ default: 'false',
38
+ },
39
+ {
40
+ name: 'isAllExpanded',
41
+ type: "boolean | 'indeterminate'",
42
+ description:
43
+ 'Aggregate expansion state across every expandable row, driving the header expand-all toggle. true when all are expanded, false when none are, indeterminate when some are.',
44
+ },
45
+ {
46
+ name: 'onExpandAll',
47
+ type: '() => void',
48
+ description: 'Expand every expandable row. Wired to the header control.',
49
+ },
50
+ {
51
+ name: 'onCollapseAll',
52
+ type: '() => void',
53
+ description: 'Collapse every row. Wired to the header control.',
54
+ },
32
55
  {
33
56
  name: 'indent',
34
57
  type: "'sm' | 'md' | 'lg'",
@@ -71,5 +94,11 @@ export const docsDense = {
71
94
  indent:
72
95
  "indent step per level: 'sm' | 'md' | 'lg' (spacing-3/4/6). Defaults to 'md'.",
73
96
  treeColumnKey: 'column carrying indent + expander. Defaults to first column.',
97
+ hasExpandAllControl:
98
+ 'show expand-all/collapse-all toggle in tree column header. Needs isAllExpanded + onExpandAll/onCollapseAll (from useTableTreeState). Defaults to false.',
99
+ isAllExpanded:
100
+ "aggregate state driving the header toggle: true (all) | false (none) | 'indeterminate' (some).",
101
+ onExpandAll: 'expand every expandable row (header control)',
102
+ onCollapseAll: 'collapse every row (header control)',
74
103
  },
75
104
  };
@@ -7,7 +7,7 @@ export const docs = {
7
7
  subComponentOf: 'Table',
8
8
  displayName: 'useTableTreeState',
9
9
  description:
10
- 'State management companion for useTableTreeData. Owns the expanded set (controlled or uncontrolled) and flattens nested data into the visible row array; collapsed subtrees are unmounted, not hidden, so the table body contains exactly the visible rows. Returns expandAll/collapseAll helpers and a ready-to-use config for the tree plugin. Note: because collapsed rows unmount, cell-local React state inside collapsed subtrees is lost on collapse; lift state that must survive.',
10
+ 'State management companion for useTableTreeData. Owns the expanded set (controlled or uncontrolled) and flattens nested data into the visible row array; collapsed subtrees are unmounted, not hidden, so the table body contains exactly the visible rows. Returns expandAll/collapseAll helpers, the aggregate isAllExpanded state (true/false/indeterminate) for a header expand-all control, and a ready-to-use config for the tree plugin. Note: because collapsed rows unmount, cell-local React state inside collapsed subtrees is lost on collapse; lift state that must survive.',
11
11
  props: [
12
12
  {
13
13
  name: 'data',
@@ -79,7 +79,7 @@ export const docsDense = {
79
79
  name: 'useTableTreeState',
80
80
  displayName: 'useTableTreeState',
81
81
  description:
82
- 'State companion for useTableTreeData. Owns expanded set (controlled or uncontrolled), flattens nested data to visible rows (collapsed subtrees unmounted, not hidden). Returns {visibleData, treeConfig, expandedIds, expandAll, collapseAll}. Cell-local state in collapsed subtrees is lost on collapse; lift state that must survive.',
82
+ 'State companion for useTableTreeData. Owns expanded set (controlled or uncontrolled), flattens nested data to visible rows (collapsed subtrees unmounted, not hidden). Returns {visibleData, treeConfig, expandedIds, isAllExpanded, expandAll, collapseAll} (isAllExpanded = true/false/indeterminate for a header expand-all control). Cell-local state in collapsed subtrees is lost on collapse; lift state that must survive.',
83
83
  propDescriptions: {
84
84
  data: 'nested data; rows carry child rows under childrenKey. Flat data => plugin is a no-op.',
85
85
  idKey: 'row ID accessor: property name or fn returning unique id',
@@ -10,11 +10,19 @@
10
10
  */
11
11
 
12
12
  import {useState} from 'react';
13
- import {describe, it, expect, vi, beforeEach} from 'vitest';
13
+ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
14
14
  import {render, screen, fireEvent, waitFor} from '@testing-library/react';
15
15
  import userEvent from '@testing-library/user-event';
16
16
  import {TestIcon} from '../__tests__/TestIcon';
17
17
  import {TextArea} from './TextArea';
18
+ import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
19
+
20
+ // FieldStatus announces status messages through the persistent useAnnounce
21
+ // singletons; remove them between tests so role/aria-live queries in this
22
+ // file never match a leftover region.
23
+ afterEach(() => {
24
+ __resetLiveRegionsForTest();
25
+ });
18
26
 
19
27
  // Mock showPopover/hidePopover since jsdom does not implement them. Used by the
20
28
  // disabledMessage tooltip.
@@ -16,7 +16,7 @@ export const docs = {
16
16
  {
17
17
  name: 'alt',
18
18
  type: 'string',
19
- description: 'Alt text for the image.',
19
+ description: 'Alt text for the image. When omitted, the image is explicitly decorative (alt="", role="presentation", aria-hidden) and hidden from screen readers; a dev warning fires if neither alt nor label is set.',
20
20
  },
21
21
  {
22
22
  name: 'label',
@@ -31,7 +31,7 @@ export const docs = {
31
31
  {
32
32
  name: 'onClick',
33
33
  type: '(e: React.MouseEvent) => void',
34
- description: 'Click handler. Adds button semantics and hover shadow.',
34
+ description: 'Click handler. Adds button semantics and a hover overlay.',
35
35
  },
36
36
  {
37
37
  name: 'isLoading',
@@ -45,6 +45,13 @@ export const docs = {
45
45
  description: 'Whether the thumbnail is disabled.',
46
46
  default: 'false',
47
47
  },
48
+ {
49
+ name: 'showRemoveOn',
50
+ type: "'always' | 'hover'",
51
+ description:
52
+ 'When the remove button is visible. `hover` (the default) reveals it on hover and on keyboard focus, and keeps it visible on any touch-capable device; `always` shows it at rest. Only applies when `onRemove` is set.',
53
+ default: "'hover'",
54
+ },
48
55
  {
49
56
  name: 'xstyle',
50
57
  type: 'StyleXStyles',
@@ -77,14 +84,14 @@ export const docs = {
77
84
  bestPractices: [
78
85
  {guidance: true, description: 'Always provide a label prop with the file name so the thumbnail and its remove button are accessible to screen readers and show a tooltip on hover.'},
79
86
  {guidance: true, description: 'Use isLoading without a src to show a skeleton during initial upload, and isLoading with a src to show a spinner overlay once a preview URL is available.'},
80
- {guidance: true, description: 'Pair onClick with a lightbox or detail view so users can inspect the full image; the thumbnail adds button semantics and a hover shadow automatically.'},
87
+ {guidance: true, description: 'Pair onClick with a lightbox or detail view so users can inspect the full image; the thumbnail adds button semantics and a hover overlay automatically.'},
81
88
  {guidance: false, description: "Don't use Thumbnail for non-image file types like PDFs or spreadsheets; use a file attachment component with an appropriate icon instead."},
82
89
  {guidance: false, description: "Don't omit alt text when a src is provided; screen readers need a description of the image content, not just the file name from label."},
83
90
  ],
84
91
  anatomy: [
85
92
  {name: 'Image', required: false, description: 'The preview image, displayed as a square with cover fit.'},
86
93
  {name: 'Placeholder', required: false, description: 'An image silhouette icon shown when no src is provided.'},
87
- {name: 'Remove button', required: false, description: 'An overlaid close button in the top-right corner. Appears when onRemove is set. Uses APCA luminance detection to stay visible on any image.'},
94
+ {name: 'Remove button', required: false, description: 'An overlaid close button in the top-right corner. Appears when onRemove is set. Sits on a fixed --color-overlay scrim with an --color-on-dark icon to stay visible on any image.'},
88
95
  {name: 'Upload overlay', required: false, description: 'A semi-transparent overlay with a spinner, shown when isLoading is true and a src preview is available.'},
89
96
  {name: 'Skeleton', required: false, description: 'A shimmer animation shown when isLoading is true and no src is set.'},
90
97
  ],
@@ -95,12 +102,13 @@ export const docs = {
95
102
  export const docsZh = {
96
103
  propDescriptions: {
97
104
  src: '\u56FE\u7247\u6E90 URL\u3002',
98
- alt: '\u56FE\u7247\u7684\u66FF\u4EE3\u6587\u672C\u3002',
105
+ alt: '\u56FE\u7247\u7684\u66FF\u4EE3\u6587\u672C\u3002\u7701\u7565\u65F6\u56FE\u7247\u4F1A\u88AB\u663E\u5F0F\u6807\u8BB0\u4E3A\u88C5\u9970\u6027\uFF08alt=""\u3001role="presentation"\u3001aria-hidden\uFF09\u5E76\u5BF9\u5C4F\u5E55\u9605\u8BFB\u5668\u9690\u85CF\uFF1B\u82E5 alt \u548C label \u5747\u672A\u8BBE\u7F6E\uFF0C\u5F00\u53D1\u73AF\u5883\u4F1A\u53D1\u51FA\u8B66\u544A\u3002',
99
106
  label: '\u65E0\u969C\u788D\u6807\u7B7E\uFF08\u5982\u6587\u4EF6\u540D\uFF09\u3002\u60AC\u505C\u65F6\u4EE5\u63D0\u793A\u5DE5\u5177\u663E\u793A\u3002',
100
107
  onRemove: '\u8986\u76D6\u5C42\u79FB\u9664\u6309\u94AE\u7684\u56DE\u8C03\u3002',
101
- onClick: '\u70B9\u51FB\u5904\u7406\u5668\u3002\u6DFB\u52A0\u6309\u94AE\u8BED\u4E49\u548C\u60AC\u505C\u9634\u5F71\u3002',
108
+ onClick: '\u70B9\u51FB\u5904\u7406\u5668\u3002\u6DFB\u52A0\u6309\u94AE\u8BED\u4E49\u548C\u60AC\u505C\u8986\u76D6\u5C42\u3002',
102
109
  isLoading: '\u663E\u793A\u9AA8\u67B6\u5C4F\uFF08\u65E0 src\uFF09\u6216\u4E0A\u4F20\u8986\u76D6\u5C42\uFF08\u6709 src\uFF09\u3002',
103
110
  isDisabled: '\u662F\u5426\u7981\u7528\u7F29\u7565\u56FE\u3002',
111
+ showRemoveOn: '\u4F55\u65F6\u663E\u793A\u79FB\u9664\u6309\u94AE\uFF1Ahover\uFF08\u9ED8\u8BA4\uFF0C\u60AC\u505C\u65F6\u4EE5\u53CA\u952E\u76D8\u805A\u7126\u65F6\u663E\u793A\uFF0C\u89E6\u6478\u8BBE\u5907\u4E0A\u4FDD\u6301\u53EF\u89C1\uFF09| always\uFF08\u59CB\u7EC8\u663E\u793A\uFF09\u3002\u4EC5\u5728\u8BBE\u7F6E onRemove \u65F6\u751F\u6548\u3002',
104
112
  xstyle: '\u7528\u4E8E\u5E03\u5C40\u81EA\u5B9A\u4E49\u7684 StyleX \u6837\u5F0F\u3002\u5FC5\u987B\u662F stylex.create() \u7684\u503C\uFF0C\u800C\u975E\u5185\u8054\u6837\u5F0F\u5BF9\u8C61\u3002',
105
113
  className: '\u6839\u5143\u7D20\u7684 CSS \u7C7B\u540D\u3002\u5EFA\u8BAE\u4F7F\u7528 xstyle\u3002',
106
114
  style: '\u6839\u5143\u7D20\u7684\u5185\u8054\u6837\u5F0F\u3002\u5EFA\u8BAE\u4F7F\u7528 xstyle\u3002',
@@ -112,7 +120,7 @@ export const docsZh = {
112
120
  bestPractices: [
113
121
  {guidance: true, description: '\u59CB\u7EC8\u63D0\u4F9B label \u5C5E\u6027\u5E76\u586B\u5199\u6587\u4EF6\u540D\uFF0C\u4EE5\u4FBF\u5C4F\u5E55\u9605\u8BFB\u5668\u80FD\u591F\u8BC6\u522B\u7F29\u7565\u56FE\u53CA\u5176\u79FB\u9664\u6309\u94AE\uFF0C\u5E76\u5728\u60AC\u505C\u65F6\u663E\u793A\u63D0\u793A\u3002'},
114
122
  {guidance: true, description: '\u4E0A\u4F20\u521D\u671F\u4F7F\u7528\u4E0D\u5E26 src \u7684 isLoading \u663E\u793A\u9AA8\u67B6\u5C4F\uFF1B\u83B7\u5F97\u9884\u89C8 URL \u540E\u4F7F\u7528\u5E26 src \u7684 isLoading \u663E\u793A\u65CB\u8F6C\u52A0\u8F7D\u8986\u76D6\u5C42\u3002'},
115
- {guidance: true, description: '\u5C06 onClick \u4E0E\u706F\u7BB1\u6216\u8BE6\u60C5\u89C6\u56FE\u914D\u5BF9\uFF0C\u4EE5\u4FBF\u7528\u6237\u67E5\u770B\u5B8C\u6574\u56FE\u7247\u2014\u2014\u7EC4\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0\u6309\u94AE\u8BED\u4E49\u548C\u60AC\u505C\u9634\u5F71\u3002'},
123
+ {guidance: true, description: '\u5C06 onClick \u4E0E\u706F\u7BB1\u6216\u8BE6\u60C5\u89C6\u56FE\u914D\u5BF9\uFF0C\u4EE5\u4FBF\u7528\u6237\u67E5\u770B\u5B8C\u6574\u56FE\u7247\u2014\u2014\u7EC4\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0\u6309\u94AE\u8BED\u4E49\u548C\u60AC\u505C\u8986\u76D6\u5C42\u3002'},
116
124
  {guidance: false, description: '\u5BF9 PDF \u6216\u7535\u5B50\u8868\u683C\u7B49\u975E\u56FE\u7247\u6587\u4EF6\u7C7B\u578B\u4F7F\u7528 Thumbnail\u2014\u2014\u5E94\u4F7F\u7528\u5E26\u6709\u76F8\u5E94\u56FE\u6807\u7684\u6587\u4EF6\u9644\u4EF6\u7EC4\u4EF6\u3002'},
117
125
  {guidance: false, description: '\u63D0\u4F9B src \u65F6\u7701\u7565 alt \u6587\u672C\u2014\u2014\u5C4F\u5E55\u9605\u8BFB\u5668\u9700\u8981\u56FE\u7247\u5185\u5BB9\u7684\u63CF\u8FF0\uFF0C\u800C\u4E0D\u4EC5\u662F label \u4E2D\u7684\u6587\u4EF6\u540D\u3002'},
118
126
  ],
@@ -128,19 +136,20 @@ export const docsDense = {
128
136
  bestPractices: [
129
137
  {guidance: true, description: 'Always set label (file name) for a11y; powers screen reader announce + hover tooltip.'},
130
138
  {guidance: true, description: 'isLoading w/o src \u2192 skeleton; isLoading w/ src \u2192 spinner overlay. Two distinct loading states.'},
131
- {guidance: true, description: 'onClick adds button semantics + hover shadow; pair with lightbox for full preview.'},
139
+ {guidance: true, description: 'onClick adds button semantics + hover overlay; pair with lightbox for full preview.'},
132
140
  {guidance: false, description: "Don't use for non-image files (PDF, xlsx); use file attachment component with icon instead."},
133
141
  {guidance: false, description: "Don't omit alt when src present; screen readers need image content description, not just label."},
134
142
  ],
135
143
  },
136
144
  propDescriptions: {
137
145
  src: 'Image source URL.',
138
- alt: 'Alt text for image.',
146
+ alt: 'Alt text for image. Omitted → explicitly decorative (alt="" + role="presentation" + aria-hidden); dev warn when src set with no alt and no label.',
139
147
  label: 'Accessible label (file name). Tooltip on hover, aria-label.',
140
148
  onRemove: '(e) => void. Overlaid remove button callback.',
141
- onClick: '(e) => void. Adds button semantics + hover shadow.',
149
+ onClick: '(e) => void. Adds button semantics + hover overlay.',
142
150
  isLoading: 'Skeleton (no src) or upload overlay (with src). Default: false.',
143
151
  isDisabled: 'Disabled state. Default: false.',
152
+ showRemoveOn: "When remove button shows: hover (default — reveal on hover/focus, stays visible on touch) | always. Only when onRemove set.",
144
153
  xstyle: 'stylex.create() for layout.',
145
154
  className: 'CSS class. Prefer xstyle.',
146
155
  style: 'Inline styles. Prefer xstyle.',