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

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 (625) 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/Center/Center.d.ts +20 -3
  33. package/dist/Center/Center.d.ts.map +1 -1
  34. package/dist/Center/Center.js +10 -2
  35. package/dist/Chat/ChatComposerInput.js +1 -1
  36. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  37. package/dist/Chat/ChatDictationButton.js +3 -1
  38. package/dist/Chat/ChatLayout.d.ts +7 -0
  39. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  40. package/dist/Chat/ChatLayout.js +16 -5
  41. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  42. package/dist/Chat/ChatMessageBubble.js +8 -8
  43. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  44. package/dist/Chat/ChatToolCalls.js +10 -3
  45. package/dist/Chat/useTriggerMenu.js +2 -2
  46. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  47. package/dist/CheckboxInput/CheckboxInput.js +6 -6
  48. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  49. package/dist/CheckboxList/CheckboxListItem.js +19 -4
  50. package/dist/Citation/Citation.d.ts +22 -1
  51. package/dist/Citation/Citation.d.ts.map +1 -1
  52. package/dist/Citation/Citation.js +20 -6
  53. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  54. package/dist/CodeBlock/CodeBlock.js +16 -10
  55. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  56. package/dist/Collapsible/Collapsible.js +3 -1
  57. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  58. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  59. package/dist/CommandPalette/CommandPalette.js +42 -3
  60. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  61. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  62. package/dist/ContextMenu/ContextMenu.js +23 -5
  63. package/dist/ContextMenu/index.d.ts +1 -0
  64. package/dist/ContextMenu/index.d.ts.map +1 -1
  65. package/dist/ContextMenu/index.js +3 -1
  66. package/dist/DateInput/DateInput.d.ts +10 -2
  67. package/dist/DateInput/DateInput.d.ts.map +1 -1
  68. package/dist/DateInput/DateInput.js +33 -19
  69. package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
  70. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  71. package/dist/DateRangeInput/DateRangeInput.js +23 -20
  72. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  73. package/dist/DateTimeInput/DateTimeInput.js +23 -18
  74. package/dist/Divider/Divider.d.ts +2 -2
  75. package/dist/Divider/Divider.d.ts.map +1 -1
  76. package/dist/Divider/Divider.js +13 -0
  77. package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
  78. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  79. package/dist/DropdownMenu/DropdownMenu.js +22 -5
  80. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +18 -12
  81. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  82. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +42 -64
  83. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  84. package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
  85. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
  86. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  87. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
  88. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
  89. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  90. package/dist/DropdownMenu/DropdownMenuRadioItem.js +10 -3
  91. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
  92. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
  93. package/dist/DropdownMenu/DropdownMenuSubMenu.js +435 -0
  94. package/dist/DropdownMenu/index.d.ts +10 -0
  95. package/dist/DropdownMenu/index.d.ts.map +1 -1
  96. package/dist/DropdownMenu/index.js +13 -0
  97. package/dist/DropdownMenu/menuItemHover.d.ts +24 -0
  98. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  99. package/dist/DropdownMenu/menuItemHover.js +34 -0
  100. package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
  101. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
  102. package/dist/DropdownMenu/menuItemRoles.js +10 -1
  103. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  104. package/dist/DropdownMenu/renderDropdownItems.js +27 -10
  105. package/dist/Field/Field.d.ts +3 -1
  106. package/dist/Field/Field.d.ts.map +1 -1
  107. package/dist/Field/Field.js +4 -1
  108. package/dist/Field/FieldLabel.d.ts +2 -1
  109. package/dist/Field/FieldLabel.d.ts.map +1 -1
  110. package/dist/Field/FieldLabel.js +9 -5
  111. package/dist/Field/inputStyles.stylex.d.ts +1 -0
  112. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  113. package/dist/Field/inputStyles.stylex.js +1 -0
  114. package/dist/FieldStatus/FieldStatus.d.ts +10 -0
  115. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  116. package/dist/FieldStatus/FieldStatus.js +51 -5
  117. package/dist/FileInput/FileInput.d.ts +10 -2
  118. package/dist/FileInput/FileInput.d.ts.map +1 -1
  119. package/dist/FileInput/FileInput.js +93 -65
  120. package/dist/Heading/Heading.d.ts.map +1 -1
  121. package/dist/Heading/Heading.js +3 -2
  122. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  123. package/dist/HoverCard/useHoverCard.js +10 -4
  124. package/dist/Icon/Icon.d.ts +15 -1
  125. package/dist/Icon/Icon.d.ts.map +1 -1
  126. package/dist/Icon/Icon.js +19 -3
  127. package/dist/Item/Item.d.ts +16 -3
  128. package/dist/Item/Item.d.ts.map +1 -1
  129. package/dist/Item/Item.js +31 -6
  130. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  131. package/dist/Layer/layerAnimations.stylex.js +10 -2
  132. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  133. package/dist/Lightbox/Lightbox.js +34 -15
  134. package/dist/List/List.d.ts.map +1 -1
  135. package/dist/List/List.js +6 -3
  136. package/dist/List/ListItem.d.ts +11 -1
  137. package/dist/List/ListItem.d.ts.map +1 -1
  138. package/dist/List/ListItem.js +2 -0
  139. package/dist/Markdown/Markdown.d.ts.map +1 -1
  140. package/dist/Markdown/Markdown.js +7 -0
  141. package/dist/MetadataList/MetadataList.d.ts +1 -1
  142. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  143. package/dist/MetadataList/MetadataList.js +4 -2
  144. package/dist/MultiSelector/MultiSelector.d.ts +9 -1
  145. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  146. package/dist/MultiSelector/MultiSelector.js +87 -45
  147. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  148. package/dist/NumberInput/NumberInput.d.ts +10 -2
  149. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  150. package/dist/NumberInput/NumberInput.js +22 -17
  151. package/dist/Outline/Outline.js +2 -2
  152. package/dist/Pagination/Pagination.d.ts.map +1 -1
  153. package/dist/Pagination/Pagination.js +11 -3
  154. package/dist/PowerSearch/PowerSearch.d.ts +9 -2
  155. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  156. package/dist/PowerSearch/PowerSearch.js +2 -0
  157. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  158. package/dist/ProgressBar/ProgressBar.js +6 -1
  159. package/dist/RadioList/RadioList.d.ts +2 -2
  160. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  161. package/dist/RadioList/RadioListItem.js +5 -5
  162. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  163. package/dist/Resizable/ResizeHandle.js +49 -19
  164. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  165. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  166. package/dist/SegmentedControl/SegmentedControlItem.js +5 -3
  167. package/dist/Selector/Selector.d.ts +8 -0
  168. package/dist/Selector/Selector.d.ts.map +1 -1
  169. package/dist/Selector/Selector.js +72 -19
  170. package/dist/SideNav/SideNav.d.ts.map +1 -1
  171. package/dist/SideNav/SideNav.js +5 -5
  172. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  173. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  174. package/dist/SideNav/SideNavItem.d.ts +1 -1
  175. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  176. package/dist/SideNav/SideNavItem.js +12 -10
  177. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  178. package/dist/Skeleton/Skeleton.js +2 -2
  179. package/dist/Slider/Slider.d.ts.map +1 -1
  180. package/dist/Slider/Slider.js +87 -34
  181. package/dist/Spinner/Spinner.d.ts +3 -2
  182. package/dist/Spinner/Spinner.d.ts.map +1 -1
  183. package/dist/Spinner/Spinner.js +11 -2
  184. package/dist/Switch/Switch.d.ts +8 -1
  185. package/dist/Switch/Switch.d.ts.map +1 -1
  186. package/dist/Switch/Switch.js +171 -91
  187. package/dist/TabList/Tab.js +2 -2
  188. package/dist/TabList/TabList.d.ts +2 -11
  189. package/dist/TabList/TabList.d.ts.map +1 -1
  190. package/dist/TabList/TabList.js +5 -9
  191. package/dist/TabList/TabListContext.d.ts +0 -5
  192. package/dist/TabList/TabListContext.d.ts.map +1 -1
  193. package/dist/TabList/TabListContext.js +0 -5
  194. package/dist/TabList/TabMenu.js +1 -1
  195. package/dist/Table/BaseTable.d.ts.map +1 -1
  196. package/dist/Table/BaseTable.js +30 -4
  197. package/dist/Table/TableCell.js +3 -3
  198. package/dist/Table/TableHeaderCell.js +3 -3
  199. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  200. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  201. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +18 -3
  202. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  203. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +58 -30
  204. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  205. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  206. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  207. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +15 -7
  208. package/dist/Table/plugins/tree/useTableTreeData.d.ts +11 -0
  209. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  210. package/dist/Table/plugins/tree/useTableTreeData.js +65 -25
  211. package/dist/Table/types.d.ts +32 -0
  212. package/dist/Table/types.d.ts.map +1 -1
  213. package/dist/Text/Text.d.ts +10 -1
  214. package/dist/Text/Text.d.ts.map +1 -1
  215. package/dist/Text/Text.js +25 -2
  216. package/dist/Text/index.d.ts +2 -2
  217. package/dist/Text/index.d.ts.map +1 -1
  218. package/dist/TextArea/TextArea.d.ts +10 -1
  219. package/dist/TextArea/TextArea.d.ts.map +1 -1
  220. package/dist/TextArea/TextArea.js +119 -52
  221. package/dist/TextInput/TextInput.d.ts +10 -2
  222. package/dist/TextInput/TextInput.d.ts.map +1 -1
  223. package/dist/TextInput/TextInput.js +20 -17
  224. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  225. package/dist/Thumbnail/Thumbnail.js +51 -45
  226. package/dist/TimeInput/TimeInput.d.ts +10 -2
  227. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  228. package/dist/TimeInput/TimeInput.js +17 -17
  229. package/dist/Timestamp/Timestamp.d.ts +31 -3
  230. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  231. package/dist/Timestamp/Timestamp.js +48 -77
  232. package/dist/Timestamp/formatInstant.d.ts +41 -0
  233. package/dist/Timestamp/formatInstant.d.ts.map +1 -0
  234. package/dist/Timestamp/formatInstant.js +177 -0
  235. package/dist/Timestamp/index.d.ts +1 -0
  236. package/dist/Timestamp/index.d.ts.map +1 -1
  237. package/dist/Timestamp/tooltipEntries.d.ts +56 -0
  238. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
  239. package/dist/Timestamp/tooltipEntries.js +163 -0
  240. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  241. package/dist/Toast/ToastViewport.js +61 -9
  242. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  243. package/dist/ToggleButton/ToggleButton.js +3 -1
  244. package/dist/Token/Token.d.ts +34 -4
  245. package/dist/Token/Token.d.ts.map +1 -1
  246. package/dist/Token/Token.js +85 -45
  247. package/dist/Token/TokenLink.d.ts +62 -0
  248. package/dist/Token/TokenLink.d.ts.map +1 -0
  249. package/dist/Token/TokenLink.js +76 -0
  250. package/dist/Token/index.d.ts +1 -1
  251. package/dist/Token/index.d.ts.map +1 -1
  252. package/dist/Tokenizer/Tokenizer.d.ts +9 -2
  253. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  254. package/dist/Tokenizer/Tokenizer.js +4 -2
  255. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  256. package/dist/Tooltip/useTooltip.js +17 -1
  257. package/dist/TopNav/TopNavItem.d.ts +3 -1
  258. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  259. package/dist/TopNav/TopNavItem.js +30 -3
  260. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  261. package/dist/TopNav/TopNavMegaMenu.js +9 -3
  262. package/dist/TreeList/TreeList.d.ts.map +1 -1
  263. package/dist/TreeList/TreeList.js +1 -0
  264. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  265. package/dist/TreeList/TreeListBranches.js +8 -6
  266. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  267. package/dist/TreeList/TreeListItem.js +32 -14
  268. package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
  269. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  270. package/dist/Typeahead/BaseTypeahead.js +22 -11
  271. package/dist/Typeahead/Typeahead.d.ts +9 -2
  272. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  273. package/dist/Typeahead/Typeahead.js +11 -2
  274. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  275. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  276. package/dist/Typeahead/TypeaheadItem.js +20 -10
  277. package/dist/astryx.css +115 -35
  278. package/dist/astryx.umd.js +51 -51
  279. package/dist/astryx.umd.js.map +4 -4
  280. package/dist/hooks/containerReveal.pool.stylex.d.ts +281 -0
  281. package/dist/hooks/containerReveal.pool.stylex.d.ts.map +1 -0
  282. package/dist/hooks/containerReveal.pool.stylex.js +281 -0
  283. package/dist/hooks/index.d.ts +4 -0
  284. package/dist/hooks/index.d.ts.map +1 -1
  285. package/dist/hooks/index.js +3 -1
  286. package/dist/hooks/isRtlElement.d.ts +18 -0
  287. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  288. package/dist/hooks/isRtlElement.js +27 -0
  289. package/dist/hooks/useAnnounce.d.ts +3 -0
  290. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  291. package/dist/hooks/useAnnounce.js +39 -1
  292. package/dist/hooks/useContainerReveal.d.ts +83 -0
  293. package/dist/hooks/useContainerReveal.d.ts.map +1 -0
  294. package/dist/hooks/useContainerReveal.js +123 -0
  295. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  296. package/dist/hooks/useFocusTrap.js +52 -11
  297. package/dist/hooks/useGridFocus.d.ts +6 -1
  298. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  299. package/dist/hooks/useGridFocus.js +12 -9
  300. package/dist/hooks/useHotkeys.d.ts +9 -0
  301. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  302. package/dist/hooks/useHotkeys.js +9 -0
  303. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  304. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  305. package/dist/hooks/useInputStatusIcon.js +169 -0
  306. package/dist/hooks/useKeyboardHint.d.ts +1 -1
  307. package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
  308. package/dist/hooks/useKeyboardHint.js +4 -2
  309. package/dist/hooks/useListFocus.d.ts +39 -1
  310. package/dist/hooks/useListFocus.d.ts.map +1 -1
  311. package/dist/hooks/useListFocus.js +54 -9
  312. package/dist/i18n/InternationalizationContext.d.ts +1 -0
  313. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  314. package/dist/i18n/InternationalizationContext.js +3 -0
  315. package/dist/i18n/InternationalizationProvider.d.ts +8 -1
  316. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  317. package/dist/i18n/InternationalizationProvider.js +5 -1
  318. package/dist/i18n/getLocaleDirection.d.ts +18 -0
  319. package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
  320. package/dist/i18n/getLocaleDirection.js +29 -0
  321. package/dist/i18n/index.d.ts +6 -0
  322. package/dist/i18n/index.d.ts.map +1 -1
  323. package/dist/i18n/index.js +7 -1
  324. package/dist/i18n/useDirection.d.ts +2 -0
  325. package/dist/i18n/useDirection.d.ts.map +1 -0
  326. package/dist/i18n/useDirection.js +27 -0
  327. package/dist/theme/defineTheme.d.ts +6 -0
  328. package/dist/theme/defineTheme.d.ts.map +1 -1
  329. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  330. package/dist/theme/derivedVarRegistry.js +13 -0
  331. package/dist/theme/expandColorScale.d.ts +19 -2
  332. package/dist/theme/expandColorScale.d.ts.map +1 -1
  333. package/dist/theme/expandColorScale.js +38 -10
  334. package/dist/theme/index.d.ts +3 -3
  335. package/dist/theme/index.d.ts.map +1 -1
  336. package/dist/theme/types.d.ts +39 -2
  337. package/dist/theme/types.d.ts.map +1 -1
  338. package/dist/utils/index.d.ts +1 -0
  339. package/dist/utils/index.d.ts.map +1 -1
  340. package/dist/utils/index.js +2 -1
  341. package/dist/utils/plainDate.d.ts +17 -0
  342. package/dist/utils/plainDate.d.ts.map +1 -1
  343. package/dist/utils/plainDate.js +23 -4
  344. package/dist/utils/rtlStyles.d.ts +24 -0
  345. package/dist/utils/rtlStyles.d.ts.map +1 -0
  346. package/dist/utils/rtlStyles.js +27 -0
  347. package/locales/en.json +120 -0
  348. package/locales/pseudo.json +90 -0
  349. package/package.json +8 -3
  350. package/src/Avatar/Avatar.doc.mjs +50 -3
  351. package/src/Avatar/Avatar.test.tsx +218 -0
  352. package/src/Avatar/Avatar.tsx +285 -79
  353. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  354. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  355. package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
  356. package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
  357. package/src/AvatarGroup/AvatarGroup.tsx +58 -3
  358. package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
  359. package/src/Banner/Banner.tsx +6 -6
  360. package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
  361. package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
  362. package/src/Breadcrumbs/index.ts +4 -0
  363. package/src/Button/Button.doc.mjs +0 -4
  364. package/src/Button/Button.test.tsx +16 -0
  365. package/src/Button/Button.tsx +6 -4
  366. package/src/Calendar/Calendar.test.tsx +170 -20
  367. package/src/Calendar/Calendar.tsx +73 -16
  368. package/src/Calendar/dayCellUtils.test.ts +18 -18
  369. package/src/Calendar/dayCellUtils.ts +2 -2
  370. package/src/Calendar/styles.ts +33 -39
  371. package/src/Card/Card.tsx +1 -1
  372. package/src/Carousel/Carousel.tsx +25 -6
  373. package/src/Center/Center.doc.mjs +38 -0
  374. package/src/Center/Center.test.tsx +75 -0
  375. package/src/Center/Center.tsx +37 -2
  376. package/src/Chat/ChatComposer.doc.mjs +2 -2
  377. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  378. package/src/Chat/ChatComposerInput.tsx +2 -2
  379. package/src/Chat/ChatDictationButton.tsx +7 -1
  380. package/src/Chat/ChatLayout.test.tsx +57 -0
  381. package/src/Chat/ChatLayout.tsx +26 -5
  382. package/src/Chat/ChatMessageBubble.tsx +15 -10
  383. package/src/Chat/ChatSystemMessage.test.tsx +5 -0
  384. package/src/Chat/ChatToolCalls.tsx +9 -2
  385. package/src/Chat/useTriggerMenu.tsx +1 -1
  386. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  387. package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
  388. package/src/CheckboxInput/CheckboxInput.tsx +21 -6
  389. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  390. package/src/CheckboxList/CheckboxList.test.tsx +94 -3
  391. package/src/CheckboxList/CheckboxListItem.tsx +17 -10
  392. package/src/Citation/Citation.doc.mjs +4 -3
  393. package/src/Citation/Citation.test.tsx +97 -0
  394. package/src/Citation/Citation.tsx +43 -11
  395. package/src/CodeBlock/CodeBlock.test.tsx +17 -0
  396. package/src/CodeBlock/CodeBlock.tsx +38 -11
  397. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  398. package/src/Collapsible/Collapsible.test.tsx +7 -0
  399. package/src/Collapsible/Collapsible.tsx +16 -6
  400. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  401. package/src/CommandPalette/CommandPalette.tsx +41 -2
  402. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  403. package/src/ContextMenu/ContextMenu.test.tsx +59 -2
  404. package/src/ContextMenu/ContextMenu.tsx +22 -11
  405. package/src/ContextMenu/index.ts +5 -0
  406. package/src/DateInput/DateInput.doc.mjs +25 -0
  407. package/src/DateInput/DateInput.test.tsx +230 -0
  408. package/src/DateInput/DateInput.tsx +51 -29
  409. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  410. package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
  411. package/src/DateRangeInput/DateRangeInput.tsx +42 -30
  412. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  413. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  414. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  415. package/src/Divider/Divider.test.tsx +32 -8
  416. package/src/Divider/Divider.tsx +14 -1
  417. package/src/DropdownMenu/DropdownMenu.doc.mjs +5 -2
  418. package/src/DropdownMenu/DropdownMenu.test.tsx +95 -0
  419. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  420. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +49 -66
  421. package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
  422. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
  423. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
  424. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +19 -4
  425. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +84 -2
  426. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  427. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +680 -0
  428. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +569 -0
  429. package/src/DropdownMenu/index.ts +16 -0
  430. package/src/DropdownMenu/menuItemHover.ts +40 -0
  431. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  432. package/src/DropdownMenu/renderDropdownItems.tsx +40 -14
  433. package/src/Field/Field.doc.mjs +4 -0
  434. package/src/Field/Field.tsx +14 -9
  435. package/src/Field/FieldLabel.test.tsx +25 -0
  436. package/src/Field/FieldLabel.tsx +12 -3
  437. package/src/Field/inputStyles.stylex.ts +2 -0
  438. package/src/FieldStatus/FieldStatus.doc.mjs +1 -0
  439. package/src/FieldStatus/FieldStatus.test.tsx +133 -0
  440. package/src/FieldStatus/FieldStatus.tsx +61 -4
  441. package/src/FileInput/FileInput.doc.mjs +23 -2
  442. package/src/FileInput/FileInput.test.tsx +104 -13
  443. package/src/FileInput/FileInput.tsx +106 -79
  444. package/src/Heading/Heading.tsx +2 -1
  445. package/src/HoverCard/useHoverCard.tsx +15 -3
  446. package/src/Icon/Icon.doc.mjs +13 -0
  447. package/src/Icon/Icon.test.tsx +89 -0
  448. package/src/Icon/Icon.tsx +51 -3
  449. package/src/Item/Item.doc.mjs +5 -0
  450. package/src/Item/Item.test.tsx +88 -0
  451. package/src/Item/Item.tsx +57 -11
  452. package/src/Layer/layerAnimations.stylex.ts +23 -0
  453. package/src/Lightbox/Lightbox.test.tsx +33 -0
  454. package/src/Lightbox/Lightbox.tsx +30 -10
  455. package/src/List/List.test.tsx +17 -29
  456. package/src/List/List.tsx +6 -1
  457. package/src/List/ListItem.doc.mjs +12 -0
  458. package/src/List/ListItem.tsx +13 -0
  459. package/src/Markdown/Markdown.test.tsx +21 -0
  460. package/src/Markdown/Markdown.tsx +4 -0
  461. package/src/MetadataList/MetadataList.test.tsx +24 -0
  462. package/src/MetadataList/MetadataList.tsx +6 -2
  463. package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
  464. package/src/MultiSelector/MultiSelector.test.tsx +436 -0
  465. package/src/MultiSelector/MultiSelector.tsx +133 -67
  466. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  467. package/src/NumberInput/NumberInput.doc.mjs +21 -0
  468. package/src/NumberInput/NumberInput.test.tsx +71 -0
  469. package/src/NumberInput/NumberInput.tsx +35 -26
  470. package/src/Outline/Outline.test.tsx +12 -12
  471. package/src/Outline/Outline.tsx +2 -2
  472. package/src/Pagination/Pagination.tsx +11 -3
  473. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  474. package/src/PowerSearch/PowerSearch.test.tsx +23 -0
  475. package/src/PowerSearch/PowerSearch.tsx +10 -1
  476. package/src/ProgressBar/ProgressBar.test.tsx +34 -0
  477. package/src/ProgressBar/ProgressBar.tsx +16 -1
  478. package/src/RadioList/RadioList.doc.mjs +6 -0
  479. package/src/RadioList/RadioList.test.tsx +26 -4
  480. package/src/RadioList/RadioList.tsx +2 -2
  481. package/src/RadioList/RadioListItem.tsx +12 -5
  482. package/src/Resizable/ResizeHandle.test.tsx +94 -0
  483. package/src/Resizable/ResizeHandle.tsx +70 -20
  484. package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
  485. package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
  486. package/src/Selector/Selector.doc.mjs +15 -0
  487. package/src/Selector/Selector.test.tsx +400 -0
  488. package/src/Selector/Selector.tsx +95 -23
  489. package/src/SideNav/SideNav.tsx +1 -8
  490. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  491. package/src/SideNav/SideNavItem.tsx +5 -3
  492. package/src/Skeleton/Skeleton.test.tsx +16 -0
  493. package/src/Skeleton/Skeleton.tsx +13 -1
  494. package/src/Slider/Slider.doc.mjs +6 -0
  495. package/src/Slider/Slider.test.tsx +240 -12
  496. package/src/Slider/Slider.tsx +96 -23
  497. package/src/Spinner/Spinner.test.tsx +10 -8
  498. package/src/Spinner/Spinner.tsx +15 -5
  499. package/src/Switch/Switch.doc.mjs +142 -42
  500. package/src/Switch/Switch.test.tsx +111 -0
  501. package/src/Switch/Switch.tsx +149 -32
  502. package/src/TabList/Tab.tsx +2 -2
  503. package/src/TabList/TabList.doc.mjs +0 -6
  504. package/src/TabList/TabList.test.tsx +3 -15
  505. package/src/TabList/TabList.tsx +6 -17
  506. package/src/TabList/TabListContext.ts +0 -6
  507. package/src/TabList/TabMenu.tsx +2 -2
  508. package/src/Table/BaseTable.tsx +34 -2
  509. package/src/Table/Table.doc.mjs +11 -0
  510. package/src/Table/Table.test.tsx +85 -0
  511. package/src/Table/TableCell.tsx +3 -3
  512. package/src/Table/TableHeaderCell.tsx +3 -3
  513. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  514. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
  515. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +48 -21
  516. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  517. package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
  518. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +38 -9
  519. package/src/Table/plugins/tree/useTableTreeData.test.tsx +161 -2
  520. package/src/Table/plugins/tree/useTableTreeData.tsx +71 -14
  521. package/src/Table/types.ts +33 -0
  522. package/src/Table/useTableRowExpansion.doc.mjs +55 -2
  523. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  524. package/src/Table/useTableTreeData.doc.mjs +9 -0
  525. package/src/Text/Heading.doc.mjs +3 -3
  526. package/src/Text/Text.doc.mjs +1 -1
  527. package/src/Text/Text.test.tsx +42 -0
  528. package/src/Text/Text.tsx +25 -1
  529. package/src/Text/index.ts +2 -6
  530. package/src/TextArea/TextArea.doc.mjs +23 -2
  531. package/src/TextArea/TextArea.test.tsx +132 -4
  532. package/src/TextArea/TextArea.tsx +161 -67
  533. package/src/TextInput/TextInput.doc.mjs +21 -0
  534. package/src/TextInput/TextInput.test.tsx +150 -0
  535. package/src/TextInput/TextInput.tsx +28 -25
  536. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  537. package/src/Thumbnail/Thumbnail.test.tsx +24 -1
  538. package/src/Thumbnail/Thumbnail.tsx +28 -35
  539. package/src/TimeInput/TimeInput.doc.mjs +21 -0
  540. package/src/TimeInput/TimeInput.test.tsx +23 -0
  541. package/src/TimeInput/TimeInput.tsx +24 -25
  542. package/src/Timestamp/Timestamp.doc.mjs +32 -6
  543. package/src/Timestamp/Timestamp.test.tsx +371 -0
  544. package/src/Timestamp/Timestamp.tsx +96 -93
  545. package/src/Timestamp/formatInstant.ts +218 -0
  546. package/src/Timestamp/index.ts +4 -0
  547. package/src/Timestamp/tooltipEntries.test.ts +552 -0
  548. package/src/Timestamp/tooltipEntries.ts +210 -0
  549. package/src/Toast/ToastViewport.test.tsx +218 -8
  550. package/src/Toast/ToastViewport.tsx +71 -12
  551. package/src/ToggleButton/ToggleButton.test.tsx +24 -0
  552. package/src/ToggleButton/ToggleButton.tsx +19 -1
  553. package/src/Token/Token.test.tsx +166 -15
  554. package/src/Token/Token.tsx +104 -47
  555. package/src/Token/TokenLink.tsx +107 -0
  556. package/src/Token/index.ts +1 -1
  557. package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
  558. package/src/Tokenizer/Tokenizer.test.tsx +23 -0
  559. package/src/Tokenizer/Tokenizer.tsx +14 -2
  560. package/src/Tooltip/Tooltip.test.tsx +46 -0
  561. package/src/Tooltip/useTooltip.tsx +20 -0
  562. package/src/TopNav/TopNav.test.tsx +93 -2
  563. package/src/TopNav/TopNavItem.doc.mjs +3 -3
  564. package/src/TopNav/TopNavItem.tsx +35 -6
  565. package/src/TopNav/TopNavMegaMenu.tsx +26 -2
  566. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
  567. package/src/TreeList/TreeList.doc.mjs +6 -0
  568. package/src/TreeList/TreeList.test.tsx +50 -10
  569. package/src/TreeList/TreeList.tsx +5 -0
  570. package/src/TreeList/TreeListBranches.tsx +8 -6
  571. package/src/TreeList/TreeListItem.tsx +33 -11
  572. package/src/Typeahead/BaseTypeahead.tsx +42 -15
  573. package/src/Typeahead/Typeahead.doc.mjs +13 -0
  574. package/src/Typeahead/Typeahead.test.tsx +112 -0
  575. package/src/Typeahead/Typeahead.tsx +17 -1
  576. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  577. package/src/__tests__/babelPluginAddExtensions.test.ts +190 -0
  578. package/src/__tests__/forcedColors.ts +60 -0
  579. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  580. package/src/doc-mjs.d.ts +19 -0
  581. package/src/hooks/containerReveal.pool.stylex.ts +464 -0
  582. package/src/hooks/index.ts +13 -0
  583. package/src/hooks/isRtlElement.ts +27 -0
  584. package/src/hooks/useAnnounce.test.tsx +75 -2
  585. package/src/hooks/useAnnounce.ts +47 -1
  586. package/src/hooks/useContainerReveal.test.tsx +116 -0
  587. package/src/hooks/useContainerReveal.ts +180 -0
  588. package/src/hooks/useFocusTrap.test.tsx +104 -0
  589. package/src/hooks/useFocusTrap.ts +61 -12
  590. package/src/hooks/useGridFocus.doc.mjs +3 -3
  591. package/src/hooks/useGridFocus.test.tsx +41 -0
  592. package/src/hooks/useGridFocus.ts +21 -10
  593. package/src/hooks/useHotkeys.ts +9 -0
  594. package/src/hooks/useInputStatusIcon.test.tsx +221 -0
  595. package/src/hooks/useInputStatusIcon.tsx +235 -0
  596. package/src/hooks/useKeyboardHint.test.tsx +22 -0
  597. package/src/hooks/useKeyboardHint.tsx +6 -2
  598. package/src/hooks/useListFocus.doc.mjs +25 -3
  599. package/src/hooks/useListFocus.test.tsx +153 -1
  600. package/src/hooks/useListFocus.ts +102 -9
  601. package/src/i18n/InternationalizationContext.ts +4 -0
  602. package/src/i18n/InternationalizationProvider.tsx +12 -2
  603. package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
  604. package/src/i18n/__tests__/useDirection.test.tsx +66 -0
  605. package/src/i18n/getLocaleDirection.ts +29 -0
  606. package/src/i18n/index.ts +6 -0
  607. package/src/i18n/useDirection.ts +29 -0
  608. package/src/reset.css +0 -26
  609. package/src/reset.test.ts +60 -0
  610. package/src/theme/defineTheme.ts +6 -0
  611. package/src/theme/derivedVarRegistry.test.ts +1 -0
  612. package/src/theme/derivedVarRegistry.ts +6 -0
  613. package/src/theme/expandColorScale.test.ts +144 -0
  614. package/src/theme/expandColorScale.ts +53 -15
  615. package/src/theme/generateThemeRules.test.ts +42 -0
  616. package/src/theme/index.ts +4 -8
  617. package/src/theme/types.ts +43 -13
  618. package/src/utils/index.ts +2 -0
  619. package/src/utils/plainDate.test.ts +24 -6
  620. package/src/utils/plainDate.ts +18 -4
  621. package/src/utils/rtlStyles.ts +27 -0
  622. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +0 -9
  623. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +0 -1
  624. package/dist/Thumbnail/thumbnail.markers.stylex.js +0 -14
  625. package/src/Thumbnail/thumbnail.markers.stylex.ts +0 -12
@@ -0,0 +1,29 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file useDirection.ts
7
+ * @input InternationalizationContext (via use())
8
+ * @output 'ltr' | 'rtl'
9
+ * @position Client hook for reading the ambient text direction. Returns 'ltr'
10
+ * when called outside a provider (matches the silent-en-fallback pattern of
11
+ * useTranslator).
12
+ *
13
+ * Use this in components that need to swap directional icons, mirror
14
+ * behavioral logic (slider math, keyboard nav), or apply direction-specific
15
+ * styling that CSS logical properties can't express.
16
+ *
17
+ * SYNC: When modified, update these files to stay in sync:
18
+ * - /packages/core/src/i18n/InternationalizationContext.ts
19
+ * - /packages/core/src/i18n/getLocaleDirection.ts (server-safe counterpart)
20
+ * - /packages/core/src/i18n/index.ts
21
+ */
22
+
23
+ import {use} from 'react';
24
+ import {InternationalizationContext} from './InternationalizationContext';
25
+
26
+ export function useDirection(): 'ltr' | 'rtl' {
27
+ const ctx = use(InternationalizationContext);
28
+ return ctx.direction;
29
+ }
package/src/reset.css CHANGED
@@ -360,32 +360,6 @@
360
360
  -webkit-tap-highlight-color: transparent;
361
361
  }
362
362
 
363
- /* ===========================================================================
364
- Touch Devices
365
- =========================================================================== */
366
-
367
- /*
368
- * Suppress focus-visible outlines on touch-only devices.
369
- *
370
- * Focus rings exist to show keyboard users where focus is. On devices
371
- * with no hover capability and a coarse pointer (phones, tablets),
372
- * there's no keyboard navigation — focus rings are visual noise that
373
- * can flash on tap, on dialog open (showModal auto-focus), or on
374
- * programmatic focus.
375
- *
376
- * This targets touch-only devices specifically:
377
- * - (hover: none) — no hover capability (not a mouse)
378
- * - (pointer: coarse) — imprecise pointer (finger, not stylus)
379
- *
380
- * Hybrid devices (laptop with touchscreen) are NOT affected because
381
- * their primary pointer is fine (trackpad/mouse) and hover is available.
382
- */
383
- @media (hover: none) and (pointer: coarse) {
384
- :where(:focus-visible) {
385
- outline: none;
386
- }
387
- }
388
-
389
363
  /* ===========================================================================
390
364
  Color Scheme
391
365
  =========================================================================== */
@@ -0,0 +1,60 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * Tests for reset.css invariants that components rely on.
5
+ *
6
+ * reset.css is a plain stylesheet, so these tests assert on its source
7
+ * text (same approach as the reset.css baseline checks in
8
+ * theme/onMediaTokens.test.ts and AspectRatio/AspectRatio.test.tsx).
9
+ */
10
+
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+
14
+ import {beforeAll, describe, expect, it} from 'vitest';
15
+
16
+ describe('reset.css accessibility invariants', () => {
17
+ let ruleBlocks: {selector: string; body: string}[];
18
+
19
+ beforeAll(() => {
20
+ const resetCSS = fs.readFileSync(
21
+ path.resolve(__dirname, './reset.css'),
22
+ 'utf-8',
23
+ );
24
+ // Strip comments, then collect every innermost `selector { body }`
25
+ // block. `[^{}]` keeps at-rule preludes (@media, @layer) out of the
26
+ // selector capture, since their own `{` terminates any earlier match.
27
+ const stripped = resetCSS.replace(/\/\*[\s\S]*?\*\//g, '');
28
+ ruleBlocks = [...stripped.matchAll(/([^{}]+)\{([^{}]*)\}/g)].map(
29
+ ([, selector, body]) => ({selector: selector.trim(), body}),
30
+ );
31
+ });
32
+
33
+ it('parses rule blocks out of reset.css', () => {
34
+ // Guards the WCAG assertion below against silently passing if the
35
+ // block parsing ever breaks.
36
+ expect(ruleBlocks.length).toBeGreaterThan(20);
37
+ expect(
38
+ ruleBlocks.some(({body}) => body.includes('box-sizing: border-box')),
39
+ ).toBe(true);
40
+ });
41
+
42
+ /**
43
+ * WCAG 2.4.7 (Focus Visible, Level AA): keyboard focus indicators must
44
+ * not be suppressed. `:focus-visible` only matches keyboard-style focus,
45
+ * so any `outline: none` on it removes the focus indicator for keyboard
46
+ * users — and a `@media (hover: none) and (pointer: coarse)` guard does
47
+ * not exempt keyboard users on coarse-pointer devices (iPad/phone with a
48
+ * Bluetooth keyboard, switch-control users).
49
+ */
50
+ it('does not suppress :focus-visible outlines (WCAG 2.4.7)', () => {
51
+ const focusVisibleBlocks = ruleBlocks.filter(({selector}) =>
52
+ selector.includes(':focus-visible'),
53
+ );
54
+ for (const {selector, body} of focusVisibleBlocks) {
55
+ expect
56
+ .soft(body, `":focus-visible" rule "${selector}" must keep the outline`)
57
+ .not.toMatch(/outline(?:-style|-width)?\s*:\s*(?:none|0)/);
58
+ }
59
+ });
60
+ });
@@ -239,9 +239,15 @@ export interface DefineThemeInput {
239
239
  * categorical hues, and fixed tokens (on-dark/on-light) use defaults.
240
240
  * Explicit `tokens` entries always take precedence.
241
241
  *
242
+ * `accent` is optional — omit it for a neutral-only theme, which keeps
243
+ * the default accent tokens and only themes the neutrals.
244
+ *
242
245
  * @example
243
246
  * ```tsx
244
247
  * color: { accent: '#0064E0', neutralStyle: 'cool', contrast: 'standard' }
248
+ *
249
+ * // Neutral-only — accent tokens stay at their defaults
250
+ * color: { neutralStyle: 'warm' }
245
251
  * ```
246
252
  */
247
253
  color?: ColorScaleConfig;
@@ -186,6 +186,7 @@ function discoverComponents(): ComponentInfo[] {
186
186
  // ---------------------------------------------------------------------------
187
187
 
188
188
  const DIR_TO_REGISTRY_KEY: Record<string, string> = {
189
+ Avatar: 'avatar',
189
190
  Banner: 'banner',
190
191
  Button: 'button',
191
192
  Card: 'card',
@@ -35,6 +35,12 @@ export interface DerivedVarEntry {
35
35
  * entries share the same property.
36
36
  */
37
37
  export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
38
+ avatar: [
39
+ {property: 'fontSize', vars: ['--_avatar-fallback-font-size']},
40
+ {property: 'fontWeight', vars: ['--_avatar-fallback-font-weight']},
41
+ {property: 'color', vars: ['--_avatar-fallback-color']},
42
+ {property: 'backgroundColor', vars: ['--_avatar-fallback-background']},
43
+ ],
38
44
  banner: [{property: 'borderRadius', vars: ['--_banner-radius']}],
39
45
  button: [{property: 'borderRadius', vars: ['--_button-radius']}],
40
46
  card: [
@@ -4,6 +4,19 @@ import {describe, it, expect} from 'vitest';
4
4
  import {expandColorScale} from './expandColorScale';
5
5
  import {defineTheme} from './defineTheme';
6
6
  import {generateThemeRules} from './generateThemeRules';
7
+ import {resolveThemeTokens} from './tokens';
8
+ import {colorDefaults} from './tokens.stylex';
9
+
10
+ /** Light-mode half of colorDefaults['--color-accent'] — the hue an accent-less config seeds from. */
11
+ const DEFAULT_ACCENT = '#0064E0';
12
+ const DEFAULT_ACCENT_DARK = '#2694FE';
13
+
14
+ /** The three tokens that only exist when a seed accent is supplied. */
15
+ const ACCENT_TOKENS = [
16
+ '--color-accent',
17
+ '--color-accent-muted',
18
+ '--color-on-accent',
19
+ ] as const;
7
20
 
8
21
  describe('expandColorScale', () => {
9
22
  it('produces all expected token keys', () => {
@@ -86,6 +99,82 @@ describe('expandColorScale', () => {
86
99
  });
87
100
  });
88
101
 
102
+ describe('expandColorScale — neutral-only themes (#2279)', () => {
103
+ it('accent is optional — a config without one expands', () => {
104
+ const tokens = expandColorScale({neutralStyle: 'warm'});
105
+ expect(tokens['--color-background-surface']).toMatch(/^light-dark\(#/);
106
+ });
107
+
108
+ it('expands an empty config', () => {
109
+ const tokens = expandColorScale({});
110
+ expect(tokens['--color-background-surface']).toMatch(/^light-dark\(#/);
111
+ expect(tokens).not.toHaveProperty('--color-accent');
112
+ });
113
+
114
+ it('omits the accent tokens so they fall through to colorDefaults', () => {
115
+ const tokens = expandColorScale({neutralStyle: 'warm'});
116
+ for (const key of ACCENT_TOKENS) {
117
+ expect(tokens).not.toHaveProperty(key);
118
+ }
119
+ // ...and the reference tokens still point at whatever --color-accent resolves to.
120
+ expect(tokens['--color-text-accent']).toBe('var(--color-accent)');
121
+ expect(tokens['--color-icon-accent']).toBe('var(--color-accent)');
122
+ });
123
+
124
+ it('seeds the neutral palettes from the light half of the default accent', () => {
125
+ // Drift guard: the module's DEFAULT_ACCENT_SEED is private, so pin the
126
+ // colorDefaults value it is copied from. Re-coloring the default accent
127
+ // without re-seeding would silently change every neutral-only theme.
128
+ expect(colorDefaults['--color-accent']).toBe(
129
+ `light-dark(${DEFAULT_ACCENT}, ${DEFAULT_ACCENT_DARK})`,
130
+ );
131
+
132
+ const neutralOnly = expandColorScale({neutralStyle: 'warm'});
133
+ const seeded = expandColorScale({
134
+ accent: DEFAULT_ACCENT,
135
+ neutralStyle: 'warm',
136
+ });
137
+ for (const [key, value] of Object.entries(seeded)) {
138
+ if ((ACCENT_TOKENS as ReadonlyArray<string>).includes(key)) {
139
+ continue;
140
+ }
141
+ expect(neutralOnly[key], key).toBe(value);
142
+ }
143
+ });
144
+
145
+ it('honours neutralStyle and contrast without an accent', () => {
146
+ const warm = expandColorScale({neutralStyle: 'warm'});
147
+ const cool = expandColorScale({neutralStyle: 'cool'});
148
+ expect(warm['--color-neutral']).not.toBe(cool['--color-neutral']);
149
+
150
+ const high = expandColorScale({contrast: 'high'});
151
+ const standard = expandColorScale({contrast: 'standard'});
152
+ expect(high['--color-text-primary']).not.toBe(
153
+ standard['--color-text-primary'],
154
+ );
155
+ });
156
+
157
+ it('does not re-color themes that do pass an accent', () => {
158
+ // Seeding from the default hex derives a DIFFERENT accent than the default
159
+ // token holds, so "just default the seed" is not behavior-preserving —
160
+ // omitting the tokens is the only way a neutral-only theme keeps the
161
+ // default accent.
162
+ const tokens = expandColorScale({accent: DEFAULT_ACCENT});
163
+ expect(tokens['--color-accent']).toMatch(/^light-dark\(#/);
164
+ expect(tokens['--color-accent']).not.toBe(colorDefaults['--color-accent']);
165
+ });
166
+
167
+ it('treats an empty accent as supplied, not absent', () => {
168
+ // '' is falsy but not nullish. Only an absent accent is neutral-only; a
169
+ // supplied-but-malformed one keeps its pre-#2279 behavior (the hex parser
170
+ // falls back to black) rather than silently dropping the accent tokens.
171
+ const tokens = expandColorScale({accent: ''});
172
+ for (const key of ACCENT_TOKENS) {
173
+ expect(tokens).toHaveProperty(key);
174
+ }
175
+ });
176
+ });
177
+
89
178
  describe('expandColorScale + defineTheme integration', () => {
90
179
  it('explicit token overrides win over generated values', () => {
91
180
  const theme = defineTheme({
@@ -110,4 +199,59 @@ describe('expandColorScale + defineTheme integration', () => {
110
199
  // The base token itself stays a resolved color pair.
111
200
  expect(css).toMatch(/--color-accent: light-dark\(#/);
112
201
  });
202
+
203
+ it('a neutral-only theme leaves the accent tokens at their defaults (#2279)', () => {
204
+ const theme = defineTheme({
205
+ name: 'test-neutral-only',
206
+ color: {neutralStyle: 'warm'},
207
+ });
208
+ for (const key of ACCENT_TOKENS) {
209
+ expect(theme.tokens).not.toHaveProperty(key);
210
+ }
211
+ // Neutrals are still themed.
212
+ expect(theme.tokens['--color-background-surface']).toMatch(
213
+ /^light-dark\(#/,
214
+ );
215
+
216
+ const css = generateThemeRules(theme).join('\n');
217
+ expect(css).not.toContain('--color-accent:');
218
+ expect(css).not.toContain('--color-on-accent:');
219
+ expect(css).toContain('--color-background-surface:');
220
+ });
221
+
222
+ it('a neutral-only theme resolves accent tokens to the defaults at runtime (#2279)', () => {
223
+ // The CSS side falls through by simply not emitting the tokens. The JS side
224
+ // (useTheme/resolveThemeTokens) has to agree: the omitted tokens come back
225
+ // from tokenDefaults, and the var() references the theme DOES emit resolve
226
+ // against them instead of leaking a literal 'var(--color-accent)'.
227
+ const theme = defineTheme({
228
+ name: 'test-neutral-only-runtime',
229
+ color: {neutralStyle: 'warm'},
230
+ });
231
+
232
+ const light = resolveThemeTokens(theme, {mode: 'light'});
233
+ expect(light['--color-accent']).toBe(DEFAULT_ACCENT);
234
+ expect(light['--color-text-accent']).toBe(DEFAULT_ACCENT);
235
+ expect(light['--color-icon-accent']).toBe(DEFAULT_ACCENT);
236
+
237
+ const dark = resolveThemeTokens(theme, {mode: 'dark'});
238
+ expect(dark['--color-accent']).toBe(DEFAULT_ACCENT_DARK);
239
+ expect(dark['--color-text-accent']).toBe(DEFAULT_ACCENT_DARK);
240
+ });
241
+
242
+ it('an explicit accent token still wins on a neutral-only theme (#2279)', () => {
243
+ // Neutral scale from HCT + a hand-picked accent: the tokens map is the only
244
+ // source of --color-accent, so the reference tokens follow it.
245
+ const theme = defineTheme({
246
+ name: 'test-neutral-only-explicit-accent',
247
+ color: {neutralStyle: 'warm'},
248
+ tokens: {'--color-accent': ['#AA0000', '#FF5555']},
249
+ });
250
+ expect(
251
+ resolveThemeTokens(theme, {mode: 'light'})['--color-text-accent'],
252
+ ).toBe('#AA0000');
253
+
254
+ const css = generateThemeRules(theme).join('\n');
255
+ expect(css).toContain('--color-text-accent: var(--color-accent);');
256
+ });
113
257
  });
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * @file expandColorScale.ts
5
- * @input Color scale configuration { accent, neutralStyle?, contrast? }
5
+ * @input Color scale configuration { accent?, neutralStyle?, contrast? }
6
6
  * @output Token overrides for derivable color tokens
7
7
  * @position Theme utility; consumed by defineTheme.ts
8
8
  *
@@ -11,6 +11,10 @@
11
11
  * derive from the accent — status colors, categorical hues, and fixed
12
12
  * tokens (on-dark/on-light) fall through to colorDefaults.
13
13
  *
14
+ * `accent` is optional: a neutral-only config still gets the full neutral
15
+ * ramp (seeded from the default accent's hue) while the accent tokens
16
+ * themselves fall through to colorDefaults, same as the tokens above.
17
+ *
14
18
  * SYNC: When modified, update:
15
19
  * - /packages/core/src/theme/defineTheme.ts
16
20
  */
@@ -31,11 +35,21 @@ import {hexToHct, tonalPalette, hexWithAlpha} from './hct';
31
35
  *
32
36
  * // With customization
33
37
  * { accent: '#B7410E', neutralStyle: 'warm', contrast: 'high' }
38
+ *
39
+ * // Neutral-only — keeps the default accent, themes the neutrals
40
+ * { neutralStyle: 'warm' }
34
41
  * ```
35
42
  */
36
43
  export interface ColorScaleConfig {
37
- /** Seed accent color as hex (#RRGGBB). Everything derives from this. */
38
- accent: string;
44
+ /**
45
+ * Seed accent color as hex (#RRGGBB). Everything derives from this.
46
+ *
47
+ * Optional. When omitted, the neutral palettes are seeded from the
48
+ * default accent's hue and the accent tokens (--color-accent,
49
+ * --color-accent-muted, --color-on-accent) are not generated — they
50
+ * fall through to colorDefaults.
51
+ */
52
+ accent?: string;
39
53
 
40
54
  /**
41
55
  * Neutral tone warmth. Controls how much of the seed's hue bleeds
@@ -69,6 +83,14 @@ const NEUTRAL_VARIANT_CHROMA: Record<string, number> = {
69
83
  neutral: 6,
70
84
  };
71
85
 
86
+ /**
87
+ * Hue source for accent-less configs — the light half of
88
+ * colorDefaults['--color-accent'] (a test guards the two against drift).
89
+ * Only its hue reaches the output: the accent tokens stay ungenerated, so
90
+ * they keep their colorDefaults values rather than this seed's derivation.
91
+ */
92
+ const DEFAULT_ACCENT_SEED = '#0064E0';
93
+
72
94
  // =============================================================================
73
95
  // Computation
74
96
  // =============================================================================
@@ -89,18 +111,23 @@ function accentWithAlpha(alpha: number): string {
89
111
  * --color-on-dark/on-light) are NOT generated — they fall through
90
112
  * to colorDefaults.
91
113
  *
114
+ * Without an `accent`, the accent tokens join that fall-through set: the
115
+ * neutrals are seeded from the default accent's hue, and --color-accent,
116
+ * --color-accent-muted and --color-on-accent keep their colorDefaults values.
117
+ *
92
118
  * @example
93
119
  * ```
94
120
  * const tokens = expandColorScale({ accent: '#0064E0' });
95
121
  * // tokens['--color-accent'] === 'light-dark(#..., #...)'
122
+ *
123
+ * const neutralOnly = expandColorScale({ neutralStyle: 'warm' });
124
+ * // neutralOnly['--color-accent'] === undefined
96
125
  * ```
97
126
  */
98
- export function expandColorScale(
99
- config: ColorScaleConfig,
100
- ): ColorScaleTokens {
127
+ export function expandColorScale(config: ColorScaleConfig): ColorScaleTokens {
101
128
  const {accent, neutralStyle = 'cool', contrast = 'standard'} = config;
102
129
 
103
- const seed = hexToHct(accent);
130
+ const seed = hexToHct(accent ?? DEFAULT_ACCENT_SEED);
104
131
  const seedHue = seed.hue;
105
132
 
106
133
  const primaryChroma = Math.max(seed.chroma, 48);
@@ -119,14 +146,25 @@ export function expandColorScale(
119
146
  const textSecondaryDarkTone = isHigh ? 80 : 70;
120
147
 
121
148
  return {
122
- // Core semantic
123
- '--color-accent': ld(P[40], P[80]),
124
- // Derived accent tokens reference --color-accent instead of baking its
125
- // resolved hex, so a scoped override of the base token re-accents the
126
- // whole subtree at runtime. --color-on-accent stays baked: it is a
127
- // contrast computation against the accent, which CSS cannot express.
128
- '--color-accent-muted': ld(accentWithAlpha(0.2), accentWithAlpha(0.25)),
129
- '--color-on-accent': ld(P[100], P[20]),
149
+ // Core semantic — only with a seed accent. Without one these fall through
150
+ // to colorDefaults, whose --color-accent is NOT what the default seed
151
+ // derives: defaulting the seed instead of omitting the tokens would
152
+ // recolor every neutral-only theme. Nullish and not truthy, matching the
153
+ // seed above, so a supplied-but-malformed accent keeps its old behavior.
154
+ ...(accent != null
155
+ ? {
156
+ '--color-accent': ld(P[40], P[80]),
157
+ // Derived accent tokens reference --color-accent instead of baking its
158
+ // resolved hex, so a scoped override of the base token re-accents the
159
+ // whole subtree at runtime. --color-on-accent stays baked: it is a
160
+ // contrast computation against the accent, which CSS cannot express.
161
+ '--color-accent-muted': ld(
162
+ accentWithAlpha(0.2),
163
+ accentWithAlpha(0.25),
164
+ ),
165
+ '--color-on-accent': ld(P[100], P[20]),
166
+ }
167
+ : null),
130
168
  '--color-neutral': ld(hexWithAlpha(N[10], 0.1), hexWithAlpha(N[90], 0.2)),
131
169
  '--color-background-surface': ld(N[99], N[10]),
132
170
  '--color-background-body': ld(N[95], N[5]),
@@ -385,6 +385,48 @@ describe('derived var expansion', () => {
385
385
  expect(rule).toContain('--_button-radius: 8px');
386
386
  });
387
387
 
388
+ it('emits internal vars for avatar fallback typography (base)', () => {
389
+ const theme = defineTheme({
390
+ name: 'test-derived-avatar',
391
+ components: {
392
+ avatar: {
393
+ base: {
394
+ fontWeight: 'var(--font-weight-normal)',
395
+ color: 'var(--color-text-secondary)',
396
+ backgroundColor: 'var(--color-accent-muted)',
397
+ },
398
+ },
399
+ },
400
+ });
401
+ const rules = generateThemeRules(theme);
402
+ const rule = rules.find(r => r.includes('.astryx-avatar'));
403
+ expect(rule).toBeDefined();
404
+ expect(rule).toContain(
405
+ '--_avatar-fallback-font-weight: var(--font-weight-normal)',
406
+ );
407
+ expect(rule).toContain(
408
+ '--_avatar-fallback-color: var(--color-text-secondary)',
409
+ );
410
+ expect(rule).toContain(
411
+ '--_avatar-fallback-background: var(--color-accent-muted)',
412
+ );
413
+ });
414
+
415
+ it('emits a per-size fallback font-size for avatar (size:sm)', () => {
416
+ const theme = defineTheme({
417
+ name: 'test-derived-avatar-size',
418
+ components: {
419
+ avatar: {
420
+ 'size:sm': {fontSize: '9px'},
421
+ },
422
+ },
423
+ });
424
+ const rules = generateThemeRules(theme);
425
+ const rule = rules.find(r => r.includes('.astryx-avatar.sm'));
426
+ expect(rule).toBeDefined();
427
+ expect(rule).toContain('--_avatar-fallback-font-size: 9px');
428
+ });
429
+
388
430
  it('does not emit derived vars for components without registry entries', () => {
389
431
  const theme = defineTheme({
390
432
  name: 'test-no-derived',
@@ -71,19 +71,13 @@ export {expandTypeScale, generateTypeScaleComponents} from './expandTypeScale';
71
71
  export type {TypeScaleConfig, TypeScaleTokens} from './expandTypeScale';
72
72
 
73
73
  export {expandRadiusScale} from './expandRadiusScale';
74
- export type {
75
- RadiusScaleConfig,
76
- RadiusScaleTokens,
77
- } from './expandRadiusScale';
74
+ export type {RadiusScaleConfig, RadiusScaleTokens} from './expandRadiusScale';
78
75
 
79
76
  export {expandColorScale} from './expandColorScale';
80
77
  export type {ColorScaleConfig, ColorScaleTokens} from './expandColorScale';
81
78
 
82
79
  export {expandMotionScale} from './expandMotionScale';
83
- export type {
84
- MotionScaleConfig,
85
- MotionScaleTokens,
86
- } from './expandMotionScale';
80
+ export type {MotionScaleConfig, MotionScaleTokens} from './expandMotionScale';
87
81
 
88
82
  // Export token defaults and vars for use in custom components and themes
89
83
  export {
@@ -155,6 +149,8 @@ export type {
155
149
  TextSize,
156
150
  TextWeight,
157
151
  TextColor,
152
+ BuiltinTextColor,
153
+ TextColorMap,
158
154
  TypographyConfig,
159
155
  TypographyRole,
160
156
  FontWeight,
@@ -15,11 +15,7 @@
15
15
  * Raw CSS values (e.g. '800') are accepted as an escape hatch.
16
16
  */
17
17
  export type FontWeight =
18
- | 'normal'
19
- | 'medium'
20
- | 'semibold'
21
- | 'bold'
22
- | (string & {});
18
+ 'normal' | 'medium' | 'semibold' | 'bold' | (string & {});
23
19
 
24
20
  /**
25
21
  * A typography role declaration (body, heading, or code).
@@ -155,15 +151,49 @@ export type TextSize =
155
151
  export type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';
156
152
 
157
153
  /**
158
- * Text color variants for Text/Heading
154
+ * Extensible map of text color variants for Text/Heading.
155
+ *
156
+ * Themes add custom colors via component overrides in defineTheme; a custom
157
+ * color renders with the `primary` baseline color from StyleX and receives its
158
+ * actual color from theme CSS (`.astryx-text.<color>` / `.astryx-heading.<color>`),
159
+ * exactly like custom text `type`s.
160
+ *
161
+ * To add type-safe custom colors, use module augmentation — the same technique
162
+ * as `ButtonVariantMap` etc.:
163
+ * ```ts
164
+ * declare module '@astryxdesign/core/Text' {
165
+ * interface TextColorMap {
166
+ * brand: true;
167
+ * danger: true;
168
+ * }
169
+ * }
170
+ * ```
171
+ *
172
+ * `astryx theme build` generates these augmentations automatically when it
173
+ * detects new `color:*` values in a theme's Text/Heading component overrides.
159
174
  */
160
- export type TextColor =
161
- | 'primary'
162
- | 'secondary'
163
- | 'disabled'
164
- | 'placeholder'
165
- | 'accent'
166
- | 'inherit';
175
+ export interface TextColorMap {
176
+ primary: true;
177
+ secondary: true;
178
+ disabled: true;
179
+ placeholder: true;
180
+ accent: true;
181
+ inherit: true;
182
+ }
183
+
184
+ /**
185
+ * Built-in text color variants for Text/Heading. The concrete keys that ship
186
+ * with the design system, independent of theme augmentation — used where a
187
+ * value must be one of the real StyleX color styles (see `resolveStyleColor`).
188
+ */
189
+ export type BuiltinTextColor =
190
+ 'primary' | 'secondary' | 'disabled' | 'placeholder' | 'accent' | 'inherit';
191
+
192
+ /**
193
+ * Text color variants for Text/Heading. Extensible via module augmentation of
194
+ * `TextColorMap`.
195
+ */
196
+ export type TextColor = keyof TextColorMap;
167
197
 
168
198
  /**
169
199
  * Display mode for Text/Heading
@@ -98,3 +98,5 @@ export {
98
98
  export type {RGBA} from './color';
99
99
 
100
100
  export {devWarn, devError, warnOnce, formatDevMessage} from './devWarning';
101
+
102
+ export {rtlStyles} from './rtlStyles';
@@ -235,19 +235,37 @@ describe('plainDateAddMonths', () => {
235
235
  });
236
236
  });
237
237
 
238
- it('overflows day into next month when target month is shorter', () => {
238
+ it('clamps to the last day when the target month is shorter', () => {
239
+ // Jan 31 + 1 month lands in February (clamped), not overflowed into
240
+ // March — matching Temporal.PlainDate.add and date-fns addMonths.
239
241
  expect(plainDateAddMonths({year: 2026, month: 1, day: 31}, 1)).toEqual({
240
242
  year: 2026,
241
- month: 3,
242
- day: 3,
243
+ month: 2,
244
+ day: 28,
243
245
  });
244
246
  });
245
247
 
246
- it('overflows Jan 31 + 1 month in leap year', () => {
248
+ it('clamps to Feb 29 in a leap year', () => {
247
249
  expect(plainDateAddMonths({year: 2024, month: 1, day: 31}, 1)).toEqual({
248
250
  year: 2024,
249
- month: 3,
250
- day: 2,
251
+ month: 2,
252
+ day: 29,
253
+ });
254
+ });
255
+
256
+ it('clamps when subtracting into a shorter month', () => {
257
+ expect(plainDateAddMonths({year: 2026, month: 3, day: 31}, -1)).toEqual({
258
+ year: 2026,
259
+ month: 2,
260
+ day: 28,
261
+ });
262
+ });
263
+
264
+ it('clamps a 31st onto a 30-day month', () => {
265
+ expect(plainDateAddMonths({year: 2026, month: 5, day: 31}, 1)).toEqual({
266
+ year: 2026,
267
+ month: 6,
268
+ day: 30,
251
269
  });
252
270
  });
253
271
  });