@astryxdesign/core 0.1.9 → 0.2.0-canary.0f56f82

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 (565) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/Avatar/Avatar.d.ts +42 -3
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +190 -59
  5. package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
  6. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  7. package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
  8. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  9. package/dist/AvatarGroup/AvatarGroup.js +58 -6
  10. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  11. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  12. package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
  13. package/dist/Banner/Banner.js +2 -2
  14. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  15. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
  16. package/dist/Breadcrumbs/index.d.ts +1 -0
  17. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  18. package/dist/Breadcrumbs/index.js +2 -1
  19. package/dist/Button/Button.d.ts +1 -1
  20. package/dist/Button/Button.d.ts.map +1 -1
  21. package/dist/Button/Button.js +6 -4
  22. package/dist/Calendar/Calendar.d.ts.map +1 -1
  23. package/dist/Calendar/Calendar.js +50 -9
  24. package/dist/Calendar/dayCellUtils.d.ts +4 -4
  25. package/dist/Calendar/dayCellUtils.js +2 -2
  26. package/dist/Calendar/styles.d.ts +30 -31
  27. package/dist/Calendar/styles.d.ts.map +1 -1
  28. package/dist/Calendar/styles.js +30 -31
  29. package/dist/Card/Card.js +1 -1
  30. package/dist/Carousel/Carousel.d.ts.map +1 -1
  31. package/dist/Carousel/Carousel.js +22 -12
  32. package/dist/Chat/ChatComposerInput.js +1 -1
  33. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  34. package/dist/Chat/ChatDictationButton.js +3 -1
  35. package/dist/Chat/ChatLayout.js +4 -4
  36. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  37. package/dist/Chat/ChatMessageBubble.js +8 -8
  38. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  39. package/dist/Chat/ChatToolCalls.js +10 -3
  40. package/dist/Chat/useTriggerMenu.js +2 -2
  41. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  42. package/dist/CheckboxInput/CheckboxInput.js +6 -6
  43. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  44. package/dist/CheckboxList/CheckboxListItem.js +19 -4
  45. package/dist/Citation/Citation.d.ts +22 -1
  46. package/dist/Citation/Citation.d.ts.map +1 -1
  47. package/dist/Citation/Citation.js +20 -6
  48. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  49. package/dist/CodeBlock/CodeBlock.js +16 -10
  50. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  51. package/dist/Collapsible/Collapsible.js +3 -1
  52. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  53. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  54. package/dist/CommandPalette/CommandPalette.js +42 -3
  55. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  56. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  57. package/dist/ContextMenu/ContextMenu.js +23 -5
  58. package/dist/ContextMenu/index.d.ts +1 -0
  59. package/dist/ContextMenu/index.d.ts.map +1 -1
  60. package/dist/ContextMenu/index.js +3 -1
  61. package/dist/DateInput/DateInput.d.ts +10 -2
  62. package/dist/DateInput/DateInput.d.ts.map +1 -1
  63. package/dist/DateInput/DateInput.js +33 -19
  64. package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
  65. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  66. package/dist/DateRangeInput/DateRangeInput.js +23 -20
  67. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  68. package/dist/DateTimeInput/DateTimeInput.js +23 -18
  69. package/dist/Divider/Divider.d.ts +2 -2
  70. package/dist/Divider/Divider.d.ts.map +1 -1
  71. package/dist/Divider/Divider.js +13 -0
  72. package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
  73. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  74. package/dist/DropdownMenu/DropdownMenu.js +22 -5
  75. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  76. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
  77. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  78. package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
  79. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
  80. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  81. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
  82. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
  83. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  84. package/dist/DropdownMenu/DropdownMenuRadioItem.js +5 -2
  85. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
  86. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
  87. package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
  88. package/dist/DropdownMenu/index.d.ts +10 -0
  89. package/dist/DropdownMenu/index.d.ts.map +1 -1
  90. package/dist/DropdownMenu/index.js +13 -0
  91. package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
  92. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  93. package/dist/DropdownMenu/menuItemHover.js +33 -0
  94. package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
  95. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
  96. package/dist/DropdownMenu/menuItemRoles.js +10 -1
  97. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  98. package/dist/DropdownMenu/renderDropdownItems.js +21 -6
  99. package/dist/Field/Field.d.ts +3 -1
  100. package/dist/Field/Field.d.ts.map +1 -1
  101. package/dist/Field/Field.js +4 -1
  102. package/dist/Field/FieldLabel.d.ts +2 -1
  103. package/dist/Field/FieldLabel.d.ts.map +1 -1
  104. package/dist/Field/FieldLabel.js +9 -5
  105. package/dist/Field/inputStyles.stylex.d.ts +1 -0
  106. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  107. package/dist/Field/inputStyles.stylex.js +1 -0
  108. package/dist/FieldStatus/FieldStatus.d.ts +10 -0
  109. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  110. package/dist/FieldStatus/FieldStatus.js +51 -5
  111. package/dist/FileInput/FileInput.d.ts +10 -2
  112. package/dist/FileInput/FileInput.d.ts.map +1 -1
  113. package/dist/FileInput/FileInput.js +93 -65
  114. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  115. package/dist/HoverCard/useHoverCard.js +10 -4
  116. package/dist/Icon/Icon.d.ts +15 -1
  117. package/dist/Icon/Icon.d.ts.map +1 -1
  118. package/dist/Icon/Icon.js +19 -3
  119. package/dist/Item/Item.d.ts +16 -3
  120. package/dist/Item/Item.d.ts.map +1 -1
  121. package/dist/Item/Item.js +31 -6
  122. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  123. package/dist/Layer/layerAnimations.stylex.js +10 -2
  124. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  125. package/dist/Lightbox/Lightbox.js +19 -13
  126. package/dist/List/List.d.ts.map +1 -1
  127. package/dist/List/List.js +6 -3
  128. package/dist/List/ListItem.d.ts +11 -1
  129. package/dist/List/ListItem.d.ts.map +1 -1
  130. package/dist/List/ListItem.js +2 -0
  131. package/dist/Markdown/Markdown.d.ts.map +1 -1
  132. package/dist/Markdown/Markdown.js +7 -0
  133. package/dist/MetadataList/MetadataList.d.ts +1 -1
  134. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  135. package/dist/MetadataList/MetadataList.js +4 -2
  136. package/dist/MultiSelector/MultiSelector.d.ts +9 -1
  137. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  138. package/dist/MultiSelector/MultiSelector.js +80 -42
  139. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  140. package/dist/NumberInput/NumberInput.d.ts +10 -2
  141. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  142. package/dist/NumberInput/NumberInput.js +22 -17
  143. package/dist/Outline/Outline.js +2 -2
  144. package/dist/Pagination/Pagination.d.ts.map +1 -1
  145. package/dist/Pagination/Pagination.js +11 -3
  146. package/dist/PowerSearch/PowerSearch.d.ts +9 -2
  147. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  148. package/dist/PowerSearch/PowerSearch.js +2 -0
  149. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  150. package/dist/ProgressBar/ProgressBar.js +6 -1
  151. package/dist/RadioList/RadioList.d.ts +2 -2
  152. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  153. package/dist/RadioList/RadioListItem.js +5 -5
  154. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  155. package/dist/Resizable/ResizeHandle.js +49 -19
  156. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  157. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  158. package/dist/SegmentedControl/SegmentedControlItem.js +5 -3
  159. package/dist/Selector/Selector.d.ts +8 -0
  160. package/dist/Selector/Selector.d.ts.map +1 -1
  161. package/dist/Selector/Selector.js +66 -17
  162. package/dist/SideNav/SideNav.d.ts.map +1 -1
  163. package/dist/SideNav/SideNav.js +5 -5
  164. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  165. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  166. package/dist/SideNav/SideNavItem.d.ts +1 -1
  167. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  168. package/dist/SideNav/SideNavItem.js +12 -10
  169. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  170. package/dist/Skeleton/Skeleton.js +2 -2
  171. package/dist/Slider/Slider.d.ts.map +1 -1
  172. package/dist/Slider/Slider.js +87 -34
  173. package/dist/Spinner/Spinner.d.ts +3 -2
  174. package/dist/Spinner/Spinner.d.ts.map +1 -1
  175. package/dist/Spinner/Spinner.js +11 -2
  176. package/dist/Switch/Switch.d.ts +8 -1
  177. package/dist/Switch/Switch.d.ts.map +1 -1
  178. package/dist/Switch/Switch.js +171 -91
  179. package/dist/TabList/Tab.js +2 -2
  180. package/dist/TabList/TabList.d.ts +2 -11
  181. package/dist/TabList/TabList.d.ts.map +1 -1
  182. package/dist/TabList/TabList.js +5 -9
  183. package/dist/TabList/TabListContext.d.ts +0 -5
  184. package/dist/TabList/TabListContext.d.ts.map +1 -1
  185. package/dist/TabList/TabListContext.js +0 -5
  186. package/dist/TabList/TabMenu.js +1 -1
  187. package/dist/Table/BaseTable.d.ts.map +1 -1
  188. package/dist/Table/BaseTable.js +30 -4
  189. package/dist/Table/TableCell.js +3 -3
  190. package/dist/Table/TableHeaderCell.js +3 -3
  191. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  192. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  193. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  194. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +37 -27
  195. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  196. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  197. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  198. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +15 -7
  199. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  200. package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
  201. package/dist/Table/types.d.ts +32 -0
  202. package/dist/Table/types.d.ts.map +1 -1
  203. package/dist/TextArea/TextArea.d.ts +10 -1
  204. package/dist/TextArea/TextArea.d.ts.map +1 -1
  205. package/dist/TextArea/TextArea.js +18 -19
  206. package/dist/TextInput/TextInput.d.ts +10 -2
  207. package/dist/TextInput/TextInput.d.ts.map +1 -1
  208. package/dist/TextInput/TextInput.js +20 -17
  209. package/dist/Thumbnail/Thumbnail.js +2 -2
  210. package/dist/TimeInput/TimeInput.d.ts +10 -2
  211. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  212. package/dist/TimeInput/TimeInput.js +17 -17
  213. package/dist/Timestamp/Timestamp.d.ts +31 -3
  214. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  215. package/dist/Timestamp/Timestamp.js +47 -76
  216. package/dist/Timestamp/formatInstant.d.ts +41 -0
  217. package/dist/Timestamp/formatInstant.d.ts.map +1 -0
  218. package/dist/Timestamp/formatInstant.js +177 -0
  219. package/dist/Timestamp/index.d.ts +1 -0
  220. package/dist/Timestamp/index.d.ts.map +1 -1
  221. package/dist/Timestamp/tooltipEntries.d.ts +56 -0
  222. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
  223. package/dist/Timestamp/tooltipEntries.js +163 -0
  224. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  225. package/dist/Toast/ToastViewport.js +61 -9
  226. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  227. package/dist/ToggleButton/ToggleButton.js +3 -1
  228. package/dist/Token/Token.d.ts +34 -4
  229. package/dist/Token/Token.d.ts.map +1 -1
  230. package/dist/Token/Token.js +85 -45
  231. package/dist/Token/TokenLink.d.ts +62 -0
  232. package/dist/Token/TokenLink.d.ts.map +1 -0
  233. package/dist/Token/TokenLink.js +76 -0
  234. package/dist/Token/index.d.ts +1 -1
  235. package/dist/Token/index.d.ts.map +1 -1
  236. package/dist/Tokenizer/Tokenizer.d.ts +9 -2
  237. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  238. package/dist/Tokenizer/Tokenizer.js +4 -2
  239. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  240. package/dist/Tooltip/useTooltip.js +17 -1
  241. package/dist/TopNav/TopNavItem.d.ts +3 -1
  242. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  243. package/dist/TopNav/TopNavItem.js +30 -3
  244. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  245. package/dist/TopNav/TopNavMegaMenu.js +9 -3
  246. package/dist/TreeList/TreeList.d.ts.map +1 -1
  247. package/dist/TreeList/TreeList.js +1 -0
  248. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  249. package/dist/TreeList/TreeListBranches.js +8 -6
  250. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  251. package/dist/TreeList/TreeListItem.js +32 -14
  252. package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
  253. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  254. package/dist/Typeahead/BaseTypeahead.js +22 -11
  255. package/dist/Typeahead/Typeahead.d.ts +9 -2
  256. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  257. package/dist/Typeahead/Typeahead.js +11 -2
  258. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  259. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  260. package/dist/Typeahead/TypeaheadItem.js +20 -10
  261. package/dist/astryx.css +74 -33
  262. package/dist/astryx.umd.js +51 -51
  263. package/dist/astryx.umd.js.map +4 -4
  264. package/dist/hooks/index.d.ts +2 -0
  265. package/dist/hooks/index.d.ts.map +1 -1
  266. package/dist/hooks/index.js +1 -0
  267. package/dist/hooks/isRtlElement.d.ts +18 -0
  268. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  269. package/dist/hooks/isRtlElement.js +27 -0
  270. package/dist/hooks/useAnnounce.d.ts +3 -0
  271. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  272. package/dist/hooks/useAnnounce.js +39 -1
  273. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  274. package/dist/hooks/useFocusTrap.js +52 -11
  275. package/dist/hooks/useGridFocus.d.ts +6 -1
  276. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  277. package/dist/hooks/useGridFocus.js +12 -9
  278. package/dist/hooks/useHotkeys.d.ts +9 -0
  279. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  280. package/dist/hooks/useHotkeys.js +9 -0
  281. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  282. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  283. package/dist/hooks/useInputStatusIcon.js +169 -0
  284. package/dist/hooks/useKeyboardHint.d.ts +1 -1
  285. package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
  286. package/dist/hooks/useKeyboardHint.js +4 -2
  287. package/dist/hooks/useListFocus.d.ts +39 -1
  288. package/dist/hooks/useListFocus.d.ts.map +1 -1
  289. package/dist/hooks/useListFocus.js +54 -9
  290. package/dist/i18n/InternationalizationContext.d.ts +1 -0
  291. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  292. package/dist/i18n/InternationalizationContext.js +3 -0
  293. package/dist/i18n/InternationalizationProvider.d.ts +8 -1
  294. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  295. package/dist/i18n/InternationalizationProvider.js +5 -1
  296. package/dist/i18n/getLocaleDirection.d.ts +18 -0
  297. package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
  298. package/dist/i18n/getLocaleDirection.js +29 -0
  299. package/dist/i18n/index.d.ts +6 -0
  300. package/dist/i18n/index.d.ts.map +1 -1
  301. package/dist/i18n/index.js +7 -1
  302. package/dist/i18n/useDirection.d.ts +2 -0
  303. package/dist/i18n/useDirection.d.ts.map +1 -0
  304. package/dist/i18n/useDirection.js +27 -0
  305. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  306. package/dist/theme/derivedVarRegistry.js +13 -0
  307. package/dist/utils/index.d.ts +1 -0
  308. package/dist/utils/index.d.ts.map +1 -1
  309. package/dist/utils/index.js +2 -1
  310. package/dist/utils/plainDate.d.ts +17 -0
  311. package/dist/utils/plainDate.d.ts.map +1 -1
  312. package/dist/utils/plainDate.js +23 -4
  313. package/dist/utils/rtlStyles.d.ts +24 -0
  314. package/dist/utils/rtlStyles.d.ts.map +1 -0
  315. package/dist/utils/rtlStyles.js +27 -0
  316. package/locales/en.json +112 -0
  317. package/locales/pseudo.json +84 -0
  318. package/package.json +6 -1
  319. package/src/Avatar/Avatar.doc.mjs +50 -3
  320. package/src/Avatar/Avatar.test.tsx +218 -0
  321. package/src/Avatar/Avatar.tsx +285 -79
  322. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  323. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  324. package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
  325. package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
  326. package/src/AvatarGroup/AvatarGroup.tsx +58 -3
  327. package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
  328. package/src/Banner/Banner.tsx +6 -6
  329. package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
  330. package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
  331. package/src/Breadcrumbs/index.ts +4 -0
  332. package/src/Button/Button.doc.mjs +0 -4
  333. package/src/Button/Button.test.tsx +16 -0
  334. package/src/Button/Button.tsx +6 -4
  335. package/src/Calendar/Calendar.test.tsx +170 -20
  336. package/src/Calendar/Calendar.tsx +73 -16
  337. package/src/Calendar/dayCellUtils.test.ts +18 -18
  338. package/src/Calendar/dayCellUtils.ts +2 -2
  339. package/src/Calendar/styles.ts +33 -39
  340. package/src/Card/Card.tsx +1 -1
  341. package/src/Carousel/Carousel.tsx +25 -6
  342. package/src/Chat/ChatComposer.doc.mjs +2 -2
  343. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  344. package/src/Chat/ChatComposerInput.tsx +2 -2
  345. package/src/Chat/ChatDictationButton.tsx +7 -1
  346. package/src/Chat/ChatLayout.tsx +4 -4
  347. package/src/Chat/ChatMessageBubble.tsx +15 -10
  348. package/src/Chat/ChatSystemMessage.test.tsx +5 -0
  349. package/src/Chat/ChatToolCalls.tsx +9 -2
  350. package/src/Chat/useTriggerMenu.tsx +1 -1
  351. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  352. package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
  353. package/src/CheckboxInput/CheckboxInput.tsx +21 -6
  354. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  355. package/src/CheckboxList/CheckboxList.test.tsx +94 -3
  356. package/src/CheckboxList/CheckboxListItem.tsx +17 -10
  357. package/src/Citation/Citation.doc.mjs +4 -3
  358. package/src/Citation/Citation.test.tsx +97 -0
  359. package/src/Citation/Citation.tsx +43 -11
  360. package/src/CodeBlock/CodeBlock.test.tsx +17 -0
  361. package/src/CodeBlock/CodeBlock.tsx +38 -11
  362. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  363. package/src/Collapsible/Collapsible.test.tsx +7 -0
  364. package/src/Collapsible/Collapsible.tsx +16 -6
  365. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  366. package/src/CommandPalette/CommandPalette.tsx +41 -2
  367. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  368. package/src/ContextMenu/ContextMenu.test.tsx +59 -2
  369. package/src/ContextMenu/ContextMenu.tsx +22 -11
  370. package/src/ContextMenu/index.ts +5 -0
  371. package/src/DateInput/DateInput.doc.mjs +25 -0
  372. package/src/DateInput/DateInput.test.tsx +230 -0
  373. package/src/DateInput/DateInput.tsx +51 -29
  374. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  375. package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
  376. package/src/DateRangeInput/DateRangeInput.tsx +42 -30
  377. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  378. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  379. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  380. package/src/Divider/Divider.test.tsx +32 -8
  381. package/src/Divider/Divider.tsx +14 -1
  382. package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
  383. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  384. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
  385. package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
  386. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
  387. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
  388. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +9 -3
  389. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +20 -2
  390. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  391. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
  392. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
  393. package/src/DropdownMenu/index.ts +16 -0
  394. package/src/DropdownMenu/menuItemHover.ts +39 -0
  395. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  396. package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
  397. package/src/Field/Field.doc.mjs +4 -0
  398. package/src/Field/Field.tsx +14 -9
  399. package/src/Field/FieldLabel.test.tsx +25 -0
  400. package/src/Field/FieldLabel.tsx +12 -3
  401. package/src/Field/inputStyles.stylex.ts +2 -0
  402. package/src/FieldStatus/FieldStatus.doc.mjs +1 -0
  403. package/src/FieldStatus/FieldStatus.test.tsx +133 -0
  404. package/src/FieldStatus/FieldStatus.tsx +61 -4
  405. package/src/FileInput/FileInput.doc.mjs +23 -2
  406. package/src/FileInput/FileInput.test.tsx +104 -13
  407. package/src/FileInput/FileInput.tsx +106 -79
  408. package/src/HoverCard/useHoverCard.tsx +15 -3
  409. package/src/Icon/Icon.doc.mjs +13 -0
  410. package/src/Icon/Icon.test.tsx +89 -0
  411. package/src/Icon/Icon.tsx +51 -3
  412. package/src/Item/Item.doc.mjs +5 -0
  413. package/src/Item/Item.test.tsx +88 -0
  414. package/src/Item/Item.tsx +57 -11
  415. package/src/Layer/layerAnimations.stylex.ts +23 -0
  416. package/src/Lightbox/Lightbox.tsx +15 -7
  417. package/src/List/List.test.tsx +17 -29
  418. package/src/List/List.tsx +6 -1
  419. package/src/List/ListItem.doc.mjs +12 -0
  420. package/src/List/ListItem.tsx +13 -0
  421. package/src/Markdown/Markdown.test.tsx +21 -0
  422. package/src/Markdown/Markdown.tsx +4 -0
  423. package/src/MetadataList/MetadataList.test.tsx +24 -0
  424. package/src/MetadataList/MetadataList.tsx +6 -2
  425. package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
  426. package/src/MultiSelector/MultiSelector.test.tsx +402 -0
  427. package/src/MultiSelector/MultiSelector.tsx +120 -59
  428. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  429. package/src/NumberInput/NumberInput.doc.mjs +21 -0
  430. package/src/NumberInput/NumberInput.test.tsx +71 -0
  431. package/src/NumberInput/NumberInput.tsx +35 -26
  432. package/src/Outline/Outline.test.tsx +12 -12
  433. package/src/Outline/Outline.tsx +2 -2
  434. package/src/Pagination/Pagination.tsx +11 -3
  435. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  436. package/src/PowerSearch/PowerSearch.test.tsx +23 -0
  437. package/src/PowerSearch/PowerSearch.tsx +10 -1
  438. package/src/ProgressBar/ProgressBar.test.tsx +34 -0
  439. package/src/ProgressBar/ProgressBar.tsx +16 -1
  440. package/src/RadioList/RadioList.doc.mjs +6 -0
  441. package/src/RadioList/RadioList.test.tsx +26 -4
  442. package/src/RadioList/RadioList.tsx +2 -2
  443. package/src/RadioList/RadioListItem.tsx +12 -5
  444. package/src/Resizable/ResizeHandle.test.tsx +94 -0
  445. package/src/Resizable/ResizeHandle.tsx +70 -20
  446. package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
  447. package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
  448. package/src/Selector/Selector.doc.mjs +15 -0
  449. package/src/Selector/Selector.test.tsx +370 -0
  450. package/src/Selector/Selector.tsx +88 -20
  451. package/src/SideNav/SideNav.tsx +1 -8
  452. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  453. package/src/SideNav/SideNavItem.tsx +5 -3
  454. package/src/Skeleton/Skeleton.test.tsx +16 -0
  455. package/src/Skeleton/Skeleton.tsx +13 -1
  456. package/src/Slider/Slider.doc.mjs +6 -0
  457. package/src/Slider/Slider.test.tsx +240 -12
  458. package/src/Slider/Slider.tsx +96 -23
  459. package/src/Spinner/Spinner.test.tsx +10 -8
  460. package/src/Spinner/Spinner.tsx +15 -5
  461. package/src/Switch/Switch.doc.mjs +142 -42
  462. package/src/Switch/Switch.test.tsx +111 -0
  463. package/src/Switch/Switch.tsx +149 -32
  464. package/src/TabList/Tab.tsx +2 -2
  465. package/src/TabList/TabList.doc.mjs +0 -6
  466. package/src/TabList/TabList.test.tsx +3 -15
  467. package/src/TabList/TabList.tsx +6 -17
  468. package/src/TabList/TabListContext.ts +0 -6
  469. package/src/TabList/TabMenu.tsx +2 -2
  470. package/src/Table/BaseTable.tsx +34 -2
  471. package/src/Table/Table.doc.mjs +11 -0
  472. package/src/Table/Table.test.tsx +85 -0
  473. package/src/Table/TableCell.tsx +3 -3
  474. package/src/Table/TableHeaderCell.tsx +3 -3
  475. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  476. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
  477. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +27 -18
  478. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  479. package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
  480. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +38 -9
  481. package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
  482. package/src/Table/types.ts +33 -0
  483. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  484. package/src/TextArea/TextArea.doc.mjs +21 -0
  485. package/src/TextArea/TextArea.test.tsx +23 -0
  486. package/src/TextArea/TextArea.tsx +27 -26
  487. package/src/TextInput/TextInput.doc.mjs +21 -0
  488. package/src/TextInput/TextInput.test.tsx +150 -0
  489. package/src/TextInput/TextInput.tsx +28 -25
  490. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  491. package/src/Thumbnail/Thumbnail.tsx +1 -1
  492. package/src/TimeInput/TimeInput.doc.mjs +21 -0
  493. package/src/TimeInput/TimeInput.test.tsx +23 -0
  494. package/src/TimeInput/TimeInput.tsx +24 -25
  495. package/src/Timestamp/Timestamp.doc.mjs +32 -6
  496. package/src/Timestamp/Timestamp.test.tsx +371 -0
  497. package/src/Timestamp/Timestamp.tsx +96 -93
  498. package/src/Timestamp/formatInstant.ts +218 -0
  499. package/src/Timestamp/index.ts +4 -0
  500. package/src/Timestamp/tooltipEntries.test.ts +552 -0
  501. package/src/Timestamp/tooltipEntries.ts +210 -0
  502. package/src/Toast/ToastViewport.test.tsx +218 -8
  503. package/src/Toast/ToastViewport.tsx +71 -12
  504. package/src/ToggleButton/ToggleButton.test.tsx +24 -0
  505. package/src/ToggleButton/ToggleButton.tsx +19 -1
  506. package/src/Token/Token.test.tsx +166 -15
  507. package/src/Token/Token.tsx +104 -47
  508. package/src/Token/TokenLink.tsx +107 -0
  509. package/src/Token/index.ts +1 -1
  510. package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
  511. package/src/Tokenizer/Tokenizer.test.tsx +23 -0
  512. package/src/Tokenizer/Tokenizer.tsx +14 -2
  513. package/src/Tooltip/Tooltip.test.tsx +46 -0
  514. package/src/Tooltip/useTooltip.tsx +20 -0
  515. package/src/TopNav/TopNav.test.tsx +93 -2
  516. package/src/TopNav/TopNavItem.doc.mjs +3 -3
  517. package/src/TopNav/TopNavItem.tsx +35 -6
  518. package/src/TopNav/TopNavMegaMenu.tsx +26 -2
  519. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
  520. package/src/TreeList/TreeList.doc.mjs +6 -0
  521. package/src/TreeList/TreeList.test.tsx +50 -10
  522. package/src/TreeList/TreeList.tsx +5 -0
  523. package/src/TreeList/TreeListBranches.tsx +8 -6
  524. package/src/TreeList/TreeListItem.tsx +33 -11
  525. package/src/Typeahead/BaseTypeahead.tsx +42 -15
  526. package/src/Typeahead/Typeahead.doc.mjs +13 -0
  527. package/src/Typeahead/Typeahead.test.tsx +112 -0
  528. package/src/Typeahead/Typeahead.tsx +17 -1
  529. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  530. package/src/__tests__/forcedColors.ts +60 -0
  531. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  532. package/src/doc-mjs.d.ts +19 -0
  533. package/src/hooks/index.ts +6 -0
  534. package/src/hooks/isRtlElement.ts +27 -0
  535. package/src/hooks/useAnnounce.test.tsx +75 -2
  536. package/src/hooks/useAnnounce.ts +47 -1
  537. package/src/hooks/useFocusTrap.test.tsx +104 -0
  538. package/src/hooks/useFocusTrap.ts +61 -12
  539. package/src/hooks/useGridFocus.doc.mjs +3 -3
  540. package/src/hooks/useGridFocus.test.tsx +41 -0
  541. package/src/hooks/useGridFocus.ts +21 -10
  542. package/src/hooks/useHotkeys.ts +9 -0
  543. package/src/hooks/useInputStatusIcon.test.tsx +221 -0
  544. package/src/hooks/useInputStatusIcon.tsx +235 -0
  545. package/src/hooks/useKeyboardHint.test.tsx +22 -0
  546. package/src/hooks/useKeyboardHint.tsx +6 -2
  547. package/src/hooks/useListFocus.doc.mjs +25 -3
  548. package/src/hooks/useListFocus.test.tsx +153 -1
  549. package/src/hooks/useListFocus.ts +102 -9
  550. package/src/i18n/InternationalizationContext.ts +4 -0
  551. package/src/i18n/InternationalizationProvider.tsx +12 -2
  552. package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
  553. package/src/i18n/__tests__/useDirection.test.tsx +66 -0
  554. package/src/i18n/getLocaleDirection.ts +29 -0
  555. package/src/i18n/index.ts +6 -0
  556. package/src/i18n/useDirection.ts +29 -0
  557. package/src/reset.css +0 -26
  558. package/src/reset.test.ts +60 -0
  559. package/src/theme/derivedVarRegistry.test.ts +1 -0
  560. package/src/theme/derivedVarRegistry.ts +6 -0
  561. package/src/theme/generateThemeRules.test.ts +42 -0
  562. package/src/utils/index.ts +2 -0
  563. package/src/utils/plainDate.test.ts +24 -6
  564. package/src/utils/plainDate.ts +18 -4
  565. package/src/utils/rtlStyles.ts +27 -0
@@ -93,6 +93,17 @@ export const docs = {
93
93
  type: 'Record<string, TablePlugin<T>>',
94
94
  description: 'Named plugins that extend table behavior via the transform pipeline. Converted to an ordered array internally.',
95
95
  },
96
+ {
97
+ name: 'rowIndexStart',
98
+ type: 'number',
99
+ description: 'ARIA row index (1-based) for the first rendered body row. The row ordinal is an accessibility concern independent of any visible index column, so setting this (or rowCount) makes the table emit aria-rowindex on body rows and aria-rowcount on the table. For a paginated/windowed view, pass the offset of the first visible row (e.g. (page - 1) * pageSize + 1) so aria-rowindex reflects position in the full dataset. Data-driven mode only.',
100
+ default: '1',
101
+ },
102
+ {
103
+ name: 'rowCount',
104
+ type: 'number',
105
+ description: 'Total number of body rows across all pages/windows, used for aria-rowcount so assistive tech can announce "row X of Y" against the full dataset. When omitted but rowIndexStart is set (windowed view with an unknown total), aria-rowcount is set to -1 per the ARIA unknown-count convention. Data-driven mode only.',
106
+ },
96
107
  {
97
108
  name: 'children',
98
109
  type: 'ReactNode',
@@ -1451,3 +1451,88 @@ describe('emptyState', () => {
1451
1451
  });
1452
1452
  });
1453
1453
  });
1454
+
1455
+ describe('ARIA row indexing (#3939)', () => {
1456
+ const bodyRows = (container: HTMLElement): HTMLTableRowElement[] =>
1457
+ Array.from(container.querySelectorAll('tbody tr'));
1458
+
1459
+ it('emits no aria-rowindex/aria-rowcount by default', () => {
1460
+ const {container} = render(<Table data={users} columns={columns} />);
1461
+ expect(screen.getByRole('table')).not.toHaveAttribute('aria-rowcount');
1462
+ for (const row of bodyRows(container)) {
1463
+ expect(row).not.toHaveAttribute('aria-rowindex');
1464
+ }
1465
+ });
1466
+
1467
+ it('numbers rows from 1 when rowCount is provided', () => {
1468
+ const {container} = render(
1469
+ <Table data={users} columns={columns} rowCount={users.length} />,
1470
+ );
1471
+ expect(screen.getByRole('table')).toHaveAttribute(
1472
+ 'aria-rowcount',
1473
+ String(users.length),
1474
+ );
1475
+ const indices = bodyRows(container).map(r =>
1476
+ r.getAttribute('aria-rowindex'),
1477
+ );
1478
+ expect(indices).toEqual(['1', '2', '3']);
1479
+ });
1480
+
1481
+ it('offsets aria-rowindex by rowIndexStart for a paginated view', () => {
1482
+ // Page 3 of a 10-per-page dataset: first visible row is dataset row 21.
1483
+ const {container} = render(
1484
+ <Table
1485
+ data={users}
1486
+ columns={columns}
1487
+ rowIndexStart={21}
1488
+ rowCount={100}
1489
+ />,
1490
+ );
1491
+ expect(screen.getByRole('table')).toHaveAttribute('aria-rowcount', '100');
1492
+ const indices = bodyRows(container).map(r =>
1493
+ r.getAttribute('aria-rowindex'),
1494
+ );
1495
+ expect(indices).toEqual(['21', '22', '23']);
1496
+ });
1497
+
1498
+ it('sets aria-rowcount to -1 (unknown) when only rowIndexStart is given', () => {
1499
+ // Windowed/cursor pagination: offset known, total unknown.
1500
+ const {container} = render(
1501
+ <Table data={users} columns={columns} rowIndexStart={5} />,
1502
+ );
1503
+ expect(screen.getByRole('table')).toHaveAttribute('aria-rowcount', '-1');
1504
+ const indices = bodyRows(container).map(r =>
1505
+ r.getAttribute('aria-rowindex'),
1506
+ );
1507
+ expect(indices).toEqual(['5', '6', '7']);
1508
+ });
1509
+
1510
+ it('does not assign an ARIA row index to the header row', () => {
1511
+ render(<Table data={users} columns={columns} rowCount={users.length} />);
1512
+ const header = screen.getAllByRole('row')[0];
1513
+ expect(header).not.toHaveAttribute('aria-rowindex');
1514
+ });
1515
+
1516
+ it('lets a plugin override the seeded aria-rowindex', () => {
1517
+ const plugin: TablePlugin<User> = {
1518
+ transformBodyRow(props, _item, index) {
1519
+ return {
1520
+ ...props,
1521
+ htmlProps: {...props.htmlProps, 'aria-rowindex': 100 + index},
1522
+ };
1523
+ },
1524
+ };
1525
+ const {container} = render(
1526
+ <Table
1527
+ data={users}
1528
+ columns={columns}
1529
+ rowCount={users.length}
1530
+ plugins={{custom: plugin}}
1531
+ />,
1532
+ );
1533
+ const indices = bodyRows(container).map(r =>
1534
+ r.getAttribute('aria-rowindex'),
1535
+ );
1536
+ expect(indices).toEqual(['100', '101', '102']);
1537
+ });
1538
+ });
@@ -161,12 +161,12 @@ const dividerRowStyles = stylex.create({
161
161
 
162
162
  const dividerColumnStyles = stylex.create({
163
163
  cell: {
164
- borderRightWidth: {
164
+ borderInlineEndWidth: {
165
165
  default: borderVars['--border-width'],
166
166
  ':last-child': '0',
167
167
  },
168
- borderRightStyle: 'solid',
169
- borderRightColor: colorVars['--color-border'],
168
+ borderInlineEndStyle: 'solid',
169
+ borderInlineEndColor: colorVars['--color-border'],
170
170
  },
171
171
  });
172
172
 
@@ -91,12 +91,12 @@ const headerDividerStyles = stylex.create({
91
91
 
92
92
  const dividerColumnStyles = stylex.create({
93
93
  cell: {
94
- borderRightWidth: {
94
+ borderInlineEndWidth: {
95
95
  default: borderVars['--border-width'],
96
96
  ':last-child': '0',
97
97
  },
98
- borderRightStyle: 'solid',
99
- borderRightColor: colorVars['--color-border'],
98
+ borderInlineEndStyle: 'solid',
99
+ borderInlineEndColor: colorVars['--color-border'],
100
100
  },
101
101
  });
102
102
 
@@ -20,6 +20,7 @@ import {
20
20
  fontWeightVars,
21
21
  } from '../../../theme/tokens.stylex';
22
22
  import {Icon} from '../../../Icon';
23
+ import {rtlStyles} from '../../../utils';
23
24
  import type {TablePlugin} from '../../types';
24
25
  import {useTranslator} from '../../../i18n';
25
26
 
@@ -333,12 +334,14 @@ export function useTableGroupedRows<T extends Record<string, unknown>>(
333
334
  })
334
335
  }
335
336
  aria-expanded={!collapsed}>
336
- <span
337
- {...stylex.props(
338
- styles.chevronIcon,
339
- !collapsed && styles.chevronExpanded,
340
- )}>
341
- <Icon icon="chevronRight" size="xsm" />
337
+ <span {...stylex.props(rtlStyles.mirror)}>
338
+ <span
339
+ {...stylex.props(
340
+ styles.chevronIcon,
341
+ !collapsed && styles.chevronExpanded,
342
+ )}>
343
+ <Icon icon="chevronRight" size="xsm" />
344
+ </span>
342
345
  </span>
343
346
  </button>
344
347
  {content}
@@ -9,6 +9,7 @@ import {
9
9
  useTableRowExpansion,
10
10
  useTableRowExpansionState,
11
11
  } from './useTableRowExpansion';
12
+ import {InternationalizationProvider} from '../../../i18n';
12
13
 
13
14
  // popover mock for context-menu tests
14
15
  beforeEach(() => {
@@ -118,6 +119,24 @@ describe('useTableRowExpansion', () => {
118
119
  expect(items.length).toBeGreaterThan(0);
119
120
  });
120
121
 
122
+ it('localizes the context-menu action label through the i18n catalog', () => {
123
+ render(
124
+ <InternationalizationProvider
125
+ locale="fr"
126
+ overrides={{
127
+ fr: {'@astryx.tableRowExpansion.expandRow': 'Développer la ligne'},
128
+ }}>
129
+ <Harness />
130
+ </InternationalizationProvider>,
131
+ );
132
+ fireEvent.contextMenu(screen.getByText('Folder A'));
133
+ const items = screen.getAllByRole('menuitem', {
134
+ name: /Développer la ligne/,
135
+ hidden: true,
136
+ });
137
+ expect(items.length).toBeGreaterThan(0);
138
+ });
139
+
121
140
  it('does not show chevron for leaf nodes', () => {
122
141
  render(<Harness />);
123
142
  // Leaf C has no children
@@ -16,6 +16,7 @@ import {useCallback, useMemo, useRef, type ReactNode} from 'react';
16
16
  import * as stylex from '@stylexjs/stylex';
17
17
  import {spacingVars, colorVars, radiusVars} from '../../../theme/tokens.stylex';
18
18
  import {Icon} from '../../../Icon';
19
+ import {rtlStyles} from '../../../utils';
19
20
  import {resolveContextActions} from '../../tableContextMenu';
20
21
  import {useTranslator} from '../../../i18n';
21
22
  import type {
@@ -361,12 +362,14 @@ function ExpansionChevron({
361
362
  }}
362
363
  aria-label={ariaLabel}
363
364
  aria-expanded={isExpanded}>
364
- <span
365
- {...stylex.props(
366
- expansionStyles.chevronIcon,
367
- isExpanded && expansionStyles.chevronExpanded,
368
- )}>
369
- <Icon icon="chevronRight" size="xsm" />
365
+ <span {...stylex.props(rtlStyles.mirror)}>
366
+ <span
367
+ {...stylex.props(
368
+ expansionStyles.chevronIcon,
369
+ isExpanded && expansionStyles.chevronExpanded,
370
+ )}>
371
+ <Icon icon="chevronRight" size="xsm" />
372
+ </span>
370
373
  </span>
371
374
  </button>
372
375
  );
@@ -533,12 +536,14 @@ export function useTableRowExpansion<T extends Record<string, unknown>>(
533
536
  ? t('@astryx.tableRowExpansion.collapseAllRows')
534
537
  : t('@astryx.tableRowExpansion.expandAllRows')
535
538
  }>
536
- <span
537
- {...stylex.props(
538
- expansionStyles.chevronIcon,
539
- allExpanded && expansionStyles.chevronExpanded,
540
- )}>
541
- <Icon icon="chevronRight" size="xsm" />
539
+ <span {...stylex.props(rtlStyles.mirror)}>
540
+ <span
541
+ {...stylex.props(
542
+ expansionStyles.chevronIcon,
543
+ allExpanded && expansionStyles.chevronExpanded,
544
+ )}>
545
+ <Icon icon="chevronRight" size="xsm" />
546
+ </span>
542
547
  </span>
543
548
  </button>
544
549
  ),
@@ -571,13 +576,17 @@ export function useTableRowExpansion<T extends Record<string, unknown>>(
571
576
  {
572
577
  id: 'row-expansion-toggle',
573
578
  group: 'row-expansion',
574
- label: isExpanded ? 'Collapse row' : 'Expand row',
579
+ label: isExpanded
580
+ ? t('@astryx.tableRowExpansion.collapseRow')
581
+ : t('@astryx.tableRowExpansion.expandRow'),
575
582
  icon: (
576
- <Icon
577
- icon={isExpanded ? 'chevronDown' : 'chevronRight'}
578
- size="xsm"
579
- aria-hidden
580
- />
583
+ <span {...stylex.props(rtlStyles.mirror)}>
584
+ <Icon
585
+ icon={isExpanded ? 'chevronDown' : 'chevronRight'}
586
+ size="xsm"
587
+ aria-hidden
588
+ />
589
+ </span>
581
590
  ),
582
591
  onSelect: () => onToggle(key),
583
592
  },
@@ -7,13 +7,13 @@
7
7
  * @position Test file; validates selection behavior (checkboxes, aria, select-all)
8
8
  */
9
9
 
10
- import {describe, it, expect} from 'vitest';
10
+ import {describe, it, expect, vi} from 'vitest';
11
11
  import {useState} from 'react';
12
- import {render, screen, within} from '@testing-library/react';
12
+ import {act, render, renderHook, screen, within} from '@testing-library/react';
13
13
  import userEvent from '@testing-library/user-event';
14
14
  import {Table} from '../../Table';
15
15
  import {useTableSelection} from './useTableSelection';
16
- import type {TableColumn} from '../../types';
16
+ import type {BodyRowRenderProps, TableColumn} from '../../types';
17
17
 
18
18
  // =============================================================================
19
19
  // Test Data
@@ -210,4 +210,62 @@ describe('useTableSelection', () => {
210
210
  const headers = within(headerRow).getAllByRole('columnheader');
211
211
  expect(headers).toHaveLength(3);
212
212
  });
213
+
214
+ it('unsubscribes detached row refs instead of accumulating listeners', () => {
215
+ const getIsItemSelected = vi.fn(() => false);
216
+ const {result, rerender} = renderHook(() =>
217
+ useTableSelection<SelectableUser>({
218
+ getIsItemSelected,
219
+ onSelectItem: vi.fn(),
220
+ onSelectAll: vi.fn(),
221
+ getIsAllSelected: () => false,
222
+ }),
223
+ );
224
+
225
+ const initialProps: BodyRowRenderProps = {
226
+ htmlProps: {},
227
+ xstyle: [],
228
+ children: null,
229
+ };
230
+ const row = document.createElement('tr');
231
+ document.body.append(row);
232
+
233
+ let detach: (() => void) | undefined;
234
+
235
+ // Simulate React replacing the callback ref as this row re-renders.
236
+ // Each detach must unsubscribe the previous ref before the next attaches.
237
+ for (let i = 0; i < 3; i++) {
238
+ act(() => {
239
+ detach?.();
240
+ });
241
+
242
+ const transformed = result.current.transformBodyRow?.(
243
+ initialProps,
244
+ selectableUsers[0],
245
+ 0,
246
+ );
247
+ expect(transformed?.ref).toBeTypeOf('function');
248
+
249
+ act(() => {
250
+ const cleanup = (
251
+ transformed?.ref as React.RefCallback<HTMLTableRowElement>
252
+ )(row);
253
+ expect(cleanup).toBeTypeOf('function');
254
+ detach = cleanup as () => void;
255
+ });
256
+ }
257
+
258
+ getIsItemSelected.mockClear();
259
+ rerender();
260
+ expect(getIsItemSelected).toHaveBeenCalledTimes(1);
261
+
262
+ act(() => {
263
+ detach?.();
264
+ });
265
+ getIsItemSelected.mockClear();
266
+ rerender();
267
+ expect(getIsItemSelected).not.toHaveBeenCalled();
268
+
269
+ row.remove();
270
+ });
213
271
  });
@@ -371,6 +371,9 @@ export function useTableSelection<T extends Record<string, unknown>>(
371
371
  store.getConfig().getIsItemSelected(item),
372
372
  );
373
373
  });
374
+ return () => {
375
+ unsub();
376
+ };
374
377
  };
375
378
 
376
379
  return {
@@ -205,7 +205,7 @@ const stickyStyles = stylex.create({
205
205
  },
206
206
  });
207
207
 
208
- // Soft drop shadow over the scrolling region (matches the EPS sticky treatment).
208
+ // Soft drop shadow over the scrolling region (a standard sticky-column shadow treatment).
209
209
  // border-collapse tables don't paint box-shadow on cells in Chromium, so it's a
210
210
  // ::after gradient strip just past the pinned edge (visible thanks to the cell's
211
211
  // overflow: visible). Opacity is gated by the scroll-state variable above.
@@ -213,7 +213,12 @@ const SHADOW_WIDTH = '6px';
213
213
  // --color-shadow is only ~10% alpha (too faint here); use a slightly stronger soft tint.
214
214
  const SHADOW_TINT = 'light-dark(rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.32))';
215
215
  const shadowStyles = stylex.create({
216
- // start-pinned: shadow falls to the right (inline-end), over scrolled content
216
+ // start-pinned: shadow falls toward inline-end (over scrolled content).
217
+ // insetInlineEnd anchors the strip to the column's inline-end edge; the strip
218
+ // must then be nudged one full width OUTWARD (past that edge) into the
219
+ // scrolled region. Outward is +X under LTR (inline-end = right) but −X under
220
+ // RTL (inline-end = left), and the fade must run from the pinned edge toward
221
+ // content in each direction — hence both transform and gradient flip on dir.
217
222
  start: {
218
223
  '::after': {
219
224
  content: '""',
@@ -222,14 +227,24 @@ const shadowStyles = stylex.create({
222
227
  bottom: 0,
223
228
  insetInlineEnd: 0,
224
229
  width: SHADOW_WIDTH,
225
- transform: 'translateX(100%)',
230
+ transform: {
231
+ default: 'translateX(100%)',
232
+ ':is([dir="rtl"] *)': 'translateX(-100%)',
233
+ },
226
234
  pointerEvents: 'none',
227
235
  transition: 'opacity 150ms ease',
228
236
  opacity: `var(${SHADOW_VAR_START}, 0)`,
229
- backgroundImage: `linear-gradient(to right, ${SHADOW_TINT}, transparent)`,
237
+ backgroundImage: {
238
+ default: `linear-gradient(to right, ${SHADOW_TINT}, transparent)`,
239
+ ':is([dir="rtl"] *)': `linear-gradient(to left, ${SHADOW_TINT}, transparent)`,
240
+ },
230
241
  },
231
242
  },
232
- // end-pinned: shadow falls to the left (inline-start), over scrolled content
243
+ // end-pinned: shadow falls toward inline-start (over scrolled content).
244
+ // insetInlineStart anchors the strip to the column's inline-start edge; the
245
+ // strip is nudged one full width OUTWARD into content — −X under LTR
246
+ // (inline-start = left) but +X under RTL (inline-start = right) — with the
247
+ // gradient fading from the pinned edge toward content in each direction.
233
248
  end: {
234
249
  '::after': {
235
250
  content: '""',
@@ -238,11 +253,17 @@ const shadowStyles = stylex.create({
238
253
  bottom: 0,
239
254
  insetInlineStart: 0,
240
255
  width: SHADOW_WIDTH,
241
- transform: 'translateX(-100%)',
256
+ transform: {
257
+ default: 'translateX(-100%)',
258
+ ':is([dir="rtl"] *)': 'translateX(100%)',
259
+ },
242
260
  pointerEvents: 'none',
243
261
  transition: 'opacity 150ms ease',
244
262
  opacity: `var(${SHADOW_VAR_END}, 0)`,
245
- backgroundImage: `linear-gradient(to left, ${SHADOW_TINT}, transparent)`,
263
+ backgroundImage: {
264
+ default: `linear-gradient(to left, ${SHADOW_TINT}, transparent)`,
265
+ ':is([dir="rtl"] *)': `linear-gradient(to right, ${SHADOW_TINT}, transparent)`,
266
+ },
246
267
  },
247
268
  },
248
269
  });
@@ -289,16 +310,24 @@ export function useTableStickyColumns<T extends Record<string, unknown>>(
289
310
  const {hasStart: hs, hasEnd: he} = stateRef.current;
290
311
  const maxScroll = el.scrollWidth - el.clientWidth;
291
312
  const hasOverflow = maxScroll > 1;
313
+ // RTL-safe scroll position. Spec-compliant browsers report a NEGATIVE
314
+ // scrollLeft under RTL (0 at the inline-start edge, decreasing toward the
315
+ // inline-end edge), so a raw `scrollLeft > 1` start test would never fire
316
+ // and the end test would be wrong-signed. Math.abs collapses both
317
+ // conventions to a distance-from-inline-start, matching the repo's own
318
+ // useScrollOverflow (overflowStart/overflowEnd use Math.abs, tolerance 1).
319
+ // No-op under LTR where scrollLeft is already >= 0.
320
+ const pos = Math.abs(el.scrollLeft);
292
321
  if (hs) {
293
322
  el.style.setProperty(
294
323
  SHADOW_VAR_START,
295
- hasOverflow && el.scrollLeft > 1 ? '1' : '0',
324
+ hasOverflow && pos > 1 ? '1' : '0',
296
325
  );
297
326
  }
298
327
  if (he) {
299
328
  el.style.setProperty(
300
329
  SHADOW_VAR_END,
301
- hasOverflow && el.scrollLeft < maxScroll - 1 ? '1' : '0',
330
+ hasOverflow && pos < maxScroll - 1 ? '1' : '0',
302
331
  );
303
332
  }
304
333
  };
@@ -42,7 +42,7 @@ import {
42
42
  import * as stylex from '@stylexjs/stylex';
43
43
  import {colorVars, radiusVars, spacingVars} from '../../../theme/tokens.stylex';
44
44
  import {Icon} from '../../../Icon';
45
- import {mergeRefs} from '../../../utils';
45
+ import {mergeRefs, rtlStyles} from '../../../utils';
46
46
  import type {
47
47
  TablePlugin,
48
48
  TableColumn,
@@ -299,12 +299,14 @@ function TreeExpander({
299
299
  : t('@astryx.tableTree.expandRow')
300
300
  }
301
301
  aria-expanded={isExpanded}>
302
- <span
303
- {...stylex.props(
304
- treeStyles.chevron,
305
- isExpanded && treeStyles.chevronExpanded,
306
- )}>
307
- <Icon icon="chevronRight" size="xsm" />
302
+ <span {...stylex.props(rtlStyles.mirror)}>
303
+ <span
304
+ {...stylex.props(
305
+ treeStyles.chevron,
306
+ isExpanded && treeStyles.chevronExpanded,
307
+ )}>
308
+ <Icon icon="chevronRight" size="xsm" />
309
+ </span>
308
310
  </span>
309
311
  </button>
310
312
  );
@@ -346,12 +348,14 @@ function TreeExpandAllToggle({
346
348
  : t('@astryx.tableTree.expandAllRows')
347
349
  }
348
350
  aria-expanded={allExpanded}>
349
- <span
350
- {...stylex.props(
351
- treeStyles.chevron,
352
- allExpanded && treeStyles.chevronExpanded,
353
- )}>
354
- <Icon icon="chevronRight" size="xsm" />
351
+ <span {...stylex.props(rtlStyles.mirror)}>
352
+ <span
353
+ {...stylex.props(
354
+ treeStyles.chevron,
355
+ allExpanded && treeStyles.chevronExpanded,
356
+ )}>
357
+ <Icon icon="chevronRight" size="xsm" />
358
+ </span>
355
359
  </span>
356
360
  </button>
357
361
  );
@@ -540,6 +540,39 @@ export interface BaseTableProps<
540
540
  /** Plugins to transform render props at each level */
541
541
  plugins?: TablePlugin<T>[];
542
542
 
543
+ /**
544
+ * ARIA row index (1-based) assigned to the **first** rendered body row.
545
+ *
546
+ * The row ordinal is an accessibility concern independent of any visible
547
+ * index column: `aria-rowindex` on each `<tr>` should reflect the row's
548
+ * position in the **full** dataset, not just the current page. For a
549
+ * paginated / windowed view, pass the offset of the first visible row,
550
+ * e.g. `(page - 1) * pageSize + 1`.
551
+ *
552
+ * Setting this (or {@link rowCount}) opts the table into emitting
553
+ * `aria-rowindex` on body rows and `aria-rowcount` on the `<table>`. Data
554
+ * rows are numbered from this value; the header row keeps native table
555
+ * semantics and is not assigned an ARIA row index (so the visible
556
+ * `useTableRowIndex` numbering and `aria-rowindex` stay in agreement).
557
+ *
558
+ * Applies to data-driven mode only (ignored in children mode).
559
+ *
560
+ * @default 1
561
+ */
562
+ rowIndexStart?: number;
563
+ /**
564
+ * Total number of body rows across **all** pages/windows, used for
565
+ * `aria-rowcount` on the `<table>`. Provide this for paginated data so
566
+ * assistive tech can announce "row X of Y" against the full dataset.
567
+ *
568
+ * When omitted but {@link rowIndexStart} is set (a windowed view with an
569
+ * unknown total, e.g. cursor pagination), `aria-rowcount` is set to `-1`
570
+ * per the ARIA convention for an unknown row count.
571
+ *
572
+ * Applies to data-driven mode only (ignored in children mode).
573
+ */
574
+ rowCount?: number;
575
+
543
576
  /** Children mode — render `<tr>`/`<td>` directly instead of data-driven */
544
577
  children?: ReactNode;
545
578
  /**
@@ -13,7 +13,7 @@ export const docs = {
13
13
  name: 'getStatus',
14
14
  type: "(item: T) => { color: 'accent' | 'success' | 'error' | 'warning' | 'red' | 'orange' | 'green' | 'yellow' | 'blue' | 'gray' | string; icon?: IconName; label: string } | null",
15
15
  description:
16
- 'Derive the status indicator for a row: a semantic color (accent, success, error, warning, red, orange, green, yellow, blue, gray — mapped to a theme token) or a raw CSS color as an escape hatch; an optional icon to signal status by shape instead of the dot (recommended when multiple statuses coexist; valid names: close, chevronDown, chevronLeft, chevronRight, check, success, error, warning, info, calendar, clock, externalLink, menu, moreHorizontal, search, arrowUp, arrowDown, arrowsUpDown, funnel, eyeSlash, viewColumns, copy, checkDouble, wrench, stop, microphone); and a required accessible label (announced via role="img" and shown in a tooltip on hover, so a status is never conveyed by color alone). Return null for rows with no status. Memoize with useCallback for a stable plugin identity.',
16
+ 'Derive the status indicator for a row: a semantic color (accent, success, error, warning, red, orange, green, yellow, blue, gray, each mapped to a theme token) or a raw CSS color as an escape hatch; an optional icon to signal status by shape instead of the dot (recommended when multiple statuses coexist; valid names: close, chevronDown, chevronLeft, chevronRight, check, success, error, warning, info, calendar, clock, externalLink, menu, moreHorizontal, search, arrowUp, arrowDown, arrowsUpDown, funnel, eyeSlash, viewColumns, copy, checkDouble, wrench, stop, microphone); and a required accessible label (announced via role="img" and shown in a tooltip on hover, so a status is never conveyed by color alone). Return null for rows with no status. Memoize with useCallback for a stable plugin identity.',
17
17
  required: true,
18
18
  },
19
19
  ],
@@ -106,6 +106,13 @@ export const docs = {
106
106
  description:
107
107
  'Status indicator that applies a colored border and icon. An optional message is displayed in a floating box below the textarea.',
108
108
  },
109
+ {
110
+ name: 'statusVariant',
111
+ type: "'attached' | 'detached' | 'tooltip'",
112
+ description:
113
+ 'How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment); detached floats below as a separate element with spacing; tooltip hides the message box and surfaces it in a tooltip on the status icon.',
114
+ default: "'attached'",
115
+ },
109
116
  {
110
117
  name: 'labelTooltip',
111
118
  type: 'string',
@@ -147,6 +154,12 @@ export const docs = {
147
154
  description:
148
155
  'HTML name attribute for the textarea element, useful for form submissions.',
149
156
  },
157
+ {
158
+ name: 'width',
159
+ type: 'SizeValue',
160
+ description:
161
+ 'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
162
+ },
150
163
  {
151
164
  name: 'onFocus',
152
165
  type: '(e: FocusEvent<HTMLTextAreaElement>) => void',
@@ -279,6 +292,13 @@ export const docsZh = {
279
292
  type: "{ type: 'warning' | 'error' | 'success'; message?: string }",
280
293
  description: '应用彩色边框和图标的状态指示器。可选消息显示在文本域下方的浮动框中。',
281
294
  },
295
+ {
296
+ name: 'statusVariant',
297
+ type: "'attached' | 'detached' | 'tooltip'",
298
+ description:
299
+ '状态消息相对于输入框的放置方式。attached 直接叠加在输入框下方(带边框处理);detached 作为独立元素浮于下方并留有间距;tooltip 隐藏消息框,并在状态图标上以提示气泡形式显示。',
300
+ default: "'attached'",
301
+ },
282
302
  {
283
303
  name: 'labelTooltip',
284
304
  type: 'string',
@@ -389,6 +409,7 @@ export const docsDense = {
389
409
  rows: 'Visible text rows.',
390
410
  maxLength: 'Max chars allowed. Shows counter (current/max) below textarea. No native enforcement.',
391
411
  status: 'Colored border+icon status. Optional floating message below textarea.',
412
+ statusVariant: 'How status message is placed: attached overlaps below input; detached floats below w/ spacing; tooltip hides the box and shows it on the status icon.',
392
413
  labelTooltip: 'Tooltip in info icon at label end.',
393
414
  startIcon: 'Icon inside leading edge of textarea wrapper.',
394
415
  hasSpellCheck: 'Enables/disables browser spell checking.',
@@ -736,3 +736,26 @@ describe('TextArea', () => {
736
736
  });
737
737
  });
738
738
  });
739
+
740
+
741
+ describe('TextArea statusVariant forwarding', () => {
742
+ it('defaults to attached (status renders with data-variant="attached")', () => {
743
+ const {container} = render(
744
+ <TextArea label="Bio" value="" onChange={() => {}} status={{type: 'error', message: 'Required'}} />,
745
+ );
746
+ expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
747
+ 'data-variant',
748
+ 'attached',
749
+ );
750
+ });
751
+
752
+ it('forwards statusVariant="detached" to the underlying Field status', () => {
753
+ const {container} = render(
754
+ <TextArea label="Bio" value="" onChange={() => {}} status={{type: 'error', message: 'Required'}} statusVariant="detached" />,
755
+ );
756
+ expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
757
+ 'data-variant',
758
+ 'detached',
759
+ );
760
+ });
761
+ });