@astryxdesign/core 0.1.9-canary.d2d84f8 → 0.1.9-canary.e00a241

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 (414) hide show
  1. package/dist/Avatar/Avatar.d.ts +6 -1
  2. package/dist/Avatar/Avatar.d.ts.map +1 -1
  3. package/dist/Avatar/Avatar.js +46 -12
  4. package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
  5. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  6. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  7. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
  8. package/dist/Breadcrumbs/index.d.ts +1 -0
  9. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  10. package/dist/Breadcrumbs/index.js +2 -1
  11. package/dist/Calendar/Calendar.d.ts.map +1 -1
  12. package/dist/Calendar/Calendar.js +50 -9
  13. package/dist/Calendar/dayCellUtils.d.ts +4 -4
  14. package/dist/Calendar/dayCellUtils.js +2 -2
  15. package/dist/Calendar/styles.d.ts +30 -31
  16. package/dist/Calendar/styles.d.ts.map +1 -1
  17. package/dist/Calendar/styles.js +30 -31
  18. package/dist/Card/Card.js +1 -1
  19. package/dist/Carousel/Carousel.d.ts.map +1 -1
  20. package/dist/Carousel/Carousel.js +22 -12
  21. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  22. package/dist/Chat/ChatDictationButton.js +3 -1
  23. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  24. package/dist/Chat/ChatMessageBubble.js +8 -8
  25. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  26. package/dist/Chat/ChatToolCalls.js +10 -3
  27. package/dist/CheckboxInput/CheckboxInput.js +4 -4
  28. package/dist/Citation/Citation.d.ts +22 -1
  29. package/dist/Citation/Citation.d.ts.map +1 -1
  30. package/dist/Citation/Citation.js +20 -6
  31. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  32. package/dist/CodeBlock/CodeBlock.js +13 -7
  33. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  34. package/dist/Collapsible/Collapsible.js +3 -1
  35. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  36. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  37. package/dist/CommandPalette/CommandPalette.js +42 -3
  38. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  39. package/dist/ContextMenu/ContextMenu.js +14 -5
  40. package/dist/ContextMenu/index.d.ts +1 -0
  41. package/dist/ContextMenu/index.d.ts.map +1 -1
  42. package/dist/ContextMenu/index.js +3 -1
  43. package/dist/DateInput/DateInput.d.ts +1 -0
  44. package/dist/DateInput/DateInput.d.ts.map +1 -1
  45. package/dist/DateInput/DateInput.js +31 -19
  46. package/dist/DateRangeInput/DateRangeInput.d.ts +1 -0
  47. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  48. package/dist/DateRangeInput/DateRangeInput.js +20 -19
  49. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  50. package/dist/DateTimeInput/DateTimeInput.js +23 -18
  51. package/dist/Divider/Divider.d.ts +2 -2
  52. package/dist/Divider/Divider.d.ts.map +1 -1
  53. package/dist/Divider/Divider.js +13 -0
  54. package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
  55. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  56. package/dist/DropdownMenu/DropdownMenu.js +22 -5
  57. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  58. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
  59. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  60. package/dist/DropdownMenu/DropdownMenuItem.js +4 -1
  61. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  62. package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
  63. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
  64. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
  65. package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
  66. package/dist/DropdownMenu/index.d.ts +10 -0
  67. package/dist/DropdownMenu/index.d.ts.map +1 -1
  68. package/dist/DropdownMenu/index.js +13 -0
  69. package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
  70. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  71. package/dist/DropdownMenu/menuItemHover.js +33 -0
  72. package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
  73. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
  74. package/dist/DropdownMenu/menuItemRoles.js +10 -1
  75. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  76. package/dist/DropdownMenu/renderDropdownItems.js +21 -6
  77. package/dist/Field/Field.d.ts +3 -1
  78. package/dist/Field/Field.d.ts.map +1 -1
  79. package/dist/Field/Field.js +4 -1
  80. package/dist/Field/inputStyles.stylex.d.ts +1 -0
  81. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  82. package/dist/Field/inputStyles.stylex.js +1 -0
  83. package/dist/FieldStatus/FieldStatus.d.ts +4 -1
  84. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  85. package/dist/FieldStatus/FieldStatus.js +4 -2
  86. package/dist/FileInput/FileInput.d.ts +1 -0
  87. package/dist/FileInput/FileInput.d.ts.map +1 -1
  88. package/dist/FileInput/FileInput.js +91 -65
  89. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  90. package/dist/HoverCard/useHoverCard.js +10 -4
  91. package/dist/Icon/Icon.d.ts +15 -1
  92. package/dist/Icon/Icon.d.ts.map +1 -1
  93. package/dist/Icon/Icon.js +19 -3
  94. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  95. package/dist/Lightbox/Lightbox.js +15 -9
  96. package/dist/List/List.d.ts.map +1 -1
  97. package/dist/List/List.js +6 -3
  98. package/dist/Markdown/Markdown.d.ts.map +1 -1
  99. package/dist/Markdown/Markdown.js +7 -0
  100. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  101. package/dist/MultiSelector/MultiSelector.js +65 -40
  102. package/dist/NumberInput/NumberInput.d.ts +1 -0
  103. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  104. package/dist/NumberInput/NumberInput.js +20 -17
  105. package/dist/Outline/Outline.js +2 -2
  106. package/dist/RadioList/RadioList.d.ts +2 -2
  107. package/dist/RadioList/RadioListItem.js +4 -4
  108. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  109. package/dist/Resizable/ResizeHandle.js +49 -19
  110. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  111. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  112. package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
  113. package/dist/Selector/Selector.d.ts.map +1 -1
  114. package/dist/Selector/Selector.js +58 -16
  115. package/dist/SideNav/SideNav.d.ts.map +1 -1
  116. package/dist/SideNav/SideNav.js +5 -5
  117. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  118. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  119. package/dist/SideNav/SideNavItem.d.ts +1 -1
  120. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  121. package/dist/SideNav/SideNavItem.js +12 -10
  122. package/dist/Slider/Slider.d.ts.map +1 -1
  123. package/dist/Slider/Slider.js +87 -34
  124. package/dist/Spinner/Spinner.d.ts +3 -2
  125. package/dist/Spinner/Spinner.d.ts.map +1 -1
  126. package/dist/Spinner/Spinner.js +11 -2
  127. package/dist/Switch/Switch.d.ts +8 -1
  128. package/dist/Switch/Switch.d.ts.map +1 -1
  129. package/dist/Switch/Switch.js +160 -91
  130. package/dist/TabList/TabList.d.ts +2 -11
  131. package/dist/TabList/TabList.d.ts.map +1 -1
  132. package/dist/TabList/TabList.js +5 -9
  133. package/dist/TabList/TabListContext.d.ts +0 -5
  134. package/dist/TabList/TabListContext.d.ts.map +1 -1
  135. package/dist/TabList/TabListContext.js +0 -5
  136. package/dist/Table/BaseTable.d.ts.map +1 -1
  137. package/dist/Table/BaseTable.js +30 -4
  138. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  139. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  140. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  141. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
  142. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  143. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  144. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  145. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +14 -6
  146. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  147. package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
  148. package/dist/Table/types.d.ts +32 -0
  149. package/dist/Table/types.d.ts.map +1 -1
  150. package/dist/TextArea/TextArea.d.ts +1 -0
  151. package/dist/TextArea/TextArea.d.ts.map +1 -1
  152. package/dist/TextArea/TextArea.js +16 -19
  153. package/dist/TextInput/TextInput.d.ts +1 -0
  154. package/dist/TextInput/TextInput.d.ts.map +1 -1
  155. package/dist/TextInput/TextInput.js +18 -17
  156. package/dist/TimeInput/TimeInput.d.ts +1 -0
  157. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  158. package/dist/TimeInput/TimeInput.js +15 -17
  159. package/dist/Timestamp/Timestamp.d.ts +31 -3
  160. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  161. package/dist/Timestamp/Timestamp.js +47 -76
  162. package/dist/Timestamp/formatInstant.d.ts +41 -0
  163. package/dist/Timestamp/formatInstant.d.ts.map +1 -0
  164. package/dist/Timestamp/formatInstant.js +177 -0
  165. package/dist/Timestamp/index.d.ts +1 -0
  166. package/dist/Timestamp/index.d.ts.map +1 -1
  167. package/dist/Timestamp/tooltipEntries.d.ts +56 -0
  168. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
  169. package/dist/Timestamp/tooltipEntries.js +163 -0
  170. package/dist/Token/Token.d.ts +30 -3
  171. package/dist/Token/Token.d.ts.map +1 -1
  172. package/dist/Token/Token.js +17 -2
  173. package/dist/Token/index.d.ts +1 -1
  174. package/dist/Token/index.d.ts.map +1 -1
  175. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  176. package/dist/Tokenizer/Tokenizer.js +2 -2
  177. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  178. package/dist/Tooltip/useTooltip.js +17 -1
  179. package/dist/TopNav/TopNavItem.d.ts +3 -1
  180. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  181. package/dist/TopNav/TopNavItem.js +30 -3
  182. package/dist/TreeList/TreeList.d.ts.map +1 -1
  183. package/dist/TreeList/TreeList.js +1 -0
  184. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  185. package/dist/TreeList/TreeListBranches.js +8 -6
  186. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  187. package/dist/TreeList/TreeListItem.js +32 -14
  188. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  189. package/dist/Typeahead/BaseTypeahead.js +19 -10
  190. package/dist/Typeahead/Typeahead.js +1 -1
  191. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  192. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  193. package/dist/Typeahead/TypeaheadItem.js +20 -10
  194. package/dist/astryx.css +38 -14
  195. package/dist/astryx.umd.js +52 -52
  196. package/dist/astryx.umd.js.map +4 -4
  197. package/dist/hooks/index.d.ts +2 -0
  198. package/dist/hooks/index.d.ts.map +1 -1
  199. package/dist/hooks/index.js +1 -0
  200. package/dist/hooks/isRtlElement.d.ts +18 -0
  201. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  202. package/dist/hooks/isRtlElement.js +27 -0
  203. package/dist/hooks/useAnnounce.d.ts +3 -0
  204. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  205. package/dist/hooks/useAnnounce.js +39 -1
  206. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  207. package/dist/hooks/useFocusTrap.js +52 -11
  208. package/dist/hooks/useGridFocus.d.ts +6 -1
  209. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  210. package/dist/hooks/useGridFocus.js +12 -9
  211. package/dist/hooks/useHotkeys.d.ts +9 -0
  212. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  213. package/dist/hooks/useHotkeys.js +9 -0
  214. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  215. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  216. package/dist/hooks/useInputStatusIcon.js +158 -0
  217. package/dist/hooks/useListFocus.d.ts +39 -1
  218. package/dist/hooks/useListFocus.d.ts.map +1 -1
  219. package/dist/hooks/useListFocus.js +54 -9
  220. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  221. package/dist/theme/derivedVarRegistry.js +13 -0
  222. package/dist/utils/index.d.ts +1 -0
  223. package/dist/utils/index.d.ts.map +1 -1
  224. package/dist/utils/index.js +2 -1
  225. package/dist/utils/plainDate.d.ts +17 -0
  226. package/dist/utils/plainDate.d.ts.map +1 -1
  227. package/dist/utils/plainDate.js +23 -4
  228. package/dist/utils/rtlStyles.d.ts +24 -0
  229. package/dist/utils/rtlStyles.d.ts.map +1 -0
  230. package/dist/utils/rtlStyles.js +27 -0
  231. package/locales/en.json +76 -0
  232. package/locales/pseudo.json +57 -0
  233. package/package.json +6 -1
  234. package/src/Avatar/Avatar.doc.mjs +18 -4
  235. package/src/Avatar/Avatar.test.tsx +106 -0
  236. package/src/Avatar/Avatar.tsx +62 -10
  237. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  238. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  239. package/src/AvatarGroup/AvatarGroup.test.tsx +16 -1
  240. package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
  241. package/src/Breadcrumbs/Breadcrumbs.test.tsx +51 -0
  242. package/src/Breadcrumbs/index.ts +4 -0
  243. package/src/Button/Button.doc.mjs +0 -4
  244. package/src/Calendar/Calendar.test.tsx +170 -20
  245. package/src/Calendar/Calendar.tsx +73 -16
  246. package/src/Calendar/dayCellUtils.test.ts +18 -18
  247. package/src/Calendar/dayCellUtils.ts +2 -2
  248. package/src/Calendar/styles.ts +33 -39
  249. package/src/Card/Card.tsx +1 -1
  250. package/src/Carousel/Carousel.tsx +25 -6
  251. package/src/Chat/ChatComposer.doc.mjs +2 -2
  252. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  253. package/src/Chat/ChatDictationButton.tsx +7 -1
  254. package/src/Chat/ChatMessageBubble.tsx +15 -10
  255. package/src/Chat/ChatSystemMessage.test.tsx +5 -0
  256. package/src/Chat/ChatToolCalls.tsx +9 -2
  257. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  258. package/src/CheckboxInput/CheckboxInput.tsx +4 -4
  259. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  260. package/src/Citation/Citation.doc.mjs +4 -3
  261. package/src/Citation/Citation.test.tsx +97 -0
  262. package/src/Citation/Citation.tsx +43 -11
  263. package/src/CodeBlock/CodeBlock.tsx +35 -8
  264. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  265. package/src/Collapsible/Collapsible.test.tsx +7 -0
  266. package/src/Collapsible/Collapsible.tsx +16 -6
  267. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  268. package/src/CommandPalette/CommandPalette.tsx +41 -2
  269. package/src/ContextMenu/ContextMenu.test.tsx +42 -0
  270. package/src/ContextMenu/ContextMenu.tsx +13 -11
  271. package/src/ContextMenu/index.ts +5 -0
  272. package/src/DateInput/DateInput.doc.mjs +15 -5
  273. package/src/DateInput/DateInput.test.tsx +210 -3
  274. package/src/DateInput/DateInput.tsx +41 -29
  275. package/src/DateRangeInput/DateRangeInput.doc.mjs +11 -3
  276. package/src/DateRangeInput/DateRangeInput.test.tsx +120 -3
  277. package/src/DateRangeInput/DateRangeInput.tsx +29 -27
  278. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  279. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  280. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  281. package/src/Divider/Divider.test.tsx +32 -8
  282. package/src/Divider/Divider.tsx +14 -1
  283. package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
  284. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  285. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
  286. package/src/DropdownMenu/DropdownMenuItem.tsx +8 -2
  287. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
  288. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  289. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
  290. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
  291. package/src/DropdownMenu/index.ts +16 -0
  292. package/src/DropdownMenu/menuItemHover.ts +39 -0
  293. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  294. package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
  295. package/src/Field/Field.tsx +14 -9
  296. package/src/Field/inputStyles.stylex.ts +2 -0
  297. package/src/FieldStatus/FieldStatus.tsx +10 -4
  298. package/src/FileInput/FileInput.doc.mjs +13 -7
  299. package/src/FileInput/FileInput.test.tsx +84 -16
  300. package/src/FileInput/FileInput.tsx +96 -79
  301. package/src/HoverCard/useHoverCard.tsx +15 -3
  302. package/src/Icon/Icon.doc.mjs +13 -0
  303. package/src/Icon/Icon.test.tsx +89 -0
  304. package/src/Icon/Icon.tsx +51 -3
  305. package/src/Lightbox/Lightbox.tsx +11 -3
  306. package/src/List/List.test.tsx +17 -29
  307. package/src/List/List.tsx +6 -1
  308. package/src/Markdown/Markdown.test.tsx +21 -0
  309. package/src/Markdown/Markdown.tsx +4 -0
  310. package/src/MultiSelector/MultiSelector.doc.mjs +11 -0
  311. package/src/MultiSelector/MultiSelector.test.tsx +306 -3
  312. package/src/MultiSelector/MultiSelector.tsx +88 -57
  313. package/src/NumberInput/NumberInput.doc.mjs +11 -5
  314. package/src/NumberInput/NumberInput.test.tsx +48 -0
  315. package/src/NumberInput/NumberInput.tsx +25 -26
  316. package/src/Outline/Outline.test.tsx +12 -12
  317. package/src/Outline/Outline.tsx +2 -2
  318. package/src/RadioList/RadioList.doc.mjs +6 -0
  319. package/src/RadioList/RadioList.tsx +2 -2
  320. package/src/RadioList/RadioListItem.tsx +4 -4
  321. package/src/Resizable/ResizeHandle.test.tsx +94 -0
  322. package/src/Resizable/ResizeHandle.tsx +70 -20
  323. package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
  324. package/src/Selector/Selector.doc.mjs +8 -0
  325. package/src/Selector/Selector.test.tsx +328 -3
  326. package/src/Selector/Selector.tsx +70 -19
  327. package/src/SideNav/SideNav.tsx +1 -8
  328. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  329. package/src/SideNav/SideNavItem.tsx +5 -3
  330. package/src/Slider/Slider.doc.mjs +6 -0
  331. package/src/Slider/Slider.test.tsx +240 -12
  332. package/src/Slider/Slider.tsx +96 -23
  333. package/src/Spinner/Spinner.test.tsx +10 -8
  334. package/src/Spinner/Spinner.tsx +15 -5
  335. package/src/Switch/Switch.doc.mjs +142 -42
  336. package/src/Switch/Switch.test.tsx +22 -0
  337. package/src/Switch/Switch.tsx +90 -33
  338. package/src/TabList/TabList.doc.mjs +0 -6
  339. package/src/TabList/TabList.test.tsx +3 -15
  340. package/src/TabList/TabList.tsx +6 -17
  341. package/src/TabList/TabListContext.ts +0 -6
  342. package/src/Table/BaseTable.tsx +34 -2
  343. package/src/Table/Table.doc.mjs +11 -0
  344. package/src/Table/Table.test.tsx +85 -0
  345. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  346. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
  347. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  348. package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
  349. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +37 -8
  350. package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
  351. package/src/Table/types.ts +33 -0
  352. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  353. package/src/TextArea/TextArea.doc.mjs +11 -5
  354. package/src/TextArea/TextArea.tsx +17 -26
  355. package/src/TextInput/TextInput.doc.mjs +11 -5
  356. package/src/TextInput/TextInput.test.tsx +130 -3
  357. package/src/TextInput/TextInput.tsx +18 -25
  358. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  359. package/src/TimeInput/TimeInput.doc.mjs +11 -5
  360. package/src/TimeInput/TimeInput.tsx +14 -25
  361. package/src/Timestamp/Timestamp.doc.mjs +32 -6
  362. package/src/Timestamp/Timestamp.test.tsx +371 -0
  363. package/src/Timestamp/Timestamp.tsx +96 -93
  364. package/src/Timestamp/formatInstant.ts +218 -0
  365. package/src/Timestamp/index.ts +4 -0
  366. package/src/Timestamp/tooltipEntries.test.ts +552 -0
  367. package/src/Timestamp/tooltipEntries.ts +210 -0
  368. package/src/Token/Token.test.tsx +21 -15
  369. package/src/Token/Token.tsx +31 -14
  370. package/src/Token/index.ts +1 -1
  371. package/src/Tokenizer/Tokenizer.doc.mjs +8 -1
  372. package/src/Tokenizer/Tokenizer.tsx +4 -2
  373. package/src/Tooltip/Tooltip.test.tsx +46 -0
  374. package/src/Tooltip/useTooltip.tsx +20 -0
  375. package/src/TopNav/TopNav.test.tsx +93 -2
  376. package/src/TopNav/TopNavItem.doc.mjs +3 -3
  377. package/src/TopNav/TopNavItem.tsx +35 -6
  378. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
  379. package/src/TreeList/TreeList.doc.mjs +6 -0
  380. package/src/TreeList/TreeList.test.tsx +50 -10
  381. package/src/TreeList/TreeList.tsx +5 -0
  382. package/src/TreeList/TreeListBranches.tsx +8 -6
  383. package/src/TreeList/TreeListItem.tsx +33 -11
  384. package/src/Typeahead/BaseTypeahead.tsx +29 -14
  385. package/src/Typeahead/Typeahead.doc.mjs +6 -0
  386. package/src/Typeahead/Typeahead.test.tsx +27 -0
  387. package/src/Typeahead/Typeahead.tsx +1 -1
  388. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  389. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  390. package/src/doc-mjs.d.ts +19 -0
  391. package/src/hooks/index.ts +6 -0
  392. package/src/hooks/isRtlElement.ts +27 -0
  393. package/src/hooks/useAnnounce.test.tsx +75 -2
  394. package/src/hooks/useAnnounce.ts +47 -1
  395. package/src/hooks/useFocusTrap.test.tsx +104 -0
  396. package/src/hooks/useFocusTrap.ts +61 -12
  397. package/src/hooks/useGridFocus.doc.mjs +3 -3
  398. package/src/hooks/useGridFocus.test.tsx +41 -0
  399. package/src/hooks/useGridFocus.ts +21 -10
  400. package/src/hooks/useHotkeys.ts +9 -0
  401. package/src/hooks/useInputStatusIcon.test.tsx +162 -0
  402. package/src/hooks/useInputStatusIcon.tsx +224 -0
  403. package/src/hooks/useListFocus.doc.mjs +25 -3
  404. package/src/hooks/useListFocus.test.tsx +153 -1
  405. package/src/hooks/useListFocus.ts +102 -9
  406. package/src/reset.css +0 -26
  407. package/src/reset.test.ts +60 -0
  408. package/src/theme/derivedVarRegistry.test.ts +1 -0
  409. package/src/theme/derivedVarRegistry.ts +6 -0
  410. package/src/theme/generateThemeRules.test.ts +42 -0
  411. package/src/utils/index.ts +2 -0
  412. package/src/utils/plainDate.test.ts +24 -6
  413. package/src/utils/plainDate.ts +18 -4
  414. package/src/utils/rtlStyles.ts +27 -0
@@ -10,6 +10,7 @@ import type {ReactNode} from 'react';
10
10
  import * as stylex from '@stylexjs/stylex';
11
11
  import {Divider} from '../Divider';
12
12
  import {DropdownMenuItem} from './DropdownMenuItem';
13
+ import {DropdownMenuSubMenu} from './DropdownMenuSubMenu';
13
14
  import {
14
15
  spacingVars,
15
16
  typographyVars,
@@ -49,18 +50,14 @@ function getSectionKey(section: DropdownMenuSection, index: number): string {
49
50
  * Converts data-driven items into DropdownMenuItem components,
50
51
  * so both modes share the same rendering and keyboard navigation path.
51
52
  */
52
- export function renderDropdownItems(
53
- items: DropdownMenuOption[],
54
- ): ReactNode {
53
+ export function renderDropdownItems(items: DropdownMenuOption[]): ReactNode {
55
54
  const elements: ReactNode[] = [];
56
55
 
57
56
  for (let i = 0; i < items.length; i++) {
58
57
  const option = items[i];
59
58
 
60
59
  if ('type' in option && option.type === 'divider') {
61
- elements.push(
62
- <Divider key={`divider-${i}`} xstyle={styles.divider} />,
63
- );
60
+ elements.push(<Divider key={`divider-${i}`} xstyle={styles.divider} />);
64
61
  } else if ('type' in option && option.type === 'section') {
65
62
  elements.push(
66
63
  <div
@@ -84,15 +81,32 @@ export function renderDropdownItems(
84
81
  </div>,
85
82
  );
86
83
  } else if (!('type' in option)) {
87
- elements.push(
88
- <DropdownMenuItem
89
- key={getItemKey(option)}
90
- icon={option.icon}
91
- label={option.label}
92
- onClick={option.onClick}
93
- isDisabled={option.isDisabled}
94
- />,
95
- );
84
+ // A plain item that declares nested `items` becomes a submenu (data-mode
85
+ // parity with the compound DropdownMenuSubMenu API); otherwise it's a
86
+ // leaf. renderDropdownItems owns the recursion and hands the rendered
87
+ // children to DropdownMenuSubMenu — so DropdownMenuSubMenu never imports
88
+ // this module back (no import cycle).
89
+ if (option.items && option.items.length > 0) {
90
+ elements.push(
91
+ <DropdownMenuSubMenu
92
+ key={getItemKey(option)}
93
+ icon={option.icon}
94
+ label={option.label}
95
+ isDisabled={option.isDisabled}>
96
+ {renderDropdownItems(option.items)}
97
+ </DropdownMenuSubMenu>,
98
+ );
99
+ } else {
100
+ elements.push(
101
+ <DropdownMenuItem
102
+ key={getItemKey(option)}
103
+ icon={option.icon}
104
+ label={option.label}
105
+ onClick={option.onClick}
106
+ isDisabled={option.isDisabled}
107
+ />,
108
+ );
109
+ }
96
110
  }
97
111
  }
98
112
 
@@ -22,6 +22,7 @@ import type {BaseProps} from '../BaseProps';
22
22
  import type {SizeValue} from '../utils/types';
23
23
  import {FieldLabel} from './FieldLabel';
24
24
  import {FieldStatus} from '../FieldStatus/FieldStatus';
25
+ import type {FieldStatusVariant} from '../FieldStatus/FieldStatus';
25
26
  import {spacingVars, borderVars} from '../theme/tokens.stylex';
26
27
  import type {IconType} from '../Icon';
27
28
  import {mergeProps} from '../utils';
@@ -156,9 +157,10 @@ export interface FieldProps extends Omit<
156
157
  * How the status message is rendered relative to the input.
157
158
  * - 'attached': Status sits directly below the input (default, for bordered inputs)
158
159
  * - 'detached': Status is a separate element below the field (for checkboxes, switches, sliders)
160
+ * - 'tooltip': No message box; the input surfaces status through a tooltip on its on-field icon
159
161
  * @default 'attached'
160
162
  */
161
- statusVariant?: 'attached' | 'detached';
163
+ statusVariant?: FieldStatusVariant;
162
164
  /**
163
165
  * Width of the field. Numbers are treated as pixels, strings are used as-is
164
166
  * (e.g. `'100%'`). Sizes the whole field — label, control, and status — so
@@ -239,14 +241,17 @@ export function Field({
239
241
  />
240
242
  );
241
243
 
242
- const statusNode = status?.message ? (
243
- <FieldStatus
244
- type={status.type}
245
- message={status.message}
246
- id={resolvedMessageID}
247
- variant={statusVariant}
248
- />
249
- ) : null;
244
+ // The 'tooltip' variant surfaces status through the input's on-field icon
245
+ // tooltip, so Field renders no message box for it.
246
+ const statusNode =
247
+ status?.message && statusVariant !== 'tooltip' ? (
248
+ <FieldStatus
249
+ type={status.type}
250
+ message={status.message}
251
+ id={resolvedMessageID}
252
+ variant={statusVariant}
253
+ />
254
+ ) : null;
250
255
 
251
256
  // ─── Horizontal-labels mode ───────────────────────────────────────────
252
257
  // Use display:contents so the parent grid's `auto 1fr` columns place
@@ -67,6 +67,8 @@ export const inputWrapperStyles = stylex.create({
67
67
  cursor: 'not-allowed',
68
68
  opacity: 0.5,
69
69
  borderColor: colorVars['--color-border-emphasized'],
70
+ // Suppress the base hover ring — a disabled control must not react to hover.
71
+ boxShadow: 'none',
70
72
  },
71
73
  });
72
74
 
@@ -71,9 +71,12 @@ const styles = stylex.create({
71
71
  gap: spacingVars['--spacing-1'],
72
72
  },
73
73
  detachedIcon: {
74
- // Match the height of the first text line so the glyph top-aligns to it
75
- // (rather than to the flex box) when the message wraps to multiple lines.
76
- lineHeight: typeScaleVars['--text-supporting-leading'],
74
+ // Center the glyph within the first text-line box so it aligns to the
75
+ // first line of the message (rather than the top of the flex row) when the
76
+ // message wraps to multiple lines.
77
+ display: 'inline-flex',
78
+ alignItems: 'center',
79
+ height: `calc(${typeScaleVars['--text-supporting-size']} * ${typeScaleVars['--text-supporting-leading']})`,
77
80
  flexShrink: 0,
78
81
  },
79
82
  });
@@ -109,6 +112,7 @@ const colorStyles = stylex.create({
109
112
  export interface FieldStatusVariantMap {
110
113
  attached: true;
111
114
  detached: true;
115
+ tooltip: true;
112
116
  }
113
117
 
114
118
  /**
@@ -143,7 +147,9 @@ export interface FieldStatusProps extends BaseProps<HTMLDivElement> {
143
147
  * decorative for assistive tech (`aria-hidden`): the message text already names
144
148
  * the status in words and is announced through the live region. The `attached`
145
149
  * variant keeps its status affordance on the bordered input, so it renders no
146
- * icon here to avoid a duplicate.
150
+ * icon here to avoid a duplicate. The `tooltip` variant renders no message box
151
+ * at all — the input surfaces the status through a tooltip on its on-field
152
+ * icon — so callers skip rendering FieldStatus for it.
147
153
  *
148
154
  * Screen-reader announcements go through the persistent `useAnnounce` live
149
155
  * regions (assertive for errors, polite otherwise) rather than `role`/
@@ -78,7 +78,7 @@ export const docs = {
78
78
  name: 'isRequired',
79
79
  type: 'boolean',
80
80
  description:
81
- 'Displays a "Required" indicator next to the label and sets aria-required. Mutually exclusive with isOptional.',
81
+ 'Displays a "Required" indicator next to the label and adds a screen-reader-only "Required" description to the trigger (assistive tech does not reliably announce aria-required on the trigger). Mutually exclusive with isOptional.',
82
82
  default: 'false',
83
83
  },
84
84
  {
@@ -121,9 +121,9 @@ export const docs = {
121
121
  },
122
122
  {
123
123
  name: 'statusVariant',
124
- type: "'attached' | 'detached'",
124
+ type: "'attached' | 'detached' | 'tooltip'",
125
125
  description:
126
- '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.',
126
+ '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.',
127
127
  default: "'attached'",
128
128
  },
129
129
  {
@@ -132,6 +132,12 @@ export const docs = {
132
132
  description:
133
133
  'Tooltip text displayed in an info icon at the end of the label.',
134
134
  },
135
+ {
136
+ name: 'width',
137
+ type: 'SizeValue',
138
+ description:
139
+ '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.',
140
+ },
135
141
  ],
136
142
  theming: {
137
143
  targets: [
@@ -255,9 +261,9 @@ export const docsZh = {
255
261
  },
256
262
  {
257
263
  name: 'statusVariant',
258
- type: "'attached' | 'detached'",
264
+ type: "'attached' | 'detached' | 'tooltip'",
259
265
  description:
260
- '状态消息相对于输入框的放置方式。attached 直接叠加在输入框下方(带边框处理);detached 作为独立元素浮于下方并留有间距。',
266
+ '状态消息相对于输入框的放置方式。attached 直接叠加在输入框下方(带边框处理);detached 作为独立元素浮于下方并留有间距;tooltip 隐藏消息框,并在状态图标上以提示气泡形式显示。',
261
267
  default: "'attached'",
262
268
  },
263
269
  ],
@@ -322,7 +328,7 @@ export const docsDense = {
322
328
  isLabelHidden: 'Visually hides label; keeps screen reader access.',
323
329
  description: 'Description text between label+input.',
324
330
  isOptional: 'Shows "Optional" indicator.',
325
- isRequired: 'Shows "Required" indicator+sets aria-required.',
331
+ isRequired: 'Shows "Required" indicator+SR-only trigger description.',
326
332
  isDisabled: 'Disables input, prevents interaction.',
327
333
  disabledMessage:
328
334
  'Explains why input is disabled. With isDisabled, shows tooltip on hover/focus + keeps trigger focusable via aria-disabled (opening picker stays blocked). Use instead of wrapping a disabled FileInput in Tooltip.',
@@ -330,7 +336,7 @@ export const docsDense = {
330
336
  placeholder: 'Placeholder when no files selected.',
331
337
  mode: "Visual mode: 'input' (compact) or 'dropzone' (drag-and-drop).",
332
338
  status: 'Validation status; colored border. Message floats below.',
333
- statusVariant: 'How status message is placed: attached overlaps below input; detached floats below w/ spacing.',
339
+ 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.',
334
340
  labelTooltip: 'Tooltip in info icon at label end.',
335
341
  },
336
342
  };
@@ -147,16 +147,33 @@ describe('FileInput', () => {
147
147
  expect(screen.getByText('Upload')).toBeInTheDocument();
148
148
  });
149
149
 
150
- it('sets aria-required when isRequired is true', () => {
150
+ it('conveys required state through the accessible description', () => {
151
151
  render(
152
152
  <FileInput label="Resume" isRequired value={null} onChange={() => {}} />,
153
153
  );
154
- // aria-required lives on the focusable role="button" wrapper, not the
154
+ const trigger = screen.getByRole('button', {name: 'Resume'});
155
+ // Required is conveyed via a visually hidden "Required" node referenced
156
+ // from aria-describedby on the focusable role="button" trigger — not the
155
157
  // hidden file input (forms-6).
156
- expect(screen.getByRole('button', {name: 'Resume'})).toHaveAttribute(
157
- 'aria-required',
158
- 'true',
158
+ expect(trigger).toHaveAccessibleDescription(/Required/);
159
+ // aria-required is not a supported property of role="button" in
160
+ // WAI-ARIA 1.2 (AT does not announce it), so it must never appear.
161
+ expect(trigger).not.toHaveAttribute('aria-required');
162
+ });
163
+
164
+ it('combines required with the description in the accessible description', () => {
165
+ render(
166
+ <FileInput
167
+ label="Resume"
168
+ description="PDF only"
169
+ isRequired
170
+ value={null}
171
+ onChange={() => {}}
172
+ />,
159
173
  );
174
+ const trigger = screen.getByRole('button', {name: 'Resume'});
175
+ expect(trigger).toHaveAccessibleDescription(/PDF only/);
176
+ expect(trigger).toHaveAccessibleDescription(/Required/);
160
177
  });
161
178
 
162
179
  it('places aria-describedby on the focusable button, not the hidden input (forms-6)', () => {
@@ -176,11 +193,11 @@ describe('FileInput', () => {
176
193
  expect(input).toHaveAttribute('aria-hidden', 'true');
177
194
  });
178
195
 
179
- it('does not set aria-required by default', () => {
196
+ it('does not mention required without isRequired', () => {
180
197
  render(<FileInput label="Resume" value={null} onChange={() => {}} />);
181
- expect(screen.getByRole('button', {name: 'Resume'})).not.toHaveAttribute(
182
- 'aria-required',
183
- );
198
+ const trigger = screen.getByRole('button', {name: 'Resume'});
199
+ expect(trigger).not.toHaveAccessibleDescription(/Required/);
200
+ expect(trigger).not.toHaveAttribute('aria-required');
184
201
  });
185
202
 
186
203
  it('sets disabled attribute when isDisabled is true', () => {
@@ -353,6 +370,40 @@ describe('FileInput', () => {
353
370
  // FieldStatus, but the polite channel must stay empty.)
354
371
  expect(politeRegion()?.textContent ?? '').toBe('');
355
372
  });
373
+
374
+ it('announces a validation error exactly once across live regions', async () => {
375
+ render(
376
+ <FileInput
377
+ label="Upload"
378
+ value={null}
379
+ onChange={() => {}}
380
+ accept=".pdf"
381
+ />,
382
+ );
383
+ fireEvent.change(fileInputEl(), {
384
+ target: {files: [createFile('note.txt', 100)]},
385
+ });
386
+ const errorText = '"note.txt" is not an accepted file type';
387
+ // The error lands in the assertive announce region (via the FieldStatus
388
+ // the derived error status mounts)…
389
+ await waitFor(() => {
390
+ expect(
391
+ document.querySelector('[data-astryx-live-region="assertive"]'),
392
+ ).toHaveTextContent(errorText);
393
+ });
394
+ // …and in exactly one live region overall. FileInput's own role="status"
395
+ // region used to duplicate the FieldStatus announcement, so the same
396
+ // error was read twice (assertively, then politely).
397
+ const liveRegions = Array.from(
398
+ document.querySelectorAll(
399
+ '[role="status"], [role="alert"], [aria-live]',
400
+ ),
401
+ );
402
+ const regionsWithError = liveRegions.filter(el =>
403
+ (el.textContent ?? '').includes(errorText),
404
+ );
405
+ expect(regionsWithError).toHaveLength(1);
406
+ });
356
407
  });
357
408
 
358
409
  describe('validation', () => {
@@ -719,16 +770,20 @@ describe('FileInput', () => {
719
770
  />,
720
771
  );
721
772
 
722
- const trigger = screen.getByRole('button');
723
773
  const tooltip = screen.getByRole('tooltip', h);
724
774
  expect(tooltip).toHaveTextContent('You need the Editor role');
725
775
 
726
- fireEvent.mouseEnter(trigger);
776
+ // The trigger button is visually hidden, so the disabled-reason tooltip
777
+ // anchors its hover listeners to the visible container surface.
778
+ const surface = document.querySelector(
779
+ '.astryx-file-input',
780
+ ) as HTMLElement;
781
+ fireEvent.mouseEnter(surface);
727
782
  await waitFor(() => {
728
783
  expect(tooltip).toHaveAttribute('popover-open');
729
784
  });
730
785
 
731
- fireEvent.mouseLeave(trigger);
786
+ fireEvent.mouseLeave(surface);
732
787
  await waitFor(() => {
733
788
  expect(tooltip).not.toHaveAttribute('popover-open');
734
789
  });
@@ -809,7 +864,10 @@ describe('FileInput', () => {
809
864
  });
810
865
 
811
866
  it('blocks opening the file picker while focusable-disabled', async () => {
812
- const user = userEvent.setup();
867
+ // The trigger is a visually-hidden button (pointer-events: none) — real
868
+ // pointer clicks land on the container surface, so bypass the pointer
869
+ // check to exercise the disabled guard directly.
870
+ const user = userEvent.setup({pointerEventsCheck: 0});
813
871
  render(
814
872
  <FileInput
815
873
  label="Resume"
@@ -850,11 +908,15 @@ describe('FileInput', () => {
850
908
  });
851
909
  });
852
910
 
853
-
854
911
  describe('FileInput statusVariant forwarding', () => {
855
912
  it('defaults to attached (status renders with data-variant="attached")', () => {
856
913
  const {container} = render(
857
- <FileInput label="Upload" value={null} onChange={() => {}} status={{type: 'error', message: 'Something went wrong'}} />,
914
+ <FileInput
915
+ label="Upload"
916
+ value={null}
917
+ onChange={() => {}}
918
+ status={{type: 'error', message: 'Something went wrong'}}
919
+ />,
858
920
  );
859
921
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
860
922
  'data-variant',
@@ -864,7 +926,13 @@ describe('FileInput statusVariant forwarding', () => {
864
926
 
865
927
  it('forwards statusVariant="detached" to the underlying Field status', () => {
866
928
  const {container} = render(
867
- <FileInput label="Upload" value={null} onChange={() => {}} status={{type: 'error', message: 'Something went wrong'}} statusVariant="detached" />,
929
+ <FileInput
930
+ label="Upload"
931
+ value={null}
932
+ onChange={() => {}}
933
+ status={{type: 'error', message: 'Something went wrong'}}
934
+ statusVariant="detached"
935
+ />,
868
936
  );
869
937
  expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
870
938
  'data-variant',