@astryxdesign/core 0.1.2 → 0.1.3-canary.102854d

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 (586) hide show
  1. package/CHANGELOG.md +165 -0
  2. package/README.md +12 -12
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +11 -5
  5. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
  6. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  7. package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
  8. package/dist/Button/Button.d.ts.map +1 -1
  9. package/dist/Button/Button.js +31 -12
  10. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  11. package/dist/ButtonGroup/ButtonGroup.js +0 -1
  12. package/dist/Calendar/Calendar.d.ts +5 -4
  13. package/dist/Calendar/Calendar.d.ts.map +1 -1
  14. package/dist/Calendar/Calendar.js +124 -61
  15. package/dist/Calendar/dayCellUtils.d.ts +67 -5
  16. package/dist/Calendar/dayCellUtils.d.ts.map +1 -1
  17. package/dist/Calendar/dayCellUtils.js +139 -18
  18. package/dist/Calendar/hooks/index.d.ts +0 -2
  19. package/dist/Calendar/hooks/index.d.ts.map +1 -1
  20. package/dist/Calendar/hooks/index.js +1 -2
  21. package/dist/Calendar/index.d.ts +3 -3
  22. package/dist/Calendar/index.d.ts.map +1 -1
  23. package/dist/Calendar/index.js +1 -1
  24. package/dist/Calendar/styles.d.ts +3 -9
  25. package/dist/Calendar/styles.d.ts.map +1 -1
  26. package/dist/Calendar/styles.js +3 -11
  27. package/dist/Carousel/Carousel.d.ts.map +1 -1
  28. package/dist/Carousel/Carousel.js +17 -3
  29. package/dist/Center/Center.d.ts +11 -1
  30. package/dist/Center/Center.d.ts.map +1 -1
  31. package/dist/Center/Center.js +9 -3
  32. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  33. package/dist/Chat/ChatComposerInput.js +0 -1
  34. package/dist/Chat/ChatMessageList.d.ts +14 -1
  35. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  36. package/dist/Chat/ChatMessageList.js +2 -0
  37. package/dist/Chat/useTriggerMenu.d.ts +8 -1
  38. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  39. package/dist/Chat/useTriggerMenu.js +15 -3
  40. package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
  41. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  42. package/dist/CheckboxInput/CheckboxInput.js +51 -9
  43. package/dist/CheckboxList/CheckboxList.d.ts +13 -1
  44. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  45. package/dist/CheckboxList/CheckboxList.js +39 -9
  46. package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
  47. package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
  48. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  49. package/dist/CheckboxList/CheckboxListItem.js +0 -1
  50. package/dist/Citation/Citation.d.ts.map +1 -1
  51. package/dist/Citation/Citation.js +9 -5
  52. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  53. package/dist/CodeBlock/CodeBlock.js +51 -37
  54. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  55. package/dist/CommandPalette/CommandPalette.js +5 -5
  56. package/dist/ContextMenu/ContextMenu.d.ts +12 -5
  57. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  58. package/dist/ContextMenu/ContextMenu.js +96 -11
  59. package/dist/DateInput/DateInput.d.ts +23 -1
  60. package/dist/DateInput/DateInput.d.ts.map +1 -1
  61. package/dist/DateInput/DateInput.js +167 -99
  62. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  63. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  64. package/dist/DateRangeInput/DateRangeInput.js +42 -9
  65. package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
  66. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  67. package/dist/DateTimeInput/DateTimeInput.js +78 -15
  68. package/dist/Dialog/Dialog.d.ts.map +1 -1
  69. package/dist/Dialog/Dialog.js +12 -0
  70. package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
  71. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  72. package/dist/DropdownMenu/DropdownMenu.js +42 -14
  73. package/dist/Field/Field.d.ts +19 -2
  74. package/dist/Field/Field.d.ts.map +1 -1
  75. package/dist/Field/Field.js +4 -0
  76. package/dist/Field/FieldLabel.d.ts +21 -2
  77. package/dist/Field/FieldLabel.d.ts.map +1 -1
  78. package/dist/Field/FieldLabel.js +41 -26
  79. package/dist/FileInput/FileInput.d.ts +22 -1
  80. package/dist/FileInput/FileInput.d.ts.map +1 -1
  81. package/dist/FileInput/FileInput.js +56 -10
  82. package/dist/Grid/Grid.d.ts +11 -1
  83. package/dist/Grid/Grid.d.ts.map +1 -1
  84. package/dist/Grid/Grid.js +32 -6
  85. package/dist/InputGroup/InputGroup.d.ts +4 -3
  86. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  87. package/dist/InputGroup/InputGroup.js +16 -6
  88. package/dist/InputGroup/InputGroupContext.d.ts +4 -0
  89. package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
  90. package/dist/InputGroup/InputGroupContext.js +2 -2
  91. package/dist/InputGroup/groupStyles.d.ts +1 -1
  92. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  93. package/dist/InputGroup/groupStyles.js +3 -3
  94. package/dist/InputGroup/index.d.ts +1 -0
  95. package/dist/InputGroup/index.d.ts.map +1 -1
  96. package/dist/Kbd/Kbd.d.ts.map +1 -1
  97. package/dist/Kbd/Kbd.js +33 -1
  98. package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
  99. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  100. package/dist/Layer/layerAnimations.stylex.js +8 -4
  101. package/dist/Layer/useLayer.d.ts +10 -0
  102. package/dist/Layer/useLayer.d.ts.map +1 -1
  103. package/dist/Layer/useLayer.js +64 -9
  104. package/dist/Layout/Layout.d.ts +4 -11
  105. package/dist/Layout/Layout.d.ts.map +1 -1
  106. package/dist/Layout/Layout.js +10 -11
  107. package/dist/Layout/LayoutFooter.d.ts +2 -2
  108. package/dist/Layout/LayoutFooter.d.ts.map +1 -1
  109. package/dist/Layout/LayoutHeader.d.ts +2 -2
  110. package/dist/Layout/LayoutHeader.d.ts.map +1 -1
  111. package/dist/Layout/LayoutPanel.d.ts +2 -2
  112. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  113. package/dist/Layout/padding.stylex.d.ts +51 -0
  114. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  115. package/dist/Layout/padding.stylex.js +63 -0
  116. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  117. package/dist/Lightbox/Lightbox.js +4 -2
  118. package/dist/Link/Link.d.ts +16 -1
  119. package/dist/Link/Link.d.ts.map +1 -1
  120. package/dist/Link/Link.js +18 -7
  121. package/dist/Markdown/Markdown.d.ts.map +1 -1
  122. package/dist/Markdown/Markdown.js +7 -0
  123. package/dist/MoreMenu/MoreMenu.d.ts +1 -7
  124. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  125. package/dist/MoreMenu/MoreMenu.js +0 -2
  126. package/dist/MultiSelector/MultiSelector.d.ts +27 -2
  127. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  128. package/dist/MultiSelector/MultiSelector.js +141 -42
  129. package/dist/MultiSelector/hooks.d.ts +12 -1
  130. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  131. package/dist/MultiSelector/hooks.js +14 -1
  132. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  133. package/dist/NavMenu/NavHeadingMenu.js +34 -3
  134. package/dist/NumberInput/NumberInput.d.ts +23 -2
  135. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  136. package/dist/NumberInput/NumberInput.js +62 -12
  137. package/dist/Pagination/Pagination.d.ts +1 -1
  138. package/dist/Pagination/Pagination.d.ts.map +1 -1
  139. package/dist/Pagination/Pagination.js +15 -1
  140. package/dist/Popover/Popover.d.ts +18 -2
  141. package/dist/Popover/Popover.d.ts.map +1 -1
  142. package/dist/Popover/Popover.js +5 -2
  143. package/dist/Popover/usePopover.d.ts +38 -3
  144. package/dist/Popover/usePopover.d.ts.map +1 -1
  145. package/dist/Popover/usePopover.js +24 -9
  146. package/dist/PowerSearch/PowerSearch.d.ts +11 -1
  147. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  148. package/dist/PowerSearch/PowerSearch.js +6 -1
  149. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  150. package/dist/ProgressBar/ProgressBar.js +3 -5
  151. package/dist/RadioList/RadioList.d.ts +20 -2
  152. package/dist/RadioList/RadioList.d.ts.map +1 -1
  153. package/dist/RadioList/RadioList.js +105 -9
  154. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  155. package/dist/RadioList/RadioListItem.js +13 -2
  156. package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
  157. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  158. package/dist/SegmentedControl/SegmentedControl.js +78 -44
  159. package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
  160. package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
  161. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  162. package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
  163. package/dist/Selector/Selector.d.ts +24 -1
  164. package/dist/Selector/Selector.d.ts.map +1 -1
  165. package/dist/Selector/Selector.js +122 -43
  166. package/dist/Selector/hooks.d.ts +8 -1
  167. package/dist/Selector/hooks.d.ts.map +1 -1
  168. package/dist/Selector/hooks.js +14 -1
  169. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  170. package/dist/SideNav/SideNavHeading.js +2 -0
  171. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  172. package/dist/SideNav/SideNavItem.js +1 -1
  173. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  174. package/dist/Skeleton/Skeleton.js +8 -2
  175. package/dist/Slider/Slider.d.ts +21 -0
  176. package/dist/Slider/Slider.d.ts.map +1 -1
  177. package/dist/Slider/Slider.js +36 -9
  178. package/dist/Spinner/Spinner.d.ts.map +1 -1
  179. package/dist/Spinner/Spinner.js +1 -1
  180. package/dist/Stack/Stack.d.ts +38 -23
  181. package/dist/Stack/Stack.d.ts.map +1 -1
  182. package/dist/Stack/Stack.js +25 -1
  183. package/dist/Stack/StackItem.d.ts +12 -23
  184. package/dist/Stack/StackItem.d.ts.map +1 -1
  185. package/dist/Stack/StackItem.js +8 -1
  186. package/dist/Switch/Switch.d.ts +23 -2
  187. package/dist/Switch/Switch.d.ts.map +1 -1
  188. package/dist/Switch/Switch.js +41 -11
  189. package/dist/TabList/Tab.d.ts.map +1 -1
  190. package/dist/TabList/Tab.js +6 -0
  191. package/dist/TabList/TabList.d.ts +16 -4
  192. package/dist/TabList/TabList.d.ts.map +1 -1
  193. package/dist/TabList/TabList.js +87 -10
  194. package/dist/TabList/TabListContext.d.ts +5 -0
  195. package/dist/TabList/TabListContext.d.ts.map +1 -1
  196. package/dist/TabList/TabListContext.js +5 -0
  197. package/dist/TabList/TabMenu.d.ts.map +1 -1
  198. package/dist/TabList/TabMenu.js +6 -1
  199. package/dist/Table/BaseTable.d.ts.map +1 -1
  200. package/dist/Table/BaseTable.js +13 -9
  201. package/dist/Table/Table.d.ts.map +1 -1
  202. package/dist/Table/Table.js +10 -1
  203. package/dist/Table/TableCell.d.ts +8 -1
  204. package/dist/Table/TableCell.d.ts.map +1 -1
  205. package/dist/Table/TableCell.js +79 -10
  206. package/dist/Table/TableHeaderCell.d.ts +8 -1
  207. package/dist/Table/TableHeaderCell.d.ts.map +1 -1
  208. package/dist/Table/TableHeaderCell.js +16 -16
  209. package/dist/Table/index.d.ts +4 -1
  210. package/dist/Table/index.d.ts.map +1 -1
  211. package/dist/Table/index.js +3 -2
  212. package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
  213. package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
  214. package/dist/Table/plugins/pagination/paginateData.js +8 -3
  215. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  216. package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
  217. package/dist/Table/plugins/rowExpansion/index.d.ts +3 -0
  218. package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -0
  219. package/dist/Table/plugins/rowExpansion/index.js +3 -0
  220. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +90 -0
  221. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -0
  222. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +398 -0
  223. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  224. package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
  225. package/dist/Table/tableContextMenu.d.ts +37 -0
  226. package/dist/Table/tableContextMenu.d.ts.map +1 -0
  227. package/dist/Table/tableContextMenu.js +140 -0
  228. package/dist/Table/types.d.ts +66 -0
  229. package/dist/Table/types.d.ts.map +1 -1
  230. package/dist/TextArea/TextArea.d.ts +22 -1
  231. package/dist/TextArea/TextArea.d.ts.map +1 -1
  232. package/dist/TextArea/TextArea.js +41 -9
  233. package/dist/TextInput/TextInput.d.ts +23 -2
  234. package/dist/TextInput/TextInput.d.ts.map +1 -1
  235. package/dist/TextInput/TextInput.js +55 -10
  236. package/dist/TimeInput/TimeInput.d.ts +23 -1
  237. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  238. package/dist/TimeInput/TimeInput.js +147 -76
  239. package/dist/Toast/Toast.d.ts.map +1 -1
  240. package/dist/Toast/Toast.js +14 -0
  241. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  242. package/dist/Toast/ToastViewport.js +131 -3
  243. package/dist/Tokenizer/Tokenizer.d.ts +12 -1
  244. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  245. package/dist/Tokenizer/Tokenizer.js +26 -4
  246. package/dist/Toolbar/Toolbar.d.ts +3 -3
  247. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  248. package/dist/Toolbar/Toolbar.js +51 -7
  249. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  250. package/dist/Tooltip/useTooltip.js +56 -9
  251. package/dist/TopNav/TopNavHeading.d.ts +7 -1
  252. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  253. package/dist/TopNav/TopNavHeading.js +8 -0
  254. package/dist/TreeList/TreeList.d.ts +1 -1
  255. package/dist/TreeList/TreeList.d.ts.map +1 -1
  256. package/dist/TreeList/TreeList.js +72 -2
  257. package/dist/TreeList/TreeListItem.d.ts +11 -1
  258. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  259. package/dist/TreeList/TreeListItem.js +51 -12
  260. package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
  261. package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
  262. package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
  263. package/dist/Typeahead/BaseTypeahead.d.ts +13 -0
  264. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  265. package/dist/Typeahead/BaseTypeahead.js +69 -6
  266. package/dist/Typeahead/Typeahead.d.ts +26 -3
  267. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  268. package/dist/Typeahead/Typeahead.js +65 -29
  269. package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
  270. package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
  271. package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
  272. package/dist/VisuallyHidden/index.d.ts +11 -0
  273. package/dist/VisuallyHidden/index.d.ts.map +1 -0
  274. package/dist/VisuallyHidden/index.js +13 -0
  275. package/dist/astryx.css +22 -0
  276. package/dist/astryx.umd.js +55 -55
  277. package/dist/astryx.umd.js.map +4 -4
  278. package/dist/hooks/focusableSelector.d.ts +22 -0
  279. package/dist/hooks/focusableSelector.d.ts.map +1 -0
  280. package/dist/hooks/focusableSelector.js +24 -0
  281. package/dist/hooks/index.d.ts +12 -2
  282. package/dist/hooks/index.d.ts.map +1 -1
  283. package/dist/hooks/index.js +7 -2
  284. package/dist/hooks/useAnnounce.d.ts +40 -0
  285. package/dist/hooks/useAnnounce.d.ts.map +1 -0
  286. package/dist/hooks/useAnnounce.js +142 -0
  287. package/dist/hooks/useClickableContainer.d.ts +16 -1
  288. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  289. package/dist/hooks/useClickableContainer.js +16 -4
  290. package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
  291. package/dist/hooks/useEntryAnimation.js +4 -4
  292. package/dist/hooks/useFocusTrap.d.ts +18 -0
  293. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  294. package/dist/hooks/useFocusTrap.js +87 -3
  295. package/dist/hooks/useGridFocus.d.ts +88 -1
  296. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  297. package/dist/hooks/useGridFocus.js +261 -62
  298. package/dist/hooks/useKeyboardHint.d.ts +82 -0
  299. package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
  300. package/dist/hooks/useKeyboardHint.js +220 -0
  301. package/dist/hooks/useListFocus.d.ts +78 -7
  302. package/dist/hooks/useListFocus.d.ts.map +1 -1
  303. package/dist/hooks/useListFocus.js +305 -52
  304. package/dist/hooks/useLongPress.d.ts +21 -0
  305. package/dist/hooks/useLongPress.d.ts.map +1 -0
  306. package/dist/hooks/useLongPress.js +89 -0
  307. package/dist/hooks/useTreeFocus.d.ts +157 -0
  308. package/dist/hooks/useTreeFocus.d.ts.map +1 -0
  309. package/dist/hooks/useTreeFocus.js +337 -0
  310. package/dist/hooks/useTypeahead.d.ts +63 -0
  311. package/dist/hooks/useTypeahead.d.ts.map +1 -0
  312. package/dist/hooks/useTypeahead.js +117 -0
  313. package/dist/index.d.ts +1 -0
  314. package/dist/index.d.ts.map +1 -1
  315. package/dist/index.js +1 -0
  316. package/dist/utils/dateTypes.d.ts +12 -0
  317. package/dist/utils/dateTypes.d.ts.map +1 -1
  318. package/dist/utils/dateTypes.js +41 -1
  319. package/dist/utils/index.d.ts +4 -0
  320. package/dist/utils/index.d.ts.map +1 -1
  321. package/dist/utils/index.js +3 -1
  322. package/dist/utils/inputAria.d.ts +29 -0
  323. package/dist/utils/inputAria.d.ts.map +1 -0
  324. package/dist/utils/inputAria.js +30 -0
  325. package/dist/utils/timeParser.d.ts.map +1 -1
  326. package/dist/utils/timeParser.js +5 -2
  327. package/docs.mjs +2 -2
  328. package/package.json +12 -8
  329. package/src/Avatar/Avatar.doc.mjs +2 -2
  330. package/src/Avatar/Avatar.test.tsx +37 -0
  331. package/src/Avatar/Avatar.tsx +10 -5
  332. package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
  333. package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
  334. package/src/Button/Button.tsx +42 -22
  335. package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
  336. package/src/ButtonGroup/ButtonGroup.tsx +0 -1
  337. package/src/Calendar/Calendar.doc.mjs +4 -4
  338. package/src/Calendar/Calendar.test.tsx +247 -30
  339. package/src/Calendar/Calendar.tsx +173 -86
  340. package/src/Calendar/dayCellUtils.test.ts +306 -1
  341. package/src/Calendar/dayCellUtils.ts +206 -13
  342. package/src/Calendar/hooks/index.ts +0 -6
  343. package/src/Calendar/index.ts +1 -3
  344. package/src/Calendar/styles.ts +4 -9
  345. package/src/Carousel/Carousel.doc.mjs +7 -1
  346. package/src/Carousel/Carousel.test.tsx +20 -0
  347. package/src/Carousel/Carousel.tsx +16 -1
  348. package/src/Center/Center.doc.mjs +12 -2
  349. package/src/Center/Center.tsx +28 -3
  350. package/src/Chat/ChatComposerInput.test.tsx +26 -7
  351. package/src/Chat/ChatComposerInput.tsx +0 -1
  352. package/src/Chat/ChatDictationButton.doc.mjs +1 -1
  353. package/src/Chat/ChatMessageList.doc.mjs +8 -0
  354. package/src/Chat/ChatMessageList.test.tsx +18 -0
  355. package/src/Chat/ChatMessageList.tsx +16 -0
  356. package/src/Chat/useTriggerMenu.tsx +22 -4
  357. package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -0
  358. package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
  359. package/src/CheckboxInput/CheckboxInput.tsx +78 -6
  360. package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
  361. package/src/CheckboxList/CheckboxList.test.tsx +192 -26
  362. package/src/CheckboxList/CheckboxList.tsx +56 -3
  363. package/src/CheckboxList/CheckboxListContext.tsx +7 -0
  364. package/src/CheckboxList/CheckboxListItem.tsx +0 -3
  365. package/src/Citation/Citation.doc.mjs +10 -0
  366. package/src/Citation/Citation.test.tsx +121 -0
  367. package/src/Citation/Citation.tsx +15 -3
  368. package/src/CodeBlock/CodeBlock.test.tsx +115 -0
  369. package/src/CodeBlock/CodeBlock.tsx +63 -33
  370. package/src/CommandPalette/CommandPalette.test.tsx +47 -1
  371. package/src/CommandPalette/CommandPalette.tsx +9 -21
  372. package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
  373. package/src/ContextMenu/ContextMenu.test.tsx +155 -1
  374. package/src/ContextMenu/ContextMenu.tsx +129 -16
  375. package/src/DateInput/DateInput.doc.mjs +291 -56
  376. package/src/DateInput/DateInput.test.tsx +248 -2
  377. package/src/DateInput/DateInput.tsx +196 -100
  378. package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
  379. package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
  380. package/src/DateRangeInput/DateRangeInput.tsx +63 -5
  381. package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
  382. package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
  383. package/src/DateTimeInput/DateTimeInput.tsx +125 -17
  384. package/src/Dialog/Dialog.doc.mjs +2 -2
  385. package/src/Dialog/Dialog.tsx +12 -0
  386. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
  387. package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
  388. package/src/DropdownMenu/DropdownMenu.tsx +52 -18
  389. package/src/Field/Field.doc.mjs +59 -18
  390. package/src/Field/Field.test.tsx +32 -0
  391. package/src/Field/Field.tsx +23 -5
  392. package/src/Field/FieldLabel.tsx +55 -17
  393. package/src/FileInput/FileInput.doc.mjs +17 -0
  394. package/src/FileInput/FileInput.test.tsx +283 -49
  395. package/src/FileInput/FileInput.tsx +76 -4
  396. package/src/Grid/Grid.doc.mjs +17 -4
  397. package/src/Grid/Grid.test.tsx +43 -30
  398. package/src/Grid/Grid.tsx +38 -3
  399. package/src/Icon/Icon.doc.mjs +3 -3
  400. package/src/InputGroup/InputGroup.doc.mjs +111 -23
  401. package/src/InputGroup/InputGroup.test.tsx +257 -60
  402. package/src/InputGroup/InputGroup.tsx +23 -5
  403. package/src/InputGroup/InputGroupContext.ts +9 -4
  404. package/src/InputGroup/groupStyles.ts +7 -1
  405. package/src/InputGroup/index.ts +1 -0
  406. package/src/Kbd/Kbd.test.tsx +22 -4
  407. package/src/Kbd/Kbd.tsx +35 -3
  408. package/src/Layer/layerAnimations.stylex.ts +20 -4
  409. package/src/Layer/useLayer.doc.mjs +5 -0
  410. package/src/Layer/useLayer.test.tsx +111 -0
  411. package/src/Layer/useLayer.tsx +90 -9
  412. package/src/Layout/Layout.tsx +8 -16
  413. package/src/Layout/LayoutFooter.doc.mjs +4 -4
  414. package/src/Layout/LayoutFooter.tsx +3 -3
  415. package/src/Layout/LayoutHeader.doc.mjs +4 -4
  416. package/src/Layout/LayoutHeader.tsx +3 -3
  417. package/src/Layout/LayoutPanel.tsx +3 -3
  418. package/src/Layout/__tests__/edgeCompensation.test.tsx +72 -0
  419. package/src/Layout/padding.stylex.ts +52 -0
  420. package/src/Lightbox/Lightbox.doc.mjs +9 -0
  421. package/src/Lightbox/Lightbox.test.tsx +53 -5
  422. package/src/Lightbox/Lightbox.tsx +9 -4
  423. package/src/Link/Link.doc.mjs +14 -0
  424. package/src/Link/Link.test.tsx +50 -0
  425. package/src/Link/Link.tsx +39 -4
  426. package/src/Markdown/Markdown.test.tsx +11 -0
  427. package/src/Markdown/Markdown.tsx +7 -0
  428. package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
  429. package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
  430. package/src/MoreMenu/MoreMenu.tsx +0 -9
  431. package/src/MultiSelector/MultiSelector.doc.mjs +35 -0
  432. package/src/MultiSelector/MultiSelector.test.tsx +375 -8
  433. package/src/MultiSelector/MultiSelector.tsx +194 -48
  434. package/src/MultiSelector/hooks.ts +27 -0
  435. package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
  436. package/src/NavMenu/NavHeadingMenu.tsx +50 -3
  437. package/src/NumberInput/NumberInput.doc.mjs +17 -0
  438. package/src/NumberInput/NumberInput.test.tsx +242 -40
  439. package/src/NumberInput/NumberInput.tsx +89 -11
  440. package/src/Pagination/Pagination.doc.mjs +3 -3
  441. package/src/Pagination/Pagination.test.tsx +117 -5
  442. package/src/Pagination/Pagination.tsx +21 -1
  443. package/src/Popover/Popover.doc.mjs +26 -0
  444. package/src/Popover/Popover.test.tsx +121 -0
  445. package/src/Popover/Popover.tsx +23 -2
  446. package/src/Popover/usePopover.doc.mjs +9 -3
  447. package/src/Popover/usePopover.tsx +70 -12
  448. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  449. package/src/PowerSearch/PowerSearch.test.tsx +97 -1
  450. package/src/PowerSearch/PowerSearch.tsx +16 -3
  451. package/src/ProgressBar/ProgressBar.test.tsx +34 -26
  452. package/src/ProgressBar/ProgressBar.tsx +3 -4
  453. package/src/RadioList/RadioList.doc.mjs +9 -0
  454. package/src/RadioList/RadioList.test.tsx +252 -16
  455. package/src/RadioList/RadioList.tsx +166 -10
  456. package/src/RadioList/RadioListItem.tsx +14 -2
  457. package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
  458. package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
  459. package/src/SegmentedControl/SegmentedControl.tsx +102 -54
  460. package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
  461. package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
  462. package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
  463. package/src/Selector/Selector.doc.mjs +31 -0
  464. package/src/Selector/Selector.test.tsx +387 -15
  465. package/src/Selector/Selector.tsx +175 -67
  466. package/src/Selector/hooks.ts +23 -0
  467. package/src/SideNav/SideNav.test.tsx +48 -0
  468. package/src/SideNav/SideNavHeading.tsx +8 -2
  469. package/src/SideNav/SideNavItem.tsx +2 -4
  470. package/src/Skeleton/Skeleton.test.tsx +25 -0
  471. package/src/Skeleton/Skeleton.tsx +11 -1
  472. package/src/Slider/Slider.doc.mjs +15 -0
  473. package/src/Slider/Slider.test.tsx +155 -2
  474. package/src/Slider/Slider.tsx +53 -5
  475. package/src/Spinner/Spinner.tsx +7 -1
  476. package/src/Stack/Stack.doc.mjs +77 -0
  477. package/src/Stack/Stack.test.tsx +55 -5
  478. package/src/Stack/Stack.tsx +73 -24
  479. package/src/Stack/StackItem.test.tsx +23 -0
  480. package/src/Stack/StackItem.tsx +20 -23
  481. package/src/Switch/Switch.doc.mjs +15 -0
  482. package/src/Switch/Switch.test.tsx +162 -27
  483. package/src/Switch/Switch.tsx +61 -21
  484. package/src/TabList/Tab.tsx +6 -0
  485. package/src/TabList/TabList.doc.mjs +9 -3
  486. package/src/TabList/TabList.test.tsx +251 -0
  487. package/src/TabList/TabList.tsx +103 -12
  488. package/src/TabList/TabListContext.ts +7 -3
  489. package/src/TabList/TabMenu.tsx +6 -3
  490. package/src/Table/BaseTable.tsx +24 -18
  491. package/src/Table/Table.doc.mjs +2 -0
  492. package/src/Table/Table.test.tsx +10 -0
  493. package/src/Table/Table.tsx +8 -0
  494. package/src/Table/TableCell.tsx +105 -24
  495. package/src/Table/TableHeaderCell.tsx +28 -29
  496. package/src/Table/index.ts +8 -2
  497. package/src/Table/plugins/pagination/paginateData.ts +10 -3
  498. package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
  499. package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
  500. package/src/Table/plugins/rowExpansion/index.ts +7 -0
  501. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +155 -0
  502. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +590 -0
  503. package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
  504. package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
  505. package/src/Table/tableContextMenu.test.tsx +181 -0
  506. package/src/Table/tableContextMenu.tsx +160 -0
  507. package/src/Table/types.ts +74 -0
  508. package/src/Table/useTableColumnResize.doc.mjs +3 -3
  509. package/src/Table/useTablePagination.doc.mjs +4 -1
  510. package/src/Table/useTableRowExpansion.doc.mjs +63 -0
  511. package/src/Table/useTableSortable.doc.mjs +4 -1
  512. package/src/Table/useTableStickyColumns.doc.mjs +2 -2
  513. package/src/Text/Text.doc.mjs +18 -18
  514. package/src/TextArea/TextArea.doc.mjs +17 -0
  515. package/src/TextArea/TextArea.test.tsx +167 -35
  516. package/src/TextArea/TextArea.tsx +62 -15
  517. package/src/TextInput/TextInput.doc.mjs +17 -0
  518. package/src/TextInput/TextInput.test.tsx +168 -34
  519. package/src/TextInput/TextInput.tsx +77 -9
  520. package/src/Thumbnail/Thumbnail.doc.mjs +4 -4
  521. package/src/TimeInput/TimeInput.doc.mjs +345 -60
  522. package/src/TimeInput/TimeInput.test.tsx +255 -7
  523. package/src/TimeInput/TimeInput.tsx +176 -70
  524. package/src/Timestamp/Timestamp.doc.mjs +19 -19
  525. package/src/Toast/Toast.tsx +14 -0
  526. package/src/Toast/ToastViewport.test.tsx +214 -0
  527. package/src/Toast/ToastViewport.tsx +167 -21
  528. package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
  529. package/src/Tokenizer/Tokenizer.test.tsx +105 -1
  530. package/src/Tokenizer/Tokenizer.tsx +37 -1
  531. package/src/Toolbar/Toolbar.test.tsx +109 -6
  532. package/src/Toolbar/Toolbar.tsx +59 -5
  533. package/src/Tooltip/Tooltip.test.tsx +68 -0
  534. package/src/Tooltip/useTooltip.tsx +55 -8
  535. package/src/TopNav/TopNav.test.tsx +50 -0
  536. package/src/TopNav/TopNavHeading.tsx +17 -1
  537. package/src/TreeList/TreeList.test.tsx +295 -6
  538. package/src/TreeList/TreeList.tsx +73 -1
  539. package/src/TreeList/TreeListItem.tsx +51 -5
  540. package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
  541. package/src/Typeahead/BaseTypeahead.tsx +93 -9
  542. package/src/Typeahead/Typeahead.doc.mjs +146 -30
  543. package/src/Typeahead/Typeahead.test.tsx +331 -1
  544. package/src/Typeahead/Typeahead.tsx +105 -33
  545. package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
  546. package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
  547. package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
  548. package/src/VisuallyHidden/index.ts +15 -0
  549. package/src/docs-script.test.mjs +50 -0
  550. package/src/hooks/focusableSelector.ts +25 -0
  551. package/src/hooks/index.ts +28 -2
  552. package/src/hooks/useAnnounce.test.tsx +101 -0
  553. package/src/hooks/useAnnounce.ts +168 -0
  554. package/src/hooks/useClickableContainer.ts +16 -4
  555. package/src/hooks/useEntryAnimation.ts +16 -4
  556. package/src/hooks/useFocusTrap.test.tsx +132 -0
  557. package/src/hooks/useFocusTrap.ts +98 -4
  558. package/src/hooks/useGridFocus.doc.mjs +40 -2
  559. package/src/hooks/useGridFocus.test.tsx +132 -0
  560. package/src/hooks/useGridFocus.ts +343 -67
  561. package/src/hooks/useKeyboardHint.doc.mjs +101 -0
  562. package/src/hooks/useKeyboardHint.test.tsx +70 -0
  563. package/src/hooks/useKeyboardHint.tsx +332 -0
  564. package/src/hooks/useListFocus.doc.mjs +50 -10
  565. package/src/hooks/useListFocus.test.tsx +375 -0
  566. package/src/hooks/useListFocus.ts +395 -57
  567. package/src/hooks/useLongPress.test.tsx +134 -0
  568. package/src/hooks/useLongPress.ts +119 -0
  569. package/src/hooks/useTreeFocus.doc.mjs +140 -0
  570. package/src/hooks/useTreeFocus.test.tsx +214 -0
  571. package/src/hooks/useTreeFocus.ts +559 -0
  572. package/src/hooks/useTypeahead.test.tsx +109 -0
  573. package/src/hooks/useTypeahead.ts +183 -0
  574. package/src/index.ts +1 -0
  575. package/src/theme/derivedVarRegistry.test.ts +10 -5
  576. package/src/utils/dateTypes.test.ts +40 -0
  577. package/src/utils/dateTypes.ts +40 -0
  578. package/src/utils/index.ts +9 -0
  579. package/src/utils/inputAria.test.ts +39 -0
  580. package/src/utils/inputAria.ts +58 -0
  581. package/src/utils/timeParser.test.ts +10 -0
  582. package/src/utils/timeParser.ts +5 -2
  583. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
  584. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
  585. package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
  586. package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
@@ -17,10 +17,12 @@ import {useRef, useMemo, type ReactNode} from 'react';
17
17
  import * as stylex from '@stylexjs/stylex';
18
18
  import {colorVars, spacingVars, radiusVars} from '../../../theme/tokens.stylex';
19
19
  import {Icon} from '../../../Icon';
20
+ import {resolveContextActions} from '../../tableContextMenu';
20
21
  import type {
21
22
  TablePlugin,
22
23
  HeaderCellRenderProps,
23
24
  TableColumn,
25
+ TableContextAction,
24
26
  } from '../../types';
25
27
 
26
28
  // =============================================================================
@@ -356,10 +358,56 @@ export function useTableSortable<
356
358
  return props;
357
359
  }
358
360
 
359
- // Find sort entry for this column
360
361
  const cfg = configRef.current;
361
362
  const entry = cfg.sort.find(e => e.sortKey === sortKey);
362
363
 
364
+ // Context-menu actions are built lazily (only when the menu opens) via
365
+ // a getter, reading the current sort state at call time — so we don't
366
+ // build an action array for every header on every render, and the
367
+ // checked/clear state always reflects the latest sort.
368
+ const getSortActions = (): TableContextAction[] => {
369
+ const c = configRef.current;
370
+ const dir = c.sort.find(e => e.sortKey === sortKey)?.direction ?? null;
371
+ const actions: TableContextAction[] = [
372
+ {
373
+ id: 'sort-asc',
374
+ group: 'sort',
375
+ label: 'Sort ascending',
376
+ icon: <Icon icon="arrowUp" size="xsm" aria-hidden />,
377
+ checked: dir === 'ascending',
378
+ onSelect: () =>
379
+ c.onSortChange([
380
+ {sortKey: sortKey as TSortKey, direction: 'ascending'},
381
+ ]),
382
+ },
383
+ {
384
+ id: 'sort-desc',
385
+ group: 'sort',
386
+ label: 'Sort descending',
387
+ icon: <Icon icon="arrowDown" size="xsm" aria-hidden />,
388
+ checked: dir === 'descending',
389
+ onSelect: () =>
390
+ c.onSortChange([
391
+ {sortKey: sortKey as TSortKey, direction: 'descending'},
392
+ ]),
393
+ },
394
+ ];
395
+ if (dir != null) {
396
+ actions.push({
397
+ id: 'sort-clear',
398
+ group: 'sort-clear',
399
+ label: 'Clear sort',
400
+ icon: <Icon icon="close" size="xsm" aria-hidden />,
401
+ onSelect: () =>
402
+ c.onSortChange(c.sort.filter(e => e.sortKey !== sortKey)),
403
+ });
404
+ }
405
+ return actions;
406
+ };
407
+
408
+ // Merge with any actions a prior plugin contributed (array or getter),
409
+ // resolving both lazily at open time.
410
+ const priorActions = props.contextMenuActions;
363
411
  return {
364
412
  ...props,
365
413
  htmlProps: {
@@ -375,6 +423,10 @@ export function useTableSortable<
375
423
  {props.content}
376
424
  </SortHeaderButton>
377
425
  ),
426
+ contextMenuActions: () => [
427
+ ...resolveContextActions(priorActions),
428
+ ...getSortActions(),
429
+ ],
378
430
  };
379
431
  },
380
432
  }),
@@ -0,0 +1,181 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file tableContextMenu.test.tsx
5
+ * @output Tests for the Table context-menu system
6
+ * @position Validates contextMenuActions aggregation + header context menus
7
+ */
8
+
9
+ import {describe, it, expect, vi, beforeEach} from 'vitest';
10
+ import {render, screen, fireEvent} from '@testing-library/react';
11
+ import {Table} from './Table';
12
+ import type {TablePlugin, TableColumn} from './types';
13
+ import {resolveContextActions} from './tableContextMenu';
14
+
15
+ // jsdom doesn't implement the Popover API; mirror the ContextMenu test's mock
16
+ // so the menu can "open" and its items become queryable (as hidden).
17
+ beforeEach(() => {
18
+ HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
19
+ this.setAttribute('popover-open', '');
20
+ const event = new Event('toggle', {bubbles: false});
21
+ Object.defineProperty(event, 'newState', {value: 'open'});
22
+ this.dispatchEvent(event);
23
+ });
24
+ HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
25
+ this.removeAttribute('popover-open');
26
+ const event = new Event('toggle', {bubbles: false});
27
+ Object.defineProperty(event, 'newState', {value: 'closed'});
28
+ this.dispatchEvent(event);
29
+ });
30
+ const originalMatches = HTMLElement.prototype.matches;
31
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
+ (HTMLElement.prototype as any).matches = function (
33
+ selector: string,
34
+ ): boolean {
35
+ if (selector === ':popover-open') {
36
+ return this.hasAttribute('popover-open');
37
+ }
38
+ return originalMatches.call(this, selector);
39
+ };
40
+ });
41
+
42
+ interface Row extends Record<string, unknown> {
43
+ id: string;
44
+ name: string;
45
+ }
46
+
47
+ const data: Row[] = [
48
+ {id: '1', name: 'Alice'},
49
+ {id: '2', name: 'Bob'},
50
+ ];
51
+
52
+ const columns: TableColumn<Row>[] = [
53
+ {key: 'name', header: 'Name'},
54
+ {key: 'id', header: 'ID'},
55
+ ];
56
+
57
+ // =============================================================================
58
+ // contextMenuActions via transformHeaderCell
59
+ // =============================================================================
60
+
61
+ describe('Table header context menu', () => {
62
+ it('renders a menu from a plugin that sets contextMenuActions', () => {
63
+ const onSelect = vi.fn();
64
+ const plugin: TablePlugin<Row> = {
65
+ transformHeaderCell: props => ({
66
+ ...props,
67
+ contextMenuActions: [{id: 'pin', label: 'Pin column', onSelect}],
68
+ }),
69
+ };
70
+ render(
71
+ <Table data={data} columns={columns} idKey="id" plugins={{plugin}} />,
72
+ );
73
+ fireEvent.contextMenu(screen.getByText('Name'));
74
+ const items = screen.getAllByRole('menuitem', {
75
+ name: 'Pin column',
76
+ hidden: true,
77
+ });
78
+ expect(items.length).toBeGreaterThan(0);
79
+ fireEvent.click(items[0]);
80
+ expect(onSelect).toHaveBeenCalledTimes(1);
81
+ });
82
+
83
+ it('concatenates actions from multiple plugins (never overridden)', () => {
84
+ const a: TablePlugin<Row> = {
85
+ transformHeaderCell: props => ({
86
+ ...props,
87
+ contextMenuActions: [
88
+ ...resolveContextActions(props.contextMenuActions),
89
+ {id: 'a', label: 'Action A', onSelect: () => {}},
90
+ ],
91
+ }),
92
+ };
93
+ const b: TablePlugin<Row> = {
94
+ transformHeaderCell: props => ({
95
+ ...props,
96
+ contextMenuActions: [
97
+ ...resolveContextActions(props.contextMenuActions),
98
+ {id: 'b', label: 'Action B', onSelect: () => {}},
99
+ ],
100
+ }),
101
+ };
102
+ render(<Table data={data} columns={columns} idKey="id" plugins={{a, b}} />);
103
+ fireEvent.contextMenu(screen.getByText('Name'));
104
+ expect(
105
+ screen.getAllByRole('menuitem', {name: 'Action A', hidden: true}).length,
106
+ ).toBeGreaterThan(0);
107
+ expect(
108
+ screen.getAllByRole('menuitem', {name: 'Action B', hidden: true}).length,
109
+ ).toBeGreaterThan(0);
110
+ });
111
+
112
+ it('does not render a menu when no plugin contributes actions', () => {
113
+ render(<Table data={data} columns={columns} idKey="id" />);
114
+ fireEvent.contextMenu(screen.getByText('Name'));
115
+ expect(
116
+ screen.queryByRole('menuitem', {hidden: true}),
117
+ ).not.toBeInTheDocument();
118
+ });
119
+ });
120
+
121
+ // =============================================================================
122
+ // Body / row context menu
123
+ // =============================================================================
124
+
125
+ describe('Table body context menu', () => {
126
+ it('renders row actions from a plugin that sets contextMenuActions in transformBodyCell', () => {
127
+ const onSelect = vi.fn();
128
+ const plugin: TablePlugin<Row> = {
129
+ transformBodyCell: (props, _column, item) => ({
130
+ ...props,
131
+ contextMenuActions: [
132
+ {
133
+ id: `delete-${item.id}`,
134
+ label: 'Delete row',
135
+ onSelect: () => {
136
+ onSelect(item.id);
137
+ },
138
+ },
139
+ ],
140
+ }),
141
+ };
142
+ render(
143
+ <Table data={data} columns={columns} idKey="id" plugins={{plugin}} />,
144
+ );
145
+ // Right-click the first body cell (Alice).
146
+ fireEvent.contextMenu(screen.getByText('Alice'));
147
+ const items = screen.getAllByRole('menuitem', {
148
+ name: 'Delete row',
149
+ hidden: true,
150
+ });
151
+ expect(items.length).toBeGreaterThan(0);
152
+ fireEvent.click(items[0]);
153
+ expect(onSelect).toHaveBeenCalledWith('1');
154
+ });
155
+
156
+ it('trigger wrapper fills the full cell so the whole cell is right-clickable', () => {
157
+ const plugin: TablePlugin<Row> = {
158
+ transformBodyCell: props => ({
159
+ ...props,
160
+ contextMenuActions: [{id: 'act', label: 'Act', onSelect: () => {}}],
161
+ }),
162
+ };
163
+ render(
164
+ <Table data={data} columns={columns} idKey="id" plugins={{plugin}} />,
165
+ );
166
+ // The context-menu trigger wraps the cell content. It must fill the cell
167
+ // (block display + 100% width) so right-clicking anywhere in the cell —
168
+ // not just on the content — opens the menu. Regression test for the bug
169
+ // where only the wide first column responded to right-click.
170
+ const alice = screen.getByText('Alice');
171
+ const trigger = alice.closest('div');
172
+ expect(trigger).not.toBeNull();
173
+ expect(trigger?.className).toBeTruthy();
174
+ // The fillCell style sets inline-size:100% + display:block on the trigger.
175
+ const styleAttr = trigger?.getAttribute('class') ?? '';
176
+ // StyleX compiles to atomic classes; just assert the wrapper carries styles
177
+ // (the visual fill is covered by the compiled CSS). The key contract is
178
+ // that the trigger is a styled block wrapper, not a bare inline element.
179
+ expect(styleAttr.length).toBeGreaterThan(0);
180
+ });
181
+ });
@@ -0,0 +1,160 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file tableContextMenu.tsx
7
+ * @input React, ContextMenu, Icon, types
8
+ * @output wrapInTableContextMenu helper
9
+ * @position Renders the aggregated `contextMenuActions` for a header cell / row
10
+ *
11
+ * SYNC: When modified, update these files to stay in sync:
12
+ * - /packages/core/src/Table/BaseTable.tsx (call sites)
13
+ * - /packages/core/src/Table/types.ts (TableContextAction)
14
+ */
15
+
16
+ import {useState, type ReactNode} from 'react';
17
+ import {ContextMenu, type ContextMenuOption} from '../ContextMenu';
18
+ import {Icon} from '../Icon';
19
+ import type {StyleXStyles} from '../theme/types';
20
+ import type {TableContextAction, TableContextActions} from './types';
21
+
22
+ /**
23
+ * Resolve a `contextMenuActions` value (array or getter) to a plain array.
24
+ * Use this when composing actions from a prior plugin's render props so you
25
+ * don't have to branch on the array-vs-getter form:
26
+ *
27
+ * ```
28
+ * contextMenuActions: () => [
29
+ * ...resolveContextActions(props.contextMenuActions),
30
+ * ...myActions,
31
+ * ]
32
+ * ```
33
+ */
34
+ export function resolveContextActions(
35
+ actions: TableContextActions | undefined,
36
+ ): TableContextAction[] {
37
+ if (typeof actions === 'function') {
38
+ return actions();
39
+ }
40
+ return actions ?? [];
41
+ }
42
+
43
+ /**
44
+ * Convert the flat action list into ContextMenu options, inserting a divider
45
+ * between groups (first-seen group order). Ungrouped actions form a trailing
46
+ * group. A `checked` action shows a trailing check icon.
47
+ */
48
+ function toContextMenuOptions(
49
+ actions: TableContextAction[],
50
+ ): ContextMenuOption[] {
51
+ const order: string[] = [];
52
+ const buckets = new Map<string, TableContextAction[]>();
53
+ for (const action of actions) {
54
+ const key = action.group ?? '__ungrouped__';
55
+ let bucket = buckets.get(key);
56
+ if (!bucket) {
57
+ bucket = [];
58
+ buckets.set(key, bucket);
59
+ order.push(key);
60
+ }
61
+ bucket.push(action);
62
+ }
63
+
64
+ const options: ContextMenuOption[] = [];
65
+ order.forEach((key, groupIndex) => {
66
+ if (groupIndex > 0) {
67
+ options.push({type: 'divider'});
68
+ }
69
+ for (const action of buckets.get(key) ?? []) {
70
+ options.push({
71
+ label: typeof action.label === 'string' ? action.label : action.id,
72
+ // A checked action (e.g. the active sort direction) shows a checkmark;
73
+ // otherwise the action's own icon. ContextMenu's data form takes a
74
+ // single leading icon, so checked state replaces the icon.
75
+ icon: action.checked ? (
76
+ <Icon icon="check" size="xsm" aria-hidden />
77
+ ) : (
78
+ action.icon
79
+ ),
80
+ isDisabled: action.disabled,
81
+ onClick: action.onSelect,
82
+ });
83
+ }
84
+ });
85
+ return options;
86
+ }
87
+
88
+ /**
89
+ * Wrap a table element (a header cell's content or a row) in a right-click
90
+ * context menu rendering the aggregated `actions`. When no plugin contributes
91
+ * actions the element is returned untouched so the native browser menu passes
92
+ * through.
93
+ */
94
+ /**
95
+ * A context menu whose actions are resolved lazily — only when the user opens
96
+ * the menu (right-click). Deferring the work means plugins that pass a getter
97
+ * don't build an action array (with its closures) for every cell on every
98
+ * render; it's computed on demand and memoized until the menu closes.
99
+ */
100
+ function LazyTableContextMenu({
101
+ element,
102
+ getActions,
103
+ triggerXstyle,
104
+ }: {
105
+ element: ReactNode;
106
+ getActions: () => TableContextAction[];
107
+ triggerXstyle?: StyleXStyles | StyleXStyles[];
108
+ }): ReactNode {
109
+ const [options, setOptions] = useState<ContextMenuOption[] | null>(null);
110
+ return (
111
+ <ContextMenu
112
+ items={options ?? []}
113
+ triggerXstyle={triggerXstyle}
114
+ onOpenChange={open => {
115
+ // Resolve actions when opening; clear on close so state derived later
116
+ // (e.g. current sort direction) is always fresh next open.
117
+ setOptions(open ? toContextMenuOptions(getActions()) : null);
118
+ }}>
119
+ {element}
120
+ </ContextMenu>
121
+ );
122
+ }
123
+
124
+ /**
125
+ * Wrap a table element (a header cell's content or a body cell) in a right-click
126
+ * context menu rendering the aggregated `actions`. Accepts a static array or a
127
+ * getter (resolved lazily on open). When there are no actions the element is
128
+ * returned untouched so the native browser menu passes through.
129
+ *
130
+ * `triggerXstyle` styles the right-click target wrapper. Cells pass a fill +
131
+ * padding style so the entire cell (padding included) opens the menu.
132
+ */
133
+ export function wrapInTableContextMenu(
134
+ element: ReactNode,
135
+ actions: TableContextActions | undefined,
136
+ triggerXstyle?: StyleXStyles | StyleXStyles[],
137
+ ): ReactNode {
138
+ // Getter form → resolve lazily on open.
139
+ if (typeof actions === 'function') {
140
+ return (
141
+ <LazyTableContextMenu
142
+ element={element}
143
+ getActions={actions}
144
+ triggerXstyle={triggerXstyle}
145
+ />
146
+ );
147
+ }
148
+ if (!actions || actions.length === 0) {
149
+ return element;
150
+ }
151
+ // item (it looked like "ascending" was always selected). Focus moves only
152
+ // when the user arrow-keys into the menu.
153
+ return (
154
+ <ContextMenu
155
+ items={toContextMenuOptions(actions)}
156
+ triggerXstyle={triggerXstyle}>
157
+ {element}
158
+ </ContextMenu>
159
+ );
160
+ }
@@ -261,6 +261,12 @@ export interface HeaderCellRenderProps {
261
261
  overlay?: ReactNode;
262
262
  /** Content rendered below the header label row (e.g. inline filter controls). */
263
263
  below?: ReactNode;
264
+ /**
265
+ * Right-click context-menu actions for this header cell. Plugins append
266
+ * their actions in `transformHeaderCell`; BaseTable concatenates the arrays
267
+ * across plugins (never overridden) and renders one menu per header cell.
268
+ */
269
+ contextMenuActions?: TableContextActions;
264
270
  /**
265
271
  * Index of this column within the final, ordered list of rendered columns
266
272
  * (after column injection/reordering by other plugins). Populated by
@@ -290,6 +296,13 @@ export interface BodyRowRenderProps {
290
296
  export interface BodyCellRenderProps {
291
297
  htmlProps: TdHTMLAttributes<HTMLTableCellElement>;
292
298
  styles: StyleXStyles[];
299
+ /**
300
+ * Right-click context-menu actions for this body cell. Plugins append their
301
+ * actions in `transformBodyCell`; BaseTable concatenates the arrays across
302
+ * plugins and across the row's cells (never overridden) and renders one menu
303
+ * per row.
304
+ */
305
+ contextMenuActions?: TableContextActions;
293
306
  /**
294
307
  * Index of this cell's column within the final ordered column list.
295
308
  * Mirrors the `columnIndex` passed to `transformHeaderCell`. Populated by
@@ -335,6 +348,50 @@ export interface ScrollWrapperRenderProps {
335
348
  afterTable?: ReactNode;
336
349
  }
337
350
 
351
+ // =============================================================================
352
+ // Context-menu actions
353
+ // =============================================================================
354
+
355
+ /**
356
+ * A single right-click context-menu action contributed by a plugin.
357
+ *
358
+ * Plugins contribute actions via the `contextMenuActions` field on
359
+ * `HeaderCellRenderProps` / `BodyCellRenderProps` (set in
360
+ * `transformHeaderCell` / `transformBodyCell`); the table aggregates actions
361
+ * from every enabled plugin into a single menu per header cell / row.
362
+ */
363
+ export interface TableContextAction {
364
+ /** Stable identifier, unique within a single menu. */
365
+ id: string;
366
+ /** Visible label for the menu item. */
367
+ label: ReactNode;
368
+ /** Optional leading icon. */
369
+ icon?: ReactNode;
370
+ /** Invoked when the item is selected. */
371
+ onSelect: () => void;
372
+ /** When true, the item is rendered but not selectable. */
373
+ disabled?: boolean;
374
+ /**
375
+ * Group key used to cluster related actions and insert a divider between
376
+ * groups (e.g. 'sort', 'selection'). Actions without a group form a trailing
377
+ * group. Group order follows first-seen order across the aggregated list.
378
+ */
379
+ group?: string;
380
+ /** When true, the item renders as checked (e.g. the active sort direction). */
381
+ checked?: boolean;
382
+ }
383
+
384
+ /**
385
+ * Context-menu actions for a cell — either a static array, or a getter that
386
+ * returns the actions lazily. Prefer the getter for actions derived from state
387
+ * (e.g. the active sort direction): it's only invoked when the menu is opened,
388
+ * so the plugin doesn't build an action array (with closures) for every cell on
389
+ * every render.
390
+ */
391
+ export type TableContextActions =
392
+ | TableContextAction[]
393
+ | (() => TableContextAction[]);
394
+
338
395
  // =============================================================================
339
396
  // Plugin Interface
340
397
  // =============================================================================
@@ -353,6 +410,10 @@ export interface ScrollWrapperRenderProps {
353
410
  * 6. `transformBodyCell` — transform each body `<td>` props
354
411
  * 7. `transformScrollWrapper` — transform the scroll-container wrapper around the table
355
412
  * 8. `transformTableContext` — wrap the table output in context providers
413
+ *
414
+ * Plugins may also contribute right-click menu actions by appending to
415
+ * `contextMenuActions` in `transformHeaderCell` / `transformBodyCell`
416
+ * (aggregated into one menu per header cell / row).
356
417
  */
357
418
  export interface TablePlugin<
358
419
  T extends Record<string, unknown> = Record<string, unknown>,
@@ -432,12 +493,25 @@ export interface TableRowComponentProps extends HTMLAttributes<HTMLTableRowEleme
432
493
  export interface TableCellComponentProps extends TdHTMLAttributes<HTMLTableCellElement> {
433
494
  children?: ReactNode;
434
495
  xstyle?: StyleXStyles | StyleXStyles[];
496
+ /**
497
+ * Right-click actions to render as a context menu around the cell content.
498
+ * The cell owns the menu wrapper so it can control how it interacts with
499
+ * padding / content sizing. Empty/undefined renders no menu (native passes
500
+ * through).
501
+ */
502
+ contextMenuActions?: TableContextActions;
435
503
  }
436
504
 
437
505
  /** Props for header cell components used in the components prop */
438
506
  export interface TableHeaderCellComponentProps extends ThHTMLAttributes<HTMLTableCellElement> {
439
507
  children?: ReactNode;
440
508
  xstyle?: StyleXStyles | StyleXStyles[];
509
+ /**
510
+ * Right-click actions to render as a context menu around the header content.
511
+ * The cell owns the menu wrapper so it can control how it interacts with
512
+ * padding / content sizing. Empty/undefined renders no menu.
513
+ */
514
+ contextMenuActions?: TableContextActions;
441
515
  }
442
516
 
443
517
  // =============================================================================
@@ -19,7 +19,7 @@ export const docs = {
19
19
  name: 'onColumnResizeEnd',
20
20
  type: '(updates: Record<string, number>) => void',
21
21
  description:
22
- 'Called when a resize completes (pointerup / Enter). Receives a map of every column key whose width changed merge it into your columnWidths state.',
22
+ 'Called when a resize completes (pointerup / Enter). Receives a map of every column key whose width changed; merge it into your columnWidths state.',
23
23
  },
24
24
  {
25
25
  name: 'minWidth',
@@ -37,7 +37,7 @@ export const docs = {
37
37
  name: 'columns',
38
38
  type: 'TableColumn<T>[]',
39
39
  description:
40
- 'Column definitions needed to derive per-column min widths and detect proportional vs pixel columns for neighbor/last-column resize behavior.',
40
+ 'Column definitions, needed to derive per-column min widths and detect proportional vs pixel columns for neighbor/last-column resize behavior.',
41
41
  },
42
42
  ],
43
43
  };
@@ -91,6 +91,6 @@ export const docsDense = {
91
91
  minWidth: 'Global min column width (px) during resize.',
92
92
  maxWidth: 'Global max column width (px) during resize. Default Infinity.',
93
93
  columns:
94
- 'Column defs derive per-column mins + proportional/pixel detection for neighbor/last-column behavior.',
94
+ 'Column defs: derive per-column mins + proportional/pixel detection for neighbor/last-column behavior.',
95
95
  },
96
96
  };
@@ -6,7 +6,10 @@ export const docs = {
6
6
  name: 'useTablePagination',
7
7
  subComponentOf: 'Table',
8
8
  displayName: 'useTablePagination',
9
- description: 'Headless pagination plugin for Table. Supports client-side slicing, server-side pagination, and cursor-based pagination. Renders Pagination controls automatically above, below, or both.',
9
+ description: 'Headless pagination plugin for Table. Call with a config object: `useTablePagination({ page, onPageChange, totalItems })`. Returns a TablePlugin to pass to `<Table plugins={{ pagination: paginationPlugin }} />`.',
10
+ usage: {
11
+ description: 'Call useTablePagination with a config object containing page state and callback. Pass the returned plugin to Table via the plugins prop.',
12
+ },
10
13
  props: [
11
14
  {
12
15
  name: 'page',
@@ -0,0 +1,63 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../docs-types').ComponentDoc} */
4
+
5
+ export const docs = {
6
+ name: 'useTableRowExpansion',
7
+ subComponentOf: 'Table',
8
+ displayName: 'useTableRowExpansion',
9
+ description:
10
+ 'Hook that returns a TablePlugin implementing expandable rows with inherited columns. Child rows use the same columns as their parents, indented by depth. Clicking the chevron (or right-click context menu) toggles expansion. Pair with useTableRowExpansionState, which flattens the tree and derives this config (expand/collapse handlers + expand-all state) from a single expandedKeys set.',
11
+ props: [
12
+ {
13
+ name: 'expandedKeys',
14
+ type: 'Set<string>',
15
+ description: 'Set of currently-expanded row keys.',
16
+ required: true,
17
+ },
18
+ {
19
+ name: 'onToggle',
20
+ type: '(key: string) => void',
21
+ description: 'Called when a row expansion is toggled.',
22
+ required: true,
23
+ },
24
+ {
25
+ name: 'getRowKey',
26
+ type: '(item: T) => string',
27
+ description: 'Derive a stable unique key from a row item.',
28
+ required: true,
29
+ },
30
+ {
31
+ name: 'getChildren',
32
+ type: '(item: T) => T[]',
33
+ description: 'Return the children of a row (determines expandability).',
34
+ required: true,
35
+ },
36
+ {
37
+ name: 'getDepth',
38
+ type: '(item: T) => number',
39
+ description: 'Return the depth of a row in the hierarchy (0 = top-level). Used for indentation.',
40
+ },
41
+ {
42
+ name: 'getIsItemExpandable',
43
+ type: '(item: T) => boolean',
44
+ description: 'Control which rows are expandable. Defaults to checking getChildren length.',
45
+ },
46
+ {
47
+ name: 'hasRowClickExpansion',
48
+ type: 'boolean',
49
+ description: 'When true, clicking anywhere on the row toggles expansion.',
50
+ default: 'false',
51
+ },
52
+ {
53
+ name: 'isAllExpanded',
54
+ type: "boolean | 'indeterminate'",
55
+ description: 'State of the expand-all toggle in the header. Enables the header toggle button.',
56
+ },
57
+ {
58
+ name: 'onToggleExpandAll',
59
+ type: '(expand: boolean) => void',
60
+ description: 'Callback when the expand-all header toggle is clicked.',
61
+ },
62
+ ],
63
+ };
@@ -6,7 +6,10 @@ export const docs = {
6
6
  name: 'useTableSortable',
7
7
  subComponentOf: 'Table',
8
8
  displayName: 'useTableSortable',
9
- description: 'Headless multi-sort plugin for Table. The consumer owns sort state and provides a callback. Shift+click enables secondary sort columns. Sort indicators render in header cells automatically.',
9
+ description: 'Headless multi-sort plugin for Table. Call with a config object: `useTableSortable({ sort, onSortChange })`. Returns a TablePlugin to pass to `<Table plugins={{ sort: sortPlugin }} />`.',
10
+ usage: {
11
+ description: 'Call useTableSortable with a config object containing sort state and callback. Pass the returned plugin to Table via the plugins prop.',
12
+ },
10
13
  props: [
11
14
  {
12
15
  name: 'sort',
@@ -13,13 +13,13 @@ export const docs = {
13
13
  name: 'startKeys',
14
14
  type: 'string[]',
15
15
  description:
16
- 'Column keys pinned to the start (inline-start / left in LTR) edge the contiguous run from the first column through the last listed key.',
16
+ 'Column keys pinned to the start (inline-start / left in LTR) edge: the contiguous run from the first column through the last listed key.',
17
17
  },
18
18
  {
19
19
  name: 'endKeys',
20
20
  type: 'string[]',
21
21
  description:
22
- 'Column keys pinned to the end (inline-end / right in LTR) edge the contiguous run from the first listed key through the last column.',
22
+ 'Column keys pinned to the end (inline-end / right in LTR) edge: the contiguous run from the first listed key through the last column.',
23
23
  },
24
24
  ],
25
25
  };