@astryxdesign/core 0.5.0 → 0.5.1-canary.f64186a

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 (597) 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/index.d.ts +1 -1
  278. package/dist/index.d.ts.map +1 -1
  279. package/dist/theme/Theme.d.ts.map +1 -1
  280. package/dist/theme/Theme.js +46 -10
  281. package/dist/theme/defineTheme.d.ts +9 -3
  282. package/dist/theme/defineTheme.d.ts.map +1 -1
  283. package/dist/theme/defineTheme.js +5 -0
  284. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  285. package/dist/theme/derivedVarRegistry.js +24 -4
  286. package/dist/theme/generateThemeRules.d.ts +21 -0
  287. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  288. package/dist/theme/generateThemeRules.js +26 -0
  289. package/dist/theme/syntax/tokens.d.ts +1 -1
  290. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  291. package/dist/theme/syntax/tokens.js +5 -2
  292. package/dist/theme/useTheme.d.ts.map +1 -1
  293. package/dist/theme/useTheme.js +6 -7
  294. package/dist/utils/dateParser.d.ts +5 -8
  295. package/dist/utils/dateParser.d.ts.map +1 -1
  296. package/dist/utils/dateParser.js +10 -11
  297. package/dist/utils/focusOutline.stylex.d.ts +25 -0
  298. package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
  299. package/dist/utils/focusOutline.stylex.js +15 -0
  300. package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
  301. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
  302. package/dist/utils/interactionOverlay.stylex.js +42 -0
  303. package/dist/utils/isApplePlatform.d.ts +18 -0
  304. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  305. package/dist/utils/isApplePlatform.js +37 -0
  306. package/dist/utils/plainDate.d.ts +11 -0
  307. package/dist/utils/plainDate.d.ts.map +1 -1
  308. package/dist/utils/plainDate.js +20 -4
  309. package/locales/af-ZA.json +7 -7
  310. package/locales/ar-SA.json +7 -7
  311. package/locales/ca-ES.json +6 -6
  312. package/locales/cs-CZ.json +7 -7
  313. package/locales/da-DK.json +7 -7
  314. package/locales/de-DE.json +7 -7
  315. package/locales/el-GR.json +7 -7
  316. package/locales/en.json +178 -6
  317. package/locales/es-ES.json +6 -6
  318. package/locales/fi-FI.json +7 -7
  319. package/locales/fr-FR.json +7 -7
  320. package/locales/he-IL.json +7 -7
  321. package/locales/hu-HU.json +7 -7
  322. package/locales/it-IT.json +7 -7
  323. package/locales/ja-JP.json +7 -7
  324. package/locales/ko-KR.json +7 -7
  325. package/locales/nl-NL.json +7 -7
  326. package/locales/no-NO.json +7 -7
  327. package/locales/pl-PL.json +7 -7
  328. package/locales/pseudo.json +130 -1
  329. package/locales/pt-BR.json +7 -7
  330. package/locales/pt-PT.json +7 -7
  331. package/locales/ro-RO.json +7 -7
  332. package/locales/ru-RU.json +7 -7
  333. package/locales/sr-SP.json +7 -7
  334. package/locales/sv-SE.json +7 -7
  335. package/locales/tr-TR.json +7 -7
  336. package/locales/uk-UA.json +7 -7
  337. package/locales/vi-VN.json +7 -7
  338. package/locales/zh-CN.json +7 -7
  339. package/locales/zh-TW.json +7 -7
  340. package/package.json +4 -5
  341. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  342. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  343. package/src/AlertDialog/AlertDialog.tsx +62 -20
  344. package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
  345. package/src/AspectRatio/AspectRatio.tsx +6 -6
  346. package/src/Avatar/Avatar.doc.mjs +12 -2
  347. package/src/Avatar/Avatar.test.tsx +80 -0
  348. package/src/Avatar/Avatar.tsx +64 -14
  349. package/src/Avatar/index.ts +2 -2
  350. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  351. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  352. package/src/AvatarGroup/AvatarGroup.tsx +12 -4
  353. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  354. package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
  355. package/src/Badge/Badge.doc.mjs +3 -2
  356. package/src/Badge/Badge.test.tsx +32 -3
  357. package/src/Badge/Badge.tsx +42 -1
  358. package/src/Banner/Banner.doc.mjs +9 -0
  359. package/src/Banner/Banner.test.tsx +76 -11
  360. package/src/Banner/Banner.tsx +21 -2
  361. package/src/Button/Button.doc.mjs +2 -1
  362. package/src/Button/Button.test.tsx +19 -4
  363. package/src/Button/Button.tsx +9 -29
  364. package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
  365. package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
  366. package/src/Calendar/Calendar.doc.mjs +3 -3
  367. package/src/Calendar/Calendar.test.tsx +112 -0
  368. package/src/Calendar/Calendar.tsx +18 -16
  369. package/src/Calendar/hooks/useCalendarDays.ts +4 -4
  370. package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
  371. package/src/Calendar/styles.ts +48 -42
  372. package/src/Card/Card.doc.mjs +10 -7
  373. package/src/Card/Card.test.tsx +113 -19
  374. package/src/Card/Card.tsx +67 -89
  375. package/src/Card/index.ts +36 -1
  376. package/src/Carousel/Carousel.doc.mjs +3 -0
  377. package/src/Carousel/Carousel.test.tsx +360 -0
  378. package/src/Carousel/Carousel.tsx +116 -15
  379. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  380. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  381. package/src/CheckboxInput/CheckboxInput.tsx +5 -0
  382. package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
  383. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  384. package/src/CodeBlock/CodeBlock.tsx +20 -4
  385. package/src/CodeBlock/highlightRanges.ts +1 -1
  386. package/src/CodeBlock/highlightStyles.ts +13 -13
  387. package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
  388. package/src/ComplexSelector/ComplexSelector.doc.mjs +7 -0
  389. package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
  390. package/src/ComplexSelector/ComplexSelector.tsx +22 -12
  391. package/src/DateInput/DateInput.doc.mjs +16 -0
  392. package/src/DateInput/DateInput.test.tsx +9 -4
  393. package/src/DateInput/DateInput.tsx +54 -3
  394. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  395. package/src/DateInput/MonthScroller.tsx +5 -1
  396. package/src/DateInput/MonthYearWheels.tsx +7 -4
  397. package/src/DateInput/NativeDateField.test.tsx +635 -0
  398. package/src/DateInput/NativeDateField.tsx +641 -0
  399. package/src/DateInput/TouchDateField.tsx +83 -33
  400. package/src/DateInput/Wheel.tsx +1 -0
  401. package/src/DateInput/index.ts +1 -0
  402. package/src/DateInput/nativeDateSegments.ts +127 -0
  403. package/src/DateRangeInput/DateRangeInput.doc.mjs +2 -2
  404. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
  405. package/src/DateRangeInput/DateRangeInput.tsx +8 -13
  406. package/src/DateTimeInput/DateTimeInput.doc.mjs +38 -21
  407. package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
  408. package/src/DateTimeInput/DateTimeInput.tsx +54 -20
  409. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
  410. package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
  411. package/src/Dialog/Dialog.test.tsx +185 -18
  412. package/src/Dialog/Dialog.tsx +35 -11
  413. package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
  414. package/src/DropdownMenu/DropdownMenu.tsx +4 -13
  415. package/src/Field/FieldLabel.test.tsx +29 -0
  416. package/src/Field/FieldLabel.tsx +7 -0
  417. package/src/Field/InputClearButton.test.tsx +15 -1
  418. package/src/Field/InputClearButton.tsx +28 -4
  419. package/src/Heading/Heading.tsx +0 -1
  420. package/src/HoverCard/HoverCard.doc.mjs +8 -2
  421. package/src/HoverCard/HoverCard.test.tsx +154 -4
  422. package/src/HoverCard/HoverCard.tsx +137 -3
  423. package/src/HoverCard/useHoverCard.tsx +23 -3
  424. package/src/Icon/Icon.test.tsx +55 -1
  425. package/src/Icon/Icon.tsx +5 -3
  426. package/src/Icon/defaultIcons.tsx +11 -2
  427. package/src/Icon/globalIconRegistry.test.tsx +16 -3
  428. package/src/Icon/globalIconRegistry.tsx +37 -6
  429. package/src/Icon/index.ts +1 -0
  430. package/src/Icon/useIcon.ts +9 -2
  431. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  432. package/src/Indicator/Indicator.doc.mjs +2 -0
  433. package/src/Item/Item.tsx +2 -7
  434. package/src/Kbd/Kbd.test.tsx +0 -17
  435. package/src/Kbd/Kbd.tsx +2 -26
  436. package/src/Layer/gestureCounter.ts +57 -0
  437. package/src/Layer/useLayer.test.tsx +368 -16
  438. package/src/Layer/useLayer.tsx +208 -35
  439. package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
  440. package/src/List/List.test.tsx +38 -0
  441. package/src/List/List.tsx +8 -1
  442. package/src/Markdown/Markdown.test.tsx +37 -0
  443. package/src/Markdown/Markdown.tsx +16 -5
  444. package/src/Markdown/parser.test.ts +33 -0
  445. package/src/Markdown/parser.ts +9 -3
  446. package/src/MetadataList/MetadataList.test.tsx +75 -2
  447. package/src/MetadataList/MetadataListItem.tsx +5 -2
  448. package/src/MultiSelector/MultiSelector.doc.mjs +22 -1
  449. package/src/MultiSelector/MultiSelector.test.tsx +205 -0
  450. package/src/MultiSelector/MultiSelector.tsx +103 -16
  451. package/src/MultiSelector/hooks.ts +9 -2
  452. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  453. package/src/NavIcon/NavIcon.test.tsx +9 -0
  454. package/src/NavIcon/NavIcon.tsx +5 -1
  455. package/src/NavItem/navItemStyles.stylex.ts +0 -8
  456. package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
  457. package/src/NavMenu/NavHeadingMenu.tsx +7 -4
  458. package/src/NumberInput/NumberInput.doc.mjs +26 -7
  459. package/src/NumberInput/NumberInput.test.tsx +563 -8
  460. package/src/NumberInput/NumberInput.tsx +77 -131
  461. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  462. package/src/NumberInput/numberInputCommit.ts +103 -0
  463. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  464. package/src/NumberInput/numberParser.test.ts +222 -0
  465. package/src/NumberInput/numberParser.ts +403 -0
  466. package/src/Outline/Outline.tsx +2 -4
  467. package/src/OverflowList/OverflowList.doc.mjs +102 -21
  468. package/src/OverflowList/OverflowList.test.tsx +550 -4
  469. package/src/OverflowList/OverflowList.tsx +100 -2
  470. package/src/Pagination/Pagination.test.tsx +3 -2
  471. package/src/Popover/Popover.doc.mjs +2 -2
  472. package/src/Popover/Popover.test.tsx +38 -0
  473. package/src/Popover/Popover.tsx +28 -66
  474. package/src/Popover/usePopover.tsx +44 -5
  475. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
  476. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
  477. package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
  478. package/src/PowerSearch/formatFilterValue.test.ts +16 -1
  479. package/src/PowerSearch/formatFilterValue.ts +2 -0
  480. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  481. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  482. package/src/ProgressBar/ProgressBar.tsx +28 -8
  483. package/src/Resizable/Resizable.doc.mjs +2 -2
  484. package/src/Resizable/useResizable.doc.mjs +21 -2
  485. package/src/Resizable/useResizable.test.ts +421 -0
  486. package/src/Resizable/useResizable.ts +133 -48
  487. package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
  488. package/src/SelectableCard/SelectableCard.tsx +16 -0
  489. package/src/Selector/Selector.doc.mjs +14 -0
  490. package/src/Selector/Selector.source-build.test.mjs +65 -0
  491. package/src/Selector/Selector.test.tsx +301 -0
  492. package/src/Selector/Selector.tsx +145 -32
  493. package/src/Selector/hooks.ts +17 -2
  494. package/src/SideNav/SideNav.doc.mjs +2 -2
  495. package/src/SideNav/SideNav.test.tsx +1069 -6
  496. package/src/SideNav/SideNav.tsx +109 -38
  497. package/src/SideNav/SideNavHeading.tsx +5 -2
  498. package/src/SideNav/SideNavItem.doc.mjs +24 -3
  499. package/src/SideNav/SideNavItem.tsx +134 -44
  500. package/src/Slider/Slider.test.tsx +106 -1
  501. package/src/Slider/Slider.tsx +52 -1
  502. package/src/Spinner/Spinner.doc.mjs +17 -5
  503. package/src/Spinner/Spinner.test.tsx +164 -0
  504. package/src/Spinner/Spinner.tsx +252 -22
  505. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  506. package/src/StatusDot/StatusDot.test.tsx +9 -0
  507. package/src/StatusDot/StatusDot.tsx +7 -1
  508. package/src/Stepper/Step.doc.mjs +1 -1
  509. package/src/Stepper/Step.tsx +7 -14
  510. package/src/Switch/Switch.doc.mjs +2 -0
  511. package/src/Switch/Switch.test.tsx +10 -0
  512. package/src/Switch/Switch.tsx +3 -0
  513. package/src/Table/BaseTable.tsx +6 -1
  514. package/src/Table/Table.doc.mjs +5 -3
  515. package/src/Table/Table.tsx +3 -8
  516. package/src/Table/TableBody.doc.mjs +2 -2
  517. package/src/Table/TableFooter.doc.mjs +1 -1
  518. package/src/Table/TableHeader.doc.mjs +1 -1
  519. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  520. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  521. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
  522. package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
  523. package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
  524. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  525. package/src/Table/useTableGroupedRows.doc.mjs +3 -3
  526. package/src/Table/useTablePagination.doc.mjs +1 -1
  527. package/src/Table/useTableSelection.doc.mjs +1 -1
  528. package/src/Text/Text.test.tsx +44 -0
  529. package/src/Text/Text.tsx +0 -1
  530. package/src/TextArea/TextArea.doc.mjs +12 -2
  531. package/src/TextArea/TextArea.test.tsx +11 -0
  532. package/src/TextArea/TextArea.tsx +34 -22
  533. package/src/Timestamp/Timestamp.test.tsx +89 -0
  534. package/src/Timestamp/Timestamp.tsx +8 -8
  535. package/src/Timestamp/formatInstant.ts +5 -0
  536. package/src/Toast/Toast.doc.mjs +213 -44
  537. package/src/Toast/Toast.tsx +118 -23
  538. package/src/Toast/ToastViewport.test.tsx +1434 -8
  539. package/src/Toast/ToastViewport.tsx +85 -14
  540. package/src/Toast/index.ts +2 -0
  541. package/src/Toast/types.ts +43 -5
  542. package/src/Toast/useToastGesture.ts +361 -0
  543. package/src/Token/Token.test.tsx +95 -0
  544. package/src/Token/Token.tsx +19 -17
  545. package/src/Token/TokenLink.tsx +12 -3
  546. package/src/Tokenizer/Tokenizer.doc.mjs +16 -3
  547. package/src/Tokenizer/Tokenizer.test.tsx +161 -0
  548. package/src/Tokenizer/Tokenizer.tsx +49 -24
  549. package/src/TopNav/TopNavHeading.tsx +2 -2
  550. package/src/TopNav/TopNavItem.tsx +3 -7
  551. package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
  552. package/src/TopNav/TopNavMegaMenu.tsx +47 -4
  553. package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
  554. package/src/TopNav/TopNavMenu.test.tsx +133 -1
  555. package/src/TopNav/TopNavMenu.tsx +38 -5
  556. package/src/TreeList/TreeList.test.tsx +49 -0
  557. package/src/TreeList/TreeList.tsx +7 -2
  558. package/src/TreeList/TreeListItem.tsx +2 -7
  559. package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
  560. package/src/Typeahead/BaseTypeahead.tsx +96 -6
  561. package/src/Typeahead/Typeahead.doc.mjs +6 -0
  562. package/src/Typeahead/Typeahead.test.tsx +154 -0
  563. package/src/Typeahead/Typeahead.tsx +9 -0
  564. package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
  565. package/src/Typeahead/TypeaheadItem.tsx +8 -1
  566. package/src/hooks/useAnnounce.doc.mjs +96 -0
  567. package/src/hooks/useDevWarning.doc.mjs +96 -0
  568. package/src/hooks/useHotkeys.test.ts +0 -18
  569. package/src/hooks/useHotkeys.ts +3 -25
  570. package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
  571. package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
  572. package/src/hooks/useInteractiveRole.doc.mjs +119 -0
  573. package/src/hooks/useLongPress.doc.mjs +123 -0
  574. package/src/hooks/useOverflow.doc.mjs +58 -17
  575. package/src/hooks/useOverflow.ts +16 -4
  576. package/src/hooks/useTypeahead.doc.mjs +153 -0
  577. package/src/index.ts +2 -0
  578. package/src/raw-import.d.ts +14 -0
  579. package/src/theme/Theme.test.tsx +104 -2
  580. package/src/theme/Theme.tsx +49 -14
  581. package/src/theme/defineTheme.test.ts +23 -0
  582. package/src/theme/defineTheme.ts +12 -3
  583. package/src/theme/derivedVarRegistry.test.ts +87 -3
  584. package/src/theme/derivedVarRegistry.ts +23 -4
  585. package/src/theme/generateThemeRules.test.ts +99 -1
  586. package/src/theme/generateThemeRules.ts +28 -0
  587. package/src/theme/syntax/tokens.ts +5 -2
  588. package/src/theme/useTheme.test.tsx +10 -0
  589. package/src/theme/useTheme.ts +16 -10
  590. package/src/utils/dateParser.test.ts +34 -2
  591. package/src/utils/dateParser.ts +11 -14
  592. package/src/utils/focusOutline.stylex.ts +50 -0
  593. package/src/utils/interactionOverlay.stylex.ts +74 -0
  594. package/src/utils/isApplePlatform.test.ts +61 -0
  595. package/src/utils/isApplePlatform.ts +37 -0
  596. package/src/utils/plainDate.test.ts +46 -0
  597. package/src/utils/plainDate.ts +18 -3
@@ -15,6 +15,7 @@ import {render, screen} from '@testing-library/react';
15
15
  import userEvent from '@testing-library/user-event';
16
16
  import {Banner} from './Banner';
17
17
  import {registerIcons, resetIcons} from '../Icon';
18
+ import {InternationalizationProvider} from '../i18n';
18
19
 
19
20
  describe('Banner', () => {
20
21
  afterEach(() => {
@@ -97,7 +98,9 @@ describe('Banner', () => {
97
98
 
98
99
  it('renders dismiss button when isDismissable', () => {
99
100
  render(<Banner status="info" title="Dismissable" isDismissable />);
100
- expect(screen.getByRole('button', {name: 'Dismiss'})).toBeInTheDocument();
101
+ expect(
102
+ screen.getByRole('button', {name: 'Dismiss Dismissable'}),
103
+ ).toBeInTheDocument();
101
104
  });
102
105
 
103
106
  it('calls onDismiss when dismiss button is clicked', async () => {
@@ -111,7 +114,7 @@ describe('Banner', () => {
111
114
  onDismiss={onDismiss}
112
115
  />,
113
116
  );
114
- await user.click(screen.getByRole('button', {name: 'Dismiss'}));
117
+ await user.click(screen.getByRole('button', {name: 'Dismiss Dismissable'}));
115
118
  expect(onDismiss).toHaveBeenCalledTimes(1);
116
119
  });
117
120
 
@@ -126,7 +129,9 @@ describe('Banner', () => {
126
129
  />,
127
130
  );
128
131
  expect(screen.getByTestId('banner')).toBeInTheDocument();
129
- await user.click(screen.getByRole('button', {name: 'Dismiss'}));
132
+ await user.click(
133
+ screen.getByRole('button', {name: 'Dismiss Self Dismissing'}),
134
+ );
130
135
  expect(screen.queryByTestId('banner')).not.toBeInTheDocument();
131
136
  });
132
137
 
@@ -142,16 +147,14 @@ describe('Banner', () => {
142
147
  data-testid="banner"
143
148
  />,
144
149
  );
145
- await user.click(screen.getByRole('button', {name: 'Dismiss'}));
150
+ await user.click(screen.getByRole('button', {name: 'Dismiss Dismissable'}));
146
151
  expect(screen.queryByTestId('banner')).not.toBeInTheDocument();
147
152
  expect(onDismiss).toHaveBeenCalledTimes(1);
148
153
  });
149
154
 
150
155
  it('does not render dismiss button when isDismissable is false', () => {
151
156
  render(<Banner status="info" title="Not Dismissable" />);
152
- expect(
153
- screen.queryByRole('button', {name: 'Dismiss'}),
154
- ).not.toBeInTheDocument();
157
+ expect(screen.queryByRole('button', {name: /^Dismiss/})).toBeNull();
155
158
  });
156
159
 
157
160
  it('renders endContent', () => {
@@ -235,7 +238,9 @@ describe('Banner', () => {
235
238
  );
236
239
  // No toggle exists, so nothing should carry disclosure state, and the
237
240
  // region needs no id for a button to point at.
238
- const dismiss = screen.getByRole('button', {name: 'Dismiss'});
241
+ const dismiss = screen.getByRole('button', {
242
+ name: 'Dismiss Plain content',
243
+ });
239
244
  expect(dismiss).not.toHaveAttribute('aria-expanded');
240
245
  expect(dismiss).not.toHaveAttribute('aria-controls');
241
246
  expect(
@@ -343,7 +348,7 @@ describe('Banner', () => {
343
348
  b => b.getAttribute('aria-label') || b.textContent,
344
349
  );
345
350
  const expandIndex = buttonNames.indexOf('Expand');
346
- const dismissIndex = buttonNames.indexOf('Dismiss');
351
+ const dismissIndex = buttonNames.indexOf('Dismiss Order Test');
347
352
  expect(expandIndex).toBeLessThan(dismissIndex);
348
353
  });
349
354
 
@@ -548,7 +553,9 @@ describe('Banner', () => {
548
553
  before.focus();
549
554
 
550
555
  await user.tab();
551
- expect(screen.getByRole('button', {name: 'Dismiss'})).toHaveFocus();
556
+ expect(
557
+ screen.getByRole('button', {name: 'Dismiss Heads up'}),
558
+ ).toHaveFocus();
552
559
 
553
560
  await user.keyboard('{Enter}');
554
561
 
@@ -565,7 +572,7 @@ describe('Banner', () => {
565
572
  <Banner status="info" title="Heads up" isDismissable />
566
573
  </>,
567
574
  );
568
- await user.click(screen.getByRole('button', {name: 'Dismiss'}));
575
+ await user.click(screen.getByRole('button', {name: 'Dismiss Heads up'}));
569
576
  expect(screen.queryByRole('status')).not.toBeInTheDocument();
570
577
  });
571
578
  });
@@ -650,4 +657,62 @@ describe('Banner', () => {
650
657
  expect(getComputedStyle(textColumn).flexBasis).not.toBe('8rem');
651
658
  });
652
659
  });
660
+
661
+ describe('dismiss control naming', () => {
662
+ it('names stacked string-title banners distinctly', () => {
663
+ render(
664
+ <>
665
+ <Banner status="error" title="Upload invoice failed" isDismissable />
666
+ <Banner status="error" title="Delete report failed" isDismissable />
667
+ </>,
668
+ );
669
+ const buttons = screen.getAllByRole('button');
670
+ expect(buttons.map(button => button.getAttribute('aria-label'))).toEqual([
671
+ 'Dismiss Upload invoice failed',
672
+ 'Dismiss Delete report failed',
673
+ ]);
674
+ for (const button of buttons) {
675
+ expect(button).toHaveAccessibleDescription('Dismiss');
676
+ }
677
+ });
678
+
679
+ it('keeps the bare name and tooltip for a rich title', () => {
680
+ render(
681
+ <Banner status="info" title={<span>Rich title</span>} isDismissable />,
682
+ );
683
+ const button = screen.getByRole('button', {name: 'Dismiss'});
684
+ expect(button).toHaveAccessibleDescription('Dismiss');
685
+ });
686
+
687
+ it('uses a translated dismissLabel for a rich title and its tooltip', () => {
688
+ render(
689
+ <Banner
690
+ status="info"
691
+ title={<span>Wartungshinweis</span>}
692
+ isDismissable
693
+ dismissLabel="Wartungshinweis schließen"
694
+ />,
695
+ );
696
+ const button = screen.getByRole('button', {
697
+ name: 'Wartungshinweis schließen',
698
+ });
699
+ expect(button).toHaveAccessibleDescription('Wartungshinweis schließen');
700
+ });
701
+
702
+ it('keeps a translated verb when the titled message falls back to English', () => {
703
+ render(
704
+ <InternationalizationProvider
705
+ locale="de-DE"
706
+ overrides={{
707
+ 'de-DE': {'@astryx.banner.dismiss': 'Schließen'},
708
+ }}>
709
+ <Banner status="info" title="Wartungshinweis" isDismissable />
710
+ </InternationalizationProvider>,
711
+ );
712
+ const button = screen.getByRole('button', {
713
+ name: 'Schließen Wartungshinweis',
714
+ });
715
+ expect(button).toHaveAccessibleDescription('Schließen');
716
+ });
717
+ });
653
718
  });
@@ -118,6 +118,15 @@ export interface BannerProps extends BaseProps<HTMLDivElement> {
118
118
  * The banner will hide itself regardless of whether this callback is provided.
119
119
  */
120
120
  onDismiss?: () => void;
121
+ /**
122
+ * Accessible name and visible tooltip for the dismiss button, replacing the default.
123
+ * Pass an already-translated string.
124
+ *
125
+ * The default is "Dismiss {title}" when `title` is a string, so stacked
126
+ * banners are told apart by a screen reader; a non-string `title` falls back
127
+ * to "Dismiss" and should set this.
128
+ */
129
+ dismissLabel?: string;
121
130
  /**
122
131
  * Action button rendered in the header area (end-aligned).
123
132
  * Typically an Button with a secondary or ghost variant.
@@ -440,6 +449,7 @@ export function Banner({
440
449
  icon,
441
450
  isDismissable = false,
442
451
  onDismiss,
452
+ dismissLabel,
443
453
  endContent,
444
454
  container = 'card',
445
455
  elevation = 'none',
@@ -490,6 +500,15 @@ export function Banner({
490
500
  const role = statusRole[status] ?? FALLBACK_ROLE;
491
501
  const iconColor = statusIconColor[status];
492
502
  const hasChildren = isRenderable(children);
503
+ // Keep the default tooltip concise while the accessible name identifies
504
+ // the banner; an explicit translated override names both surfaces.
505
+ const dismiss = t('@astryx.banner.dismiss');
506
+ const dismissTooltip = dismissLabel ?? dismiss;
507
+ const dismissName =
508
+ dismissLabel ??
509
+ (typeof title === 'string'
510
+ ? t('@astryx.banner.dismissTitled', {dismiss, title})
511
+ : dismiss);
493
512
 
494
513
  if (isDismissed) {
495
514
  return null;
@@ -657,8 +676,8 @@ export function Banner({
657
676
  <Button
658
677
  variant="ghost"
659
678
  size="sm"
660
- label={t('@astryx.banner.dismiss')}
661
- tooltip={t('@astryx.banner.dismiss')}
679
+ label={dismissName}
680
+ tooltip={dismissTooltip}
662
681
  icon={<Icon icon="close" size="sm" color="inherit" />}
663
682
  onClick={handleDismiss}
664
683
  isIconOnly
@@ -181,7 +181,7 @@ export const docs = {
181
181
  },
182
182
  theming: {
183
183
  targets: [
184
- {className: 'astryx-button', visualProps: ['size', 'variant']},
184
+ {className: 'astryx-button', visualProps: ['size', 'variant', 'elevation']},
185
185
  ],
186
186
  vars: [
187
187
  {name: '--_button-radius', description: 'Border radius', default: 'var(--radius-element)', private: true},
@@ -262,6 +262,7 @@ export const docsZh = {
262
262
  visualProps: [
263
263
  'size',
264
264
  'variant',
265
+ 'elevation',
265
266
  ],
266
267
  },
267
268
  ],
@@ -476,6 +476,21 @@ describe('Button', () => {
476
476
  });
477
477
 
478
478
  describe('elevation', () => {
479
+ it('reflects each elevation level as a theme attribute', () => {
480
+ const attrFor = (elevation: 'none' | 'low' | 'med' | 'high') => {
481
+ const {container} = render(
482
+ <Button label="Save" elevation={elevation} />,
483
+ );
484
+ return container
485
+ .querySelector('button')!
486
+ .getAttribute('data-elevation');
487
+ };
488
+ expect(attrFor('none')).toBe('none');
489
+ expect(attrFor('low')).toBe('low');
490
+ expect(attrFor('med')).toBe('med');
491
+ expect(attrFor('high')).toBe('high');
492
+ });
493
+
479
494
  it('renders a distinct class for each elevation level', () => {
480
495
  const classFor = (elevation: 'none' | 'low' | 'med' | 'high') => {
481
496
  const {container} = render(
@@ -493,13 +508,13 @@ describe('Button', () => {
493
508
  });
494
509
 
495
510
  it('defaults to flat (elevation none)', () => {
496
- const {container: def} = render(<Button label="Save" />);
511
+ const {container} = render(<Button label="Save" />);
512
+ const button = container.querySelector('button')!;
513
+ expect(button).toHaveAttribute('data-elevation', 'none');
497
514
  const {container: none} = render(
498
515
  <Button label="Save" elevation="none" />,
499
516
  );
500
- expect(def.querySelector('button')!.className).toBe(
501
- none.querySelector('button')!.className,
502
- );
517
+ expect(button.className).toBe(none.querySelector('button')!.className);
503
518
  });
504
519
  });
505
520
 
@@ -48,6 +48,7 @@ import {useLinkComponent} from '../Link/useLinkComponent';
48
48
  import type {LinkComponentType} from '../Link/types';
49
49
  import {themeProps} from '../utils/themeProps';
50
50
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
51
+ import {interactionOverlayStyles} from '../utils/interactionOverlay.stylex';
51
52
  import {useTranslator} from '../i18n';
52
53
  import type {ButtonVariantMap} from './index';
53
54
 
@@ -200,35 +201,14 @@ const variants = stylex.create({
200
201
  primary: {
201
202
  backgroundColor: colorVars['--color-accent'],
202
203
  color: colorVars['--color-on-accent'],
203
- backgroundImage: {
204
- default: null,
205
- ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
206
- '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
207
- },
208
- ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
209
- },
210
204
  },
211
205
  secondary: {
212
206
  backgroundColor: colorVars['--color-neutral'],
213
207
  color: colorVars['--color-text-primary'],
214
- backgroundImage: {
215
- default: null,
216
- ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
217
- '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
218
- },
219
- ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
220
- },
221
208
  },
222
209
  ghost: {
223
210
  backgroundColor: 'transparent',
224
211
  color: colorVars['--color-text-primary'],
225
- backgroundImage: {
226
- default: null,
227
- ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
228
- '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
229
- },
230
- ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
231
- },
232
212
  },
233
213
  destructive: {
234
214
  backgroundColor: colorVars['--color-error'],
@@ -237,13 +217,6 @@ const variants = stylex.create({
237
217
  // red button reads as another control's focus. Only the color differs —
238
218
  // width, style and offset come from the shared outline.
239
219
  outlineColor: {default: null, ':focus-visible': colorVars['--color-error']},
240
- backgroundImage: {
241
- default: null,
242
- ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
243
- '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
244
- },
245
- ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
246
- },
247
220
  },
248
221
  });
249
222
 
@@ -665,6 +638,7 @@ export function Button({
665
638
  styles.base,
666
639
  sizeStyles[size],
667
640
  isIconOnly && styles.iconOnly,
641
+ interactionOverlayStyles.backgroundImage,
668
642
  buttonDisabled && styles.disabled,
669
643
  useAriaDisabled && styles.ariaDisabled,
670
644
  renderAsLink && styles.link,
@@ -689,7 +663,13 @@ export function Button({
689
663
  );
690
664
 
691
665
  const sharedMergedProps = mergeProps(
692
- themeProps('button', {variant, size}),
666
+ // Inside a group the group owns the surface's elevation, so the button
667
+ // reflects the tier it actually paints rather than the prop it was handed.
668
+ themeProps('button', {
669
+ variant,
670
+ size,
671
+ elevation: buttonGroup ? 'none' : elevation,
672
+ }),
693
673
  sharedStylexProps,
694
674
  className,
695
675
  style,
@@ -46,8 +46,8 @@ export const docs = {
46
46
  {guidance: false, description: "Don't mix wildly different actions. A Save button next to a Delete button in the same group is confusing."},
47
47
  {guidance: false, description: "Don't use ButtonGroup for navigation. Use SegmentedControl or TabList for switching between views."},
48
48
  {guidance: false, description: "Don't nest ButtonGroups. If you need multiple groups, place them side by side with a gap."},
49
- {guidance: true, description: 'Name the group for what its buttons act on. The label is the group\u2019s accessible name and a screen reader reads it before each member.'},
50
- {guidance: true, description: 'Keep the group a single Tab stop. Arrow keys move between members along the orientation, Home/End jump to the ends, and disabled members are skipped — the WAI-ARIA APG roving tabindex technique: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex'},
49
+ {guidance: true, description: 'Name the group for what its buttons act on. The label is the group\'s accessible name and a screen reader reads it before each member.'},
50
+ {guidance: true, description: 'Keep the group a single Tab stop. Arrow keys move between members along the orientation, Home/End jump to the ends, and disabled members are skipped. This is the WAI-ARIA APG roving tabindex technique: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex'},
51
51
  {guidance: false, description: "Don't disable the group to show that an action is in flight. A disabled member drops focus, so a keyboard user loses their place; leave the group enabled and show progress on the button that started the work."},
52
52
  ],
53
53
  anatomy: [
@@ -626,6 +626,19 @@ describe('ButtonGroup', () => {
626
626
  'high',
627
627
  );
628
628
  });
629
+
630
+ it('reports flat on a member, since the group owns the surface', () => {
631
+ render(
632
+ <ButtonGroup label="Actions" elevation="high">
633
+ <Button label="One" elevation="high" />
634
+ </ButtonGroup>,
635
+ );
636
+
637
+ expect(screen.getByRole('button', {name: 'One'})).toHaveAttribute(
638
+ 'data-elevation',
639
+ 'none',
640
+ );
641
+ });
629
642
  });
630
643
 
631
644
  // ===========================================================================
@@ -78,7 +78,7 @@ export const docs = {
78
78
  name: 'minRangeSpan',
79
79
  type: 'number',
80
80
  description:
81
- 'Range mode: min days a range must span, both endpoints counted (2 forbids a single-day range). Default 1.',
81
+ 'Range mode: min days a range must span, both endpoints counted (2 forbids a single-day range). Clicking the start again commits a one-day range when allowed, or cancels the in-progress selection when the minimum is longer. Default 1.',
82
82
  },
83
83
  {
84
84
  name: 'focusDate',
@@ -156,7 +156,7 @@ export const docsZh = {
156
156
  {name: 'max', type: 'ISODateString', description: '可选择的最晚日期。'},
157
157
  {name: 'dateConstraints', type: 'Array<(date: Date) => boolean>', description: '自定义约束函数。'},
158
158
  {name: 'maxRangeSpan', type: 'number', description: '范围模式:范围最多可跨越的天数,含首尾两端(7 = 7 天窗口)。选定起始日后限制窗口大小。'},
159
- {name: 'minRangeSpan', type: 'number', description: '范围模式:范围最少需跨越的天数,含首尾两端(2 表示禁止单日范围)。默认为 1。'},
159
+ {name: 'minRangeSpan', type: 'number', description: '范围模式:范围最少需跨越的天数,含首尾两端(2 表示禁止单日范围)。再次点击开始日期时,若最小范围允许则提交单日范围;否则取消进行中的选择。默认为 1。'},
160
160
  {name: 'focusDate', type: 'ISODateString', description: '受控可见月份。未设置时,日历打开时显示已选日期所在月份;若无选中值,则显示今天,并将其限制在 min/max 范围内。'},
161
161
  {name: 'onFocusDateChange', type: '(focusDate: ISODateString) => void', description: '导航回调函数。'},
162
162
  {name: 'handleRef', type: 'React.Ref<CalendarHandle>', description: '日历导航的命令式句柄,包括 navigateTo()。'},
@@ -221,7 +221,7 @@ export const docsDense = {
221
221
  max: 'maximum selectable date',
222
222
  dateConstraints: 'custom constraint fns',
223
223
  maxRangeSpan: 'range mode: max days a range may span, both ends counted (7 = 7-day window)',
224
- minRangeSpan: 'range mode: min days a range must span, both ends counted (default 1)',
224
+ minRangeSpan: 'range mode: min days a range must span, both ends counted; repeated start click commits one day when allowed, otherwise cancels (default 1)',
225
225
  focusDate: 'controlled visible month (default: selected date, else today clamped into min/max)',
226
226
  onFocusDateChange: 'navigation callback',
227
227
  handleRef: 'imperative navigation handle',
@@ -13,6 +13,10 @@ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
13
13
  import {act, render, screen, within, waitFor} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {getButton} from '../__tests__/fastRoleQueries';
16
+ import {
17
+ getForcedColorsRules,
18
+ getAllInjectedCss,
19
+ } from '../__tests__/forcedColors';
16
20
  import * as stylex from '@stylexjs/stylex';
17
21
  import {Calendar} from './Calendar';
18
22
  import type {CalendarHandle} from './Calendar';
@@ -161,6 +165,27 @@ describe('Calendar', () => {
161
165
  ).toEqual([...localizedNames.slice(1), localizedNames[0]]);
162
166
  });
163
167
 
168
+ it('updates the month header and subsequent navigation with provider locale', async () => {
169
+ const user = userEvent.setup();
170
+ const renderCalendar = (locale: 'en-US' | 'es-ES') => (
171
+ <InternationalizationProvider locale={locale}>
172
+ <Calendar focusDate="2026-01-01" />
173
+ </InternationalizationProvider>
174
+ );
175
+ const {rerender} = render(renderCalendar('en-US'));
176
+
177
+ expect(screen.getByText('January 2026')).toBeInTheDocument();
178
+
179
+ rerender(renderCalendar('es-ES'));
180
+ expect(screen.getByText('enero de 2026')).toBeInTheDocument();
181
+
182
+ const nextButton =
183
+ document.querySelector<HTMLButtonElement>('[data-nav="next"]');
184
+ expect(nextButton).not.toBeNull();
185
+ await user.click(nextButton!);
186
+ expect(screen.getByText('febrero de 2026')).toBeInTheDocument();
187
+ });
188
+
164
189
  it('displays correct number of day cells', () => {
165
190
  render(<Calendar />);
166
191
 
@@ -363,6 +388,46 @@ describe('Calendar', () => {
363
388
  expect(getDayButton(9)).toBeDisabled(); // 2-day span — too short
364
389
  });
365
390
 
391
+ it('commits a same-day range with the default minimum', async () => {
392
+ const user = userEvent.setup();
393
+ const handleChange = vi.fn();
394
+
395
+ render(
396
+ <Calendar mode="range" focusDate="2026-01-01" onChange={handleChange} />,
397
+ );
398
+
399
+ await user.click(getDayButton(10));
400
+ await user.click(getDayButton(10));
401
+
402
+ expect(handleChange).toHaveBeenCalledWith({
403
+ start: '2026-01-10',
404
+ end: '2026-01-10',
405
+ });
406
+ });
407
+
408
+ it('commits a same-day range when the minimum permits it, including with a maximum', async () => {
409
+ const user = userEvent.setup();
410
+ const handleChange = vi.fn();
411
+
412
+ render(
413
+ <Calendar
414
+ mode="range"
415
+ focusDate="2026-01-01"
416
+ onChange={handleChange}
417
+ minRangeSpan={1}
418
+ maxRangeSpan={7}
419
+ />,
420
+ );
421
+
422
+ await user.click(getDayButton(10));
423
+ await user.click(getDayButton(10));
424
+
425
+ expect(handleChange).toHaveBeenCalledWith({
426
+ start: '2026-01-10',
427
+ end: '2026-01-10',
428
+ });
429
+ });
430
+
366
431
  it('clears the in-progress start when the anchor is clicked again', async () => {
367
432
  const user = userEvent.setup();
368
433
  const handleChange = vi.fn();
@@ -389,6 +454,33 @@ describe('Calendar', () => {
389
454
  expect(getDayButton(9)).not.toBeDisabled();
390
455
  });
391
456
 
457
+ it('announces the cleared range in the provider locale', async () => {
458
+ const user = userEvent.setup();
459
+
460
+ render(
461
+ <InternationalizationProvider locale="ja-JP">
462
+ <Calendar mode="range" focusDate="2026-01-01" />
463
+ </InternationalizationProvider>,
464
+ );
465
+
466
+ // The day button's own accessible name is already localized through the
467
+ // provider. The announcement has to use the same date string: formatting
468
+ // it without the locale silently falls back to the host locale, so a
469
+ // Japanese user hears an English date.
470
+ const anchor = document.querySelector<HTMLButtonElement>(
471
+ 'button[data-date="2026-01-10"]',
472
+ );
473
+ const localizedDate = anchor?.getAttribute('aria-label');
474
+ expect(localizedDate).toBeTruthy();
475
+
476
+ await user.click(anchor as HTMLButtonElement);
477
+ await user.click(anchor as HTMLButtonElement);
478
+
479
+ await waitFor(() => {
480
+ expect(politeRegion()?.textContent).toContain(localizedDate);
481
+ });
482
+ });
483
+
392
484
  it('does not apply range-span constraints in single mode', async () => {
393
485
  const user = userEvent.setup();
394
486
 
@@ -1430,3 +1522,23 @@ describe('Calendar', () => {
1430
1522
  });
1431
1523
  });
1432
1524
  });
1525
+
1526
+ // jsdom cannot emulate forced-colors rendering, so this asserts that the
1527
+ // compiled output includes the forced-colors rules; visual behavior needs
1528
+ // manual verification under Windows High Contrast.
1529
+ describe('forced colors (WCAG 1.4.11)', () => {
1530
+ it('compiles a forced-colors fill so the selected date survives Windows High Contrast', () => {
1531
+ render(
1532
+ <Calendar mode="single" value="2026-01-15" focusDate="2026-01-01" />,
1533
+ );
1534
+
1535
+ const css = getForcedColorsRules();
1536
+ // Without these the accent fill is stripped and the selected date renders
1537
+ // identically to every other day in the month.
1538
+ expect(css).toContain('background-color: highlight;');
1539
+ expect(css).toContain('color: highlighttext;');
1540
+ // A <button> keeps the native ButtonFace surface and ignores the authored
1541
+ // Highlight fill unless it opts out of UA remapping.
1542
+ expect(getAllInjectedCss()).toContain('forced-color-adjust: none;');
1543
+ });
1544
+ });
@@ -19,7 +19,6 @@
19
19
  */
20
20
 
21
21
  import {
22
- use,
23
22
  useState,
24
23
  useMemo,
25
24
  useCallback,
@@ -61,6 +60,7 @@ import {
61
60
  } from '../utils/plainDate';
62
61
  import {mergeProps, composeEventHandlers, rtlStyles} from '../utils';
63
62
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
63
+ import {interactionOverlayStyles} from '../utils/interactionOverlay.stylex';
64
64
  import {getInitialFocusDate} from './getInitialFocusDate';
65
65
  import {
66
66
  computeDayCellState,
@@ -89,7 +89,7 @@ import type {
89
89
  } from '../utils/dateTypes';
90
90
  import {normalizeDayOfWeek} from '../utils/dateTypes';
91
91
  import {themeProps} from '../utils/themeProps';
92
- import {useTranslator, InternationalizationContext} from '../i18n';
92
+ import {useLocale, useTranslator} from '../i18n';
93
93
 
94
94
  /** Imperative handle for Calendar handleRef */
95
95
 
@@ -137,8 +137,10 @@ interface CalendarBaseProps extends Omit<
137
137
  * Range mode only. Minimum number of days a selected range must span,
138
138
  * counting both endpoints — `minRangeSpan={2}` forbids a single-day range.
139
139
  * Once a start date is picked, days closer than this to it are disabled —
140
- * except the start itself, which stays selectable as the active anchor.
141
- * Defaults to 1 (a same-day start and end is allowed).
140
+ * except the start itself, which stays selectable. Clicking the start again
141
+ * commits a one-day range when the minimum allows it; otherwise it cancels
142
+ * the in-progress selection so the start can be moved. Defaults to 1 (a
143
+ * same-day start and end is allowed).
142
144
  */
143
145
  minRangeSpan?: number;
144
146
 
@@ -225,7 +227,7 @@ export type CalendarProps = CalendarSingleProps | CalendarRangeProps;
225
227
  */
226
228
  export function Calendar({ref, ...props}: CalendarProps) {
227
229
  const t = useTranslator();
228
- const {locale} = use(InternationalizationContext);
230
+ const locale = useLocale();
229
231
  const {
230
232
  handleRef,
231
233
  mode = 'single',
@@ -452,17 +454,16 @@ export function Calendar({ref, ...props}: CalendarProps) {
452
454
  // Second click - complete the range
453
455
  const startPd = plainDateFromISO(rangeSelectionStart);
454
456
 
455
- // Clicking the anchor again clears the in-progress start rather than
456
- // committing a zero-length range. This is also the escape hatch when
457
- // `minRangeSpan` disables the days around the anchor: without it the
458
- // anchor would be the only clickable day left and the start could
459
- // never be moved. `minRangeSpan` leaves the anchor itself enabled
460
- // precisely so this toggle stays reachable.
461
- if (plainDateIsEqual(date, startPd)) {
457
+ // Clicking the anchor again commits a one-day range when the minimum
458
+ // span allows it. For longer minimum spans, the repeated click clears
459
+ // the in-progress start instead: the anchor is the only nearby day
460
+ // that remains enabled, so this preserves an escape hatch for moving
461
+ // the start without violating the configured minimum.
462
+ if (plainDateIsEqual(date, startPd) && (minRangeSpan ?? 1) > 1) {
462
463
  setRangeSelectionStart(null);
463
464
  announce(
464
465
  t('@astryx.calendar.rangeClearedAnnounce', {
465
- date: plainDateFormat(date, DATE_FORMAT_WITH_WEEKDAY),
466
+ date: plainDateFormat(date, DATE_FORMAT_WITH_WEEKDAY, locale),
466
467
  }),
467
468
  );
468
469
  return;
@@ -503,7 +504,7 @@ export function Calendar({ref, ...props}: CalendarProps) {
503
504
  }
504
505
  }
505
506
  },
506
- [mode, onChange, rangeSelectionStart, announce, t, locale],
507
+ [mode, onChange, rangeSelectionStart, minRangeSpan, announce, t, locale],
507
508
  );
508
509
 
509
510
  return (
@@ -652,7 +653,7 @@ function MonthGrid({
652
653
  pendingFocus,
653
654
  onPendingFocusHandled,
654
655
  }: MonthGridProps) {
655
- const {locale} = use(InternationalizationContext);
656
+ const locale = useLocale();
656
657
  const year = month.year;
657
658
 
658
659
  // Use hooks for days generation and constraints
@@ -1033,7 +1034,7 @@ function DayCell({
1033
1034
  onDayHover,
1034
1035
  }: DayCellProps) {
1035
1036
  const t = useTranslator();
1036
- const {locale} = use(InternationalizationContext);
1037
+ const locale = useLocale();
1037
1038
  const {date, isOutside, dayNumber} = day;
1038
1039
 
1039
1040
  if (isOutside && !hasOutsideDays) {
@@ -1178,6 +1179,7 @@ function DayCell({
1178
1179
  focusOutlineProps.focusVisible(
1179
1180
  dayCellStyles.day,
1180
1181
  dayCellTheme.day,
1182
+ interactionOverlayStyles.backgroundImage,
1181
1183
  isOutside && dayCellStyles.dayOutside,
1182
1184
  isOutside && dayCellTheme.dayOutside,
1183
1185
  showsTodayRing && dayCellStyles.dayToday,