@astryxdesign/core 0.1.4 → 0.1.5-canary.76e6697

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 (635) hide show
  1. package/CHANGELOG.md +141 -0
  2. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +20 -18
  5. package/dist/AlertDialog/useImperativeAlertDialog.d.ts +0 -2
  6. package/dist/AlertDialog/useImperativeAlertDialog.d.ts.map +1 -1
  7. package/dist/AlertDialog/useImperativeAlertDialog.js +3 -5
  8. package/dist/AppShell/AppShell.d.ts +1 -1
  9. package/dist/AppShell/AppShell.d.ts.map +1 -1
  10. package/dist/AppShell/AppShell.js +55 -53
  11. package/dist/AspectRatio/AspectRatio.d.ts +48 -10
  12. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  13. package/dist/AspectRatio/AspectRatio.js +33 -12
  14. package/dist/AspectRatio/index.d.ts +1 -1
  15. package/dist/AspectRatio/index.d.ts.map +1 -1
  16. package/dist/Avatar/Avatar.d.ts.map +1 -1
  17. package/dist/Avatar/Avatar.js +28 -26
  18. package/dist/Avatar/AvatarStatusDot.js +6 -6
  19. package/dist/AvatarGroup/AvatarGroup.js +6 -6
  20. package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -7
  21. package/dist/Badge/Badge.js +3 -3
  22. package/dist/Banner/Banner.d.ts.map +1 -1
  23. package/dist/Banner/Banner.js +32 -25
  24. package/dist/Blockquote/Blockquote.js +7 -7
  25. package/dist/Breadcrumbs/BreadcrumbItem.js +17 -17
  26. package/dist/Breadcrumbs/Breadcrumbs.js +7 -7
  27. package/dist/Button/Button.js +19 -19
  28. package/dist/ButtonGroup/ButtonGroup.js +7 -7
  29. package/dist/Calendar/Calendar.d.ts.map +1 -1
  30. package/dist/Calendar/Calendar.js +68 -48
  31. package/dist/Calendar/dayCellUtils.d.ts.map +1 -1
  32. package/dist/Calendar/styles.d.ts +2 -2
  33. package/dist/Calendar/styles.d.ts.map +1 -1
  34. package/dist/Calendar/styles.js +2 -2
  35. package/dist/Card/Card.d.ts +4 -2
  36. package/dist/Card/Card.d.ts.map +1 -1
  37. package/dist/Card/Card.js +18 -10
  38. package/dist/Carousel/Carousel.d.ts.map +1 -1
  39. package/dist/Carousel/Carousel.js +24 -21
  40. package/dist/Center/Center.js +3 -3
  41. package/dist/Chat/ChatComposer.js +23 -23
  42. package/dist/Chat/ChatComposerDrawer.js +14 -14
  43. package/dist/Chat/ChatComposerInput.d.ts +1 -1
  44. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  45. package/dist/Chat/ChatComposerInput.js +27 -15
  46. package/dist/Chat/ChatDictationButton.d.ts +1 -1
  47. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  48. package/dist/Chat/ChatDictationButton.js +13 -11
  49. package/dist/Chat/ChatLayout.js +17 -17
  50. package/dist/Chat/ChatLayoutScrollButton.d.ts +1 -1
  51. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  52. package/dist/Chat/ChatLayoutScrollButton.js +12 -10
  53. package/dist/Chat/ChatMessage.js +12 -12
  54. package/dist/Chat/ChatMessageBubble.js +7 -7
  55. package/dist/Chat/ChatMessageList.js +14 -14
  56. package/dist/Chat/ChatMessageMetadata.d.ts +1 -1
  57. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  58. package/dist/Chat/ChatMessageMetadata.js +14 -12
  59. package/dist/Chat/ChatPastedTextToken.js +13 -13
  60. package/dist/Chat/ChatSendButton.js +3 -3
  61. package/dist/Chat/ChatSystemMessage.d.ts +1 -1
  62. package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
  63. package/dist/Chat/ChatSystemMessage.js +17 -17
  64. package/dist/Chat/ChatTokenizedText.d.ts +1 -1
  65. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  66. package/dist/Chat/ChatTokenizedText.js +24 -15
  67. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  68. package/dist/Chat/ChatToolCalls.js +81 -74
  69. package/dist/Chat/index.d.ts +1 -1
  70. package/dist/Chat/index.d.ts.map +1 -1
  71. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  72. package/dist/Chat/useTriggerMenu.js +15 -15
  73. package/dist/CheckboxInput/CheckboxInput.d.ts +1 -1
  74. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  75. package/dist/CheckboxInput/CheckboxInput.js +25 -23
  76. package/dist/CheckboxList/CheckboxList.js +9 -9
  77. package/dist/CheckboxList/CheckboxListItem.d.ts +1 -1
  78. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  79. package/dist/CheckboxList/CheckboxListItem.js +8 -6
  80. package/dist/Citation/Citation.js +10 -10
  81. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  82. package/dist/ClickableCard/ClickableCard.js +32 -9
  83. package/dist/Code/Code.js +3 -3
  84. package/dist/CodeBlock/CodeBlock.d.ts +10 -1
  85. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  86. package/dist/CodeBlock/CodeBlock.js +88 -52
  87. package/dist/Collapsible/Collapsible.d.ts +9 -3
  88. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  89. package/dist/Collapsible/Collapsible.js +109 -22
  90. package/dist/Collapsible/CollapsibleGroup.d.ts +37 -7
  91. package/dist/Collapsible/CollapsibleGroup.d.ts.map +1 -1
  92. package/dist/Collapsible/CollapsibleGroup.js +64 -12
  93. package/dist/Collapsible/CollapsibleGroupContext.d.ts +24 -0
  94. package/dist/Collapsible/CollapsibleGroupContext.d.ts.map +1 -1
  95. package/dist/Collapsible/CollapsibleGroupContext.js +26 -3
  96. package/dist/Collapsible/index.d.ts +1 -0
  97. package/dist/Collapsible/index.d.ts.map +1 -1
  98. package/dist/Collapsible/useCollapsible.d.ts +4 -1
  99. package/dist/Collapsible/useCollapsible.d.ts.map +1 -1
  100. package/dist/Collapsible/useCollapsible.js +20 -6
  101. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  102. package/dist/CommandPalette/CommandPalette.js +36 -34
  103. package/dist/CommandPalette/CommandPaletteEmpty.js +3 -3
  104. package/dist/CommandPalette/CommandPaletteFooter.js +16 -16
  105. package/dist/CommandPalette/CommandPaletteGroup.js +5 -5
  106. package/dist/CommandPalette/CommandPaletteInput.js +13 -13
  107. package/dist/CommandPalette/CommandPaletteItem.js +3 -3
  108. package/dist/CommandPalette/CommandPaletteList.js +3 -3
  109. package/dist/ContextMenu/ContextMenu.d.ts +7 -2
  110. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  111. package/dist/ContextMenu/ContextMenu.js +76 -43
  112. package/dist/DateInput/DateInput.js +18 -18
  113. package/dist/DateRangeInput/DateRangeInput.js +21 -21
  114. package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
  115. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  116. package/dist/DateTimeInput/DateTimeInput.js +30 -26
  117. package/dist/DateTimeInput/index.d.ts +1 -1
  118. package/dist/DateTimeInput/index.d.ts.map +1 -1
  119. package/dist/Dialog/Dialog.js +9 -9
  120. package/dist/Dialog/DialogHeader.js +16 -16
  121. package/dist/Dialog/useImperativeDialog.js +3 -3
  122. package/dist/Divider/Divider.js +7 -7
  123. package/dist/DropdownMenu/DropdownMenu.js +10 -10
  124. package/dist/DropdownMenu/DropdownMenuItem.d.ts +2 -17
  125. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  126. package/dist/DropdownMenu/DropdownMenuItem.js +3 -3
  127. package/dist/DropdownMenu/renderDropdownItems.js +10 -10
  128. package/dist/EmptyState/EmptyState.js +9 -9
  129. package/dist/Field/Field.js +17 -17
  130. package/dist/Field/FieldLabel.js +15 -15
  131. package/dist/Field/InputClearButton.js +5 -5
  132. package/dist/FieldStatus/FieldStatus.js +3 -3
  133. package/dist/FileInput/FileInput.js +29 -29
  134. package/dist/FormLayout/FormLayout.js +5 -5
  135. package/dist/Grid/Grid.d.ts +4 -3
  136. package/dist/Grid/Grid.d.ts.map +1 -1
  137. package/dist/Grid/Grid.js +29 -12
  138. package/dist/Grid/GridSpan.js +3 -3
  139. package/dist/HStack/HStack.js +3 -3
  140. package/dist/Heading/Heading.js +10 -10
  141. package/dist/HoverCard/HoverCard.js +9 -9
  142. package/dist/HoverCard/useHoverCard.d.ts +5 -1
  143. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  144. package/dist/HoverCard/useHoverCard.js +3 -3
  145. package/dist/Icon/Icon.d.ts.map +1 -1
  146. package/dist/Icon/Icon.js +16 -12
  147. package/dist/Icon/defaultIcons.js +116 -116
  148. package/dist/IconButton/IconButton.js +3 -3
  149. package/dist/InputGroup/InputGroup.js +11 -11
  150. package/dist/InputGroup/InputGroupText.js +3 -3
  151. package/dist/Item/Item.js +18 -18
  152. package/dist/Kbd/Kbd.js +5 -5
  153. package/dist/Layer/LayerProvider.js +7 -7
  154. package/dist/Layer/useLayer.d.ts +29 -2
  155. package/dist/Layer/useLayer.d.ts.map +1 -1
  156. package/dist/Layer/useLayer.js +44 -31
  157. package/dist/Layout/Layout.js +21 -21
  158. package/dist/Layout/LayoutContent.js +3 -3
  159. package/dist/Layout/LayoutFooter.js +5 -5
  160. package/dist/Layout/LayoutHeader.js +5 -5
  161. package/dist/Layout/LayoutPanel.js +3 -3
  162. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  163. package/dist/Lightbox/Lightbox.js +55 -31
  164. package/dist/Lightbox/useLightbox.d.ts +0 -1
  165. package/dist/Lightbox/useLightbox.d.ts.map +1 -1
  166. package/dist/Lightbox/useLightbox.js +3 -4
  167. package/dist/Link/Link.d.ts +0 -2
  168. package/dist/Link/Link.d.ts.map +1 -1
  169. package/dist/Link/Link.js +15 -17
  170. package/dist/Link/LinkProvider.js +3 -3
  171. package/dist/Link/useLinkify.js +3 -3
  172. package/dist/List/List.js +11 -11
  173. package/dist/List/ListItem.js +11 -11
  174. package/dist/Markdown/Markdown.d.ts.map +1 -1
  175. package/dist/Markdown/Markdown.js +102 -102
  176. package/dist/MetadataList/MetadataList.js +10 -10
  177. package/dist/MetadataList/MetadataListItem.js +15 -15
  178. package/dist/MobileNav/MobileNav.d.ts +1 -1
  179. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  180. package/dist/MobileNav/MobileNav.js +26 -23
  181. package/dist/MobileNav/MobileNavToggle.js +5 -5
  182. package/dist/MoreMenu/MoreMenu.js +3 -3
  183. package/dist/MultiSelector/MultiSelector.js +56 -56
  184. package/dist/NavIcon/NavIcon.js +3 -3
  185. package/dist/NavMenu/NavHeadingMenu.js +5 -5
  186. package/dist/NavMenu/NavHeadingMenuItem.js +8 -8
  187. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  188. package/dist/NumberInput/NumberInput.js +48 -32
  189. package/dist/Outline/Outline.js +15 -15
  190. package/dist/OverflowList/OverflowList.js +8 -8
  191. package/dist/Overlay/Overlay.js +3 -3
  192. package/dist/Overlay/OverlayScrim.js +5 -5
  193. package/dist/Overlay/useOverlay.d.ts +0 -3
  194. package/dist/Overlay/useOverlay.d.ts.map +1 -1
  195. package/dist/Overlay/useOverlay.js +3 -6
  196. package/dist/Pagination/Pagination.d.ts +1 -1
  197. package/dist/Pagination/Pagination.d.ts.map +1 -1
  198. package/dist/Pagination/Pagination.js +125 -72
  199. package/dist/Popover/Popover.js +16 -16
  200. package/dist/Popover/usePopover.js +7 -7
  201. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  202. package/dist/PowerSearch/PowerSearch.js +110 -92
  203. package/dist/PowerSearch/PowerSearchEditPopover.js +84 -84
  204. package/dist/PowerSearch/PowerSearchFilterEditor.js +3 -3
  205. package/dist/PowerSearch/PowerSearchToken.js +5 -5
  206. package/dist/PowerSearch/PowerSearchValueEditor.js +54 -54
  207. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  208. package/dist/ProgressBar/ProgressBar.js +25 -18
  209. package/dist/RadioList/RadioList.js +7 -7
  210. package/dist/RadioList/RadioListItem.d.ts +1 -1
  211. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  212. package/dist/RadioList/RadioListItem.js +24 -21
  213. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  214. package/dist/Resizable/ResizeHandle.js +28 -10
  215. package/dist/Section/Section.js +5 -5
  216. package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
  217. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  218. package/dist/SegmentedControl/SegmentedControl.js +32 -10
  219. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  220. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  221. package/dist/SegmentedControl/SegmentedControlItem.js +18 -12
  222. package/dist/SelectableCard/SelectableCard.js +5 -5
  223. package/dist/Selector/Selector.js +46 -46
  224. package/dist/Selector/SelectorOption.js +3 -3
  225. package/dist/SideNav/SideNav.d.ts.map +1 -1
  226. package/dist/SideNav/SideNav.js +38 -34
  227. package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
  228. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  229. package/dist/SideNav/SideNavCollapseButton.js +8 -6
  230. package/dist/SideNav/SideNavHeading.js +87 -87
  231. package/dist/SideNav/SideNavItem.js +42 -42
  232. package/dist/SideNav/SideNavSection.d.ts +1 -1
  233. package/dist/SideNav/SideNavSection.d.ts.map +1 -1
  234. package/dist/SideNav/SideNavSection.js +18 -16
  235. package/dist/Skeleton/Skeleton.js +3 -3
  236. package/dist/Slider/Slider.js +23 -23
  237. package/dist/Spinner/Spinner.js +9 -9
  238. package/dist/StatusDot/StatusDot.js +5 -5
  239. package/dist/Switch/Switch.d.ts +8 -4
  240. package/dist/Switch/Switch.d.ts.map +1 -1
  241. package/dist/Switch/Switch.js +34 -29
  242. package/dist/TabList/Tab.js +18 -18
  243. package/dist/TabList/TabList.js +5 -5
  244. package/dist/TabList/TabMenu.d.ts.map +1 -1
  245. package/dist/TabList/TabMenu.js +57 -30
  246. package/dist/TabList/tab.markers.stylex.d.ts +1 -1
  247. package/dist/Table/BaseTable.d.ts.map +1 -1
  248. package/dist/Table/BaseTable.js +50 -39
  249. package/dist/Table/Table.js +7 -7
  250. package/dist/Table/TableBody.d.ts +1 -1
  251. package/dist/Table/TableBody.d.ts.map +1 -1
  252. package/dist/Table/TableBody.js +9 -5
  253. package/dist/Table/TableCell.js +3 -3
  254. package/dist/Table/TableFooter.d.ts +1 -1
  255. package/dist/Table/TableFooter.d.ts.map +1 -1
  256. package/dist/Table/TableFooter.js +9 -5
  257. package/dist/Table/TableHeader.d.ts +1 -1
  258. package/dist/Table/TableHeader.d.ts.map +1 -1
  259. package/dist/Table/TableHeader.js +9 -5
  260. package/dist/Table/TableHeaderCell.js +3 -3
  261. package/dist/Table/TableRow.js +5 -5
  262. package/dist/Table/index.d.ts +2 -0
  263. package/dist/Table/index.d.ts.map +1 -1
  264. package/dist/Table/index.js +1 -0
  265. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  266. package/dist/Table/plugins/columnResize/useTableColumnResize.js +14 -11
  267. package/dist/Table/plugins/filtering/useTableFiltering.js +71 -71
  268. package/dist/Table/plugins/groupedRows/index.d.ts +3 -0
  269. package/dist/Table/plugins/groupedRows/index.d.ts.map +1 -0
  270. package/dist/Table/plugins/groupedRows/index.js +3 -0
  271. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +78 -0
  272. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -0
  273. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +250 -0
  274. package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
  275. package/dist/Table/plugins/pagination/paginateData.js +5 -1
  276. package/dist/Table/plugins/pagination/useTablePagination.js +7 -7
  277. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +1 -1
  278. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +23 -23
  279. package/dist/Table/plugins/selection/useTableSelection.js +18 -18
  280. package/dist/Table/plugins/selection/useTableSelectionState.d.ts.map +1 -1
  281. package/dist/Table/plugins/selection/useTableSelectionState.js +11 -1
  282. package/dist/Table/plugins/sortable/useTableSortable.js +17 -17
  283. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  284. package/dist/Table/plugins/sortable/useTableSortableState.js +8 -4
  285. package/dist/Table/tableContextMenu.js +9 -9
  286. package/dist/Text/Text.js +10 -10
  287. package/dist/TextArea/TextArea.js +14 -14
  288. package/dist/TextInput/TextInput.js +15 -15
  289. package/dist/Thumbnail/Thumbnail.d.ts +3 -2
  290. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  291. package/dist/Thumbnail/Thumbnail.js +30 -29
  292. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  293. package/dist/TimeInput/TimeInput.js +26 -21
  294. package/dist/Timestamp/Timestamp.d.ts +1 -1
  295. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  296. package/dist/Timestamp/Timestamp.js +37 -26
  297. package/dist/Toast/Toast.d.ts.map +1 -1
  298. package/dist/Toast/Toast.js +25 -17
  299. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  300. package/dist/Toast/ToastViewport.js +23 -11
  301. package/dist/Toast/useToast.d.ts.map +1 -1
  302. package/dist/Toast/useToast.js +44 -4
  303. package/dist/ToggleButton/ToggleButton.js +12 -12
  304. package/dist/ToggleButton/ToggleButtonGroup.js +5 -5
  305. package/dist/Token/Token.js +21 -21
  306. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  307. package/dist/Tokenizer/Tokenizer.js +36 -34
  308. package/dist/Toolbar/Toolbar.js +18 -18
  309. package/dist/Tooltip/Tooltip.js +11 -11
  310. package/dist/Tooltip/useTooltip.d.ts +5 -1
  311. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  312. package/dist/Tooltip/useTooltip.js +3 -3
  313. package/dist/TopNav/TopNav.js +32 -32
  314. package/dist/TopNav/TopNavHeading.js +67 -67
  315. package/dist/TopNav/TopNavItem.js +5 -5
  316. package/dist/TopNav/TopNavMegaMenu.js +30 -30
  317. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +1 -1
  318. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
  319. package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +25 -14
  320. package/dist/TopNav/TopNavMegaMenuItem.js +16 -16
  321. package/dist/TopNav/TopNavMenu.js +32 -32
  322. package/dist/TreeList/TreeList.js +8 -8
  323. package/dist/TreeList/TreeListBranches.js +11 -11
  324. package/dist/TreeList/TreeListItem.js +30 -30
  325. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  326. package/dist/Typeahead/BaseTypeahead.js +23 -20
  327. package/dist/Typeahead/Typeahead.js +12 -12
  328. package/dist/Typeahead/TypeaheadItem.js +10 -10
  329. package/dist/VStack/VStack.js +3 -3
  330. package/dist/VisuallyHidden/VisuallyHidden.d.ts +0 -3
  331. package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
  332. package/dist/VisuallyHidden/VisuallyHidden.js +0 -3
  333. package/dist/astryx.css +7 -0
  334. package/dist/astryx.umd.js +63 -63
  335. package/dist/astryx.umd.js.map +4 -4
  336. package/dist/docs-types.d.ts +8 -2
  337. package/dist/docs-types.d.ts.map +1 -1
  338. package/dist/hooks/focusableSelector.d.ts +1 -1
  339. package/dist/hooks/focusableSelector.d.ts.map +1 -1
  340. package/dist/hooks/focusableSelector.js +1 -1
  341. package/dist/hooks/index.d.ts +2 -0
  342. package/dist/hooks/index.d.ts.map +1 -1
  343. package/dist/hooks/index.js +1 -0
  344. package/dist/hooks/useFocusTrap.d.ts +3 -0
  345. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  346. package/dist/hooks/useFocusTrap.js +38 -1
  347. package/dist/hooks/useHotkeys.d.ts +51 -0
  348. package/dist/hooks/useHotkeys.d.ts.map +1 -0
  349. package/dist/hooks/useHotkeys.js +160 -0
  350. package/dist/hooks/useInteractiveRole.d.ts +6 -2
  351. package/dist/hooks/useInteractiveRole.d.ts.map +1 -1
  352. package/dist/hooks/useInteractiveRole.js +6 -2
  353. package/dist/hooks/useKeyboardHint.js +9 -9
  354. package/dist/hooks/useStreamingText.d.ts +3 -1
  355. package/dist/hooks/useStreamingText.d.ts.map +1 -1
  356. package/dist/hooks/useStreamingText.js +14 -5
  357. package/dist/theme/MediaTheme.js +3 -3
  358. package/dist/theme/Theme.js +7 -7
  359. package/dist/theme/defineTheme.d.ts +1 -1
  360. package/dist/theme/defineTheme.d.ts.map +1 -1
  361. package/dist/theme/expandColorScale.d.ts.map +1 -1
  362. package/dist/theme/expandColorScale.js +10 -3
  363. package/dist/theme/hct.d.ts +0 -15
  364. package/dist/theme/hct.d.ts.map +1 -1
  365. package/dist/theme/hct.js +9 -9
  366. package/dist/theme/syntax/SyntaxTheme.js +5 -5
  367. package/dist/theme/tokens.d.ts +10 -2
  368. package/dist/theme/tokens.d.ts.map +1 -1
  369. package/dist/theme/tokens.js +220 -4
  370. package/dist/theme/useTheme.d.ts +3 -2
  371. package/dist/theme/useTheme.d.ts.map +1 -1
  372. package/dist/theme/useTheme.js +73 -6
  373. package/dist/utils/color.d.ts +42 -0
  374. package/dist/utils/color.d.ts.map +1 -0
  375. package/dist/utils/color.js +150 -0
  376. package/dist/utils/composeEventHandlers.d.ts +30 -0
  377. package/dist/utils/composeEventHandlers.d.ts.map +1 -0
  378. package/dist/utils/composeEventHandlers.js +40 -0
  379. package/dist/utils/index.d.ts +3 -0
  380. package/dist/utils/index.d.ts.map +1 -1
  381. package/dist/utils/index.js +3 -1
  382. package/dist/utils/timeParser.d.ts.map +1 -1
  383. package/dist/utils/timeParser.js +8 -5
  384. package/package.json +4 -4
  385. package/src/AlertDialog/AlertDialog.doc.mjs +4 -0
  386. package/src/AlertDialog/AlertDialog.tsx +2 -0
  387. package/src/AlertDialog/useImperativeAlertDialog.tsx +0 -2
  388. package/src/AppShell/AppShell.tsx +2 -0
  389. package/src/AspectRatio/AspectRatio.doc.mjs +28 -1
  390. package/src/AspectRatio/AspectRatio.test.tsx +142 -1
  391. package/src/AspectRatio/AspectRatio.tsx +70 -10
  392. package/src/AspectRatio/index.ts +5 -1
  393. package/src/Avatar/Avatar.doc.mjs +11 -0
  394. package/src/Avatar/Avatar.test.tsx +32 -1
  395. package/src/Avatar/Avatar.tsx +14 -22
  396. package/src/Avatar/AvatarStatusDot.tsx +2 -2
  397. package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -0
  398. package/src/AvatarGroup/AvatarGroup.tsx +2 -2
  399. package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -2
  400. package/src/Banner/Banner.doc.mjs +8 -0
  401. package/src/Banner/Banner.test.tsx +38 -0
  402. package/src/Banner/Banner.tsx +8 -1
  403. package/src/Calendar/Calendar.doc.mjs +1 -1
  404. package/src/Calendar/Calendar.test.tsx +122 -17
  405. package/src/Calendar/Calendar.tsx +26 -5
  406. package/src/Calendar/dayCellUtils.ts +3 -1
  407. package/src/Calendar/styles.ts +12 -2
  408. package/src/Card/Card.doc.mjs +1 -1
  409. package/src/Card/Card.tsx +16 -6
  410. package/src/Carousel/Carousel.doc.mjs +12 -12
  411. package/src/Carousel/Carousel.test.tsx +13 -0
  412. package/src/Carousel/Carousel.tsx +4 -2
  413. package/src/Chat/Chat.doc.mjs +1 -1
  414. package/src/Chat/ChatComposerInput.test.tsx +27 -1
  415. package/src/Chat/ChatComposerInput.tsx +20 -15
  416. package/src/Chat/ChatDictationButton.test.tsx +43 -0
  417. package/src/Chat/ChatDictationButton.tsx +4 -4
  418. package/src/Chat/ChatLayoutScrollButton.test.tsx +33 -0
  419. package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
  420. package/src/Chat/ChatMessageMetadata.test.tsx +32 -0
  421. package/src/Chat/ChatMessageMetadata.tsx +4 -6
  422. package/src/Chat/ChatSystemMessage.test.tsx +26 -11
  423. package/src/Chat/ChatSystemMessage.tsx +7 -7
  424. package/src/Chat/ChatTokenizedText.test.tsx +29 -16
  425. package/src/Chat/ChatTokenizedText.tsx +15 -8
  426. package/src/Chat/ChatToolCalls.test.tsx +55 -0
  427. package/src/Chat/ChatToolCalls.tsx +10 -12
  428. package/src/Chat/index.ts +1 -4
  429. package/src/Chat/useTriggerMenu.tsx +1 -4
  430. package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -3
  431. package/src/CheckboxInput/CheckboxInput.test.tsx +71 -4
  432. package/src/CheckboxInput/CheckboxInput.tsx +2 -0
  433. package/src/CheckboxList/CheckboxList.test.tsx +19 -0
  434. package/src/CheckboxList/CheckboxListItem.tsx +11 -2
  435. package/src/Citation/Citation.doc.mjs +5 -0
  436. package/src/ClickableCard/ClickableCard.tsx +45 -2
  437. package/src/CodeBlock/CodeBlock.doc.mjs +7 -2
  438. package/src/CodeBlock/CodeBlock.test.tsx +122 -3
  439. package/src/CodeBlock/CodeBlock.tsx +62 -4
  440. package/src/Collapsible/Collapsible.doc.mjs +8 -4
  441. package/src/Collapsible/Collapsible.test.tsx +403 -0
  442. package/src/Collapsible/Collapsible.tsx +85 -10
  443. package/src/Collapsible/CollapsibleGroup.doc.mjs +27 -3
  444. package/src/Collapsible/CollapsibleGroup.test.tsx +314 -0
  445. package/src/Collapsible/CollapsibleGroup.tsx +97 -9
  446. package/src/Collapsible/CollapsibleGroupContext.tsx +34 -2
  447. package/src/Collapsible/index.ts +1 -0
  448. package/src/Collapsible/useCollapsible.ts +20 -6
  449. package/src/CommandPalette/CommandPalette.doc.mjs +5 -0
  450. package/src/CommandPalette/CommandPalette.tsx +5 -3
  451. package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +5 -0
  452. package/src/CommandPalette/CommandPaletteGroup.doc.mjs +10 -0
  453. package/src/CommandPalette/CommandPaletteInput.doc.mjs +6 -0
  454. package/src/CommandPalette/CommandPaletteItem.doc.mjs +6 -0
  455. package/src/CommandPalette/CommandPaletteList.doc.mjs +9 -0
  456. package/src/ContextMenu/ContextMenu.doc.mjs +15 -0
  457. package/src/ContextMenu/ContextMenu.test.tsx +87 -0
  458. package/src/ContextMenu/ContextMenu.tsx +87 -28
  459. package/src/ContextMenu/ContextMenuItem.doc.mjs +6 -0
  460. package/src/DateInput/DateInput.test.tsx +11 -20
  461. package/src/DateRangeInput/DateRangeInput.doc.mjs +9 -6
  462. package/src/DateRangeInput/DateRangeInput.test.tsx +31 -44
  463. package/src/DateTimeInput/DateTimeInput.doc.mjs +3 -2
  464. package/src/DateTimeInput/DateTimeInput.test.tsx +118 -16
  465. package/src/DateTimeInput/DateTimeInput.tsx +8 -2
  466. package/src/DateTimeInput/index.ts +1 -0
  467. package/src/Dialog/Dialog.doc.mjs +4 -0
  468. package/src/Dialog/DialogHeader.doc.mjs +45 -0
  469. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -1
  470. package/src/DropdownMenu/DropdownMenu.test.tsx +22 -2
  471. package/src/DropdownMenu/DropdownMenuItem.tsx +5 -17
  472. package/src/EmptyState/EmptyState.doc.mjs +1 -1
  473. package/src/Field/Field.test.tsx +1 -4
  474. package/src/Field/FieldLabel.test.tsx +2 -2
  475. package/src/FieldStatus/FieldStatus.test.tsx +282 -0
  476. package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -3
  477. package/src/Grid/Grid.test.tsx +43 -18
  478. package/src/Grid/Grid.tsx +26 -9
  479. package/src/HoverCard/HoverCard.doc.mjs +6 -6
  480. package/src/HoverCard/useHoverCard.doc.mjs +5 -5
  481. package/src/HoverCard/useHoverCard.tsx +9 -2
  482. package/src/Icon/Icon.test.tsx +41 -29
  483. package/src/Icon/Icon.tsx +6 -2
  484. package/src/InputGroup/InputGroup.doc.mjs +1 -0
  485. package/src/InputGroup/InputGroup.tsx +2 -2
  486. package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +185 -0
  487. package/src/Item/Item.tsx +1 -1
  488. package/src/Layer/useLayer.doc.mjs +2 -2
  489. package/src/Layer/useLayer.test.tsx +221 -2
  490. package/src/Layer/useLayer.tsx +69 -30
  491. package/src/Layout/Layout.test.tsx +285 -0
  492. package/src/Layout/LayoutContent.doc.mjs +12 -0
  493. package/src/Layout/LayoutPanel.doc.mjs +40 -0
  494. package/src/Layout/LayoutSlots.test.tsx +364 -0
  495. package/src/Lightbox/Lightbox.doc.mjs +5 -0
  496. package/src/Lightbox/Lightbox.test.tsx +123 -2
  497. package/src/Lightbox/Lightbox.tsx +29 -1
  498. package/src/Lightbox/useLightbox.tsx +0 -1
  499. package/src/Link/Link.tsx +0 -2
  500. package/src/Markdown/Markdown.tsx +9 -7
  501. package/src/Markdown/parser.perf.test.ts +34 -12
  502. package/src/MobileNav/MobileNav.test.tsx +56 -0
  503. package/src/MobileNav/MobileNav.tsx +13 -8
  504. package/src/NavMenu/NavMenu.doc.mjs +15 -0
  505. package/src/NumberInput/NumberInput.test.tsx +48 -3
  506. package/src/NumberInput/NumberInput.tsx +32 -15
  507. package/src/Outline/Outline.doc.mjs +2 -0
  508. package/src/Outline/parseOutlineFromMarkdown.test.ts +80 -0
  509. package/src/OverflowList/OverflowList.test.tsx +416 -0
  510. package/src/Overlay/Overlay.doc.mjs +6 -0
  511. package/src/Overlay/Overlay.test.tsx +356 -0
  512. package/src/Overlay/useOverlay.tsx +0 -3
  513. package/src/Pagination/Pagination.test.tsx +162 -0
  514. package/src/Pagination/Pagination.tsx +80 -26
  515. package/src/Popover/Popover.doc.mjs +6 -6
  516. package/src/Popover/Popover.test.tsx +65 -0
  517. package/src/Popover/usePopover.doc.mjs +1 -1
  518. package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
  519. package/src/PowerSearch/PowerSearch.test.tsx +109 -1
  520. package/src/PowerSearch/PowerSearch.tsx +37 -16
  521. package/src/ProgressBar/ProgressBar.doc.mjs +2 -0
  522. package/src/ProgressBar/ProgressBar.test.tsx +30 -0
  523. package/src/ProgressBar/ProgressBar.tsx +12 -5
  524. package/src/RadioList/RadioList.test.tsx +19 -0
  525. package/src/RadioList/RadioListItem.tsx +9 -4
  526. package/src/Resizable/ResizeHandle.test.tsx +218 -0
  527. package/src/Resizable/ResizeHandle.tsx +22 -4
  528. package/src/SegmentedControl/SegmentedControl.doc.mjs +1 -1
  529. package/src/SegmentedControl/SegmentedControl.test.tsx +192 -0
  530. package/src/SegmentedControl/SegmentedControl.tsx +27 -5
  531. package/src/SegmentedControl/SegmentedControlItem.tsx +9 -4
  532. package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
  533. package/src/Selector/Selector.test.tsx +27 -1
  534. package/src/SideNav/SideNav.doc.mjs +7 -1
  535. package/src/SideNav/SideNav.test.tsx +66 -0
  536. package/src/SideNav/SideNav.tsx +6 -2
  537. package/src/SideNav/SideNavCollapseButton.tsx +4 -3
  538. package/src/SideNav/SideNavSection.tsx +6 -4
  539. package/src/SizeContext/SizeContext.test.tsx +226 -0
  540. package/src/Switch/Switch.doc.mjs +7 -7
  541. package/src/Switch/Switch.test.tsx +102 -3
  542. package/src/Switch/Switch.tsx +20 -7
  543. package/src/TabList/TabList.test.tsx +185 -1
  544. package/src/TabList/TabMenu.tsx +45 -9
  545. package/src/Table/BaseTable.tsx +13 -2
  546. package/src/Table/Table.doc.mjs +6 -1
  547. package/src/Table/Table.test.tsx +87 -0
  548. package/src/Table/TableBody.tsx +15 -2
  549. package/src/Table/TableFooter.tsx +15 -2
  550. package/src/Table/TableHeader.tsx +15 -2
  551. package/src/Table/index.ts +5 -0
  552. package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +13 -0
  553. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +3 -1
  554. package/src/Table/plugins/groupedRows/index.ts +7 -0
  555. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +231 -0
  556. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +349 -0
  557. package/src/Table/plugins/pagination/paginateData.ts +5 -1
  558. package/src/Table/plugins/pagination/useTablePagination.test.tsx +13 -0
  559. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +1 -1
  560. package/src/Table/plugins/selection/useTableSelectionState.test.tsx +23 -0
  561. package/src/Table/plugins/selection/useTableSelectionState.tsx +11 -6
  562. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +35 -1
  563. package/src/Table/plugins/sortable/useTableSortableState.tsx +8 -4
  564. package/src/Table/useTableGroupedRows.doc.mjs +71 -0
  565. package/src/TextArea/TextArea.test.tsx +3 -3
  566. package/src/TextInput/TextInput.test.tsx +3 -3
  567. package/src/Thumbnail/Thumbnail.test.tsx +36 -2
  568. package/src/Thumbnail/Thumbnail.tsx +4 -2
  569. package/src/TimeInput/TimeInput.test.tsx +37 -0
  570. package/src/TimeInput/TimeInput.tsx +11 -1
  571. package/src/Timestamp/Timestamp.doc.mjs +1 -1
  572. package/src/Timestamp/Timestamp.test.tsx +52 -0
  573. package/src/Timestamp/Timestamp.tsx +30 -16
  574. package/src/Toast/Toast.tsx +11 -3
  575. package/src/Toast/ToastViewport.test.tsx +64 -0
  576. package/src/Toast/ToastViewport.tsx +12 -0
  577. package/src/Toast/useToast.test.tsx +258 -0
  578. package/src/Toast/useToast.tsx +41 -0
  579. package/src/ToggleButton/ToggleButton.doc.mjs +1 -0
  580. package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
  581. package/src/Tokenizer/Tokenizer.test.tsx +54 -0
  582. package/src/Tokenizer/Tokenizer.tsx +5 -4
  583. package/src/Tooltip/Tooltip.doc.mjs +6 -6
  584. package/src/Tooltip/useTooltip.doc.mjs +5 -5
  585. package/src/Tooltip/useTooltip.tsx +12 -2
  586. package/src/TopNav/TopNav.doc.mjs +1 -1
  587. package/src/TopNav/TopNav.test.tsx +23 -7
  588. package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +9 -2
  589. package/src/TreeList/TreeList.doc.mjs +2 -2
  590. package/src/Typeahead/BaseTypeahead.doc.mjs +19 -0
  591. package/src/Typeahead/BaseTypeahead.tsx +5 -2
  592. package/src/Typeahead/Typeahead.doc.mjs +1 -1
  593. package/src/Typeahead/Typeahead.test.tsx +45 -1
  594. package/src/VisuallyHidden/VisuallyHidden.tsx +0 -3
  595. package/src/__tests__/TestIcon.tsx +26 -0
  596. package/src/__tests__/fastRoleQueries.ts +66 -0
  597. package/src/docPropReferences.test.ts +178 -0
  598. package/src/docs-types.ts +9 -1
  599. package/src/hooks/focusableSelector.ts +1 -1
  600. package/src/hooks/index.ts +3 -0
  601. package/src/hooks/useFocusTrap.doc.mjs +4 -2
  602. package/src/hooks/useFocusTrap.test.tsx +149 -1
  603. package/src/hooks/useFocusTrap.ts +50 -1
  604. package/src/hooks/useHotkeys.doc.mjs +52 -0
  605. package/src/hooks/useHotkeys.test.ts +245 -0
  606. package/src/hooks/useHotkeys.ts +203 -0
  607. package/src/hooks/useInteractiveRole.ts +12 -4
  608. package/src/hooks/useStreamingText.test.ts +54 -19
  609. package/src/hooks/useStreamingText.ts +16 -5
  610. package/src/hooks/useTreeFocus.test.tsx +1 -3
  611. package/src/reset.css +29 -0
  612. package/src/theme/SyntaxTheme.doc.mjs +4 -4
  613. package/src/theme/defineTheme.ts +4 -13
  614. package/src/theme/derivedVarRegistry.test.ts +2 -2
  615. package/src/theme/expandColorScale.test.ts +29 -0
  616. package/src/theme/expandColorScale.ts +11 -6
  617. package/src/theme/hct.ts +9 -17
  618. package/src/theme/themingTargets.test.ts +353 -0
  619. package/src/theme/tokens.test.ts +182 -9
  620. package/src/theme/tokens.ts +239 -4
  621. package/src/theme/useTheme.test.tsx +126 -2
  622. package/src/theme/useTheme.ts +87 -6
  623. package/src/utils/color.test.ts +133 -0
  624. package/src/utils/color.ts +148 -0
  625. package/src/utils/composeEventHandlers.test.ts +71 -0
  626. package/src/utils/composeEventHandlers.ts +44 -0
  627. package/src/utils/index.ts +4 -0
  628. package/src/utils/mergeProps.test.ts +166 -0
  629. package/src/utils/sharedResizeObserver.test.ts +2 -2
  630. package/src/utils/timeParser.test.ts +13 -0
  631. package/src/utils/timeParser.ts +8 -5
  632. package/dist/Carousel/carousel.markers.stylex.d.ts +0 -7
  633. package/dist/Carousel/carousel.markers.stylex.d.ts.map +0 -1
  634. package/dist/Carousel/carousel.markers.stylex.js +0 -12
  635. package/src/Carousel/carousel.markers.stylex.ts +0 -10
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
13
- import {render, screen} from '@testing-library/react';
13
+ import {render, screen, fireEvent} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {TabList} from './TabList';
16
16
  import {Tab} from './Tab';
@@ -702,3 +702,187 @@ describe('TabMenu', () => {
702
702
  expect(reportsItem).not.toHaveAttribute('aria-current');
703
703
  });
704
704
  });
705
+
706
+ describe('TabMenu keyboard navigation (roving tabindex)', () => {
707
+ const menuOptions = [
708
+ {value: 'analytics', label: 'Analytics'},
709
+ {value: 'reports', label: 'Reports'},
710
+ ];
711
+
712
+ it('exposes the overflow menu as a single Tab stop (one item tabbable, rest -1)', async () => {
713
+ const user = userEvent.setup();
714
+ render(
715
+ <TabList value="home" onChange={() => {}}>
716
+ <Tab value="home" label="Home" />
717
+ <TabMenu label="More" options={menuOptions} />
718
+ </TabList>,
719
+ );
720
+
721
+ await user.click(screen.getByRole('button', {name: /More/}));
722
+
723
+ const analytics = screen.getByRole('menuitem', {
724
+ name: 'Analytics',
725
+ hidden: true,
726
+ });
727
+ const reports = screen.getByRole('menuitem', {
728
+ name: 'Reports',
729
+ hidden: true,
730
+ });
731
+
732
+ // Exactly one menu item is in the Tab sequence; arrow keys reach the rest.
733
+ expect(analytics).toHaveAttribute('tabindex', '0');
734
+ expect(reports).toHaveAttribute('tabindex', '-1');
735
+
736
+ const tabbable = [analytics, reports].filter(
737
+ el => el.getAttribute('tabindex') === '0',
738
+ );
739
+ expect(tabbable).toHaveLength(1);
740
+ });
741
+
742
+ it('moves focus between items with ArrowDown and ArrowUp', async () => {
743
+ const user = userEvent.setup();
744
+ render(
745
+ <TabList value="home" onChange={() => {}}>
746
+ <Tab value="home" label="Home" />
747
+ <TabMenu label="More" options={menuOptions} />
748
+ </TabList>,
749
+ );
750
+
751
+ await user.click(screen.getByRole('button', {name: /More/}));
752
+ const menu = screen.getByRole('menu', {hidden: true});
753
+ const analytics = screen.getByRole('menuitem', {
754
+ name: 'Analytics',
755
+ hidden: true,
756
+ });
757
+ const reports = screen.getByRole('menuitem', {
758
+ name: 'Reports',
759
+ hidden: true,
760
+ });
761
+
762
+ fireEvent.keyDown(menu, {key: 'ArrowDown'});
763
+ expect(analytics).toHaveFocus();
764
+
765
+ fireEvent.keyDown(menu, {key: 'ArrowDown'});
766
+ expect(reports).toHaveFocus();
767
+
768
+ fireEvent.keyDown(menu, {key: 'ArrowUp'});
769
+ expect(analytics).toHaveFocus();
770
+ });
771
+
772
+ it('moves the roving tab stop with arrow navigation', async () => {
773
+ const user = userEvent.setup();
774
+ render(
775
+ <TabList value="home" onChange={() => {}}>
776
+ <Tab value="home" label="Home" />
777
+ <TabMenu label="More" options={menuOptions} />
778
+ </TabList>,
779
+ );
780
+
781
+ await user.click(screen.getByRole('button', {name: /More/}));
782
+ const menu = screen.getByRole('menu', {hidden: true});
783
+ const analytics = screen.getByRole('menuitem', {
784
+ name: 'Analytics',
785
+ hidden: true,
786
+ });
787
+ const reports = screen.getByRole('menuitem', {
788
+ name: 'Reports',
789
+ hidden: true,
790
+ });
791
+
792
+ fireEvent.keyDown(menu, {key: 'ArrowDown'}); // focus analytics
793
+ fireEvent.keyDown(menu, {key: 'ArrowDown'}); // focus reports
794
+
795
+ // The tab stop follows focus, so it is still a single stop after moving.
796
+ expect(reports).toHaveAttribute('tabindex', '0');
797
+ expect(analytics).toHaveAttribute('tabindex', '-1');
798
+ });
799
+
800
+ it('jumps to first and last item with Home and End', async () => {
801
+ const user = userEvent.setup();
802
+ const options = [
803
+ {value: 'analytics', label: 'Analytics'},
804
+ {value: 'reports', label: 'Reports'},
805
+ {value: 'exports', label: 'Exports'},
806
+ ];
807
+ render(
808
+ <TabList value="home" onChange={() => {}}>
809
+ <Tab value="home" label="Home" />
810
+ <TabMenu label="More" options={options} />
811
+ </TabList>,
812
+ );
813
+
814
+ await user.click(screen.getByRole('button', {name: /More/}));
815
+ const menu = screen.getByRole('menu', {hidden: true});
816
+ const analytics = screen.getByRole('menuitem', {
817
+ name: 'Analytics',
818
+ hidden: true,
819
+ });
820
+ const exports = screen.getByRole('menuitem', {
821
+ name: 'Exports',
822
+ hidden: true,
823
+ });
824
+
825
+ fireEvent.keyDown(menu, {key: 'End'});
826
+ expect(exports).toHaveFocus();
827
+
828
+ fireEvent.keyDown(menu, {key: 'Home'});
829
+ expect(analytics).toHaveFocus();
830
+ });
831
+
832
+ it('selects an item with Enter and calls onChange', async () => {
833
+ const user = userEvent.setup();
834
+ const handleChange = vi.fn();
835
+ render(
836
+ <TabList value="home" onChange={handleChange}>
837
+ <Tab value="home" label="Home" />
838
+ <TabMenu label="More" options={menuOptions} />
839
+ </TabList>,
840
+ );
841
+
842
+ await user.click(screen.getByRole('button', {name: /More/}));
843
+ const analytics = screen.getByRole('menuitem', {
844
+ name: 'Analytics',
845
+ hidden: true,
846
+ });
847
+ analytics.focus();
848
+ fireEvent.keyDown(analytics, {key: 'Enter'});
849
+
850
+ expect(handleChange).toHaveBeenCalledWith('analytics');
851
+ });
852
+
853
+ it('closes the menu when Tab is pressed inside it (APG menu-button)', async () => {
854
+ const user = userEvent.setup();
855
+ render(
856
+ <TabList value="home" onChange={() => {}}>
857
+ <Tab value="home" label="Home" />
858
+ <TabMenu label="More" options={menuOptions} />
859
+ </TabList>,
860
+ );
861
+
862
+ await user.click(screen.getByRole('button', {name: /More/}));
863
+ const menu = screen.getByRole('menu', {hidden: true});
864
+
865
+ const hidePopover = vi.mocked(HTMLElement.prototype.hidePopover);
866
+ hidePopover.mockClear();
867
+ fireEvent.keyDown(menu, {key: 'Tab'});
868
+ expect(hidePopover).toHaveBeenCalled();
869
+ });
870
+
871
+ it('closes the menu when Escape is pressed', async () => {
872
+ const user = userEvent.setup();
873
+ render(
874
+ <TabList value="home" onChange={() => {}}>
875
+ <Tab value="home" label="Home" />
876
+ <TabMenu label="More" options={menuOptions} />
877
+ </TabList>,
878
+ );
879
+
880
+ await user.click(screen.getByRole('button', {name: /More/}));
881
+ const menu = screen.getByRole('menu', {hidden: true});
882
+
883
+ const hidePopover = vi.mocked(HTMLElement.prototype.hidePopover);
884
+ hidePopover.mockClear();
885
+ fireEvent.keyDown(menu, {key: 'Escape'});
886
+ expect(hidePopover).toHaveBeenCalled();
887
+ });
888
+ });
@@ -16,7 +16,7 @@
16
16
  * - /packages/cli/templates/blocks/components/TabList/ (showcase blocks)
17
17
  */
18
18
 
19
- import React, {useCallback, useId, type ReactNode} from 'react';
19
+ import React, {useCallback, useId, useRef, type ReactNode} from 'react';
20
20
  import * as stylex from '@stylexjs/stylex';
21
21
  import {Icon} from '../Icon';
22
22
  import {renderIconSlot, type IconType} from '../Icon';
@@ -262,6 +262,7 @@ export function TabMenu({
262
262
  }: TabMenuProps) {
263
263
  const tabListCtx = useTabListContext();
264
264
  const menuId = useId();
265
+ const buttonRef = useRef<HTMLButtonElement>(null);
265
266
 
266
267
  const popover = usePopover({
267
268
  hasLightDismiss: true,
@@ -270,20 +271,50 @@ export function TabMenu({
270
271
  // The popup's own role="menu" is the exposed semantics; a modal dialog
271
272
  // wrapper would announce an unnamed dialog around the menu.
272
273
  role: 'none',
274
+ // Return focus to the trigger when the menu closes (Escape, Tab, select,
275
+ // or light dismiss) so keyboard focus is never dropped to <body>.
276
+ onHide: useCallback(() => {
277
+ buttonRef.current?.focus();
278
+ }, []),
273
279
  });
274
280
 
275
- const {listRef, handleKeyDown: handleListKeyDown} =
276
- useListFocus<HTMLDivElement>({
277
- onEscape: () => popover.hide(),
278
- });
281
+ // The overflow menu is a composite widget: a single roving tab stop with
282
+ // arrow-key navigation between items, per the APG menu pattern. The hook owns
283
+ // item tabindex — items render tabIndex={-1} and exactly one is promoted to 0.
284
+ const {
285
+ listRef,
286
+ handleKeyDown: handleListKeyDown,
287
+ handleFocus,
288
+ focusFirst,
289
+ } = useListFocus<HTMLDivElement>({
290
+ hasRovingTabIndex: true,
291
+ onEscape: () => popover.hide(),
292
+ });
279
293
 
280
294
  const handleToggle = useCallback(() => {
281
295
  if (popover.isOpen) {
282
296
  popover.hide();
283
297
  } else {
284
298
  popover.show();
299
+ // Move focus into the menu on open so arrow navigation works and the
300
+ // roving tab stop lands on a real item (APG menu-button focus-on-open).
301
+ requestAnimationFrame(() => focusFirst());
285
302
  }
286
- }, [popover]);
303
+ }, [popover, focusFirst]);
304
+
305
+ const handleMenuKeyDown = useCallback(
306
+ (e: React.KeyboardEvent) => {
307
+ // APG menu-button: Tab leaves the menu rather than walking its items.
308
+ // Close and let onHide return focus to the trigger, from which the
309
+ // browser's default Tab continues to the next element.
310
+ if (e.key === 'Tab') {
311
+ popover.hide();
312
+ return;
313
+ }
314
+ handleListKeyDown(e);
315
+ },
316
+ [handleListKeyDown, popover],
317
+ );
287
318
 
288
319
  const selectedOption = options.find(o => o.value === tabListCtx.value);
289
320
  const triggerLabel = selectedOption?.label ?? label;
@@ -299,7 +330,11 @@ export function TabMenu({
299
330
  [tabListCtx, popover],
300
331
  );
301
332
 
302
- const setButtonRef = mergeRefs<HTMLButtonElement>(popover.triggerRef, ref);
333
+ const setButtonRef = mergeRefs<HTMLButtonElement>(
334
+ popover.triggerRef,
335
+ buttonRef,
336
+ ref,
337
+ );
303
338
 
304
339
  return (
305
340
  <>
@@ -357,7 +392,8 @@ export function TabMenu({
357
392
  id={menuId}
358
393
  role="menu"
359
394
  aria-label={label}
360
- onKeyDown={handleListKeyDown}
395
+ onKeyDown={handleMenuKeyDown}
396
+ onFocus={handleFocus}
361
397
  {...mergeProps(
362
398
  themeProps('tab-menu-dropdown'),
363
399
  stylex.props(styles.dropdown),
@@ -371,7 +407,7 @@ export function TabMenu({
371
407
  <div
372
408
  key={option.value}
373
409
  role="menuitem"
374
- tabIndex={0}
410
+ tabIndex={-1}
375
411
  aria-current={isSelected ? 'true' : undefined}
376
412
  onClick={() => handleSelect(option.value)}
377
413
  onKeyDown={e => {
@@ -279,11 +279,18 @@ function areRowPropsEqual<T extends Record<string, unknown>>(
279
279
  return true;
280
280
  }
281
281
 
282
- // Different object reference - compare values
282
+ // Different object reference - compare values. This is intentionally a
283
+ // one-level shallow compare: nested fields rely on reference identity.
283
284
  const prevItem = prevProps.item;
284
285
  const nextItem = nextProps.item;
285
286
  const keys = Object.keys(nextItem);
286
287
 
288
+ // A key deleted from nextItem would never be visited by the loop below,
289
+ // and the row would keep rendering the removed field's stale value.
290
+ if (Object.keys(prevItem).length !== keys.length) {
291
+ return false;
292
+ }
293
+
287
294
  for (const key of keys) {
288
295
  if (prevItem[key] !== nextItem[key]) {
289
296
  return false;
@@ -365,9 +372,13 @@ function BaseTableInner<T extends Record<string, unknown>>({
365
372
  const headerCells = resolvedColumns.map((col, columnIndex) => {
366
373
  const headerContent = col.header ?? col.key;
367
374
 
368
- // Build initial htmlProps with column alignment if specified
375
+ // Build initial htmlProps with column alignment if specified.
376
+ // `scope: 'col'` is the default so every column header associates its
377
+ // data cells with the correct column for screen readers; a plugin's
378
+ // transformHeaderCell can override it via htmlProps.scope.
369
379
  const initialHeaderHtmlProps: Record<string, unknown> = {
370
380
  'data-column-key': col.key,
381
+ scope: 'col',
371
382
  };
372
383
  if (col.align) {
373
384
  initialHeaderHtmlProps.style = {textAlign: col.align};
@@ -25,6 +25,11 @@ export const docs = {
25
25
  theming: {
26
26
  targets: [
27
27
  {className: 'astryx-base-table'},
28
+ {className: 'astryx-table'},
29
+ {className: 'astryx-table-scroll-wrapper'},
30
+ {className: 'astryx-table-header'},
31
+ {className: 'astryx-table-body'},
32
+ {className: 'astryx-table-footer'},
28
33
  {className: 'astryx-table-row'},
29
34
  {className: 'astryx-table-cell'},
30
35
  {className: 'astryx-table-header-cell'},
@@ -40,7 +45,7 @@ export const docs = {
40
45
  {
41
46
  name: 'columns',
42
47
  type: 'TableColumn<T>[]',
43
- description: 'Column definitions: each column has {key, header, width?, align?, renderCell?}. The `header` field sets the column heading text. If omitted, columns are auto-generated from data object keys.',
48
+ description: 'Column definitions: each column has {key, header, width?, align?, renderCell?}. The `header` field sets the column heading text. If omitted, columns are auto-generated from data object keys. The `width` field is typed as `ColumnWidth` (not a number) — use `proportional(n)` or `pixel(n)` helpers imported from `@astryxdesign/core/Table`. Example: `width: pixel(120)` for 120px fixed, `width: proportional(1)` for flex distribution.',
44
49
  },
45
50
  {
46
51
  name: 'idKey',
@@ -15,6 +15,9 @@ import {BaseTable} from './BaseTable';
15
15
  import {Table} from './Table';
16
16
  import {TableRow} from './TableRow';
17
17
  import {TableCell} from './TableCell';
18
+ import {TableHeader} from './TableHeader';
19
+ import {TableBody} from './TableBody';
20
+ import {TableFooter} from './TableFooter';
18
21
  import {
19
22
  proportional,
20
23
  pixel,
@@ -229,6 +232,34 @@ describe('BaseTable', () => {
229
232
  expect(headers[2]).toHaveTextContent('Email');
230
233
  });
231
234
 
235
+ it('renders every column header with scope="col"', () => {
236
+ render(<BaseTable data={users} columns={columns} />);
237
+ const headers = screen.getAllByRole('columnheader');
238
+ expect(headers).toHaveLength(3);
239
+ for (const header of headers) {
240
+ expect(header).toHaveAttribute('scope', 'col');
241
+ }
242
+ });
243
+
244
+ it('lets a consumer override scope via header html props', () => {
245
+ // A `<th scope="row">` maps to the `rowheader` role, so query the DOM
246
+ // directly to assert the attribute regardless of the resolved ARIA role.
247
+ const plugin: TablePlugin<User> = {
248
+ transformHeaderCell: (props, column) =>
249
+ column.key === 'name'
250
+ ? {...props, htmlProps: {...props.htmlProps, scope: 'row'}}
251
+ : props,
252
+ };
253
+ const {container} = render(
254
+ <BaseTable data={users} columns={columns} plugins={[plugin]} />,
255
+ );
256
+ const headerCells = container.querySelectorAll('thead th');
257
+ // columns fixture order: name, age, email — plugin overrides name → 'row'
258
+ expect(headerCells[0]).toHaveAttribute('scope', 'row');
259
+ expect(headerCells[1]).toHaveAttribute('scope', 'col');
260
+ expect(headerCells[2]).toHaveAttribute('scope', 'col');
261
+ });
262
+
232
263
  it('renders data cells', () => {
233
264
  render(<BaseTable data={users} columns={columns} />);
234
265
  const cells = screen.getAllByRole('cell');
@@ -617,6 +648,29 @@ describe('BaseTable', () => {
617
648
  // =============================================================================
618
649
 
619
650
  describe('Table', () => {
651
+ it('clears a cell when the field is removed from the row object (#3595)', () => {
652
+ const cols: TableColumn<Record<string, unknown>>[] = [
653
+ {key: 'name', header: 'Name'},
654
+ {key: 'status', header: 'Status'},
655
+ ];
656
+ const {rerender} = render(
657
+ <Table
658
+ data={[{id: '1', name: 'Alice', status: 'active'}]}
659
+ columns={cols}
660
+ idKey="id"
661
+ />,
662
+ );
663
+ expect(screen.getByText('active')).toBeInTheDocument();
664
+
665
+ // Clearing a field by omitting it (optimistic update / server response)
666
+ // must re-render the row — the memo previously only compared the keys of
667
+ // the NEW item, so the deleted field's stale value kept rendering.
668
+ rerender(
669
+ <Table data={[{id: '1', name: 'Alice'}]} columns={cols} idKey="id" />,
670
+ );
671
+ expect(screen.queryByText('active')).not.toBeInTheDocument();
672
+ });
673
+
620
674
  it('renders a table with correct structure', () => {
621
675
  render(<Table data={users} columns={columns} />);
622
676
  expect(screen.getByRole('table')).toBeInTheDocument();
@@ -1232,4 +1286,37 @@ describe('emptyState', () => {
1232
1286
  expect(screen.getByText('Name')).toBeInTheDocument();
1233
1287
  expect(screen.getByText('Age')).toBeInTheDocument();
1234
1288
  });
1289
+
1290
+ describe('table section rest forwarding', () => {
1291
+ it('forwards data-testid and id to the tbody, thead, and tfoot', () => {
1292
+ const {container} = render(
1293
+ <table>
1294
+ <TableHeader data-testid="thead" id="head-1">
1295
+ <tr>
1296
+ <th>H</th>
1297
+ </tr>
1298
+ </TableHeader>
1299
+ <TableBody data-testid="tbody" id="body-1">
1300
+ <tr>
1301
+ <td>B</td>
1302
+ </tr>
1303
+ </TableBody>
1304
+ <TableFooter data-testid="tfoot" id="foot-1">
1305
+ <tr>
1306
+ <td>F</td>
1307
+ </tr>
1308
+ </TableFooter>
1309
+ </table>,
1310
+ );
1311
+ const thead = container.querySelector('thead')!;
1312
+ const tbody = container.querySelector('tbody')!;
1313
+ const tfoot = container.querySelector('tfoot')!;
1314
+ expect(thead).toHaveAttribute('data-testid', 'thead');
1315
+ expect(thead).toHaveAttribute('id', 'head-1');
1316
+ expect(tbody).toHaveAttribute('data-testid', 'tbody');
1317
+ expect(tbody).toHaveAttribute('id', 'body-1');
1318
+ expect(tfoot).toHaveAttribute('data-testid', 'tfoot');
1319
+ expect(tfoot).toHaveAttribute('id', 'foot-1');
1320
+ });
1321
+ });
1235
1322
  });
@@ -13,11 +13,24 @@ export interface TableBodyProps extends BaseProps<HTMLTableSectionElement> {
13
13
  children: ReactNode;
14
14
  }
15
15
 
16
- export function TableBody({ref, children, xstyle}: TableBodyProps) {
16
+ export function TableBody({
17
+ ref,
18
+ children,
19
+ xstyle,
20
+ className,
21
+ style,
22
+ ...rest
23
+ }: TableBodyProps) {
17
24
  return (
18
25
  <tbody
19
26
  ref={ref}
20
- {...mergeProps(themeProps('table-body'), stylex.props(xstyle))}>
27
+ {...mergeProps(
28
+ themeProps('table-body'),
29
+ stylex.props(xstyle),
30
+ className,
31
+ style,
32
+ )}
33
+ {...rest}>
21
34
  {children}
22
35
  </tbody>
23
36
  );
@@ -13,11 +13,24 @@ export interface TableFooterProps extends BaseProps<HTMLTableSectionElement> {
13
13
  children: ReactNode;
14
14
  }
15
15
 
16
- export function TableFooter({ref, children, xstyle}: TableFooterProps) {
16
+ export function TableFooter({
17
+ ref,
18
+ children,
19
+ xstyle,
20
+ className,
21
+ style,
22
+ ...rest
23
+ }: TableFooterProps) {
17
24
  return (
18
25
  <tfoot
19
26
  ref={ref}
20
- {...mergeProps(themeProps('table-footer'), stylex.props(xstyle))}>
27
+ {...mergeProps(
28
+ themeProps('table-footer'),
29
+ stylex.props(xstyle),
30
+ className,
31
+ style,
32
+ )}
33
+ {...rest}>
21
34
  {children}
22
35
  </tfoot>
23
36
  );
@@ -13,11 +13,24 @@ export interface TableHeaderProps extends BaseProps<HTMLTableSectionElement> {
13
13
  children: ReactNode;
14
14
  }
15
15
 
16
- export function TableHeader({ref, children, xstyle}: TableHeaderProps) {
16
+ export function TableHeader({
17
+ ref,
18
+ children,
19
+ xstyle,
20
+ className,
21
+ style,
22
+ ...rest
23
+ }: TableHeaderProps) {
17
24
  return (
18
25
  <thead
19
26
  ref={ref}
20
- {...mergeProps(themeProps('table-header'), stylex.props(xstyle))}>
27
+ {...mergeProps(
28
+ themeProps('table-header'),
29
+ stylex.props(xstyle),
30
+ className,
31
+ style,
32
+ )}
33
+ {...rest}>
21
34
  {children}
22
35
  </thead>
23
36
  );
@@ -26,6 +26,7 @@ export {useTableColumnSettings} from './plugins/columnSettings';
26
26
  export {useTableColumnSettingsState} from './plugins/columnSettings';
27
27
  export {useTableColumnResize} from './plugins/columnResize';
28
28
  export {useTableStickyColumns} from './plugins/stickyColumns';
29
+ export {useTableGroupedRows} from './plugins/groupedRows';
29
30
  export {
30
31
  useTableRowExpansion,
31
32
  useTableRowExpansionState,
@@ -102,6 +103,10 @@ export type {
102
103
  export type {UseTableColumnResizeConfig} from './plugins/columnResize';
103
104
  export type {UseTableStickyColumnsConfig} from './plugins/stickyColumns';
104
105
  export type {UseTableRowExpansionConfig} from './plugins/rowExpansion';
106
+ export type {
107
+ UseTableGroupedRowsConfig,
108
+ UseTableGroupedRowsResult,
109
+ } from './plugins/groupedRows';
105
110
  export type {
106
111
  UseTableFilteringConfig,
107
112
  TableFilterState,
@@ -551,6 +551,19 @@ describe('useTableColumnResize', () => {
551
551
  expect(handle).toHaveAttribute('aria-valuenow', '200');
552
552
  });
553
553
 
554
+ it('handle has a numeric aria-valuenow on initial render (before any width is measured)', () => {
555
+ // A focusable role="separator" requires aria-valuenow per the ARIA spec.
556
+ // Before the column width has been measured there is no override width, so
557
+ // the handle must fall back to a defined numeric value (the column
558
+ // minWidth) rather than omitting the attribute.
559
+ render(<ResizeTable minWidth={80} />);
560
+ const handle = getResizeHandles()[0];
561
+ const valueNow = handle.getAttribute('aria-valuenow');
562
+ expect(valueNow).not.toBeNull();
563
+ expect(Number.isNaN(Number(valueNow))).toBe(false);
564
+ expect(valueNow).toBe('80');
565
+ });
566
+
554
567
  it('handle has aria-label with column header text', () => {
555
568
  render(<ResizeTable />);
556
569
  const handle = getResizeHandles()[0];
@@ -676,7 +676,9 @@ function ResizeHandle({
676
676
  <div
677
677
  role="separator"
678
678
  aria-orientation="vertical"
679
- aria-valuenow={currentWidth ?? undefined}
679
+ // A focusable role="separator" requires a numeric aria-valuenow, so fall
680
+ // back to the column's minWidth before the width has been measured.
681
+ aria-valuenow={currentWidth ?? minWidth}
680
682
  aria-valuemin={minWidth}
681
683
  aria-valuemax={maxWidth === Infinity ? undefined : maxWidth}
682
684
  aria-label={ariaLabel}
@@ -0,0 +1,7 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ export {useTableGroupedRows} from './useTableGroupedRows';
4
+ export type {
5
+ UseTableGroupedRowsConfig,
6
+ UseTableGroupedRowsResult,
7
+ } from './useTableGroupedRows';