@astryxdesign/core 0.5.0 → 0.5.1-canary.70169cd

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 (622) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +45 -20
  5. package/dist/AspectRatio/AspectRatio.d.ts +6 -6
  6. package/dist/Avatar/Avatar.d.ts +25 -1
  7. package/dist/Avatar/Avatar.d.ts.map +1 -1
  8. package/dist/Avatar/Avatar.js +43 -9
  9. package/dist/Avatar/index.d.ts +2 -2
  10. package/dist/Avatar/index.d.ts.map +1 -1
  11. package/dist/Avatar/index.js +1 -1
  12. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  13. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  14. package/dist/AvatarGroup/AvatarGroup.js +5 -2
  15. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  16. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  17. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroupOverflow.js +11 -7
  19. package/dist/Badge/Badge.d.ts.map +1 -1
  20. package/dist/Badge/Badge.js +26 -2
  21. package/dist/Banner/Banner.d.ts +10 -1
  22. package/dist/Banner/Banner.d.ts.map +1 -1
  23. package/dist/Banner/Banner.js +11 -2
  24. package/dist/Button/Button.d.ts.map +1 -1
  25. package/dist/Button/Button.js +8 -7
  26. package/dist/Calendar/Calendar.d.ts +4 -2
  27. package/dist/Calendar/Calendar.d.ts.map +1 -1
  28. package/dist/Calendar/Calendar.js +15 -21
  29. package/dist/Calendar/hooks/useCalendarDays.js +4 -6
  30. package/dist/Calendar/hooks/useCalendarNavigation.js +4 -6
  31. package/dist/Calendar/styles.d.ts +5 -20
  32. package/dist/Calendar/styles.d.ts.map +1 -1
  33. package/dist/Calendar/styles.js +15 -17
  34. package/dist/Card/Card.d.ts +12 -12
  35. package/dist/Card/Card.d.ts.map +1 -1
  36. package/dist/Card/Card.js +17 -9
  37. package/dist/Card/index.d.ts +35 -1
  38. package/dist/Card/index.d.ts.map +1 -1
  39. package/dist/Card/index.js +21 -1
  40. package/dist/Carousel/Carousel.d.ts.map +1 -1
  41. package/dist/Carousel/Carousel.js +108 -7
  42. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  43. package/dist/CheckboxInput/CheckboxInput.js +7 -1
  44. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  45. package/dist/CodeBlock/CodeBlock.js +15 -4
  46. package/dist/CodeBlock/highlightRanges.js +1 -1
  47. package/dist/CodeBlock/highlightStyles.js +13 -13
  48. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  49. package/dist/CommandPalette/CommandPaletteItem.js +2 -7
  50. package/dist/ComplexSelector/ComplexSelector.d.ts +10 -2
  51. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  52. package/dist/ComplexSelector/ComplexSelector.js +14 -7
  53. package/dist/DateInput/DateInput.d.ts +43 -0
  54. package/dist/DateInput/DateInput.d.ts.map +1 -1
  55. package/dist/DateInput/DateInput.js +22 -5
  56. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  57. package/dist/DateInput/MonthScroller.js +5 -3
  58. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
  59. package/dist/DateInput/MonthYearWheels.js +6 -4
  60. package/dist/DateInput/NativeDateField.d.ts +10 -0
  61. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  62. package/dist/DateInput/NativeDateField.js +494 -0
  63. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  64. package/dist/DateInput/TouchDateField.js +52 -25
  65. package/dist/DateInput/Wheel.d.ts.map +1 -1
  66. package/dist/DateInput/Wheel.js +1 -0
  67. package/dist/DateInput/index.d.ts +1 -1
  68. package/dist/DateInput/index.d.ts.map +1 -1
  69. package/dist/DateInput/nativeDateSegments.d.ts +22 -0
  70. package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
  71. package/dist/DateInput/nativeDateSegments.js +111 -0
  72. package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
  73. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  74. package/dist/DateRangeInput/DateRangeInput.js +3 -5
  75. package/dist/DateTimeInput/DateTimeInput.d.ts +23 -24
  76. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  77. package/dist/DateTimeInput/DateTimeInput.js +35 -10
  78. package/dist/DateTimeInput/TouchDateTimeField.d.ts +6 -0
  79. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -0
  80. package/dist/DateTimeInput/TouchDateTimeField.js +1021 -0
  81. package/dist/Dialog/Dialog.d.ts +16 -2
  82. package/dist/Dialog/Dialog.d.ts.map +1 -1
  83. package/dist/Dialog/Dialog.js +28 -7
  84. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  85. package/dist/DropdownMenu/DropdownMenu.js +4 -13
  86. package/dist/Field/FieldLabel.d.ts.map +1 -1
  87. package/dist/Field/FieldLabel.js +9 -1
  88. package/dist/Field/InputClearButton.d.ts +9 -3
  89. package/dist/Field/InputClearButton.d.ts.map +1 -1
  90. package/dist/Field/InputClearButton.js +14 -3
  91. package/dist/Heading/Heading.d.ts.map +1 -1
  92. package/dist/Heading/Heading.js +0 -1
  93. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  94. package/dist/HoverCard/HoverCard.js +104 -3
  95. package/dist/HoverCard/useHoverCard.d.ts +14 -2
  96. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  97. package/dist/HoverCard/useHoverCard.js +7 -1
  98. package/dist/Icon/Icon.d.ts +4 -2
  99. package/dist/Icon/Icon.d.ts.map +1 -1
  100. package/dist/Icon/defaultIcons.d.ts +3 -2
  101. package/dist/Icon/defaultIcons.d.ts.map +1 -1
  102. package/dist/Icon/defaultIcons.js +7 -0
  103. package/dist/Icon/globalIconRegistry.d.ts +13 -0
  104. package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
  105. package/dist/Icon/globalIconRegistry.js +34 -6
  106. package/dist/Icon/index.d.ts +1 -1
  107. package/dist/Icon/index.d.ts.map +1 -1
  108. package/dist/Icon/useIcon.d.ts +5 -2
  109. package/dist/Icon/useIcon.d.ts.map +1 -1
  110. package/dist/Icon/useIcon.js +3 -0
  111. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  112. package/dist/Indicator/CheckboxIndicator.js +6 -2
  113. package/dist/Item/Item.d.ts.map +1 -1
  114. package/dist/Item/Item.js +2 -2
  115. package/dist/Kbd/Kbd.d.ts.map +1 -1
  116. package/dist/Kbd/Kbd.js +2 -26
  117. package/dist/Layer/gestureCounter.d.ts +8 -0
  118. package/dist/Layer/gestureCounter.d.ts.map +1 -0
  119. package/dist/Layer/gestureCounter.js +53 -0
  120. package/dist/Layer/useLayer.d.ts +23 -13
  121. package/dist/Layer/useLayer.d.ts.map +1 -1
  122. package/dist/Layer/useLayer.js +146 -24
  123. package/dist/List/List.d.ts +1 -1
  124. package/dist/List/List.d.ts.map +1 -1
  125. package/dist/List/List.js +15 -4
  126. package/dist/Markdown/Markdown.d.ts +1 -1
  127. package/dist/Markdown/Markdown.d.ts.map +1 -1
  128. package/dist/Markdown/Markdown.js +20 -7
  129. package/dist/Markdown/parser.d.ts.map +1 -1
  130. package/dist/Markdown/parser.js +5 -3
  131. package/dist/MetadataList/MetadataListItem.d.ts +1 -1
  132. package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
  133. package/dist/MetadataList/MetadataListItem.js +4 -1
  134. package/dist/MultiSelector/MultiSelector.d.ts +18 -1
  135. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  136. package/dist/MultiSelector/MultiSelector.js +58 -11
  137. package/dist/MultiSelector/hooks.d.ts +7 -1
  138. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  139. package/dist/MultiSelector/hooks.js +3 -2
  140. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  141. package/dist/NavIcon/NavIcon.js +5 -1
  142. package/dist/NavItem/navItemStyles.stylex.d.ts +0 -8
  143. package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
  144. package/dist/NavItem/navItemStyles.stylex.js +0 -2
  145. package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
  146. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  147. package/dist/NavMenu/NavHeadingMenu.js +7 -4
  148. package/dist/NumberInput/NumberInput.d.ts +6 -1
  149. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  150. package/dist/NumberInput/NumberInput.js +95 -126
  151. package/dist/NumberInput/numberInputCommit.d.ts +34 -0
  152. package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
  153. package/dist/NumberInput/numberInputCommit.js +71 -0
  154. package/dist/NumberInput/numberParser.d.ts +64 -0
  155. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  156. package/dist/NumberInput/numberParser.js +350 -0
  157. package/dist/Outline/Outline.d.ts.map +1 -1
  158. package/dist/Outline/Outline.js +2 -3
  159. package/dist/OverflowList/OverflowList.d.ts +41 -1
  160. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  161. package/dist/OverflowList/OverflowList.js +43 -2
  162. package/dist/Popover/Popover.d.ts.map +1 -1
  163. package/dist/Popover/Popover.js +8 -14
  164. package/dist/Popover/usePopover.d.ts +15 -41
  165. package/dist/Popover/usePopover.d.ts.map +1 -1
  166. package/dist/Popover/usePopover.js +26 -7
  167. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchValueEditor.js +91 -18
  169. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  170. package/dist/PowerSearch/formatFilterValue.js +4 -2
  171. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  172. package/dist/ProgressBar/ProgressBar.js +18 -5
  173. package/dist/Resizable/useResizable.d.ts +19 -1
  174. package/dist/Resizable/useResizable.d.ts.map +1 -1
  175. package/dist/Resizable/useResizable.js +104 -38
  176. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  177. package/dist/SelectableCard/SelectableCard.js +9 -0
  178. package/dist/Selector/Selector.d.ts +18 -1
  179. package/dist/Selector/Selector.d.ts.map +1 -1
  180. package/dist/Selector/Selector.js +92 -21
  181. package/dist/Selector/hooks.d.ts +7 -1
  182. package/dist/Selector/hooks.d.ts.map +1 -1
  183. package/dist/Selector/hooks.js +3 -2
  184. package/dist/SideNav/SideNav.d.ts +6 -1
  185. package/dist/SideNav/SideNav.d.ts.map +1 -1
  186. package/dist/SideNav/SideNav.js +57 -27
  187. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  188. package/dist/SideNav/SideNavHeading.js +5 -4
  189. package/dist/SideNav/SideNavItem.d.ts +29 -4
  190. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  191. package/dist/SideNav/SideNavItem.js +75 -20
  192. package/dist/Slider/Slider.d.ts.map +1 -1
  193. package/dist/Slider/Slider.js +34 -2
  194. package/dist/Spinner/Spinner.d.ts +3 -1
  195. package/dist/Spinner/Spinner.d.ts.map +1 -1
  196. package/dist/Spinner/Spinner.js +199 -20
  197. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  198. package/dist/StatusDot/StatusDot.js +6 -1
  199. package/dist/Stepper/Step.d.ts.map +1 -1
  200. package/dist/Stepper/Step.js +7 -6
  201. package/dist/Switch/Switch.d.ts.map +1 -1
  202. package/dist/Switch/Switch.js +5 -1
  203. package/dist/Table/BaseTable.d.ts.map +1 -1
  204. package/dist/Table/BaseTable.js +6 -1
  205. package/dist/Table/Table.d.ts.map +1 -1
  206. package/dist/Table/Table.js +3 -6
  207. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  208. package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
  209. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
  210. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  211. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +34 -3
  212. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  213. package/dist/Table/plugins/selection/useTableSelection.js +25 -1
  214. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  215. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  216. package/dist/Text/Text.d.ts.map +1 -1
  217. package/dist/Text/Text.js +0 -1
  218. package/dist/TextArea/TextArea.d.ts.map +1 -1
  219. package/dist/TextArea/TextArea.js +13 -8
  220. package/dist/Timestamp/Timestamp.d.ts +1 -1
  221. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  222. package/dist/Timestamp/Timestamp.js +10 -18
  223. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  224. package/dist/Timestamp/formatInstant.js +10 -5
  225. package/dist/Toast/Toast.d.ts +17 -2
  226. package/dist/Toast/Toast.d.ts.map +1 -1
  227. package/dist/Toast/Toast.js +77 -11
  228. package/dist/Toast/ToastViewport.d.ts +1 -0
  229. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  230. package/dist/Toast/ToastViewport.js +76 -21
  231. package/dist/Toast/index.d.ts +1 -1
  232. package/dist/Toast/index.d.ts.map +1 -1
  233. package/dist/Toast/types.d.ts +38 -0
  234. package/dist/Toast/types.d.ts.map +1 -1
  235. package/dist/Toast/useToastGesture.d.ts +26 -0
  236. package/dist/Toast/useToastGesture.d.ts.map +1 -0
  237. package/dist/Toast/useToastGesture.js +223 -0
  238. package/dist/Token/Token.d.ts +1 -1
  239. package/dist/Token/Token.d.ts.map +1 -1
  240. package/dist/Token/Token.js +23 -12
  241. package/dist/Token/TokenLink.d.ts +1 -1
  242. package/dist/Token/TokenLink.d.ts.map +1 -1
  243. package/dist/Token/TokenLink.js +5 -2
  244. package/dist/Tokenizer/Tokenizer.d.ts +12 -1
  245. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  246. package/dist/Tokenizer/Tokenizer.js +31 -21
  247. package/dist/TopNav/TopNavHeading.js +2 -2
  248. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  249. package/dist/TopNav/TopNavItem.js +3 -3
  250. package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
  251. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  252. package/dist/TopNav/TopNavMegaMenu.js +30 -9
  253. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  254. package/dist/TopNav/TopNavMegaMenuItem.js +3 -3
  255. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  256. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  257. package/dist/TopNav/TopNavMenu.js +21 -6
  258. package/dist/TreeList/TreeList.d.ts +1 -1
  259. package/dist/TreeList/TreeList.d.ts.map +1 -1
  260. package/dist/TreeList/TreeList.js +7 -2
  261. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  262. package/dist/TreeList/TreeListItem.js +2 -2
  263. package/dist/Typeahead/BaseTypeahead.d.ts +33 -0
  264. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  265. package/dist/Typeahead/BaseTypeahead.js +51 -8
  266. package/dist/Typeahead/Typeahead.d.ts +8 -1
  267. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  268. package/dist/Typeahead/Typeahead.js +2 -0
  269. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  270. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  271. package/dist/Typeahead/TypeaheadItem.js +7 -2
  272. package/dist/astryx.css +87 -22
  273. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  274. package/dist/hooks/useHotkeys.js +3 -25
  275. package/dist/hooks/useOverflow.d.ts.map +1 -1
  276. package/dist/hooks/useOverflow.js +14 -4
  277. package/dist/i18n/InternationalizationContext.d.ts +2 -0
  278. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  279. package/dist/i18n/InternationalizationContext.js +3 -1
  280. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  281. package/dist/i18n/InternationalizationProvider.js +3 -1
  282. package/dist/i18n/resolve.d.ts +1 -1
  283. package/dist/i18n/resolve.d.ts.map +1 -1
  284. package/dist/i18n/resolve.js +37 -38
  285. package/dist/i18n/useTranslator.d.ts.map +1 -1
  286. package/dist/i18n/useTranslator.js +2 -3
  287. package/dist/index.d.ts +1 -1
  288. package/dist/index.d.ts.map +1 -1
  289. package/dist/theme/Theme.d.ts.map +1 -1
  290. package/dist/theme/Theme.js +46 -10
  291. package/dist/theme/defineTheme.d.ts +9 -3
  292. package/dist/theme/defineTheme.d.ts.map +1 -1
  293. package/dist/theme/defineTheme.js +5 -0
  294. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  295. package/dist/theme/derivedVarRegistry.js +24 -4
  296. package/dist/theme/generateThemeRules.d.ts +21 -0
  297. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  298. package/dist/theme/generateThemeRules.js +26 -0
  299. package/dist/theme/syntax/tokens.d.ts +1 -1
  300. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  301. package/dist/theme/syntax/tokens.js +5 -2
  302. package/dist/theme/useTheme.d.ts.map +1 -1
  303. package/dist/theme/useTheme.js +6 -7
  304. package/dist/utils/dateParser.d.ts +5 -8
  305. package/dist/utils/dateParser.d.ts.map +1 -1
  306. package/dist/utils/dateParser.js +10 -11
  307. package/dist/utils/focusOutline.stylex.d.ts +25 -0
  308. package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
  309. package/dist/utils/focusOutline.stylex.js +15 -0
  310. package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
  311. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
  312. package/dist/utils/interactionOverlay.stylex.js +42 -0
  313. package/dist/utils/isApplePlatform.d.ts +18 -0
  314. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  315. package/dist/utils/isApplePlatform.js +37 -0
  316. package/dist/utils/plainDate.d.ts +11 -0
  317. package/dist/utils/plainDate.d.ts.map +1 -1
  318. package/dist/utils/plainDate.js +20 -4
  319. package/locales/af-ZA.json +7 -7
  320. package/locales/ar-SA.json +7 -7
  321. package/locales/ca-ES.json +6 -6
  322. package/locales/cs-CZ.json +7 -7
  323. package/locales/da-DK.json +7 -7
  324. package/locales/de-DE.json +7 -7
  325. package/locales/el-GR.json +7 -7
  326. package/locales/en.json +178 -6
  327. package/locales/es-ES.json +6 -6
  328. package/locales/fi-FI.json +7 -7
  329. package/locales/fr-FR.json +7 -7
  330. package/locales/he-IL.json +7 -7
  331. package/locales/hu-HU.json +7 -7
  332. package/locales/it-IT.json +7 -7
  333. package/locales/ja-JP.json +7 -7
  334. package/locales/ko-KR.json +7 -7
  335. package/locales/nl-NL.json +7 -7
  336. package/locales/no-NO.json +7 -7
  337. package/locales/pl-PL.json +7 -7
  338. package/locales/pseudo.json +130 -1
  339. package/locales/pt-BR.json +7 -7
  340. package/locales/pt-PT.json +7 -7
  341. package/locales/ro-RO.json +7 -7
  342. package/locales/ru-RU.json +7 -7
  343. package/locales/sr-SP.json +7 -7
  344. package/locales/sv-SE.json +7 -7
  345. package/locales/tr-TR.json +7 -7
  346. package/locales/uk-UA.json +7 -7
  347. package/locales/vi-VN.json +7 -7
  348. package/locales/zh-CN.json +7 -7
  349. package/locales/zh-TW.json +7 -7
  350. package/package.json +4 -5
  351. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  352. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  353. package/src/AlertDialog/AlertDialog.tsx +62 -20
  354. package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
  355. package/src/AspectRatio/AspectRatio.tsx +6 -6
  356. package/src/Avatar/Avatar.doc.mjs +12 -2
  357. package/src/Avatar/Avatar.test.tsx +80 -0
  358. package/src/Avatar/Avatar.tsx +64 -14
  359. package/src/Avatar/index.ts +2 -2
  360. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  361. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  362. package/src/AvatarGroup/AvatarGroup.tsx +12 -4
  363. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  364. package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
  365. package/src/Badge/Badge.doc.mjs +3 -2
  366. package/src/Badge/Badge.test.tsx +32 -3
  367. package/src/Badge/Badge.tsx +42 -1
  368. package/src/Banner/Banner.doc.mjs +9 -0
  369. package/src/Banner/Banner.test.tsx +76 -11
  370. package/src/Banner/Banner.tsx +21 -2
  371. package/src/Button/Button.doc.mjs +2 -1
  372. package/src/Button/Button.test.tsx +19 -4
  373. package/src/Button/Button.tsx +9 -29
  374. package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
  375. package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
  376. package/src/Calendar/Calendar.doc.mjs +4 -4
  377. package/src/Calendar/Calendar.test.tsx +112 -0
  378. package/src/Calendar/Calendar.tsx +18 -16
  379. package/src/Calendar/hooks/useCalendarDays.ts +4 -4
  380. package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
  381. package/src/Calendar/styles.ts +48 -42
  382. package/src/Card/Card.doc.mjs +10 -7
  383. package/src/Card/Card.test.tsx +113 -19
  384. package/src/Card/Card.tsx +67 -89
  385. package/src/Card/index.ts +36 -1
  386. package/src/Carousel/Carousel.doc.mjs +3 -0
  387. package/src/Carousel/Carousel.test.tsx +360 -0
  388. package/src/Carousel/Carousel.tsx +116 -15
  389. package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -1
  390. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  391. package/src/CheckboxInput/CheckboxInput.tsx +5 -0
  392. package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
  393. package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
  394. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  395. package/src/CodeBlock/CodeBlock.tsx +20 -4
  396. package/src/CodeBlock/highlightRanges.ts +1 -1
  397. package/src/CodeBlock/highlightStyles.ts +13 -13
  398. package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
  399. package/src/ComplexSelector/ComplexSelector.doc.mjs +9 -2
  400. package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
  401. package/src/ComplexSelector/ComplexSelector.tsx +22 -12
  402. package/src/DateInput/DateInput.doc.mjs +17 -1
  403. package/src/DateInput/DateInput.test.tsx +9 -4
  404. package/src/DateInput/DateInput.tsx +54 -3
  405. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  406. package/src/DateInput/MonthScroller.tsx +5 -1
  407. package/src/DateInput/MonthYearWheels.tsx +7 -4
  408. package/src/DateInput/NativeDateField.test.tsx +635 -0
  409. package/src/DateInput/NativeDateField.tsx +641 -0
  410. package/src/DateInput/TouchDateField.tsx +83 -33
  411. package/src/DateInput/Wheel.tsx +1 -0
  412. package/src/DateInput/index.ts +1 -0
  413. package/src/DateInput/nativeDateSegments.ts +127 -0
  414. package/src/DateRangeInput/DateRangeInput.doc.mjs +3 -3
  415. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
  416. package/src/DateRangeInput/DateRangeInput.tsx +8 -13
  417. package/src/DateTimeInput/DateTimeInput.doc.mjs +39 -22
  418. package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
  419. package/src/DateTimeInput/DateTimeInput.tsx +54 -20
  420. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
  421. package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
  422. package/src/Dialog/Dialog.test.tsx +185 -18
  423. package/src/Dialog/Dialog.tsx +35 -11
  424. package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
  425. package/src/DropdownMenu/DropdownMenu.tsx +4 -13
  426. package/src/Field/Field.doc.mjs +1 -1
  427. package/src/Field/FieldLabel.test.tsx +29 -0
  428. package/src/Field/FieldLabel.tsx +7 -0
  429. package/src/Field/InputClearButton.test.tsx +15 -1
  430. package/src/Field/InputClearButton.tsx +28 -4
  431. package/src/FieldStatus/FieldStatus.doc.mjs +1 -1
  432. package/src/FileInput/FileInput.doc.mjs +1 -1
  433. package/src/Heading/Heading.tsx +0 -1
  434. package/src/HoverCard/HoverCard.doc.mjs +8 -2
  435. package/src/HoverCard/HoverCard.test.tsx +154 -4
  436. package/src/HoverCard/HoverCard.tsx +137 -3
  437. package/src/HoverCard/useHoverCard.tsx +23 -3
  438. package/src/Icon/Icon.test.tsx +55 -1
  439. package/src/Icon/Icon.tsx +5 -3
  440. package/src/Icon/defaultIcons.tsx +11 -2
  441. package/src/Icon/globalIconRegistry.test.tsx +16 -3
  442. package/src/Icon/globalIconRegistry.tsx +37 -6
  443. package/src/Icon/index.ts +1 -0
  444. package/src/Icon/useIcon.ts +9 -2
  445. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  446. package/src/Indicator/Indicator.doc.mjs +3 -1
  447. package/src/InputGroup/InputGroup.doc.mjs +1 -1
  448. package/src/Item/Item.tsx +2 -7
  449. package/src/Kbd/Kbd.test.tsx +0 -17
  450. package/src/Kbd/Kbd.tsx +2 -26
  451. package/src/Layer/gestureCounter.ts +57 -0
  452. package/src/Layer/useLayer.test.tsx +368 -16
  453. package/src/Layer/useLayer.tsx +208 -35
  454. package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
  455. package/src/List/List.test.tsx +38 -0
  456. package/src/List/List.tsx +8 -1
  457. package/src/Markdown/Markdown.test.tsx +37 -0
  458. package/src/Markdown/Markdown.tsx +16 -5
  459. package/src/Markdown/parser.test.ts +33 -0
  460. package/src/Markdown/parser.ts +9 -3
  461. package/src/MetadataList/MetadataList.test.tsx +75 -2
  462. package/src/MetadataList/MetadataListItem.tsx +5 -2
  463. package/src/MultiSelector/MultiSelector.doc.mjs +23 -2
  464. package/src/MultiSelector/MultiSelector.test.tsx +205 -0
  465. package/src/MultiSelector/MultiSelector.tsx +103 -16
  466. package/src/MultiSelector/hooks.ts +9 -2
  467. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  468. package/src/NavIcon/NavIcon.test.tsx +9 -0
  469. package/src/NavIcon/NavIcon.tsx +5 -1
  470. package/src/NavItem/navItemStyles.stylex.ts +0 -8
  471. package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
  472. package/src/NavMenu/NavHeadingMenu.tsx +7 -4
  473. package/src/NumberInput/NumberInput.doc.mjs +27 -8
  474. package/src/NumberInput/NumberInput.test.tsx +563 -8
  475. package/src/NumberInput/NumberInput.tsx +77 -131
  476. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  477. package/src/NumberInput/numberInputCommit.ts +103 -0
  478. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  479. package/src/NumberInput/numberParser.test.ts +222 -0
  480. package/src/NumberInput/numberParser.ts +403 -0
  481. package/src/Outline/Outline.tsx +2 -4
  482. package/src/OverflowList/OverflowList.doc.mjs +102 -21
  483. package/src/OverflowList/OverflowList.test.tsx +550 -4
  484. package/src/OverflowList/OverflowList.tsx +100 -2
  485. package/src/Pagination/Pagination.test.tsx +3 -2
  486. package/src/Popover/Popover.doc.mjs +2 -2
  487. package/src/Popover/Popover.test.tsx +38 -0
  488. package/src/Popover/Popover.tsx +28 -66
  489. package/src/Popover/usePopover.tsx +44 -5
  490. package/src/PowerSearch/PowerSearch.doc.mjs +1 -1
  491. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
  492. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
  493. package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
  494. package/src/PowerSearch/formatFilterValue.test.ts +16 -1
  495. package/src/PowerSearch/formatFilterValue.ts +2 -0
  496. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  497. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  498. package/src/ProgressBar/ProgressBar.tsx +28 -8
  499. package/src/RadioList/RadioList.doc.mjs +1 -1
  500. package/src/Resizable/Resizable.doc.mjs +2 -2
  501. package/src/Resizable/useResizable.doc.mjs +21 -2
  502. package/src/Resizable/useResizable.test.ts +421 -0
  503. package/src/Resizable/useResizable.ts +133 -48
  504. package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
  505. package/src/SelectableCard/SelectableCard.tsx +16 -0
  506. package/src/Selector/Selector.doc.mjs +15 -1
  507. package/src/Selector/Selector.source-build.test.mjs +65 -0
  508. package/src/Selector/Selector.test.tsx +301 -0
  509. package/src/Selector/Selector.tsx +145 -32
  510. package/src/Selector/hooks.ts +17 -2
  511. package/src/SideNav/SideNav.doc.mjs +2 -2
  512. package/src/SideNav/SideNav.test.tsx +1069 -6
  513. package/src/SideNav/SideNav.tsx +109 -38
  514. package/src/SideNav/SideNavHeading.tsx +5 -2
  515. package/src/SideNav/SideNavItem.doc.mjs +24 -3
  516. package/src/SideNav/SideNavItem.tsx +134 -44
  517. package/src/Slider/Slider.doc.mjs +2 -2
  518. package/src/Slider/Slider.test.tsx +106 -1
  519. package/src/Slider/Slider.tsx +52 -1
  520. package/src/Spinner/Spinner.doc.mjs +17 -5
  521. package/src/Spinner/Spinner.test.tsx +164 -0
  522. package/src/Spinner/Spinner.tsx +252 -22
  523. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  524. package/src/StatusDot/StatusDot.test.tsx +9 -0
  525. package/src/StatusDot/StatusDot.tsx +7 -1
  526. package/src/Stepper/Step.doc.mjs +1 -1
  527. package/src/Stepper/Step.tsx +7 -14
  528. package/src/Switch/Switch.doc.mjs +3 -1
  529. package/src/Switch/Switch.test.tsx +10 -0
  530. package/src/Switch/Switch.tsx +3 -0
  531. package/src/Table/BaseTable.tsx +6 -1
  532. package/src/Table/Table.doc.mjs +5 -3
  533. package/src/Table/Table.tsx +3 -8
  534. package/src/Table/TableBody.doc.mjs +2 -2
  535. package/src/Table/TableFooter.doc.mjs +1 -1
  536. package/src/Table/TableHeader.doc.mjs +1 -1
  537. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  538. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  539. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
  540. package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
  541. package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
  542. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  543. package/src/Table/useTableGroupedRows.doc.mjs +3 -3
  544. package/src/Table/useTablePagination.doc.mjs +1 -1
  545. package/src/Table/useTableSelection.doc.mjs +1 -1
  546. package/src/Text/Text.test.tsx +44 -0
  547. package/src/Text/Text.tsx +0 -1
  548. package/src/TextArea/TextArea.doc.mjs +13 -3
  549. package/src/TextArea/TextArea.test.tsx +11 -0
  550. package/src/TextArea/TextArea.tsx +34 -22
  551. package/src/TextInput/TextInput.doc.mjs +1 -1
  552. package/src/TimeInput/TimeInput.doc.mjs +1 -1
  553. package/src/Timestamp/Timestamp.test.tsx +89 -0
  554. package/src/Timestamp/Timestamp.tsx +8 -8
  555. package/src/Timestamp/formatInstant.ts +5 -0
  556. package/src/Toast/Toast.doc.mjs +213 -44
  557. package/src/Toast/Toast.tsx +118 -23
  558. package/src/Toast/ToastViewport.test.tsx +1434 -8
  559. package/src/Toast/ToastViewport.tsx +85 -14
  560. package/src/Toast/index.ts +2 -0
  561. package/src/Toast/types.ts +43 -5
  562. package/src/Toast/useToastGesture.ts +361 -0
  563. package/src/Token/Token.test.tsx +95 -0
  564. package/src/Token/Token.tsx +19 -17
  565. package/src/Token/TokenLink.tsx +12 -3
  566. package/src/Tokenizer/Tokenizer.doc.mjs +17 -4
  567. package/src/Tokenizer/Tokenizer.test.tsx +161 -0
  568. package/src/Tokenizer/Tokenizer.tsx +49 -24
  569. package/src/TopNav/TopNavHeading.tsx +2 -2
  570. package/src/TopNav/TopNavItem.tsx +3 -7
  571. package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
  572. package/src/TopNav/TopNavMegaMenu.tsx +47 -4
  573. package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
  574. package/src/TopNav/TopNavMenu.test.tsx +133 -1
  575. package/src/TopNav/TopNavMenu.tsx +38 -5
  576. package/src/TreeList/TreeList.test.tsx +49 -0
  577. package/src/TreeList/TreeList.tsx +7 -2
  578. package/src/TreeList/TreeListItem.tsx +2 -7
  579. package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
  580. package/src/Typeahead/BaseTypeahead.tsx +96 -6
  581. package/src/Typeahead/Typeahead.doc.mjs +7 -1
  582. package/src/Typeahead/Typeahead.test.tsx +154 -0
  583. package/src/Typeahead/Typeahead.tsx +9 -0
  584. package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
  585. package/src/Typeahead/TypeaheadItem.tsx +8 -1
  586. package/src/hooks/useAnnounce.doc.mjs +96 -0
  587. package/src/hooks/useDevWarning.doc.mjs +96 -0
  588. package/src/hooks/useHotkeys.test.ts +0 -18
  589. package/src/hooks/useHotkeys.ts +3 -25
  590. package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
  591. package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
  592. package/src/hooks/useInteractiveRole.doc.mjs +119 -0
  593. package/src/hooks/useLongPress.doc.mjs +123 -0
  594. package/src/hooks/useOverflow.doc.mjs +58 -17
  595. package/src/hooks/useOverflow.ts +16 -4
  596. package/src/hooks/useTypeahead.doc.mjs +153 -0
  597. package/src/i18n/InternationalizationContext.ts +3 -0
  598. package/src/i18n/InternationalizationProvider.tsx +8 -1
  599. package/src/i18n/__tests__/resolve.test.ts +23 -1
  600. package/src/i18n/resolve.ts +46 -49
  601. package/src/i18n/useTranslator.ts +2 -7
  602. package/src/index.ts +2 -0
  603. package/src/raw-import.d.ts +14 -0
  604. package/src/theme/Theme.test.tsx +104 -2
  605. package/src/theme/Theme.tsx +49 -14
  606. package/src/theme/defineTheme.test.ts +23 -0
  607. package/src/theme/defineTheme.ts +12 -3
  608. package/src/theme/derivedVarRegistry.test.ts +87 -3
  609. package/src/theme/derivedVarRegistry.ts +23 -4
  610. package/src/theme/generateThemeRules.test.ts +99 -1
  611. package/src/theme/generateThemeRules.ts +28 -0
  612. package/src/theme/syntax/tokens.ts +5 -2
  613. package/src/theme/useTheme.test.tsx +10 -0
  614. package/src/theme/useTheme.ts +16 -10
  615. package/src/utils/dateParser.test.ts +34 -2
  616. package/src/utils/dateParser.ts +11 -14
  617. package/src/utils/focusOutline.stylex.ts +50 -0
  618. package/src/utils/interactionOverlay.stylex.ts +74 -0
  619. package/src/utils/isApplePlatform.test.ts +61 -0
  620. package/src/utils/isApplePlatform.ts +37 -0
  621. package/src/utils/plainDate.test.ts +46 -0
  622. package/src/utils/plainDate.ts +18 -3
@@ -42,6 +42,7 @@ import * as stylex from '@stylexjs/stylex';
42
42
  import type {ThemeMode} from './types';
43
43
  import {colorVars, typographyVars} from './tokens.stylex';
44
44
  import {generateThemeCSS, type DefinedTheme} from './defineTheme';
45
+ import {generateDataTokenDefaultsCSS} from './generateThemeRules';
45
46
  import {registerTheme} from './themeRegistry';
46
47
  import {dataAttr} from '../naming';
47
48
  import {ThemeContext} from './useTheme';
@@ -98,6 +99,16 @@ ThemeNestingContext.displayName = 'ThemeNestingContext';
98
99
  /** Track which themes have already been injected */
99
100
  const injectedThemes = new Set<string>();
100
101
 
102
+ /**
103
+ * How many mounted `Theme`s are relying on the injected data-token defaults.
104
+ *
105
+ * The defaults are one document-wide `:root` block, shared by every theme, so
106
+ * they are injected once and removed only when the last theme that took a
107
+ * reference unmounts — tearing them down with whichever provider happened to
108
+ * inject them would strip the palette from the providers still mounted.
109
+ */
110
+ let dataTokenDefaultsRefCount = 0;
111
+
101
112
  /**
102
113
  * Hook to inject theme CSS into the document.
103
114
  * Built themes (from `astryx theme build`) skip injection — their CSS
@@ -112,6 +123,8 @@ function useThemeStyleInjection(theme: DefinedTheme): void {
112
123
  return;
113
124
  }
114
125
 
126
+ // Second and later `Theme`s using this theme do no work at all —
127
+ // generation included. Its CSS is document-wide and identical for each.
115
128
  const themeKey = `astryx-theme-${theme.name}`;
116
129
  if (injectedThemes.has(themeKey)) {
117
130
  return;
@@ -130,8 +143,26 @@ function useThemeStyleInjection(theme: DefinedTheme): void {
130
143
  );
131
144
 
132
145
  const {prose, component} = generateThemeCSS(theme);
133
- if (!prose && !component) {
134
- return;
146
+ const base = generateDataTokenDefaultsCSS();
147
+ injectedThemes.add(themeKey);
148
+ const cleanups: (() => void)[] = [() => injectedThemes.delete(themeKey)];
149
+
150
+ // Data token defaults go into @layer astryx-base, where StyleX puts the
151
+ // core token defaults, so a theme's own `--color-data-*` outranks them by
152
+ // layer. Appended (never prepended) so it cannot register `astryx-base`
153
+ // ahead of `reset` and invert the layer order.
154
+ if (base) {
155
+ if (dataTokenDefaultsRefCount++ === 0) {
156
+ const baseStyle = document.createElement('style');
157
+ baseStyle.setAttribute(dataAttr('theme-base'), '');
158
+ baseStyle.textContent = `@layer astryx-base {\n${base}\n}`;
159
+ document.head.appendChild(baseStyle);
160
+ }
161
+ cleanups.push(() => {
162
+ if (--dataTokenDefaultsRefCount === 0) {
163
+ document.querySelector(`style[${dataAttr('theme-base')}]`)?.remove();
164
+ }
165
+ });
135
166
  }
136
167
 
137
168
  // Prose defaults go into @layer reset — lowest priority, scoped to
@@ -154,20 +185,24 @@ function useThemeStyleInjection(theme: DefinedTheme): void {
154
185
  document.head.appendChild(compStyle);
155
186
  }
156
187
 
157
- injectedThemes.add(themeKey);
188
+ if (prose || component) {
189
+ cleanups.push(() => {
190
+ // Matched by the astryx id marker, which is always written above.
191
+ const proseEl = document.querySelector(
192
+ `style[${dataAttr('theme-prose')}="${theme.name}"][${dataAttr('id')}="${id}"]`,
193
+ );
194
+ const compEl = document.querySelector(
195
+ `style[${dataAttr('theme')}="${theme.name}"][${dataAttr('id')}="${id}"]`,
196
+ );
197
+ proseEl?.remove();
198
+ compEl?.remove();
199
+ });
200
+ }
158
201
 
159
202
  return () => {
160
- // Remove both prose and component style tags (matched by the new
161
- // astryx id marker, which is always written above).
162
- const proseEl = document.querySelector(
163
- `style[${dataAttr('theme-prose')}="${theme.name}"][${dataAttr('id')}="${id}"]`,
164
- );
165
- const compEl = document.querySelector(
166
- `style[${dataAttr('theme')}="${theme.name}"][${dataAttr('id')}="${id}"]`,
167
- );
168
- proseEl?.remove();
169
- compEl?.remove();
170
- injectedThemes.delete(themeKey);
203
+ for (const cleanup of cleanups) {
204
+ cleanup();
205
+ }
171
206
  };
172
207
  }, [theme, id]);
173
208
  }
@@ -116,6 +116,29 @@ describe('generateThemeCSS', () => {
116
116
  expect(css).toContain('font-family: var(--font-family-heading)');
117
117
  });
118
118
 
119
+ it('keeps the data palette out of a theme that never mentions it', () => {
120
+ // That the palette IS declared is covered by `seeds the whole palette
121
+ // once, at :root` in generateThemeRules.test.ts. It is theme-independent,
122
+ // so there is nothing about it a theme can be used to assert.
123
+ const {component} = generateThemeCSS(defineTheme({name: 'chartless'}));
124
+ expect(component).not.toContain('--color-data-');
125
+ });
126
+
127
+ it('puts only the named data token in the theme block, not its siblings', () => {
128
+ const theme = defineTheme({
129
+ name: 'brand-charts',
130
+ tokens: {'--color-data-categorical-blue': '#00A3FF'},
131
+ });
132
+ const {component} = generateThemeCSS(theme);
133
+ expect(component).toContain('--color-data-categorical-blue: #00A3FF;');
134
+ // Leaving the siblings out of the theme's own block is what lets a nested
135
+ // theme inherit a parent's override instead of shadowing it.
136
+ expect(component).not.toContain('--color-data-categorical-orange');
137
+ // Defaults reach the stylesheet without entering the theme's own tokens,
138
+ // which are what `astryx theme build` reports as overrides.
139
+ expect(theme.tokens['--color-data-categorical-orange']).toBeUndefined();
140
+ });
141
+
119
142
  it('splits prose into reset layer and components into astryx-theme', () => {
120
143
  const theme = defineTheme({
121
144
  name: 'split-test',
@@ -36,7 +36,16 @@
36
36
  * - /packages/cli/assets/docs/theme.doc.mjs (`astryx docs theme`)
37
37
  */
38
38
 
39
- import type {IconRegistry} from '../Icon/globalIconRegistry';
39
+ import type {ReactNode} from 'react';
40
+ import type {IconName, NamespacedIconName} from '../Icon/globalIconRegistry';
41
+
42
+ /**
43
+ * Icon overrides a theme may declare: any built-in semantic name, plus the
44
+ * namespaced keys components and libraries own (`'richtext:bold'`).
45
+ */
46
+ type ThemeIconOverrides = Partial<
47
+ Record<IconName | NamespacedIconName, ReactNode>
48
+ >;
40
49
  import type {IndicatorRegistry} from '../Indicator/types';
41
50
  import type {TypographyConfig, FontWeight} from './types';
42
51
  import {
@@ -319,7 +328,7 @@ export interface DefineThemeInput {
319
328
  */
320
329
  components?: ComponentStyleMap;
321
330
  /** Icon registry — maps semantic icon names to React nodes */
322
- icons?: Partial<IconRegistry>;
331
+ icons?: ThemeIconOverrides;
323
332
  /**
324
333
  * Indicator overrides — replaces the components that draw stateful control
325
334
  * visuals with the theme's own, by name.
@@ -381,7 +390,7 @@ export interface DefinedTheme {
381
390
  /** Component style overrides */
382
391
  components?: ComponentStyleMap;
383
392
  /** Icon registry */
384
- icons?: Partial<IconRegistry>;
393
+ icons?: ThemeIconOverrides;
385
394
  /** Indicator overrides for stateful control visuals, keyed by name */
386
395
  indicators?: IndicatorRegistry;
387
396
  /** Whether this theme has been pre-compiled by theme build CLI */
@@ -213,6 +213,7 @@ function discoverComponents(): ComponentInfo[] {
213
213
  // ---------------------------------------------------------------------------
214
214
 
215
215
  const DIR_TO_REGISTRY_KEY: Record<string, string> = {
216
+ Avatar: 'avatar',
216
217
  Banner: 'banner',
217
218
  Button: 'button',
218
219
  Card: 'card',
@@ -221,13 +222,13 @@ const DIR_TO_REGISTRY_KEY: Record<string, string> = {
221
222
  Dialog: 'dialog',
222
223
  DropdownMenu: 'dropdown-menu',
223
224
  Field: 'field',
224
- HoverCard: 'hovercard',
225
+ HoverCard: 'hover-card',
225
226
  NumberInput: 'number-input',
226
227
  Popover: 'popover',
227
- ProgressBar: 'progressbar-mark',
228
+ ProgressBar: 'progress-bar-mark',
228
229
  Section: 'section',
229
230
  SegmentedControl: 'segmented-control',
230
- TextArea: 'textarea',
231
+ TextArea: 'text-area',
231
232
  };
232
233
 
233
234
  /**
@@ -279,6 +280,13 @@ const VARS_WITHOUT_DERIVED_MAPPING = new Set([
279
280
  '--_thumbnail-hit-inset',
280
281
  '--_input-clear-hit-inset',
281
282
  '--_input-clear-hit-content',
283
+ // Placement and swipe lifecycle values are private Toast behavior. A theme
284
+ // author controls the surface transform/opacity as a whole, not these values.
285
+ '--_toast-slide-y',
286
+ '--_toast-swipe-y',
287
+ '--_toast-swipe-exit-y',
288
+ '--_toast-swipe-opacity',
289
+ '--_toast-swipe-scale',
282
290
  // Indentation and row-spacing metrics: --tree-list-indent is the authorable
283
291
  // step, --_tree-indent the per-row distance TreeListItem computes from it.
284
292
  // --tree-list-row-gap is applied as half a padding-block on each row wrapper,
@@ -292,6 +300,19 @@ const VARS_WITHOUT_DERIVED_MAPPING = new Set([
292
300
  // other.
293
301
  '--_card-elevation',
294
302
  '--_card-ring',
303
+ // The colour inside that composed ring, for a variant only a theme knows.
304
+ // It is one component of one shadow in the list, so no standard property
305
+ // maps onto it either — a theme sets it beside the fill it has to contrast.
306
+ '--selectable-card-ring-color',
307
+ // The spinner's ring is drawn as an SVG circle, so none of its four vars is
308
+ // a CSS property of the element carrying the theme target: `width` and
309
+ // `borderWidth` would name a box the ring is not, and a `color` mapping
310
+ // would take the label's text color with it. They are public vars a theme
311
+ // sets directly under a size- or shade-variant key.
312
+ '--spinner-diameter',
313
+ '--spinner-stroke-width',
314
+ '--spinner-color',
315
+ '--spinner-track-color',
295
316
  ]);
296
317
 
297
318
  // ---------------------------------------------------------------------------
@@ -418,6 +439,21 @@ describe('getDerivedVars', () => {
418
439
  expect(getDerivedVars('unknown', 'borderRadius')).toEqual([]);
419
440
  });
420
441
 
442
+ it('resolves a deprecated key to the entries of the key that replaced it', () => {
443
+ // A theme written against the old spelling still selects the element (the
444
+ // component emits both classes), so its derived vars must still expand —
445
+ // otherwise the rule lands and the var half of it silently does nothing.
446
+ expect(getDerivedVars('hovercard', 'borderRadius')).toEqual(
447
+ getDerivedVars('hover-card', 'borderRadius'),
448
+ );
449
+ expect(getDerivedVars('textarea', 'paddingInline')).toEqual(
450
+ getDerivedVars('text-area', 'paddingInline'),
451
+ );
452
+ expect(getDerivedVars('progressbar-mark', 'width')).toEqual(
453
+ getDerivedVars('progress-bar-mark', 'width'),
454
+ );
455
+ });
456
+
421
457
  it('returns empty for unregistered property', () => {
422
458
  expect(getDerivedVars('card', 'color')).toEqual([]);
423
459
  });
@@ -441,3 +477,51 @@ describe('getDerivedVars', () => {
441
477
  }
442
478
  });
443
479
  });
480
+
481
+ // ---------------------------------------------------------------------------
482
+ // Read check: a registered var nothing reads is a dead theming knob
483
+ // ---------------------------------------------------------------------------
484
+
485
+ /**
486
+ * Every source file under packages/core/src, concatenated once.
487
+ *
488
+ * `--_popover-radius` shipped documented and registered while `usePopover`
489
+ * hardcoded its radius, so `popover: {borderRadius}` set a var no element ever
490
+ * read. Sync between source, docs and registry cannot catch that: the three
491
+ * agreed with each other, and none of them required a reader.
492
+ */
493
+ function readAllSource(dir: string): string {
494
+ let out = '';
495
+ for (const entry of readdirSync(dir, {withFileTypes: true})) {
496
+ const path = join(dir, entry.name);
497
+ if (entry.isDirectory()) {
498
+ out += readAllSource(path);
499
+ } else if (
500
+ (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) &&
501
+ !entry.name.includes('.test.') &&
502
+ !entry.name.endsWith('.d.ts')
503
+ ) {
504
+ out += readFileSync(path, 'utf-8');
505
+ }
506
+ }
507
+ return out;
508
+ }
509
+
510
+ describe('registered derived vars are read by component styles', () => {
511
+ const source = readAllSource(SRC_DIR);
512
+
513
+ for (const [component, entries] of Object.entries(derivedVarRegistry)) {
514
+ for (const varName of entries.flatMap(e => e.vars ?? [])) {
515
+ it(`${component}: ${varName} is read via var()`, () => {
516
+ expect(
517
+ source.includes(`var(${varName})`) ||
518
+ source.includes(`var(${varName},`),
519
+ `${varName} is registered as the derived var for a CSS property on ` +
520
+ `\`${component}\`, but no component reads it. A theme setting that ` +
521
+ `property would write a var nothing consumes. Read it in the ` +
522
+ `element's StyleX styles, or drop the derived entry.`,
523
+ ).toBe(true);
524
+ });
525
+ }
526
+ }
527
+ });
@@ -43,6 +43,7 @@ export interface DerivedVarEntry {
43
43
  * entries share the same property.
44
44
  */
45
45
  export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
46
+ avatar: [{property: 'borderRadius', vars: ['--_avatar-radius']}],
46
47
  banner: [{property: 'borderRadius', vars: ['--_banner-radius']}],
47
48
  button: [{property: 'borderRadius', vars: ['--_button-radius']}],
48
49
  card: [
@@ -66,13 +67,13 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
66
67
  {property: 'padding', vars: ['--_dropdown-menu-padding']},
67
68
  ],
68
69
  field: [{property: 'borderRadius', vars: ['--_field-radius']}],
69
- hovercard: [{property: 'borderRadius', vars: ['--_hovercard-radius']}],
70
+ 'hover-card': [{property: 'borderRadius', vars: ['--_hovercard-radius']}],
70
71
  'number-input': [
71
72
  {property: 'padding', expand: 'container'},
72
73
  {property: 'borderRadius', vars: ['--_field-radius']},
73
74
  ],
74
75
  popover: [{property: 'borderRadius', vars: ['--_popover-radius']}],
75
- 'progressbar-mark': [
76
+ 'progress-bar-mark': [
76
77
  {property: 'width', vars: ['--_progressbar-mark-width'], replaces: true},
77
78
  {property: 'height', vars: ['--_progressbar-mark-height'], replaces: true},
78
79
  ],
@@ -81,7 +82,7 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
81
82
  {property: 'borderRadius', vars: ['--_segmented-control-radius']},
82
83
  {property: 'padding', vars: ['--_segmented-control-padding']},
83
84
  ],
84
- textarea: [
85
+ 'text-area': [
85
86
  {
86
87
  property: 'paddingInline',
87
88
  vars: ['--_textarea-inline-padding'],
@@ -90,6 +91,21 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
90
91
  ],
91
92
  };
92
93
 
94
+ /**
95
+ * Deprecated component keys → the key that superseded them.
96
+ *
97
+ * A renamed target keeps emitting its old class, so a theme written against
98
+ * the old key still selects the element. Without this the rule would land but
99
+ * its derived vars would not expand, and the half that travels through a var
100
+ * (a hover card's radius, a text area's inline padding) would silently do
101
+ * nothing. Drop these with the classes, in the next major.
102
+ */
103
+ const DEPRECATED_REGISTRY_KEYS: Record<string, string> = {
104
+ hovercard: 'hover-card',
105
+ 'progressbar-mark': 'progress-bar-mark',
106
+ textarea: 'text-area',
107
+ };
108
+
93
109
  /**
94
110
  * Look up derived var entries for a component + CSS property.
95
111
  * Returns matching entries in priority order, or empty array if none.
@@ -98,7 +114,10 @@ export function getDerivedVars(
98
114
  component: string,
99
115
  property: string,
100
116
  ): DerivedVarEntry[] {
101
- const entries = derivedVarRegistry[component];
117
+ const renamedTo = DEPRECATED_REGISTRY_KEYS[component];
118
+ const entries =
119
+ derivedVarRegistry[component] ??
120
+ (renamedTo ? derivedVarRegistry[renamedTo] : undefined);
102
121
  if (!entries) {
103
122
  return [];
104
123
  }
@@ -7,7 +7,13 @@
7
7
  */
8
8
 
9
9
  import {describe, it, expect} from 'vitest';
10
- import {defineTheme, generateThemeCSS, generateThemeRules} from './index';
10
+ import {
11
+ dataTokenDefaults,
12
+ defineTheme,
13
+ generateThemeCSS,
14
+ generateThemeRules,
15
+ } from './index';
16
+ import {generateDataTokenDefaultsCSS} from './generateThemeRules';
11
17
 
12
18
  const defaultInput = {
13
19
  name: 'default',
@@ -702,3 +708,95 @@ describe('physical padding longhands', () => {
702
708
  expect(rule).not.toContain('--_dropdown-menu-padding');
703
709
  });
704
710
  });
711
+
712
+ describe('renamed theme targets', () => {
713
+ // The renamed targets emit both classes, so a rule written against either
714
+ // key selects the element. What is easy to miss is the derived-var half: a
715
+ // key the registry does not know still emits a rule, minus every var the
716
+ // component actually reads — the same silent nothing a misspelled key gives.
717
+ it('expands derived vars for a renamed key and its deprecated spelling', () => {
718
+ const rules = (component: string, styles: Record<string, string>) =>
719
+ generateThemeRules(
720
+ defineTheme({
721
+ name: `test-renamed-${component}`,
722
+ components: {[component]: {base: styles}},
723
+ }),
724
+ ).join('\n');
725
+
726
+ const hoverCard = rules('hover-card', {borderRadius: '9px'});
727
+ expect(hoverCard).toContain('.astryx-hover-card');
728
+ expect(hoverCard).toContain('--_hovercard-radius: 9px');
729
+ expect(rules('hovercard', {borderRadius: '9px'})).toContain(
730
+ '--_hovercard-radius: 9px',
731
+ );
732
+
733
+ const textArea = rules('text-area', {paddingInline: '11px'});
734
+ expect(textArea).toContain('.astryx-text-area');
735
+ expect(textArea).toContain('--_textarea-inline-padding: 11px');
736
+ expect(rules('textarea', {paddingInline: '11px'})).toContain(
737
+ '--_textarea-inline-padding: 11px',
738
+ );
739
+
740
+ const mark = rules('progress-bar-mark', {width: '3px'});
741
+ expect(mark).toContain('.astryx-progress-bar-mark');
742
+ expect(mark).toContain('--_progressbar-mark-width: 3px');
743
+ expect(rules('progressbar-mark', {width: '3px'})).toContain(
744
+ '--_progressbar-mark-width: 3px',
745
+ );
746
+ });
747
+ });
748
+
749
+ describe('data visualization tokens', () => {
750
+ const scopeBlock = (theme: Parameters<typeof generateThemeRules>[0]) =>
751
+ generateThemeRules(theme).find(r => r.includes(':scope'));
752
+
753
+ it('seeds the whole palette once, at :root', () => {
754
+ const css = generateDataTokenDefaultsCSS();
755
+
756
+ expect(css.startsWith(':root {')).toBe(true);
757
+ for (const [name, value] of Object.entries(dataTokenDefaults)) {
758
+ expect(css).toContain(`${name}: ${value};`);
759
+ }
760
+ });
761
+
762
+ it('leaves the defaults out of a theme scope block', () => {
763
+ // A scope block that re-declared them would shadow a parent theme's
764
+ // override in every nested <Theme>, which no other token family does.
765
+ expect(scopeBlock(defineTheme({name: 'data-bare'}))).toBeUndefined();
766
+ });
767
+
768
+ it("puts only the theme's own data token in its scope block", () => {
769
+ const block = scopeBlock(
770
+ defineTheme({
771
+ name: 'data-override',
772
+ tokens: {'--color-data-categorical-blue': ['#123456', '#654321']},
773
+ }),
774
+ )!;
775
+
776
+ expect(block).toContain(
777
+ '--color-data-categorical-blue: light-dark(#123456, #654321);',
778
+ );
779
+ expect(block.match(/--color-data-/g)).toHaveLength(1);
780
+ expect(block).not.toContain('--color-data-categorical-orange');
781
+ });
782
+
783
+ it('keeps the palette out of the scoped stylesheet', () => {
784
+ // The palette's own contents are asserted once, against
785
+ // `dataTokenDefaults`, in `seeds the whole palette once, at :root` above.
786
+ const {component, prose} = generateThemeCSS(
787
+ defineTheme({name: 'data-css'}),
788
+ );
789
+
790
+ expect(component).not.toContain('--color-data-');
791
+ expect(prose).not.toContain('--color-data-');
792
+ });
793
+
794
+ it('keeps generateThemeCSS to its two scoped blocks', () => {
795
+ // The defaults are theme-independent, so they are not part of the theme
796
+ // CSS contract: `astryx theme build` formats them from the public
797
+ // `dataTokenDefaults` export instead.
798
+ expect(
799
+ Object.keys(generateThemeCSS(defineTheme({name: 'data-shape'}))).sort(),
800
+ ).toEqual(['component', 'prose']);
801
+ });
802
+ });
@@ -18,6 +18,7 @@
18
18
  import type {DefinedTheme} from './defineTheme';
19
19
  import {parseStyleKey} from '../utils/parseStyleKey';
20
20
  import {getDerivedVars} from './derivedVarRegistry';
21
+ import {dataTokenDefaults} from './domainTokens/dataTokens';
21
22
  import {cssVar, classPrefix, dataAttrNamespace} from '../naming';
22
23
 
23
24
  /**
@@ -758,6 +759,30 @@ export function generateOnMediaCSS(theme: DefinedTheme): string {
758
759
  return `@scope (${scopeSelector}) to (${THEME_SCOPE_TO}) {\n${inner}\n}`;
759
760
  }
760
761
 
762
+ /**
763
+ * The `--color-data-*` defaults as one unscoped `:root` block.
764
+ *
765
+ * Core tokens reach CSS once, at `:root`, from StyleX's `defineVars` output in
766
+ * `@layer astryx-base`; a theme's own scope block then carries only the tokens
767
+ * that theme overrides, which is why a nested theme inherits its parent's
768
+ * override instead of shadowing it. Data tokens are not StyleX vars, so nothing
769
+ * declares them — this is their equivalent, and callers put it in
770
+ * `@layer astryx-base` so a theme's override wins by layer rather than by
771
+ * specificity. Seeding it per theme scope instead re-declares the default
772
+ * inside every nested theme, which is the shadowing this shape avoids.
773
+ *
774
+ * @internal Not exported from `@astryxdesign/core/theme`: the `<Theme>`
775
+ * runtime is the only caller. `astryx theme build` formats the same block from
776
+ * the public `dataTokenDefaults` export, and a CLI test asserts the two are
777
+ * byte-identical.
778
+ */
779
+ export function generateDataTokenDefaultsCSS(): string {
780
+ const declarations = Object.entries(dataTokenDefaults)
781
+ .map(([prop, value]) => ` ${prop}: ${value};`)
782
+ .join('\n');
783
+ return `:root {\n${declarations}\n}`;
784
+ }
785
+
761
786
  /**
762
787
  * Generate layered CSS for a theme — runtime path.
763
788
  *
@@ -768,6 +793,9 @@ export function generateOnMediaCSS(theme: DefinedTheme): string {
768
793
  * This separation ensures prose defaults (what bare HTML looks like in a theme)
769
794
  * sit at reset-layer priority where any class-based style wins, while component
770
795
  * overrides sit above StyleX so themes can restyle components intentionally.
796
+ *
797
+ * The theme-independent `--color-data-*` defaults are not part of this output:
798
+ * see `generateDataTokenDefaultsCSS`.
771
799
  */
772
800
  export function generateThemeCSS(theme: DefinedTheme): ThemeCSSOutput {
773
801
  const {component, prose} = generateThemeRulesSplit(theme);
@@ -44,8 +44,11 @@ export const syntaxTokenDefaults = {
44
44
  '--color-syntax-attribute': 'var(--color-text-teal)',
45
45
  // property -> cyan text (object properties)
46
46
  '--color-syntax-property': 'var(--color-text-cyan)',
47
- // punctuation -> disabled text (brackets, semicolons)
48
- '--color-syntax-punctuation': 'var(--color-text-disabled)',
47
+ // punctuation -> secondary text (brackets, semicolons). Not disabled text:
48
+ // disabled grey is calibrated to fail AA on purpose (WCAG exempts inactive
49
+ // controls), and punctuation in a code sample is normal, always-active
50
+ // text — see #5386.
51
+ '--color-syntax-punctuation': 'var(--color-text-secondary)',
49
52
  // background -> muted surface
50
53
  '--color-syntax-background': 'var(--color-background-muted)',
51
54
  } as const;
@@ -108,6 +108,16 @@ describe('useTheme', () => {
108
108
  expect(result.current.token('--color-text-primary')).toBe('#DFE2E5');
109
109
  });
110
110
 
111
+ it('keeps the token resolver and return object stable across rerenders', () => {
112
+ const {result, rerender} = renderHook(() => useTheme());
113
+ const first = result.current;
114
+
115
+ rerender();
116
+
117
+ expect(result.current.token).toBe(first.token);
118
+ expect(result.current).toBe(first);
119
+ });
120
+
111
121
  it('returns empty string for unknown tokens', () => {
112
122
  const {result} = renderHook(() => useTheme(), {
113
123
  wrapper: ({children}) => wrapper({children, mode: 'light'}),
@@ -21,7 +21,13 @@
21
21
  * - /packages/core/src/theme/index.ts
22
22
  */
23
23
 
24
- import {createContext, use, useMemo, useSyncExternalStore} from 'react';
24
+ import {
25
+ createContext,
26
+ use,
27
+ useCallback,
28
+ useMemo,
29
+ useSyncExternalStore,
30
+ } from 'react';
25
31
  import type {ThemeMode} from './types';
26
32
  import type {DefinedTheme} from './defineTheme';
27
33
  import {resolveThemeTokens} from './tokens';
@@ -281,14 +287,14 @@ export function useTheme(): UseThemeReturn {
281
287
  [theme, effectiveMode],
282
288
  );
283
289
 
284
- const token = (name: string): string => {
285
- return tokens[name] ?? '';
286
- };
290
+ const token = useCallback(
291
+ (name: string): string => tokens[name] ?? '',
292
+ [tokens],
293
+ );
294
+ const name = theme?.name ?? 'default';
287
295
 
288
- return {
289
- name: theme?.name ?? 'default',
290
- mode: effectiveMode,
291
- token,
292
- tokens,
293
- };
296
+ return useMemo(
297
+ () => ({name, mode: effectiveMode, token, tokens}),
298
+ [name, effectiveMode, token, tokens],
299
+ );
294
300
  }
@@ -9,8 +9,8 @@
9
9
  * SYNC: When dateParser.ts changes, update tests to match new behavior
10
10
  */
11
11
 
12
- import {describe, it, expect} from 'vitest';
13
- import {parseDateInput} from './dateParser';
12
+ import {describe, it, expect, vi} from 'vitest';
13
+ import {isLocaleDayFirst, parseDateInput} from './dateParser';
14
14
 
15
15
  describe('parseDateInput', () => {
16
16
  describe('ISO format (YYYY-MM-DD)', () => {
@@ -280,6 +280,14 @@ describe('parseDateInput', () => {
280
280
  describe('ambiguous numeric formats follow the passed locale (#5074)', () => {
281
281
  // Both numbers are <= 12, so the day/month order is genuinely ambiguous
282
282
  // and resolved by isLocaleDayFirst(locale) rather than the host locale.
283
+ it('defaults ambiguous input to English month-first order', () => {
284
+ expect(parseDateInput('3/4/2026')).toEqual({
285
+ year: 2026,
286
+ month: 3,
287
+ day: 4,
288
+ });
289
+ });
290
+
283
291
  it('reads month-first for en-US', () => {
284
292
  expect(parseDateInput('3/4/2026', 'en-US')).toEqual({
285
293
  year: 2026,
@@ -297,6 +305,30 @@ describe('parseDateInput', () => {
297
305
  });
298
306
  });
299
307
 
308
+ describe('isLocaleDayFirst', () => {
309
+ it('defaults to English month-first order', () => {
310
+ expect(isLocaleDayFirst()).toBe(false);
311
+ });
312
+
313
+ it('requests Gregorian calendar data for locale ordering', () => {
314
+ const OriginalDateTimeFormat = globalThis.Intl.DateTimeFormat;
315
+ const dateTimeFormatSpy = vi
316
+ .spyOn(globalThis.Intl, 'DateTimeFormat')
317
+ .mockImplementation(function DateTimeFormat(locale, options) {
318
+ return new OriginalDateTimeFormat(locale, options);
319
+ });
320
+
321
+ try {
322
+ isLocaleDayFirst('en-US-u-ca-buddhist');
323
+ expect(dateTimeFormatSpy).toHaveBeenCalledWith('en-US-u-ca-buddhist', {
324
+ calendar: 'gregory',
325
+ });
326
+ } finally {
327
+ dateTimeFormatSpy.mockRestore();
328
+ }
329
+ });
330
+ });
331
+
300
332
  describe('edge cases', () => {
301
333
  it('returns null for empty string', () => {
302
334
  expect(parseDateInput('')).toBeNull();