@astryxdesign/core 0.1.2 → 0.1.3-canary.6d57c8d

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 (567) 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 +2 -4
  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 +82 -43
  15. package/dist/Calendar/hooks/index.d.ts +0 -2
  16. package/dist/Calendar/hooks/index.d.ts.map +1 -1
  17. package/dist/Calendar/hooks/index.js +1 -2
  18. package/dist/Calendar/index.d.ts +3 -3
  19. package/dist/Calendar/index.d.ts.map +1 -1
  20. package/dist/Calendar/index.js +1 -1
  21. package/dist/Calendar/styles.d.ts +3 -9
  22. package/dist/Calendar/styles.d.ts.map +1 -1
  23. package/dist/Calendar/styles.js +3 -11
  24. package/dist/Carousel/Carousel.d.ts.map +1 -1
  25. package/dist/Carousel/Carousel.js +17 -3
  26. package/dist/Center/Center.d.ts +11 -1
  27. package/dist/Center/Center.d.ts.map +1 -1
  28. package/dist/Center/Center.js +9 -3
  29. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  30. package/dist/Chat/ChatComposerInput.js +0 -1
  31. package/dist/Chat/ChatMessageList.d.ts +14 -1
  32. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  33. package/dist/Chat/ChatMessageList.js +2 -0
  34. package/dist/Chat/useTriggerMenu.d.ts +8 -1
  35. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  36. package/dist/Chat/useTriggerMenu.js +15 -3
  37. package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
  38. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  39. package/dist/CheckboxInput/CheckboxInput.js +51 -9
  40. package/dist/CheckboxList/CheckboxList.d.ts +13 -1
  41. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  42. package/dist/CheckboxList/CheckboxList.js +39 -9
  43. package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
  44. package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
  45. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  46. package/dist/CheckboxList/CheckboxListItem.js +0 -1
  47. package/dist/Citation/Citation.d.ts.map +1 -1
  48. package/dist/Citation/Citation.js +9 -5
  49. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  50. package/dist/CodeBlock/CodeBlock.js +51 -37
  51. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  52. package/dist/CommandPalette/CommandPalette.js +5 -5
  53. package/dist/ContextMenu/ContextMenu.d.ts +4 -5
  54. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  55. package/dist/ContextMenu/ContextMenu.js +93 -11
  56. package/dist/DateInput/DateInput.d.ts +23 -1
  57. package/dist/DateInput/DateInput.d.ts.map +1 -1
  58. package/dist/DateInput/DateInput.js +167 -99
  59. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  60. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  61. package/dist/DateRangeInput/DateRangeInput.js +42 -9
  62. package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
  63. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  64. package/dist/DateTimeInput/DateTimeInput.js +78 -15
  65. package/dist/Dialog/Dialog.d.ts.map +1 -1
  66. package/dist/Dialog/Dialog.js +12 -0
  67. package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
  68. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  69. package/dist/DropdownMenu/DropdownMenu.js +42 -14
  70. package/dist/Field/Field.d.ts +19 -2
  71. package/dist/Field/Field.d.ts.map +1 -1
  72. package/dist/Field/Field.js +4 -0
  73. package/dist/Field/FieldLabel.d.ts +21 -2
  74. package/dist/Field/FieldLabel.d.ts.map +1 -1
  75. package/dist/Field/FieldLabel.js +41 -26
  76. package/dist/FileInput/FileInput.d.ts +22 -1
  77. package/dist/FileInput/FileInput.d.ts.map +1 -1
  78. package/dist/FileInput/FileInput.js +56 -10
  79. package/dist/Grid/Grid.d.ts +11 -1
  80. package/dist/Grid/Grid.d.ts.map +1 -1
  81. package/dist/Grid/Grid.js +32 -6
  82. package/dist/InputGroup/InputGroup.d.ts +4 -3
  83. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  84. package/dist/InputGroup/InputGroup.js +16 -6
  85. package/dist/InputGroup/InputGroupContext.d.ts +4 -0
  86. package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
  87. package/dist/InputGroup/InputGroupContext.js +2 -2
  88. package/dist/InputGroup/groupStyles.d.ts +1 -1
  89. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  90. package/dist/InputGroup/groupStyles.js +3 -3
  91. package/dist/InputGroup/index.d.ts +1 -0
  92. package/dist/InputGroup/index.d.ts.map +1 -1
  93. package/dist/Kbd/Kbd.d.ts.map +1 -1
  94. package/dist/Kbd/Kbd.js +33 -1
  95. package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
  96. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  97. package/dist/Layer/layerAnimations.stylex.js +8 -4
  98. package/dist/Layer/useLayer.d.ts +10 -0
  99. package/dist/Layer/useLayer.d.ts.map +1 -1
  100. package/dist/Layer/useLayer.js +64 -9
  101. package/dist/Layout/Layout.d.ts +4 -11
  102. package/dist/Layout/Layout.d.ts.map +1 -1
  103. package/dist/Layout/Layout.js +10 -11
  104. package/dist/Layout/LayoutFooter.d.ts +2 -2
  105. package/dist/Layout/LayoutFooter.d.ts.map +1 -1
  106. package/dist/Layout/LayoutHeader.d.ts +2 -2
  107. package/dist/Layout/LayoutHeader.d.ts.map +1 -1
  108. package/dist/Layout/LayoutPanel.d.ts +2 -2
  109. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  110. package/dist/Layout/padding.stylex.d.ts +51 -0
  111. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  112. package/dist/Layout/padding.stylex.js +63 -0
  113. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  114. package/dist/Lightbox/Lightbox.js +4 -2
  115. package/dist/Link/Link.d.ts +16 -1
  116. package/dist/Link/Link.d.ts.map +1 -1
  117. package/dist/Link/Link.js +18 -7
  118. package/dist/Markdown/Markdown.d.ts.map +1 -1
  119. package/dist/Markdown/Markdown.js +7 -0
  120. package/dist/MoreMenu/MoreMenu.d.ts +1 -7
  121. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  122. package/dist/MoreMenu/MoreMenu.js +0 -2
  123. package/dist/MultiSelector/MultiSelector.d.ts +27 -2
  124. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  125. package/dist/MultiSelector/MultiSelector.js +141 -42
  126. package/dist/MultiSelector/hooks.d.ts +12 -1
  127. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  128. package/dist/MultiSelector/hooks.js +14 -1
  129. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  130. package/dist/NavMenu/NavHeadingMenu.js +34 -3
  131. package/dist/NumberInput/NumberInput.d.ts +23 -2
  132. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  133. package/dist/NumberInput/NumberInput.js +62 -12
  134. package/dist/Pagination/Pagination.d.ts +1 -1
  135. package/dist/Pagination/Pagination.d.ts.map +1 -1
  136. package/dist/Pagination/Pagination.js +15 -1
  137. package/dist/Popover/Popover.d.ts +18 -2
  138. package/dist/Popover/Popover.d.ts.map +1 -1
  139. package/dist/Popover/Popover.js +5 -2
  140. package/dist/Popover/usePopover.d.ts +38 -3
  141. package/dist/Popover/usePopover.d.ts.map +1 -1
  142. package/dist/Popover/usePopover.js +24 -9
  143. package/dist/PowerSearch/PowerSearch.d.ts +11 -1
  144. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  145. package/dist/PowerSearch/PowerSearch.js +6 -1
  146. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  147. package/dist/ProgressBar/ProgressBar.js +3 -5
  148. package/dist/RadioList/RadioList.d.ts +20 -2
  149. package/dist/RadioList/RadioList.d.ts.map +1 -1
  150. package/dist/RadioList/RadioList.js +105 -9
  151. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  152. package/dist/RadioList/RadioListItem.js +13 -2
  153. package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
  154. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  155. package/dist/SegmentedControl/SegmentedControl.js +78 -44
  156. package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
  157. package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
  158. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  159. package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
  160. package/dist/Selector/Selector.d.ts +24 -1
  161. package/dist/Selector/Selector.d.ts.map +1 -1
  162. package/dist/Selector/Selector.js +122 -43
  163. package/dist/Selector/hooks.d.ts +8 -1
  164. package/dist/Selector/hooks.d.ts.map +1 -1
  165. package/dist/Selector/hooks.js +14 -1
  166. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  167. package/dist/SideNav/SideNavHeading.js +2 -0
  168. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  169. package/dist/SideNav/SideNavItem.js +1 -1
  170. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  171. package/dist/Skeleton/Skeleton.js +8 -2
  172. package/dist/Slider/Slider.d.ts +21 -0
  173. package/dist/Slider/Slider.d.ts.map +1 -1
  174. package/dist/Slider/Slider.js +36 -9
  175. package/dist/Spinner/Spinner.d.ts.map +1 -1
  176. package/dist/Spinner/Spinner.js +1 -1
  177. package/dist/Stack/Stack.d.ts +38 -23
  178. package/dist/Stack/Stack.d.ts.map +1 -1
  179. package/dist/Stack/Stack.js +25 -1
  180. package/dist/Stack/StackItem.d.ts +12 -23
  181. package/dist/Stack/StackItem.d.ts.map +1 -1
  182. package/dist/Stack/StackItem.js +8 -1
  183. package/dist/Switch/Switch.d.ts +23 -2
  184. package/dist/Switch/Switch.d.ts.map +1 -1
  185. package/dist/Switch/Switch.js +41 -11
  186. package/dist/TabList/Tab.d.ts.map +1 -1
  187. package/dist/TabList/Tab.js +6 -0
  188. package/dist/TabList/TabList.d.ts +16 -4
  189. package/dist/TabList/TabList.d.ts.map +1 -1
  190. package/dist/TabList/TabList.js +87 -10
  191. package/dist/TabList/TabListContext.d.ts +5 -0
  192. package/dist/TabList/TabListContext.d.ts.map +1 -1
  193. package/dist/TabList/TabListContext.js +5 -0
  194. package/dist/TabList/TabMenu.d.ts.map +1 -1
  195. package/dist/TabList/TabMenu.js +6 -1
  196. package/dist/Table/BaseTable.d.ts.map +1 -1
  197. package/dist/Table/BaseTable.js +11 -8
  198. package/dist/Table/Table.d.ts.map +1 -1
  199. package/dist/Table/Table.js +10 -1
  200. package/dist/Table/TableCell.d.ts +8 -1
  201. package/dist/Table/TableCell.d.ts.map +1 -1
  202. package/dist/Table/TableCell.js +10 -10
  203. package/dist/Table/TableHeaderCell.d.ts +8 -1
  204. package/dist/Table/TableHeaderCell.d.ts.map +1 -1
  205. package/dist/Table/TableHeaderCell.js +16 -16
  206. package/dist/Table/index.d.ts +2 -1
  207. package/dist/Table/index.d.ts.map +1 -1
  208. package/dist/Table/index.js +2 -2
  209. package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
  210. package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
  211. package/dist/Table/plugins/pagination/paginateData.js +8 -3
  212. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  213. package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
  214. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  215. package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
  216. package/dist/Table/tableContextMenu.d.ts +33 -0
  217. package/dist/Table/tableContextMenu.d.ts.map +1 -0
  218. package/dist/Table/tableContextMenu.js +133 -0
  219. package/dist/Table/types.d.ts +66 -0
  220. package/dist/Table/types.d.ts.map +1 -1
  221. package/dist/TextArea/TextArea.d.ts +22 -1
  222. package/dist/TextArea/TextArea.d.ts.map +1 -1
  223. package/dist/TextArea/TextArea.js +41 -9
  224. package/dist/TextInput/TextInput.d.ts +23 -2
  225. package/dist/TextInput/TextInput.d.ts.map +1 -1
  226. package/dist/TextInput/TextInput.js +55 -10
  227. package/dist/TimeInput/TimeInput.d.ts +23 -1
  228. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  229. package/dist/TimeInput/TimeInput.js +147 -76
  230. package/dist/Toast/Toast.d.ts.map +1 -1
  231. package/dist/Toast/Toast.js +14 -0
  232. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  233. package/dist/Toast/ToastViewport.js +131 -3
  234. package/dist/Tokenizer/Tokenizer.d.ts +12 -1
  235. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  236. package/dist/Tokenizer/Tokenizer.js +26 -4
  237. package/dist/Toolbar/Toolbar.d.ts +3 -3
  238. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  239. package/dist/Toolbar/Toolbar.js +51 -7
  240. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  241. package/dist/Tooltip/useTooltip.js +56 -9
  242. package/dist/TopNav/TopNavHeading.d.ts +7 -1
  243. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  244. package/dist/TopNav/TopNavHeading.js +8 -0
  245. package/dist/TreeList/TreeList.d.ts +1 -1
  246. package/dist/TreeList/TreeList.d.ts.map +1 -1
  247. package/dist/TreeList/TreeList.js +72 -2
  248. package/dist/TreeList/TreeListItem.d.ts +11 -1
  249. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  250. package/dist/TreeList/TreeListItem.js +51 -12
  251. package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
  252. package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
  253. package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
  254. package/dist/Typeahead/BaseTypeahead.d.ts +13 -0
  255. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  256. package/dist/Typeahead/BaseTypeahead.js +69 -6
  257. package/dist/Typeahead/Typeahead.d.ts +26 -3
  258. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  259. package/dist/Typeahead/Typeahead.js +65 -29
  260. package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
  261. package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
  262. package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
  263. package/dist/VisuallyHidden/index.d.ts +11 -0
  264. package/dist/VisuallyHidden/index.d.ts.map +1 -0
  265. package/dist/VisuallyHidden/index.js +13 -0
  266. package/dist/astryx.css +18 -0
  267. package/dist/astryx.umd.js +55 -55
  268. package/dist/astryx.umd.js.map +4 -4
  269. package/dist/hooks/focusableSelector.d.ts +22 -0
  270. package/dist/hooks/focusableSelector.d.ts.map +1 -0
  271. package/dist/hooks/focusableSelector.js +24 -0
  272. package/dist/hooks/index.d.ts +12 -2
  273. package/dist/hooks/index.d.ts.map +1 -1
  274. package/dist/hooks/index.js +7 -2
  275. package/dist/hooks/useAnnounce.d.ts +40 -0
  276. package/dist/hooks/useAnnounce.d.ts.map +1 -0
  277. package/dist/hooks/useAnnounce.js +142 -0
  278. package/dist/hooks/useClickableContainer.d.ts +16 -1
  279. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  280. package/dist/hooks/useClickableContainer.js +16 -4
  281. package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
  282. package/dist/hooks/useEntryAnimation.js +4 -4
  283. package/dist/hooks/useFocusTrap.d.ts +18 -0
  284. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  285. package/dist/hooks/useFocusTrap.js +87 -3
  286. package/dist/hooks/useGridFocus.d.ts +88 -1
  287. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  288. package/dist/hooks/useGridFocus.js +261 -62
  289. package/dist/hooks/useKeyboardHint.d.ts +82 -0
  290. package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
  291. package/dist/hooks/useKeyboardHint.js +220 -0
  292. package/dist/hooks/useListFocus.d.ts +78 -7
  293. package/dist/hooks/useListFocus.d.ts.map +1 -1
  294. package/dist/hooks/useListFocus.js +305 -52
  295. package/dist/hooks/useLongPress.d.ts +21 -0
  296. package/dist/hooks/useLongPress.d.ts.map +1 -0
  297. package/dist/hooks/useLongPress.js +89 -0
  298. package/dist/hooks/useTreeFocus.d.ts +157 -0
  299. package/dist/hooks/useTreeFocus.d.ts.map +1 -0
  300. package/dist/hooks/useTreeFocus.js +337 -0
  301. package/dist/hooks/useTypeahead.d.ts +63 -0
  302. package/dist/hooks/useTypeahead.d.ts.map +1 -0
  303. package/dist/hooks/useTypeahead.js +117 -0
  304. package/dist/index.d.ts +1 -0
  305. package/dist/index.d.ts.map +1 -1
  306. package/dist/index.js +1 -0
  307. package/dist/utils/dateTypes.d.ts +12 -0
  308. package/dist/utils/dateTypes.d.ts.map +1 -1
  309. package/dist/utils/dateTypes.js +41 -1
  310. package/dist/utils/index.d.ts +4 -0
  311. package/dist/utils/index.d.ts.map +1 -1
  312. package/dist/utils/index.js +3 -1
  313. package/dist/utils/inputAria.d.ts +29 -0
  314. package/dist/utils/inputAria.d.ts.map +1 -0
  315. package/dist/utils/inputAria.js +30 -0
  316. package/dist/utils/timeParser.d.ts.map +1 -1
  317. package/dist/utils/timeParser.js +5 -2
  318. package/docs.mjs +2 -2
  319. package/package.json +12 -8
  320. package/src/Avatar/Avatar.test.tsx +37 -0
  321. package/src/Avatar/Avatar.tsx +10 -5
  322. package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
  323. package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
  324. package/src/Button/Button.tsx +3 -16
  325. package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
  326. package/src/ButtonGroup/ButtonGroup.tsx +0 -1
  327. package/src/Calendar/Calendar.doc.mjs +4 -4
  328. package/src/Calendar/Calendar.test.tsx +168 -30
  329. package/src/Calendar/Calendar.tsx +121 -66
  330. package/src/Calendar/hooks/index.ts +0 -6
  331. package/src/Calendar/index.ts +1 -3
  332. package/src/Calendar/styles.ts +4 -9
  333. package/src/Carousel/Carousel.doc.mjs +7 -1
  334. package/src/Carousel/Carousel.test.tsx +20 -0
  335. package/src/Carousel/Carousel.tsx +16 -1
  336. package/src/Center/Center.doc.mjs +12 -2
  337. package/src/Center/Center.tsx +28 -3
  338. package/src/Chat/ChatComposerInput.test.tsx +26 -7
  339. package/src/Chat/ChatComposerInput.tsx +0 -1
  340. package/src/Chat/ChatDictationButton.doc.mjs +1 -1
  341. package/src/Chat/ChatMessageList.doc.mjs +8 -0
  342. package/src/Chat/ChatMessageList.test.tsx +18 -0
  343. package/src/Chat/ChatMessageList.tsx +16 -0
  344. package/src/Chat/useTriggerMenu.tsx +22 -4
  345. package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -0
  346. package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
  347. package/src/CheckboxInput/CheckboxInput.tsx +78 -6
  348. package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
  349. package/src/CheckboxList/CheckboxList.test.tsx +192 -26
  350. package/src/CheckboxList/CheckboxList.tsx +56 -3
  351. package/src/CheckboxList/CheckboxListContext.tsx +7 -0
  352. package/src/CheckboxList/CheckboxListItem.tsx +0 -3
  353. package/src/Citation/Citation.doc.mjs +10 -0
  354. package/src/Citation/Citation.test.tsx +121 -0
  355. package/src/Citation/Citation.tsx +15 -3
  356. package/src/CodeBlock/CodeBlock.test.tsx +115 -0
  357. package/src/CodeBlock/CodeBlock.tsx +63 -33
  358. package/src/CommandPalette/CommandPalette.test.tsx +47 -1
  359. package/src/CommandPalette/CommandPalette.tsx +9 -21
  360. package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
  361. package/src/ContextMenu/ContextMenu.test.tsx +155 -1
  362. package/src/ContextMenu/ContextMenu.tsx +113 -16
  363. package/src/DateInput/DateInput.doc.mjs +286 -56
  364. package/src/DateInput/DateInput.test.tsx +248 -2
  365. package/src/DateInput/DateInput.tsx +196 -100
  366. package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
  367. package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
  368. package/src/DateRangeInput/DateRangeInput.tsx +63 -5
  369. package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
  370. package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
  371. package/src/DateTimeInput/DateTimeInput.tsx +125 -17
  372. package/src/Dialog/Dialog.doc.mjs +2 -2
  373. package/src/Dialog/Dialog.tsx +12 -0
  374. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
  375. package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
  376. package/src/DropdownMenu/DropdownMenu.tsx +52 -18
  377. package/src/Field/Field.doc.mjs +59 -18
  378. package/src/Field/Field.test.tsx +32 -0
  379. package/src/Field/Field.tsx +23 -5
  380. package/src/Field/FieldLabel.tsx +55 -17
  381. package/src/FileInput/FileInput.doc.mjs +17 -0
  382. package/src/FileInput/FileInput.test.tsx +283 -49
  383. package/src/FileInput/FileInput.tsx +76 -4
  384. package/src/Grid/Grid.doc.mjs +17 -4
  385. package/src/Grid/Grid.test.tsx +43 -30
  386. package/src/Grid/Grid.tsx +38 -3
  387. package/src/Icon/Icon.doc.mjs +3 -3
  388. package/src/InputGroup/InputGroup.doc.mjs +111 -23
  389. package/src/InputGroup/InputGroup.test.tsx +257 -60
  390. package/src/InputGroup/InputGroup.tsx +23 -5
  391. package/src/InputGroup/InputGroupContext.ts +9 -4
  392. package/src/InputGroup/groupStyles.ts +7 -1
  393. package/src/InputGroup/index.ts +1 -0
  394. package/src/Kbd/Kbd.test.tsx +22 -4
  395. package/src/Kbd/Kbd.tsx +35 -3
  396. package/src/Layer/layerAnimations.stylex.ts +20 -4
  397. package/src/Layer/useLayer.doc.mjs +5 -0
  398. package/src/Layer/useLayer.test.tsx +111 -0
  399. package/src/Layer/useLayer.tsx +90 -9
  400. package/src/Layout/Layout.tsx +8 -16
  401. package/src/Layout/LayoutFooter.doc.mjs +4 -4
  402. package/src/Layout/LayoutFooter.tsx +3 -3
  403. package/src/Layout/LayoutHeader.doc.mjs +4 -4
  404. package/src/Layout/LayoutHeader.tsx +3 -3
  405. package/src/Layout/LayoutPanel.tsx +3 -3
  406. package/src/Layout/padding.stylex.ts +52 -0
  407. package/src/Lightbox/Lightbox.doc.mjs +9 -0
  408. package/src/Lightbox/Lightbox.test.tsx +53 -5
  409. package/src/Lightbox/Lightbox.tsx +9 -4
  410. package/src/Link/Link.doc.mjs +14 -0
  411. package/src/Link/Link.test.tsx +50 -0
  412. package/src/Link/Link.tsx +39 -4
  413. package/src/Markdown/Markdown.test.tsx +11 -0
  414. package/src/Markdown/Markdown.tsx +7 -0
  415. package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
  416. package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
  417. package/src/MoreMenu/MoreMenu.tsx +0 -9
  418. package/src/MultiSelector/MultiSelector.doc.mjs +30 -0
  419. package/src/MultiSelector/MultiSelector.test.tsx +375 -8
  420. package/src/MultiSelector/MultiSelector.tsx +194 -48
  421. package/src/MultiSelector/hooks.ts +27 -0
  422. package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
  423. package/src/NavMenu/NavHeadingMenu.tsx +50 -3
  424. package/src/NumberInput/NumberInput.doc.mjs +17 -0
  425. package/src/NumberInput/NumberInput.test.tsx +242 -40
  426. package/src/NumberInput/NumberInput.tsx +89 -11
  427. package/src/Pagination/Pagination.doc.mjs +3 -3
  428. package/src/Pagination/Pagination.test.tsx +117 -5
  429. package/src/Pagination/Pagination.tsx +21 -1
  430. package/src/Popover/Popover.doc.mjs +26 -0
  431. package/src/Popover/Popover.test.tsx +121 -0
  432. package/src/Popover/Popover.tsx +23 -2
  433. package/src/Popover/usePopover.doc.mjs +9 -3
  434. package/src/Popover/usePopover.tsx +70 -12
  435. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  436. package/src/PowerSearch/PowerSearch.test.tsx +97 -1
  437. package/src/PowerSearch/PowerSearch.tsx +16 -3
  438. package/src/ProgressBar/ProgressBar.test.tsx +34 -26
  439. package/src/ProgressBar/ProgressBar.tsx +3 -4
  440. package/src/RadioList/RadioList.doc.mjs +9 -0
  441. package/src/RadioList/RadioList.test.tsx +252 -16
  442. package/src/RadioList/RadioList.tsx +166 -10
  443. package/src/RadioList/RadioListItem.tsx +14 -2
  444. package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
  445. package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
  446. package/src/SegmentedControl/SegmentedControl.tsx +102 -54
  447. package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
  448. package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
  449. package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
  450. package/src/Selector/Selector.doc.mjs +26 -0
  451. package/src/Selector/Selector.test.tsx +387 -15
  452. package/src/Selector/Selector.tsx +175 -67
  453. package/src/Selector/hooks.ts +23 -0
  454. package/src/SideNav/SideNav.test.tsx +48 -0
  455. package/src/SideNav/SideNavHeading.tsx +8 -2
  456. package/src/SideNav/SideNavItem.tsx +2 -4
  457. package/src/Skeleton/Skeleton.test.tsx +25 -0
  458. package/src/Skeleton/Skeleton.tsx +11 -1
  459. package/src/Slider/Slider.doc.mjs +15 -0
  460. package/src/Slider/Slider.test.tsx +155 -2
  461. package/src/Slider/Slider.tsx +53 -5
  462. package/src/Spinner/Spinner.tsx +7 -1
  463. package/src/Stack/Stack.doc.mjs +77 -0
  464. package/src/Stack/Stack.test.tsx +55 -5
  465. package/src/Stack/Stack.tsx +73 -24
  466. package/src/Stack/StackItem.test.tsx +23 -0
  467. package/src/Stack/StackItem.tsx +20 -23
  468. package/src/Switch/Switch.doc.mjs +15 -0
  469. package/src/Switch/Switch.test.tsx +162 -27
  470. package/src/Switch/Switch.tsx +61 -21
  471. package/src/TabList/Tab.tsx +6 -0
  472. package/src/TabList/TabList.doc.mjs +6 -0
  473. package/src/TabList/TabList.test.tsx +251 -0
  474. package/src/TabList/TabList.tsx +103 -12
  475. package/src/TabList/TabListContext.ts +7 -3
  476. package/src/TabList/TabMenu.tsx +6 -3
  477. package/src/Table/BaseTable.tsx +21 -17
  478. package/src/Table/Table.doc.mjs +2 -0
  479. package/src/Table/Table.test.tsx +10 -0
  480. package/src/Table/Table.tsx +8 -0
  481. package/src/Table/TableCell.tsx +25 -23
  482. package/src/Table/TableHeaderCell.tsx +28 -29
  483. package/src/Table/index.ts +3 -2
  484. package/src/Table/plugins/pagination/paginateData.ts +10 -3
  485. package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
  486. package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
  487. package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
  488. package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
  489. package/src/Table/tableContextMenu.test.tsx +157 -0
  490. package/src/Table/tableContextMenu.tsx +142 -0
  491. package/src/Table/types.ts +74 -0
  492. package/src/Table/useTableColumnResize.doc.mjs +3 -3
  493. package/src/Table/useTableStickyColumns.doc.mjs +2 -2
  494. package/src/Text/Text.doc.mjs +18 -18
  495. package/src/TextArea/TextArea.doc.mjs +17 -0
  496. package/src/TextArea/TextArea.test.tsx +167 -35
  497. package/src/TextArea/TextArea.tsx +62 -15
  498. package/src/TextInput/TextInput.doc.mjs +17 -0
  499. package/src/TextInput/TextInput.test.tsx +168 -34
  500. package/src/TextInput/TextInput.tsx +77 -9
  501. package/src/Thumbnail/Thumbnail.doc.mjs +4 -4
  502. package/src/TimeInput/TimeInput.doc.mjs +340 -60
  503. package/src/TimeInput/TimeInput.test.tsx +255 -7
  504. package/src/TimeInput/TimeInput.tsx +176 -70
  505. package/src/Timestamp/Timestamp.doc.mjs +19 -19
  506. package/src/Toast/Toast.tsx +14 -0
  507. package/src/Toast/ToastViewport.test.tsx +214 -0
  508. package/src/Toast/ToastViewport.tsx +167 -21
  509. package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
  510. package/src/Tokenizer/Tokenizer.test.tsx +105 -1
  511. package/src/Tokenizer/Tokenizer.tsx +37 -1
  512. package/src/Toolbar/Toolbar.test.tsx +109 -6
  513. package/src/Toolbar/Toolbar.tsx +59 -5
  514. package/src/Tooltip/Tooltip.test.tsx +68 -0
  515. package/src/Tooltip/useTooltip.tsx +55 -8
  516. package/src/TopNav/TopNav.test.tsx +50 -0
  517. package/src/TopNav/TopNavHeading.tsx +17 -1
  518. package/src/TreeList/TreeList.test.tsx +295 -6
  519. package/src/TreeList/TreeList.tsx +73 -1
  520. package/src/TreeList/TreeListItem.tsx +51 -5
  521. package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
  522. package/src/Typeahead/BaseTypeahead.tsx +93 -9
  523. package/src/Typeahead/Typeahead.doc.mjs +141 -30
  524. package/src/Typeahead/Typeahead.test.tsx +331 -1
  525. package/src/Typeahead/Typeahead.tsx +105 -33
  526. package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
  527. package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
  528. package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
  529. package/src/VisuallyHidden/index.ts +15 -0
  530. package/src/docs-script.test.mjs +50 -0
  531. package/src/hooks/focusableSelector.ts +25 -0
  532. package/src/hooks/index.ts +28 -2
  533. package/src/hooks/useAnnounce.test.tsx +101 -0
  534. package/src/hooks/useAnnounce.ts +168 -0
  535. package/src/hooks/useClickableContainer.ts +16 -4
  536. package/src/hooks/useEntryAnimation.ts +16 -4
  537. package/src/hooks/useFocusTrap.test.tsx +132 -0
  538. package/src/hooks/useFocusTrap.ts +98 -4
  539. package/src/hooks/useGridFocus.doc.mjs +40 -2
  540. package/src/hooks/useGridFocus.test.tsx +132 -0
  541. package/src/hooks/useGridFocus.ts +343 -67
  542. package/src/hooks/useKeyboardHint.doc.mjs +101 -0
  543. package/src/hooks/useKeyboardHint.test.tsx +70 -0
  544. package/src/hooks/useKeyboardHint.tsx +332 -0
  545. package/src/hooks/useListFocus.doc.mjs +50 -10
  546. package/src/hooks/useListFocus.test.tsx +375 -0
  547. package/src/hooks/useListFocus.ts +395 -57
  548. package/src/hooks/useLongPress.test.tsx +134 -0
  549. package/src/hooks/useLongPress.ts +119 -0
  550. package/src/hooks/useTreeFocus.doc.mjs +140 -0
  551. package/src/hooks/useTreeFocus.test.tsx +214 -0
  552. package/src/hooks/useTreeFocus.ts +559 -0
  553. package/src/hooks/useTypeahead.test.tsx +109 -0
  554. package/src/hooks/useTypeahead.ts +183 -0
  555. package/src/index.ts +1 -0
  556. package/src/theme/derivedVarRegistry.test.ts +10 -5
  557. package/src/utils/dateTypes.test.ts +40 -0
  558. package/src/utils/dateTypes.ts +40 -0
  559. package/src/utils/index.ts +9 -0
  560. package/src/utils/inputAria.test.ts +39 -0
  561. package/src/utils/inputAria.ts +58 -0
  562. package/src/utils/timeParser.test.ts +10 -0
  563. package/src/utils/timeParser.ts +5 -2
  564. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
  565. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
  566. package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
  567. package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
@@ -0,0 +1,157 @@
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(
103
+ <Table data={data} columns={columns} idKey="id" plugins={{a, b}} />,
104
+ );
105
+ fireEvent.contextMenu(screen.getByText('Name'));
106
+ expect(
107
+ screen.getAllByRole('menuitem', {name: 'Action A', hidden: true}).length,
108
+ ).toBeGreaterThan(0);
109
+ expect(
110
+ screen.getAllByRole('menuitem', {name: 'Action B', hidden: true}).length,
111
+ ).toBeGreaterThan(0);
112
+ });
113
+
114
+ it('does not render a menu when no plugin contributes actions', () => {
115
+ render(<Table data={data} columns={columns} idKey="id" />);
116
+ fireEvent.contextMenu(screen.getByText('Name'));
117
+ expect(
118
+ screen.queryByRole('menuitem', {hidden: true}),
119
+ ).not.toBeInTheDocument();
120
+ });
121
+ });
122
+
123
+ // =============================================================================
124
+ // Body / row context menu
125
+ // =============================================================================
126
+
127
+ describe('Table body context menu', () => {
128
+ it('renders row actions from a plugin that sets contextMenuActions in transformBodyCell', () => {
129
+ const onSelect = vi.fn();
130
+ const plugin: TablePlugin<Row> = {
131
+ transformBodyCell: (props, _column, item) => ({
132
+ ...props,
133
+ contextMenuActions: [
134
+ {
135
+ id: `delete-${item.id}`,
136
+ label: 'Delete row',
137
+ onSelect: () => {
138
+ onSelect(item.id);
139
+ },
140
+ },
141
+ ],
142
+ }),
143
+ };
144
+ render(
145
+ <Table data={data} columns={columns} idKey="id" plugins={{plugin}} />,
146
+ );
147
+ // Right-click the first body cell (Alice).
148
+ fireEvent.contextMenu(screen.getByText('Alice'));
149
+ const items = screen.getAllByRole('menuitem', {
150
+ name: 'Delete row',
151
+ hidden: true,
152
+ });
153
+ expect(items.length).toBeGreaterThan(0);
154
+ fireEvent.click(items[0]);
155
+ expect(onSelect).toHaveBeenCalledWith('1');
156
+ });
157
+ });
@@ -0,0 +1,142 @@
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 {TableContextAction, TableContextActions} from './types';
20
+
21
+ /**
22
+ * Resolve a `contextMenuActions` value (array or getter) to a plain array.
23
+ * Use this when composing actions from a prior plugin's render props so you
24
+ * don't have to branch on the array-vs-getter form:
25
+ *
26
+ * ```
27
+ * contextMenuActions: () => [
28
+ * ...resolveContextActions(props.contextMenuActions),
29
+ * ...myActions,
30
+ * ]
31
+ * ```
32
+ */
33
+ export function resolveContextActions(
34
+ actions: TableContextActions | undefined,
35
+ ): TableContextAction[] {
36
+ if (typeof actions === 'function') {
37
+ return actions();
38
+ }
39
+ return actions ?? [];
40
+ }
41
+
42
+ /**
43
+ * Convert the flat action list into ContextMenu options, inserting a divider
44
+ * between groups (first-seen group order). Ungrouped actions form a trailing
45
+ * group. A `checked` action shows a trailing check icon.
46
+ */
47
+ function toContextMenuOptions(
48
+ actions: TableContextAction[],
49
+ ): ContextMenuOption[] {
50
+ const order: string[] = [];
51
+ const buckets = new Map<string, TableContextAction[]>();
52
+ for (const action of actions) {
53
+ const key = action.group ?? '__ungrouped__';
54
+ let bucket = buckets.get(key);
55
+ if (!bucket) {
56
+ bucket = [];
57
+ buckets.set(key, bucket);
58
+ order.push(key);
59
+ }
60
+ bucket.push(action);
61
+ }
62
+
63
+ const options: ContextMenuOption[] = [];
64
+ order.forEach((key, groupIndex) => {
65
+ if (groupIndex > 0) {
66
+ options.push({type: 'divider'});
67
+ }
68
+ for (const action of buckets.get(key) ?? []) {
69
+ options.push({
70
+ label: typeof action.label === 'string' ? action.label : action.id,
71
+ // A checked action (e.g. the active sort direction) shows a checkmark;
72
+ // otherwise the action's own icon. ContextMenu's data form takes a
73
+ // single leading icon, so checked state replaces the icon.
74
+ icon: action.checked ? (
75
+ <Icon icon="check" size="xsm" aria-hidden />
76
+ ) : (
77
+ action.icon
78
+ ),
79
+ isDisabled: action.disabled,
80
+ onClick: action.onSelect,
81
+ });
82
+ }
83
+ });
84
+ return options;
85
+ }
86
+
87
+ /**
88
+ * Wrap a table element (a header cell's content or a row) in a right-click
89
+ * context menu rendering the aggregated `actions`. When no plugin contributes
90
+ * actions the element is returned untouched so the native browser menu passes
91
+ * through.
92
+ */
93
+ /**
94
+ * A context menu whose actions are resolved lazily — only when the user opens
95
+ * the menu (right-click). Deferring the work means plugins that pass a getter
96
+ * don't build an action array (with its closures) for every cell on every
97
+ * render; it's computed on demand and memoized until the menu closes.
98
+ */
99
+ function LazyTableContextMenu({
100
+ element,
101
+ getActions,
102
+ }: {
103
+ element: ReactNode;
104
+ getActions: () => TableContextAction[];
105
+ }): ReactNode {
106
+ const [options, setOptions] = useState<ContextMenuOption[] | null>(null);
107
+ return (
108
+ <ContextMenu
109
+ items={options ?? []}
110
+ onOpenChange={open => {
111
+ // Resolve actions when opening; clear on close so state derived later
112
+ // (e.g. current sort direction) is always fresh next open.
113
+ setOptions(open ? toContextMenuOptions(getActions()) : null);
114
+ }}>
115
+ {element}
116
+ </ContextMenu>
117
+ );
118
+ }
119
+
120
+ /**
121
+ * Wrap a table element (a header cell's content or a body cell) in a right-click
122
+ * context menu rendering the aggregated `actions`. Accepts a static array or a
123
+ * getter (resolved lazily on open). When there are no actions the element is
124
+ * returned untouched so the native browser menu passes through.
125
+ */
126
+ export function wrapInTableContextMenu(
127
+ element: ReactNode,
128
+ actions: TableContextActions | undefined,
129
+ ): ReactNode {
130
+ // Getter form → resolve lazily on open.
131
+ if (typeof actions === 'function') {
132
+ return <LazyTableContextMenu element={element} getActions={actions} />;
133
+ }
134
+ if (!actions || actions.length === 0) {
135
+ return element;
136
+ }
137
+ // item (it looked like "ascending" was always selected). Focus moves only
138
+ // when the user arrow-keys into the menu.
139
+ return (
140
+ <ContextMenu items={toContextMenuOptions(actions)}>{element}</ContextMenu>
141
+ );
142
+ }
@@ -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
  };
@@ -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
  };
@@ -124,15 +124,15 @@ export const docs = {
124
124
  description:
125
125
  'Text renders styled body text and headings from the theme. Use Text with a semantic type for body copy, labels, and captions, and Heading for section titles that output the correct h1\u2013h6 element.',
126
126
  bestPractices: [
127
- { guidance: true, description: 'Pick a semantic type (body, label, supporting, large, code) instead of manually setting size and weight \u2014 the theme handles the details.' },
127
+ { guidance: true, description: 'Pick a semantic type (body, label, supporting, large, code) instead of manually setting size and weight; the theme handles the details.' },
128
128
  { guidance: true, description: 'Set accessibilityLevel on Heading when the visual level differs from the document outline so screen readers announce the correct hierarchy.' },
129
- { guidance: true, description: 'Use maxLines with a number to truncate long content \u2014 a tooltip appears automatically on hover so no text is lost.' },
129
+ { guidance: true, description: 'Use maxLines with a number to truncate long content; a tooltip appears automatically on hover so no text is lost.' },
130
130
  { guidance: true, description: 'Enable hasTabularNumbers for columns of numeric data so digits align vertically across rows.' },
131
- { guidance: false, description: 'Override size and weight when a semantic type already matches \u2014 extra overrides fight the theme and break when themes change.' },
132
- { guidance: false, description: 'Skip heading levels in the document outline \u2014 go h1 then h2 then h3, never h1 then h3.' },
133
- { guidance: false, description: 'Use raw HTML tags like <p>, <h1>\u2013<h6>, or <span> for text \u2014 Text and Heading apply the correct theme tokens automatically.' },
134
- { guidance: false, description: 'Pass a `variant` prop \u2014 Text does not have a `variant` prop. Use `type` for semantic styling (body, label, large, supporting, code) or use Heading for headings.' },
135
- { guidance: false, description: 'Use Text for headings \u2014 use Heading with a `level` prop (1\u20136) for section titles and headings.' },
131
+ { guidance: false, description: 'Override size and weight when a semantic type already matches; extra overrides fight the theme and break when themes change.' },
132
+ { guidance: false, description: 'Skip heading levels in the document outline; go h1 then h2 then h3, never h1 then h3.' },
133
+ { guidance: false, description: 'Use raw HTML tags like <p>, <h1>\u2013<h6>, or <span> for text; Text and Heading apply the correct theme tokens automatically.' },
134
+ { guidance: false, description: 'Pass a `variant` prop; Text does not have a `variant` prop. Use `type` for semantic styling (body, label, large, supporting, code) or use Heading for headings.' },
135
+ { guidance: false, description: 'Use Text for headings; use Heading with a `level` prop (1\u20136) for section titles and headings.' },
136
136
  ],
137
137
  },
138
138
  };
@@ -143,15 +143,15 @@ export const docsZh = {
143
143
  description:
144
144
  'Text renders styled body text and headings from the theme. Use Text with a semantic type for body copy, labels, and captions, and Heading for section titles that output the correct h1\u2013h6 element.',
145
145
  bestPractices: [
146
- { guidance: true, description: 'Pick a semantic type (body, label, supporting, large, code) instead of manually setting size and weight \u2014 the theme handles the details.' },
146
+ { guidance: true, description: 'Pick a semantic type (body, label, supporting, large, code) instead of manually setting size and weight; the theme handles the details.' },
147
147
  { guidance: true, description: 'Set accessibilityLevel on Heading when the visual level differs from the document outline so screen readers announce the correct hierarchy.' },
148
- { guidance: true, description: 'Use maxLines with a number to truncate long content \u2014 a tooltip appears automatically on hover so no text is lost.' },
148
+ { guidance: true, description: 'Use maxLines with a number to truncate long content; a tooltip appears automatically on hover so no text is lost.' },
149
149
  { guidance: true, description: 'Enable hasTabularNumbers for columns of numeric data so digits align vertically across rows.' },
150
- { guidance: false, description: 'Override size and weight when a semantic type already matches \u2014 extra overrides fight the theme and break when themes change.' },
151
- { guidance: false, description: 'Skip heading levels in the document outline \u2014 go h1 then h2 then h3, never h1 then h3.' },
152
- { guidance: false, description: 'Use raw HTML tags like <p>, <h1>\u2013<h6>, or <span> for text \u2014 Text and Heading apply the correct theme tokens automatically.' },
153
- { guidance: false, description: 'Pass a `variant` prop \u2014 Text does not have a `variant` prop. Use `type` for semantic styling (body, label, large, supporting, code) or use Heading for headings.' },
154
- { guidance: false, description: 'Use Text for headings \u2014 use Heading with a `level` prop (1\u20136) for section titles and headings.' },
150
+ { guidance: false, description: 'Override size and weight when a semantic type already matches; extra overrides fight the theme and break when themes change.' },
151
+ { guidance: false, description: 'Skip heading levels in the document outline; go h1 then h2 then h3, never h1 then h3.' },
152
+ { guidance: false, description: 'Use raw HTML tags like <p>, <h1>\u2013<h6>, or <span> for text; Text and Heading apply the correct theme tokens automatically.' },
153
+ { guidance: false, description: 'Pass a `variant` prop; Text does not have a `variant` prop. Use `type` for semantic styling (body, label, large, supporting, code) or use Heading for headings.' },
154
+ { guidance: false, description: 'Use Text for headings; use Heading with a `level` prop (1\u20136) for section titles and headings.' },
155
155
  ],
156
156
  },
157
157
  };
@@ -165,12 +165,12 @@ export const docsDense = {
165
165
  bestPractices: [
166
166
  { guidance: true, description: 'Semantic type (body, label, supporting, large, code) instead of manual size/weight.' },
167
167
  { guidance: true, description: 'accessibilityLevel on Heading when visual level differs from document outline.' },
168
- { guidance: true, description: 'maxLines for truncation \u2014 tooltip shows full text on hover.' },
168
+ { guidance: true, description: 'maxLines for truncation; tooltip shows full text on hover.' },
169
169
  { guidance: true, description: 'hasTabularNumbers for aligned numeric columns.' },
170
170
  { guidance: false, description: 'Override size/weight when a semantic type already matches.' },
171
- { guidance: false, description: 'Skip heading levels \u2014 sequential h1 \u2192 h2 \u2192 h3.' },
172
- { guidance: false, description: 'Raw <p>/<h1>/<span> \u2014 use Text/Heading for theme tokens.' },
173
- { guidance: false, description: '`variant` prop \u2014 does not exist. Use `type` for text styling or Heading for headings.' },
171
+ { guidance: false, description: 'Skip heading levels; sequential h1 \u2192 h2 \u2192 h3.' },
172
+ { guidance: false, description: 'Raw <p>/<h1>/<span>; use Text/Heading for theme tokens.' },
173
+ { guidance: false, description: '`variant` prop, which does not exist. Use `type` for text styling or Heading for headings.' },
174
174
  { guidance: false, description: 'Text for headings: use Heading with level (1\u20136).' },
175
175
  ],
176
176
  },
@@ -70,6 +70,12 @@ export const docs = {
70
70
  description: 'Disables the textarea, preventing interaction.',
71
71
  default: 'false',
72
72
  },
73
+ {
74
+ name: 'disabledMessage',
75
+ type: 'string',
76
+ description:
77
+ 'Explains why the textarea is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the textarea focusable via aria-disabled (the field becomes read-only). Use this instead of wrapping a disabled TextArea in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
78
+ },
73
79
  {
74
80
  name: 'isLoading',
75
81
  type: 'boolean',
@@ -174,6 +180,7 @@ export const docs = {
174
180
  { guidance: false, description: 'Avoid using TextArea for short, single-line values like names or emails; use TextInput instead.' },
175
181
  { guidance: false, description: 'Don\'t rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.' },
176
182
  { guidance: false, description: 'Don\'t show a status message without also setting the status type; the colored border and icon are what draw the user\'s attention to the message.' },
183
+ { guidance: false, description: 'Don\'t wrap a disabled TextArea in Tooltip to explain why it\'s disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
177
184
  ],
178
185
  },
179
186
  };
@@ -239,6 +246,12 @@ export const docsZh = {
239
246
  description: '禁用文本域,阻止交互。',
240
247
  default: 'false',
241
248
  },
249
+ {
250
+ name: 'disabledMessage',
251
+ type: 'string',
252
+ description:
253
+ '说明文本域被禁用的原因。与 isDisabled 一起使用时,在悬停/键盘聚焦时显示工具提示,并通过 aria-disabled 保持文本域可聚焦(字段变为只读)。请使用此属性,而不是用 Tooltip 包裹已禁用的 TextArea。',
254
+ },
242
255
  {
243
256
  name: 'isLoading',
244
257
  type: 'boolean',
@@ -336,6 +349,7 @@ export const docsZh = {
336
349
  { guidance: false, description: 'Avoid using TextArea for short, single-line values like names or emails; use TextInput instead.' },
337
350
  { guidance: false, description: 'Don\'t rely solely on placeholder text to communicate the purpose of the field; placeholders disappear on focus and are not accessible labels.' },
338
351
  { guidance: false, description: 'Don\'t show a status message without also setting the status type; the colored border and icon are what draw the user\'s attention to the message.' },
352
+ { guidance: false, description: 'Don\'t wrap a disabled TextArea in Tooltip to explain why it\'s disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
339
353
  ],
340
354
  },
341
355
  };
@@ -354,6 +368,7 @@ export const docsDense = {
354
368
  { guidance: false, description: 'Avoid TextArea for single-line values; use TextInput.' },
355
369
  { guidance: false, description: 'Don\'t use placeholder as only label; disappears on focus, not accessible.' },
356
370
  { guidance: false, description: 'Don\'t show status message without status type; border and icon draw attention.' },
371
+ { guidance: false, description: 'Don\'t wrap a disabled TextArea in Tooltip to explain the disabled state; use the disabledMessage prop instead.' },
357
372
  ],
358
373
  },
359
374
  propDescriptions: {
@@ -367,6 +382,8 @@ export const docsDense = {
367
382
  isOptional: 'Shows "Optional" indicator. Mutually exclusive w/ isRequired.',
368
383
  isRequired: 'Shows "Required" indicator+sets aria-required. Mutually exclusive w/ isOptional.',
369
384
  isDisabled: 'Disables textarea, prevents interaction.',
385
+ disabledMessage:
386
+ 'Explains why textarea is disabled. With isDisabled, shows tooltip on hover/focus + keeps textarea focusable via aria-disabled (field becomes read-only). Use instead of wrapping a disabled TextArea in Tooltip.',
370
387
  isLoading: 'Loading state w/ spinner inside input.',
371
388
  placeholder: 'Placeholder when textarea empty.',
372
389
  rows: 'Visible text rows.',