@astryxdesign/core 0.4.7 → 0.5.0-canary.055e75f

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 +161 -1
  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/AppShell/AppShell.d.ts.map +1 -1
  6. package/dist/AppShell/AppShell.js +3 -2
  7. package/dist/AspectRatio/AspectRatio.d.ts +24 -0
  8. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  9. package/dist/AspectRatio/AspectRatio.js +23 -4
  10. package/dist/Avatar/Avatar.d.ts +25 -1
  11. package/dist/Avatar/Avatar.d.ts.map +1 -1
  12. package/dist/Avatar/Avatar.js +58 -19
  13. package/dist/Avatar/index.d.ts +2 -2
  14. package/dist/Avatar/index.d.ts.map +1 -1
  15. package/dist/Avatar/index.js +1 -1
  16. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  17. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroup.js +8 -4
  19. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  20. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  21. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  22. package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
  23. package/dist/Banner/Banner.d.ts +40 -15
  24. package/dist/Banner/Banner.d.ts.map +1 -1
  25. package/dist/Banner/Banner.js +51 -18
  26. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  27. package/dist/BottomSheet/BottomSheet.js +17 -4
  28. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  29. package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
  30. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  31. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
  32. package/dist/Button/Button.d.ts.map +1 -1
  33. package/dist/Button/Button.js +11 -6
  34. package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
  35. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  36. package/dist/ButtonGroup/ButtonGroup.js +26 -7
  37. package/dist/Calendar/Calendar.d.ts +3 -1
  38. package/dist/Calendar/Calendar.d.ts.map +1 -1
  39. package/dist/Calendar/Calendar.js +14 -15
  40. package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
  41. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
  42. package/dist/Calendar/getInitialFocusDate.js +62 -0
  43. package/dist/Calendar/styles.d.ts +5 -14
  44. package/dist/Calendar/styles.d.ts.map +1 -1
  45. package/dist/Calendar/styles.js +15 -15
  46. package/dist/Card/Card.d.ts +6 -9
  47. package/dist/Card/Card.d.ts.map +1 -1
  48. package/dist/Card/Card.js +6 -6
  49. package/dist/Carousel/Carousel.d.ts.map +1 -1
  50. package/dist/Carousel/Carousel.js +3 -3
  51. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  52. package/dist/Chat/ChatComposerInput.js +2 -3
  53. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  54. package/dist/Chat/ChatLayout.js +3 -3
  55. package/dist/Chat/ChatMessageList.d.ts +22 -3
  56. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  57. package/dist/Chat/ChatMessageList.js +6 -3
  58. package/dist/Chat/ChatTokenizedText.d.ts +2 -0
  59. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  60. package/dist/Chat/ChatTokenizedText.js +11 -6
  61. package/dist/Chat/useChatComposerTokens.js +1 -1
  62. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  63. package/dist/CheckboxInput/CheckboxInput.js +10 -3
  64. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  65. package/dist/ClickableCard/ClickableCard.js +3 -3
  66. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  67. package/dist/CodeBlock/CodeBlock.js +15 -4
  68. package/dist/CodeBlock/highlightRanges.js +1 -1
  69. package/dist/CodeBlock/highlightStyles.js +13 -13
  70. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  71. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  72. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  73. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  74. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  75. package/dist/ContextMenu/ContextMenu.js +4 -3
  76. package/dist/DateInput/DateInput.d.ts +43 -0
  77. package/dist/DateInput/DateInput.d.ts.map +1 -1
  78. package/dist/DateInput/DateInput.js +22 -2
  79. package/dist/DateInput/NativeDateField.d.ts +10 -0
  80. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  81. package/dist/DateInput/NativeDateField.js +494 -0
  82. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  83. package/dist/DateInput/TouchDateField.js +82 -23
  84. package/dist/DateInput/index.d.ts +1 -1
  85. package/dist/DateInput/index.d.ts.map +1 -1
  86. package/dist/DateInput/nativeDateSegments.d.ts +22 -0
  87. package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
  88. package/dist/DateInput/nativeDateSegments.js +111 -0
  89. package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
  90. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  91. package/dist/DateTimeInput/DateTimeInput.js +406 -12
  92. package/dist/DateTimeInput/index.d.ts +1 -1
  93. package/dist/DateTimeInput/index.d.ts.map +1 -1
  94. package/dist/Dialog/Dialog.d.ts +21 -1
  95. package/dist/Dialog/Dialog.d.ts.map +1 -1
  96. package/dist/Dialog/Dialog.js +110 -58
  97. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  98. package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
  99. package/dist/Field/FieldLabel.d.ts.map +1 -1
  100. package/dist/Field/FieldLabel.js +9 -1
  101. package/dist/FileInput/FileInput.d.ts.map +1 -1
  102. package/dist/FileInput/FileInput.js +3 -2
  103. package/dist/Heading/Heading.d.ts.map +1 -1
  104. package/dist/Heading/Heading.js +6 -2
  105. package/dist/HoverCard/HoverCard.d.ts +6 -0
  106. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  107. package/dist/HoverCard/HoverCard.js +104 -3
  108. package/dist/HoverCard/useHoverCard.d.ts +19 -2
  109. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  110. package/dist/HoverCard/useHoverCard.js +74 -26
  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 +4 -2
  115. package/dist/Kbd/Kbd.d.ts.map +1 -1
  116. package/dist/Kbd/Kbd.js +2 -19
  117. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  118. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  119. package/dist/Layer/LayerDepthContext.js +66 -0
  120. package/dist/Layer/index.d.ts +3 -0
  121. package/dist/Layer/index.d.ts.map +1 -1
  122. package/dist/Layer/index.js +4 -0
  123. package/dist/Layer/layerStack.d.ts +98 -0
  124. package/dist/Layer/layerStack.d.ts.map +1 -0
  125. package/dist/Layer/layerStack.js +306 -0
  126. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  127. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  128. package/dist/Layer/useLayerDismissal.js +91 -0
  129. package/dist/Lightbox/Lightbox.d.ts +1 -0
  130. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  131. package/dist/Lightbox/Lightbox.js +103 -81
  132. package/dist/Markdown/Markdown.d.ts.map +1 -1
  133. package/dist/Markdown/Markdown.js +9 -4
  134. package/dist/Markdown/index.d.ts +1 -1
  135. package/dist/Markdown/index.d.ts.map +1 -1
  136. package/dist/Markdown/parser.d.ts +38 -1
  137. package/dist/Markdown/parser.d.ts.map +1 -1
  138. package/dist/Markdown/parser.js +182 -32
  139. package/dist/MobileNav/MobileNav.d.ts +6 -1
  140. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  141. package/dist/MobileNav/MobileNav.js +61 -36
  142. package/dist/MultiSelector/MultiSelector.d.ts +32 -1
  143. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  144. package/dist/MultiSelector/MultiSelector.js +63 -11
  145. package/dist/MultiSelector/index.d.ts +1 -1
  146. package/dist/MultiSelector/index.d.ts.map +1 -1
  147. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  148. package/dist/NavIcon/NavIcon.js +5 -1
  149. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  150. package/dist/NavMenu/NavHeadingMenu.js +3 -2
  151. package/dist/NumberInput/NumberInput.d.ts +6 -1
  152. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  153. package/dist/NumberInput/NumberInput.js +54 -104
  154. package/dist/NumberInput/numberInputCommit.d.ts +34 -0
  155. package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
  156. package/dist/NumberInput/numberInputCommit.js +71 -0
  157. package/dist/NumberInput/numberParser.d.ts +64 -0
  158. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  159. package/dist/NumberInput/numberParser.js +350 -0
  160. package/dist/Outline/Outline.d.ts.map +1 -1
  161. package/dist/Outline/Outline.js +3 -2
  162. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  163. package/dist/OverflowList/OverflowList.js +3 -2
  164. package/dist/Overlay/Overlay.d.ts.map +1 -1
  165. package/dist/Overlay/Overlay.js +3 -2
  166. package/dist/Popover/usePopover.d.ts.map +1 -1
  167. package/dist/Popover/usePopover.js +20 -17
  168. package/dist/PowerSearch/PowerSearch.d.ts +8 -2
  169. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  170. package/dist/PowerSearch/PowerSearch.js +19 -6
  171. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
  172. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  173. package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
  174. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
  175. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  176. package/dist/PowerSearch/PowerSearchValueEditor.js +110 -27
  177. package/dist/PowerSearch/types.d.ts +2 -0
  178. package/dist/PowerSearch/types.d.ts.map +1 -1
  179. package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
  180. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  181. package/dist/PowerSearch/usePowerSearchSource.js +14 -5
  182. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  183. package/dist/ProgressBar/ProgressBar.js +18 -5
  184. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  185. package/dist/Resizable/ResizeHandle.js +3 -2
  186. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  187. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  188. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  189. package/dist/SelectableCard/SelectableCard.js +3 -3
  190. package/dist/Selector/Selector.d.ts +17 -0
  191. package/dist/Selector/Selector.d.ts.map +1 -1
  192. package/dist/Selector/Selector.js +81 -14
  193. package/dist/SideNav/SideNav.d.ts.map +1 -1
  194. package/dist/SideNav/SideNav.js +4 -3
  195. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  196. package/dist/SideNav/SideNavHeading.js +8 -7
  197. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  198. package/dist/SideNav/SideNavItem.js +4 -3
  199. package/dist/Slider/Slider.d.ts.map +1 -1
  200. package/dist/Slider/Slider.js +37 -5
  201. package/dist/Spinner/Spinner.d.ts +3 -3
  202. package/dist/Spinner/Spinner.d.ts.map +1 -1
  203. package/dist/Spinner/Spinner.js +130 -78
  204. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  205. package/dist/StatusDot/StatusDot.js +6 -1
  206. package/dist/Stepper/Step.d.ts +140 -0
  207. package/dist/Stepper/Step.d.ts.map +1 -0
  208. package/dist/Stepper/Step.js +1045 -0
  209. package/dist/Stepper/StepStatus.d.ts +24 -0
  210. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  211. package/dist/Stepper/StepStatus.js +1 -0
  212. package/dist/Stepper/Stepper.d.ts +93 -0
  213. package/dist/Stepper/Stepper.d.ts.map +1 -0
  214. package/dist/Stepper/Stepper.js +184 -0
  215. package/dist/Stepper/StepperContext.d.ts +41 -0
  216. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  217. package/dist/Stepper/StepperContext.js +34 -0
  218. package/dist/Stepper/index.d.ts +8 -0
  219. package/dist/Stepper/index.d.ts.map +1 -0
  220. package/dist/Stepper/index.js +7 -0
  221. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  222. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  223. package/dist/Stepper/stepper.stylex.js +20 -0
  224. package/dist/Switch/Switch.d.ts.map +1 -1
  225. package/dist/Switch/Switch.js +8 -3
  226. package/dist/TabList/Tab.d.ts +15 -2
  227. package/dist/TabList/Tab.d.ts.map +1 -1
  228. package/dist/TabList/Tab.js +32 -7
  229. package/dist/TabList/TabList.d.ts +46 -7
  230. package/dist/TabList/TabList.d.ts.map +1 -1
  231. package/dist/TabList/TabList.js +353 -23
  232. package/dist/TabList/TabListContext.d.ts +11 -1
  233. package/dist/TabList/TabListContext.d.ts.map +1 -1
  234. package/dist/TabList/TabListContext.js +11 -2
  235. package/dist/TabList/TabMenu.d.ts.map +1 -1
  236. package/dist/TabList/TabMenu.js +3 -2
  237. package/dist/TabList/index.d.ts +2 -2
  238. package/dist/TabList/index.d.ts.map +1 -1
  239. package/dist/Table/BaseTable.d.ts.map +1 -1
  240. package/dist/Table/BaseTable.js +10 -2
  241. package/dist/Table/Table.d.ts.map +1 -1
  242. package/dist/Table/Table.js +3 -6
  243. package/dist/Table/TableRow.d.ts +16 -5
  244. package/dist/Table/TableRow.d.ts.map +1 -1
  245. package/dist/Table/TableRow.js +16 -5
  246. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  247. package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
  248. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  249. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
  250. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  251. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  252. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  253. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  254. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  255. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  256. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  257. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  258. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  259. package/dist/Table/plugins/selection/useTableSelection.js +19 -5
  260. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  261. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  262. package/dist/Table/types.d.ts +22 -4
  263. package/dist/Table/types.d.ts.map +1 -1
  264. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  265. package/dist/Table/useBaseTablePlugins.js +5 -0
  266. package/dist/Text/Text.d.ts.map +1 -1
  267. package/dist/Text/Text.js +6 -2
  268. package/dist/TextArea/TextArea.d.ts.map +1 -1
  269. package/dist/TextArea/TextArea.js +9 -3
  270. package/dist/TextInput/TextInput.d.ts.map +1 -1
  271. package/dist/TextInput/TextInput.js +3 -2
  272. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  273. package/dist/TimeInput/TimeInput.js +3 -2
  274. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  275. package/dist/Timestamp/Timestamp.js +5 -3
  276. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  277. package/dist/Toast/ToastViewport.js +27 -8
  278. package/dist/Token/TokenLink.d.ts.map +1 -1
  279. package/dist/Token/TokenLink.js +2 -2
  280. package/dist/Tokenizer/Tokenizer.d.ts +3 -1
  281. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  282. package/dist/Tokenizer/Tokenizer.js +2 -0
  283. package/dist/Tooltip/Tooltip.d.ts +5 -0
  284. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  285. package/dist/Tooltip/useTooltip.d.ts +5 -0
  286. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  287. package/dist/Tooltip/useTooltip.js +39 -24
  288. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  289. package/dist/TopNav/TopNavHeading.js +5 -4
  290. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  291. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  292. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  293. package/dist/TopNav/TopNavMenu.js +4 -3
  294. package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
  295. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  296. package/dist/Typeahead/BaseTypeahead.js +68 -29
  297. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  298. package/dist/Typeahead/Typeahead.js +3 -2
  299. package/dist/astryx.css +98 -7
  300. package/dist/hooks/index.d.ts +1 -0
  301. package/dist/hooks/index.d.ts.map +1 -1
  302. package/dist/hooks/index.js +1 -0
  303. package/dist/hooks/useFocusTrap.d.ts +7 -4
  304. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  305. package/dist/hooks/useFocusTrap.js +60 -95
  306. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  307. package/dist/hooks/useHotkeys.js +3 -18
  308. package/dist/hooks/useMergedRefs.d.ts +18 -0
  309. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  310. package/dist/hooks/useMergedRefs.js +25 -0
  311. package/dist/index.d.ts +1 -0
  312. package/dist/index.d.ts.map +1 -1
  313. package/dist/index.js +1 -0
  314. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  315. package/dist/theme/derivedVarRegistry.js +24 -4
  316. package/dist/theme/syntax/tokens.d.ts +1 -1
  317. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  318. package/dist/theme/syntax/tokens.js +5 -2
  319. package/dist/utils/groupItems.d.ts +5 -1
  320. package/dist/utils/groupItems.d.ts.map +1 -1
  321. package/dist/utils/groupItems.js +9 -9
  322. package/dist/utils/index.d.ts +1 -1
  323. package/dist/utils/index.d.ts.map +1 -1
  324. package/dist/utils/isApplePlatform.d.ts +18 -0
  325. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  326. package/dist/utils/isApplePlatform.js +37 -0
  327. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  328. package/dist/utils/sharedResizeObserver.js +10 -1
  329. package/dist/utils/timeParser.d.ts +1 -1
  330. package/dist/utils/timeParser.d.ts.map +1 -1
  331. package/dist/utils/timeParser.js +26 -12
  332. package/locales/en.json +154 -10
  333. package/locales/pseudo.json +108 -0
  334. package/package.json +8 -3
  335. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  336. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  337. package/src/AlertDialog/AlertDialog.tsx +62 -20
  338. package/src/AppShell/AppShell.tsx +3 -2
  339. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  340. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  341. package/src/AspectRatio/AspectRatio.tsx +40 -1
  342. package/src/Avatar/Avatar.doc.mjs +14 -3
  343. package/src/Avatar/Avatar.test.tsx +97 -0
  344. package/src/Avatar/Avatar.tsx +125 -52
  345. package/src/Avatar/index.ts +2 -2
  346. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  347. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  348. package/src/AvatarGroup/AvatarGroup.tsx +15 -6
  349. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  350. package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
  351. package/src/Banner/Banner.doc.mjs +13 -11
  352. package/src/Banner/Banner.test.tsx +102 -15
  353. package/src/Banner/Banner.tsx +72 -25
  354. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  355. package/src/BottomSheet/BottomSheet.tsx +17 -4
  356. package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
  357. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  358. package/src/Button/Button.doc.mjs +24 -1
  359. package/src/Button/Button.test.tsx +32 -4
  360. package/src/Button/Button.tsx +12 -5
  361. package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
  362. package/src/ButtonGroup/ButtonGroup.test.tsx +404 -1
  363. package/src/ButtonGroup/ButtonGroup.tsx +23 -5
  364. package/src/Calendar/Calendar.doc.mjs +4 -3
  365. package/src/Calendar/Calendar.test.tsx +103 -0
  366. package/src/Calendar/Calendar.tsx +19 -16
  367. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  368. package/src/Calendar/getInitialFocusDate.ts +93 -0
  369. package/src/Calendar/styles.ts +49 -31
  370. package/src/Card/Card.doc.mjs +10 -7
  371. package/src/Card/Card.test.tsx +44 -19
  372. package/src/Card/Card.tsx +12 -32
  373. package/src/Carousel/Carousel.tsx +3 -2
  374. package/src/Chat/ChatComposerInput.tsx +5 -1
  375. package/src/Chat/ChatLayout.tsx +3 -2
  376. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  377. package/src/Chat/ChatMessageList.test.tsx +46 -0
  378. package/src/Chat/ChatMessageList.tsx +28 -4
  379. package/src/Chat/ChatTokenizedText.tsx +17 -10
  380. package/src/Chat/useChatComposerTokens.ts +1 -1
  381. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  382. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  383. package/src/CheckboxInput/CheckboxInput.tsx +8 -2
  384. package/src/ClickableCard/ClickableCard.tsx +3 -2
  385. package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
  386. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  387. package/src/CodeBlock/CodeBlock.tsx +20 -4
  388. package/src/CodeBlock/highlightRanges.ts +1 -1
  389. package/src/CodeBlock/highlightStyles.ts +13 -13
  390. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  391. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  392. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  393. package/src/ContextMenu/ContextMenu.tsx +4 -3
  394. package/src/DateInput/DateInput.doc.mjs +16 -0
  395. package/src/DateInput/DateInput.tsx +55 -2
  396. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  397. package/src/DateInput/NativeDateField.test.tsx +635 -0
  398. package/src/DateInput/NativeDateField.tsx +641 -0
  399. package/src/DateInput/TouchDateField.tsx +108 -24
  400. package/src/DateInput/index.ts +1 -0
  401. package/src/DateInput/nativeDateSegments.ts +127 -0
  402. package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
  403. package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
  404. package/src/DateTimeInput/DateTimeInput.tsx +556 -24
  405. package/src/DateTimeInput/index.ts +1 -0
  406. package/src/Dialog/Dialog.doc.mjs +8 -3
  407. package/src/Dialog/Dialog.test.tsx +429 -2
  408. package/src/Dialog/Dialog.tsx +133 -58
  409. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  410. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
  411. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
  412. package/src/Field/Field.doc.mjs +13 -2
  413. package/src/Field/FieldLabel.test.tsx +29 -0
  414. package/src/Field/FieldLabel.tsx +7 -0
  415. package/src/FileInput/FileInput.tsx +3 -2
  416. package/src/Heading/Heading.test.tsx +23 -1
  417. package/src/Heading/Heading.tsx +6 -2
  418. package/src/HoverCard/HoverCard.doc.mjs +13 -2
  419. package/src/HoverCard/HoverCard.test.tsx +154 -4
  420. package/src/HoverCard/HoverCard.tsx +143 -3
  421. package/src/HoverCard/useHoverCard.tsx +104 -33
  422. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  423. package/src/Indicator/Indicator.doc.mjs +2 -0
  424. package/src/Item/Item.tsx +5 -4
  425. package/src/Kbd/Kbd.tsx +2 -19
  426. package/src/Layer/LayerDepthContext.tsx +62 -0
  427. package/src/Layer/index.ts +9 -0
  428. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  429. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  430. package/src/Layer/layerStack.ts +362 -0
  431. package/src/Layer/useLayer.test.tsx +62 -14
  432. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  433. package/src/Layer/useLayerDismissal.ts +173 -0
  434. package/src/Layout/Layout.doc.mjs +2 -2
  435. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  436. package/src/Lightbox/Lightbox.tsx +124 -102
  437. package/src/Link/Link.doc.mjs +39 -0
  438. package/src/Markdown/Markdown.doc.mjs +5 -0
  439. package/src/Markdown/Markdown.tsx +9 -4
  440. package/src/Markdown/incremental.test.ts +16 -2
  441. package/src/Markdown/index.ts +1 -0
  442. package/src/Markdown/parser.perf.test.ts +96 -1
  443. package/src/Markdown/parser.test.ts +178 -2
  444. package/src/Markdown/parser.ts +253 -32
  445. package/src/MobileNav/MobileNav.tsx +62 -36
  446. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  447. package/src/MultiSelector/MultiSelector.doc.mjs +49 -1
  448. package/src/MultiSelector/MultiSelector.test.tsx +277 -0
  449. package/src/MultiSelector/MultiSelector.tsx +142 -11
  450. package/src/MultiSelector/index.ts +1 -0
  451. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  452. package/src/NavIcon/NavIcon.test.tsx +9 -0
  453. package/src/NavIcon/NavIcon.tsx +5 -1
  454. package/src/NavMenu/NavHeadingMenu.tsx +3 -2
  455. package/src/NumberInput/NumberInput.doc.mjs +31 -7
  456. package/src/NumberInput/NumberInput.test.tsx +436 -8
  457. package/src/NumberInput/NumberInput.tsx +62 -114
  458. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  459. package/src/NumberInput/numberInputCommit.ts +103 -0
  460. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  461. package/src/NumberInput/numberParser.test.ts +222 -0
  462. package/src/NumberInput/numberParser.ts +403 -0
  463. package/src/Outline/Outline.tsx +3 -2
  464. package/src/OverflowList/OverflowList.tsx +3 -2
  465. package/src/Overlay/Overlay.tsx +3 -2
  466. package/src/Pagination/Pagination.test.tsx +3 -2
  467. package/src/Popover/usePopover.tsx +31 -28
  468. package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
  469. package/src/PowerSearch/PowerSearch.test.tsx +240 -1
  470. package/src/PowerSearch/PowerSearch.tsx +34 -5
  471. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +288 -0
  472. package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
  473. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +111 -1
  474. package/src/PowerSearch/PowerSearchValueEditor.tsx +124 -10
  475. package/src/PowerSearch/types.ts +2 -0
  476. package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
  477. package/src/PowerSearch/usePowerSearchSource.ts +13 -3
  478. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  479. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  480. package/src/ProgressBar/ProgressBar.tsx +28 -8
  481. package/src/Resizable/ResizeHandle.tsx +3 -2
  482. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  483. package/src/SelectableCard/SelectableCard.tsx +3 -2
  484. package/src/Selector/Selector.doc.mjs +26 -1
  485. package/src/Selector/Selector.test.tsx +311 -1
  486. package/src/Selector/Selector.tsx +139 -16
  487. package/src/SideNav/SideNav.doc.mjs +6 -6
  488. package/src/SideNav/SideNav.tsx +4 -2
  489. package/src/SideNav/SideNavHeading.tsx +12 -12
  490. package/src/SideNav/SideNavItem.tsx +4 -2
  491. package/src/Slider/Slider.test.tsx +106 -1
  492. package/src/Slider/Slider.tsx +55 -3
  493. package/src/Spinner/Spinner.test.tsx +147 -1
  494. package/src/Spinner/Spinner.tsx +120 -101
  495. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  496. package/src/StatusDot/StatusDot.test.tsx +9 -0
  497. package/src/StatusDot/StatusDot.tsx +7 -1
  498. package/src/Stepper/Step.doc.mjs +98 -0
  499. package/src/Stepper/Step.tsx +1638 -0
  500. package/src/Stepper/StepStatus.ts +26 -0
  501. package/src/Stepper/Stepper.doc.mjs +370 -0
  502. package/src/Stepper/Stepper.test.tsx +1024 -0
  503. package/src/Stepper/Stepper.tsx +258 -0
  504. package/src/Stepper/StepperContext.ts +71 -0
  505. package/src/Stepper/index.ts +18 -0
  506. package/src/Stepper/stepper.stylex.ts +19 -0
  507. package/src/Switch/Switch.doc.mjs +2 -0
  508. package/src/Switch/Switch.test.tsx +10 -0
  509. package/src/Switch/Switch.tsx +6 -2
  510. package/src/TabList/Tab.doc.mjs +13 -1
  511. package/src/TabList/Tab.tsx +67 -7
  512. package/src/TabList/TabList.doc.mjs +22 -6
  513. package/src/TabList/TabList.test.tsx +559 -0
  514. package/src/TabList/TabList.tsx +490 -22
  515. package/src/TabList/TabListContext.ts +13 -2
  516. package/src/TabList/TabMenu.tsx +3 -2
  517. package/src/TabList/index.ts +6 -2
  518. package/src/Table/BaseTable.tsx +12 -4
  519. package/src/Table/Table.doc.mjs +9 -2
  520. package/src/Table/Table.test.tsx +132 -14
  521. package/src/Table/Table.tsx +3 -8
  522. package/src/Table/TableBody.doc.mjs +40 -0
  523. package/src/Table/TableFooter.doc.mjs +40 -0
  524. package/src/Table/TableHeader.doc.mjs +40 -0
  525. package/src/Table/TableRow.tsx +16 -5
  526. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  527. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  528. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  529. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  530. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
  531. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  532. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  533. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  534. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  535. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  536. package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
  537. package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
  538. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  539. package/src/Table/types.ts +22 -4
  540. package/src/Table/useBaseTablePlugins.ts +5 -0
  541. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  542. package/src/Table/useTablePagination.doc.mjs +7 -0
  543. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  544. package/src/Table/useTableSelection.doc.mjs +31 -0
  545. package/src/Text/Text.test.tsx +23 -1
  546. package/src/Text/Text.tsx +6 -2
  547. package/src/TextArea/TextArea.doc.mjs +8 -2
  548. package/src/TextArea/TextArea.test.tsx +11 -0
  549. package/src/TextArea/TextArea.tsx +15 -8
  550. package/src/TextInput/TextInput.doc.mjs +10 -0
  551. package/src/TextInput/TextInput.tsx +3 -2
  552. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  553. package/src/TimeInput/TimeInput.tsx +2 -2
  554. package/src/Timestamp/Timestamp.test.tsx +18 -0
  555. package/src/Timestamp/Timestamp.tsx +4 -2
  556. package/src/Toast/Toast.doc.mjs +6 -0
  557. package/src/Toast/ToastViewport.tsx +17 -1
  558. package/src/Token/TokenLink.tsx +2 -2
  559. package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
  560. package/src/Tokenizer/Tokenizer.tsx +4 -0
  561. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  562. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  563. package/src/Tooltip/Tooltip.test.tsx +32 -0
  564. package/src/Tooltip/Tooltip.tsx +5 -0
  565. package/src/Tooltip/useTooltip.tsx +47 -24
  566. package/src/TopNav/TopNavHeading.tsx +5 -4
  567. package/src/TopNav/TopNavMegaMenu.tsx +3 -2
  568. package/src/TopNav/TopNavMenu.tsx +4 -3
  569. package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
  570. package/src/Typeahead/BaseTypeahead.tsx +85 -33
  571. package/src/Typeahead/Typeahead.doc.mjs +5 -0
  572. package/src/Typeahead/Typeahead.test.tsx +49 -0
  573. package/src/Typeahead/Typeahead.tsx +3 -2
  574. package/src/hooks/index.ts +2 -0
  575. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  576. package/src/hooks/useFocusTrap.test.tsx +14 -0
  577. package/src/hooks/useFocusTrap.ts +62 -111
  578. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  579. package/src/hooks/useHotkeys.ts +3 -18
  580. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  581. package/src/hooks/useMergedRefs.test.tsx +62 -0
  582. package/src/hooks/useMergedRefs.ts +36 -0
  583. package/src/index.ts +1 -0
  584. package/src/raw-import.d.ts +14 -0
  585. package/src/theme/MediaTheme.doc.mjs +5 -5
  586. package/src/theme/derivedVarRegistry.test.ts +19 -3
  587. package/src/theme/derivedVarRegistry.ts +23 -4
  588. package/src/theme/generateThemeRules.test.ts +37 -0
  589. package/src/theme/syntax/tokens.ts +5 -2
  590. package/src/utils/groupItems.ts +12 -6
  591. package/src/utils/index.ts +1 -1
  592. package/src/utils/isApplePlatform.test.ts +61 -0
  593. package/src/utils/isApplePlatform.ts +37 -0
  594. package/src/utils/sharedResizeObserver.ts +10 -2
  595. package/src/utils/timeParser.test.ts +6 -1
  596. package/src/utils/timeParser.ts +35 -13
  597. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -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';
@@ -263,6 +267,58 @@ describe('Calendar', () => {
263
267
  expect(day15).not.toBeDisabled();
264
268
  });
265
269
 
270
+ // ─── Initial Visible Month ───────────────────────────────────
271
+
272
+ describe('opens on a month inside the min/max window', () => {
273
+ beforeEach(() => {
274
+ vi.useFakeTimers({toFake: ['Date']});
275
+ vi.setSystemTime(new Date(2026, 7, 21, 12, 0, 0));
276
+ });
277
+ afterEach(() => {
278
+ vi.useRealTimers();
279
+ });
280
+
281
+ it('opens on today when today is inside the window', () => {
282
+ render(<Calendar min="2026-01-01" max="2026-12-31" />);
283
+
284
+ expect(screen.getByText('August 2026')).toBeInTheDocument();
285
+ });
286
+
287
+ it('opens on min when the window is entirely in the future', () => {
288
+ render(<Calendar min="2027-03-04" max="2027-06-30" />);
289
+
290
+ expect(screen.getByText('March 2027')).toBeInTheDocument();
291
+ expect(getDayButton(4, 'March', 2027)).not.toBeDisabled();
292
+ });
293
+
294
+ it('opens on max when the window is entirely in the past', () => {
295
+ render(<Calendar min="2019-01-01" max="2019-04-30" />);
296
+
297
+ expect(screen.getByText('April 2019')).toBeInTheDocument();
298
+ expect(getDayButton(30, 'April', 2019)).not.toBeDisabled();
299
+ });
300
+
301
+ it('keeps max in the last pane in the two-month layout', () => {
302
+ render(<Calendar numberOfMonths={2} min="2019-01-01" max="2019-04-30" />);
303
+
304
+ expect(screen.getByText('March 2019 – April 2019')).toBeInTheDocument();
305
+ });
306
+
307
+ it('still honors an explicit focusDate outside the window', () => {
308
+ render(
309
+ <Calendar focusDate="2026-01-01" min="2027-03-04" max="2027-06-30" />,
310
+ );
311
+
312
+ expect(screen.getByText('January 2026')).toBeInTheDocument();
313
+ });
314
+
315
+ it('still opens on the selected value outside the window', () => {
316
+ render(<Calendar defaultValue="2031-07-04" min="2019-01-01" />);
317
+
318
+ expect(screen.getByText('July 2031')).toBeInTheDocument();
319
+ });
320
+ });
321
+
266
322
  it('respects custom dateConstraints', () => {
267
323
  // Only allow weekdays
268
324
  const isWeekday = (date: Date) => {
@@ -337,6 +393,33 @@ describe('Calendar', () => {
337
393
  expect(getDayButton(9)).not.toBeDisabled();
338
394
  });
339
395
 
396
+ it('announces the cleared range in the provider locale', async () => {
397
+ const user = userEvent.setup();
398
+
399
+ render(
400
+ <InternationalizationProvider locale="ja-JP">
401
+ <Calendar mode="range" focusDate="2026-01-01" />
402
+ </InternationalizationProvider>,
403
+ );
404
+
405
+ // The day button's own accessible name is already localized through the
406
+ // provider. The announcement has to use the same date string: formatting
407
+ // it without the locale silently falls back to the host locale, so a
408
+ // Japanese user hears an English date.
409
+ const anchor = document.querySelector<HTMLButtonElement>(
410
+ 'button[data-date="2026-01-10"]',
411
+ );
412
+ const localizedDate = anchor?.getAttribute('aria-label');
413
+ expect(localizedDate).toBeTruthy();
414
+
415
+ await user.click(anchor as HTMLButtonElement);
416
+ await user.click(anchor as HTMLButtonElement);
417
+
418
+ await waitFor(() => {
419
+ expect(politeRegion()?.textContent).toContain(localizedDate);
420
+ });
421
+ });
422
+
340
423
  it('does not apply range-span constraints in single mode', async () => {
341
424
  const user = userEvent.setup();
342
425
 
@@ -1378,3 +1461,23 @@ describe('Calendar', () => {
1378
1461
  });
1379
1462
  });
1380
1463
  });
1464
+
1465
+ // jsdom cannot emulate forced-colors rendering, so this asserts that the
1466
+ // compiled output includes the forced-colors rules; visual behavior needs
1467
+ // manual verification under Windows High Contrast.
1468
+ describe('forced colors (WCAG 1.4.11)', () => {
1469
+ it('compiles a forced-colors fill so the selected date survives Windows High Contrast', () => {
1470
+ render(
1471
+ <Calendar mode="single" value="2026-01-15" focusDate="2026-01-01" />,
1472
+ );
1473
+
1474
+ const css = getForcedColorsRules();
1475
+ // Without these the accent fill is stripped and the selected date renders
1476
+ // identically to every other day in the month.
1477
+ expect(css).toContain('background-color: highlight;');
1478
+ expect(css).toContain('color: highlighttext;');
1479
+ // A <button> keeps the native ButtonFace surface and ignores the authored
1480
+ // Highlight fill unless it opts out of UA remapping.
1481
+ expect(getAllInjectedCss()).toContain('forced-color-adjust: none;');
1482
+ });
1483
+ });
@@ -11,6 +11,7 @@
11
11
  *
12
12
  * SYNC: When modified, update these files to stay in sync:
13
13
  * - /packages/core/src/Calendar/Calendar.doc.mjs (props table, features, implementation notes)
14
+ * - /packages/core/src/Calendar/getInitialFocusDate.ts (which month the calendar opens on)
14
15
  * - /packages/core/src/Calendar/Calendar.test.tsx (tests for new/changed behavior)
15
16
  * - /packages/core/src/Calendar/index.ts (exports if types change)
16
17
  * - /apps/storybook/stories/Calendar.stories.tsx (storybook stories)
@@ -60,6 +61,7 @@ import {
60
61
  } from '../utils/plainDate';
61
62
  import {mergeProps, composeEventHandlers, rtlStyles} from '../utils';
62
63
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
64
+ import {getInitialFocusDate} from './getInitialFocusDate';
63
65
  import {
64
66
  computeDayCellState,
65
67
  computeRangeRounding,
@@ -142,7 +144,9 @@ interface CalendarBaseProps extends Omit<
142
144
 
143
145
  /**
144
146
  * Controlled focus date (which month is visible).
145
- * If not provided, defaults to selected date or today.
147
+ * If not provided, defaults to the selected date, else today clamped into
148
+ * the `min`/`max` window (so a window that excludes today opens on the
149
+ * bound nearest to it, not on an all-disabled month).
146
150
  */
147
151
  focusDate?: ISODateString;
148
152
 
@@ -277,20 +281,19 @@ export function Calendar({ref, ...props}: CalendarProps) {
277
281
  // Determine effective value
278
282
  const effectiveValue = value !== undefined ? value : internalValue;
279
283
 
280
- // Focus date state (which month is visible)
281
- const [internalFocusDate, setInternalFocusDate] = useState<PlainDate>(() => {
282
- if (focusDateProp) {
283
- return plainDateFromISO(focusDateProp);
284
- }
285
- if (effectiveValue) {
286
- if (typeof effectiveValue === 'string') {
287
- return plainDateFromISO(effectiveValue);
288
- } else {
289
- return plainDateFromISO(effectiveValue.start);
290
- }
291
- }
292
- return plainDateToday();
293
- });
284
+ // Focus date state (which month is visible). Falls back to today, clamped
285
+ // into the min/max window so a window that doesn't contain today doesn't
286
+ // open on an all-disabled month.
287
+ const [internalFocusDate, setInternalFocusDate] = useState<PlainDate>(() =>
288
+ getInitialFocusDate({
289
+ focusDate: focusDateProp,
290
+ value: effectiveValue,
291
+ min,
292
+ max,
293
+ numberOfMonths,
294
+ today,
295
+ }),
296
+ );
294
297
 
295
298
  // Use controlled focusDate if callback is provided, otherwise use internal state
296
299
  const isControlledFocus =
@@ -459,7 +462,7 @@ export function Calendar({ref, ...props}: CalendarProps) {
459
462
  setRangeSelectionStart(null);
460
463
  announce(
461
464
  t('@astryx.calendar.rangeClearedAnnounce', {
462
- date: plainDateFormat(date, DATE_FORMAT_WITH_WEEKDAY),
465
+ date: plainDateFormat(date, DATE_FORMAT_WITH_WEEKDAY, locale),
463
466
  }),
464
467
  );
465
468
  return;
@@ -0,0 +1,94 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file getInitialFocusDate.test.ts
5
+ * @input Uses vitest
6
+ * @output Test suite for getInitialFocusDate
7
+ * @position Tests for getInitialFocusDate.ts
8
+ *
9
+ * SYNC: When getInitialFocusDate.ts changes, update tests accordingly
10
+ */
11
+
12
+ import {describe, it, expect} from 'vitest';
13
+ import {getInitialFocusDate} from './getInitialFocusDate';
14
+ import {plainDateFromISO, plainDateToISO} from '../utils/plainDate';
15
+
16
+ const TODAY = plainDateFromISO('2026-08-21');
17
+
18
+ function focusISO(options: Partial<Parameters<typeof getInitialFocusDate>[0]>) {
19
+ return plainDateToISO(
20
+ getInitialFocusDate({numberOfMonths: 1, today: TODAY, ...options}),
21
+ );
22
+ }
23
+
24
+ describe('getInitialFocusDate', () => {
25
+ it('opens on today when there are no bounds', () => {
26
+ expect(focusISO({})).toBe('2026-08-21');
27
+ });
28
+
29
+ it('opens on today when today is inside the min/max window', () => {
30
+ expect(focusISO({min: '2026-01-01', max: '2026-12-31'})).toBe('2026-08-21');
31
+ });
32
+
33
+ it('treats the bounds as inclusive', () => {
34
+ expect(focusISO({min: '2026-08-21'})).toBe('2026-08-21');
35
+ expect(focusISO({max: '2026-08-21'})).toBe('2026-08-21');
36
+ });
37
+
38
+ it('opens on min when the whole window is in the future', () => {
39
+ expect(focusISO({min: '2027-03-04', max: '2027-06-30'})).toBe('2027-03-04');
40
+ });
41
+
42
+ it('opens on max when the whole window is in the past', () => {
43
+ expect(focusISO({min: '2019-01-01', max: '2019-04-30'})).toBe('2019-04-01');
44
+ });
45
+
46
+ it('clamps against a one-sided min', () => {
47
+ expect(focusISO({min: '2030-05-17'})).toBe('2030-05-17');
48
+ });
49
+
50
+ it('clamps against a one-sided max', () => {
51
+ expect(focusISO({max: '2020-02-09'})).toBe('2020-02-01');
52
+ });
53
+
54
+ it('lands max in the last pane in the two-month layout', () => {
55
+ // Opening on max's month would spend the second pane entirely
56
+ // out of bounds, so the window's end sits on the right instead.
57
+ expect(focusISO({max: '2020-02-09', numberOfMonths: 2})).toBe('2020-01-01');
58
+ });
59
+
60
+ it('does not shift the two-month layout back past min', () => {
61
+ expect(
62
+ focusISO({min: '2020-02-03', max: '2020-02-09', numberOfMonths: 2}),
63
+ ).toBe('2020-02-03');
64
+ });
65
+
66
+ it('prefers the selected value over the bounds', () => {
67
+ expect(focusISO({value: '2031-07-04', min: '2019-01-01'})).toBe(
68
+ '2031-07-04',
69
+ );
70
+ });
71
+
72
+ it('uses a range value start as the visible month', () => {
73
+ expect(focusISO({value: {start: '2019-03-08', end: '2019-03-19'}})).toBe(
74
+ '2019-03-08',
75
+ );
76
+ });
77
+
78
+ it('prefers an explicit focusDate over everything else', () => {
79
+ expect(
80
+ focusISO({
81
+ focusDate: '2015-11-02',
82
+ value: '2031-07-04',
83
+ min: '2026-01-01',
84
+ max: '2026-12-31',
85
+ }),
86
+ ).toBe('2015-11-02');
87
+ });
88
+
89
+ it('prefers min when the bounds are inverted', () => {
90
+ // Degenerate input (min after max) — resolve it deterministically
91
+ // rather than reading the second bound off a contradiction.
92
+ expect(focusISO({min: '2027-01-01', max: '2020-01-01'})).toBe('2027-01-01');
93
+ });
94
+ });
@@ -0,0 +1,93 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file getInitialFocusDate.ts
5
+ * @input PlainDate utilities, min/max bounds, today
6
+ * @output Exports getInitialFocusDate — the month Calendar opens on
7
+ * @position Calendar-specific helper; used by Calendar.tsx
8
+ *
9
+ * SYNC: When modified, update:
10
+ * - /packages/core/src/Calendar/getInitialFocusDate.test.ts
11
+ * - /packages/core/src/Calendar/Calendar.tsx (the only caller)
12
+ */
13
+
14
+ import type {ISODateString, DateRange} from '../utils/dateTypes';
15
+ import {
16
+ type PlainDate,
17
+ plainDateFromISO,
18
+ plainDateSetFirstOfMonth,
19
+ plainDateAddMonths,
20
+ plainDateIsBefore,
21
+ plainDateIsAfter,
22
+ } from '../utils/plainDate';
23
+
24
+ export interface InitialFocusDateOptions {
25
+ /** Controlled visible month, if the consumer supplied one. */
26
+ focusDate?: ISODateString;
27
+ /** Selected value (single date or range), controlled or uncontrolled. */
28
+ value?: ISODateString | DateRange;
29
+ /** Earliest selectable date. */
30
+ min?: ISODateString;
31
+ /** Latest selectable date. */
32
+ max?: ISODateString;
33
+ /** How many month panes the calendar renders (1 or 2). */
34
+ numberOfMonths: number;
35
+ /** Today, injected so the caller keeps a single memoized source of "now". */
36
+ today: PlainDate;
37
+ }
38
+
39
+ /**
40
+ * Picks the date whose month the calendar opens on.
41
+ *
42
+ * An explicit `focusDate` wins, then the selected value — both are the
43
+ * consumer's own instruction about where to look, so neither is second-guessed
44
+ * against `min`/`max`.
45
+ *
46
+ * Otherwise the calendar opens on today, clamped into the `min`/`max` window.
47
+ * Without the clamp a window that doesn't contain today (a 2019 audit range, a
48
+ * booking window opening next spring) opened on today's month with every day
49
+ * disabled, leaving prev/next clicking as the only way in.
50
+ *
51
+ * When clamping forward to `min`, that month leads: the whole selectable window
52
+ * runs ahead of it. When clamping back to `max`, the last pane lands on `max`'s
53
+ * month instead — with `numberOfMonths={2}` opening on `[max, max + 1]` would
54
+ * spend half the calendar on a month that is entirely out of bounds. That
55
+ * shift never crosses `min`'s month.
56
+ */
57
+ export function getInitialFocusDate(
58
+ options: InitialFocusDateOptions,
59
+ ): PlainDate {
60
+ const {focusDate, value, min, max, numberOfMonths, today} = options;
61
+
62
+ if (focusDate) {
63
+ return plainDateFromISO(focusDate);
64
+ }
65
+
66
+ if (value) {
67
+ return plainDateFromISO(typeof value === 'string' ? value : value.start);
68
+ }
69
+
70
+ const minDate = min ? plainDateFromISO(min) : null;
71
+ const maxDate = max ? plainDateFromISO(max) : null;
72
+
73
+ if (minDate && plainDateIsBefore(today, minDate)) {
74
+ return minDate;
75
+ }
76
+
77
+ if (maxDate && plainDateIsAfter(today, maxDate)) {
78
+ const lastPaneOffset = Math.max(0, numberOfMonths - 1);
79
+ const shifted = plainDateAddMonths(
80
+ plainDateSetFirstOfMonth(maxDate),
81
+ -lastPaneOffset,
82
+ );
83
+ if (
84
+ minDate &&
85
+ plainDateIsBefore(shifted, plainDateSetFirstOfMonth(minDate))
86
+ ) {
87
+ return minDate;
88
+ }
89
+ return shifted;
90
+ }
91
+
92
+ return today;
93
+ }
@@ -51,19 +51,12 @@ export const calendarStyles = stylex.create({
51
51
  },
52
52
  monthsContainer: {
53
53
  display: 'flex',
54
+ // Wraps rather than overflowing: two months side by side need ~488px, so
55
+ // an unwrapped row scrolls the document sideways below that and puts the
56
+ // next-month button off-viewport (WCAG 1.4.10). Above 488px nothing moves.
57
+ flexWrap: 'wrap',
54
58
  gap: spacingVars['--spacing-4'],
55
59
  },
56
- srOnly: {
57
- position: 'absolute',
58
- width: '1px',
59
- height: '1px',
60
- padding: 0,
61
- margin: '-1px',
62
- overflow: 'hidden',
63
- clip: 'rect(0, 0, 0, 0)',
64
- whiteSpace: 'nowrap',
65
- borderWidth: 0,
66
- },
67
60
  /**
68
61
  * Wrapper for the month nav chevrons. RTL mirroring is applied by
69
62
  * composing the shared `rtlStyles.mirror` transform onto this wrapper
@@ -123,6 +116,17 @@ export const monthGridStyles = stylex.create({
123
116
  // Day Cell Styles - Structural (layout, sizing, positioning)
124
117
  // =============================================================================
125
118
 
119
+ // Half the gap between the day button and its cell — (--size-element-md minus
120
+ // --size-element-sm) / 2 — so the band's rounded caps line up with the button
121
+ // and the button's ::before bleeds out to meet its neighbour's. Deliberately a
122
+ // literal and NOT a spacing token: this is a layout value derived from the two
123
+ // size tokens, and pinning it to --spacing-0-5 desynchronises it from them
124
+ // (matcha sets that step to 3px, which overlaps adjacent days' hit targets by
125
+ // 2px). Deriving it with calc() from the size tokens would be better still and
126
+ // would close butter's 4px dead gap; that needs its own measured change.
127
+ const BAND_INSET = '2px';
128
+ const HIT_BLEED = '-2px';
129
+
126
130
  export const dayCellStyles = stylex.create({
127
131
  // Cell container
128
132
  cell: {
@@ -137,53 +141,53 @@ export const dayCellStyles = stylex.create({
137
141
  // Range background - structural positioning
138
142
  rangeBg: {
139
143
  position: 'absolute',
140
- top: '2px',
141
- bottom: '2px',
144
+ top: BAND_INSET,
145
+ bottom: BAND_INSET,
142
146
  insetInlineStart: 0,
143
147
  insetInlineEnd: 0,
144
148
  },
145
149
  rangeBgRadiusStart: {
146
- insetInlineStart: '2px',
150
+ insetInlineStart: BAND_INSET,
147
151
  borderStartStartRadius: radiusVars['--radius-full'],
148
152
  borderEndStartRadius: radiusVars['--radius-full'],
149
153
  },
150
154
  rangeBgRadiusEnd: {
151
- insetInlineEnd: '2px',
155
+ insetInlineEnd: BAND_INSET,
152
156
  borderStartEndRadius: radiusVars['--radius-full'],
153
157
  borderEndEndRadius: radiusVars['--radius-full'],
154
158
  },
155
159
  rangeInsetStart: {
156
- insetInlineStart: '2px',
160
+ insetInlineStart: BAND_INSET,
157
161
  },
158
162
  rangeInsetEnd: {
159
- insetInlineEnd: '2px',
163
+ insetInlineEnd: BAND_INSET,
160
164
  },
161
165
 
162
166
  // Preview background - structural positioning
163
167
  previewBg: {
164
168
  position: 'absolute',
165
- top: '2px',
166
- bottom: '2px',
169
+ top: BAND_INSET,
170
+ bottom: BAND_INSET,
167
171
  insetInlineStart: 0,
168
172
  insetInlineEnd: 0,
169
173
  },
170
174
  previewBgRadiusStart: {
171
- insetInlineStart: '2px',
175
+ insetInlineStart: BAND_INSET,
172
176
  borderStartStartRadius: radiusVars['--radius-full'],
173
177
  borderEndStartRadius: radiusVars['--radius-full'],
174
178
  },
175
179
  previewBgRadiusEnd: {
176
- insetInlineEnd: '2px',
180
+ insetInlineEnd: BAND_INSET,
177
181
  borderStartEndRadius: radiusVars['--radius-full'],
178
182
  borderEndEndRadius: radiusVars['--radius-full'],
179
183
  },
180
184
  previewStart: {
181
- insetInlineStart: '2px',
185
+ insetInlineStart: BAND_INSET,
182
186
  borderStartStartRadius: radiusVars['--radius-full'],
183
187
  borderEndStartRadius: radiusVars['--radius-full'],
184
188
  },
185
189
  previewEnd: {
186
- insetInlineEnd: '2px',
190
+ insetInlineEnd: BAND_INSET,
187
191
  borderStartEndRadius: radiusVars['--radius-full'],
188
192
  borderEndEndRadius: radiusVars['--radius-full'],
189
193
  },
@@ -195,7 +199,7 @@ export const dayCellStyles = stylex.create({
195
199
  display: 'flex',
196
200
  alignItems: 'center',
197
201
  justifyContent: 'center',
198
- borderRadius: '50%',
202
+ borderRadius: radiusVars['--radius-full'],
199
203
  borderWidth: 0,
200
204
  borderStyle: 'none',
201
205
  cursor: {
@@ -213,14 +217,14 @@ export const dayCellStyles = stylex.create({
213
217
  },
214
218
  transitionDuration: durationVars['--duration-fast'],
215
219
  transitionTimingFunction: easeVars['--ease-standard'],
216
- // Expand hit target by 2px on each side to prevent gaps
220
+ // Expand hit target so adjacent days meet with no gap
217
221
  '::before': {
218
222
  content: '""',
219
223
  position: 'absolute',
220
- top: '-2px',
221
- insetInlineEnd: '-2px',
222
- bottom: '-2px',
223
- insetInlineStart: '-2px',
224
+ top: HIT_BLEED,
225
+ insetInlineEnd: HIT_BLEED,
226
+ bottom: HIT_BLEED,
227
+ insetInlineStart: HIT_BLEED,
224
228
  },
225
229
  },
226
230
 
@@ -280,8 +284,22 @@ export const dayCellTheme = stylex.create({
280
284
 
281
285
  // Selected state (single selection or range endpoints)
282
286
  daySelected: {
283
- backgroundColor: colorVars['--color-accent'],
284
- color: colorVars['--color-on-accent'],
287
+ // Forced colors (Windows High Contrast) strips the accent fill, which
288
+ // leaves the selected date looking exactly like every other day.
289
+ // Highlight/HighlightText is the platform convention for a selected
290
+ // control (WCAG 1.4.11), and `forced-color-adjust: none` is required
291
+ // because this is a <button>: the UA otherwise keeps the native
292
+ // ButtonFace surface and ignores the authored fill, the same trap
293
+ // ToggleButton documents.
294
+ forcedColorAdjust: 'none',
295
+ backgroundColor: {
296
+ default: colorVars['--color-accent'],
297
+ '@media (forced-colors: active)': 'Highlight',
298
+ },
299
+ color: {
300
+ default: colorVars['--color-on-accent'],
301
+ '@media (forced-colors: active)': 'HighlightText',
302
+ },
285
303
  backgroundImage: {
286
304
  default: null,
287
305
  ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
@@ -57,8 +57,9 @@ export const docs = {
57
57
  {
58
58
  name: 'padding',
59
59
  type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
60
- description: 'Internal padding using the spacing scale.',
61
- default: '4',
60
+ description:
61
+ "Internal padding using the spacing scale. Omit it and the card takes the theme's card padding rather than a step, so passing a step is a decision to override the theme, not a way to restate the default.",
62
+ default: "the theme's card padding (spacing step 4 with no theme)",
62
63
  },
63
64
  {
64
65
  name: 'variant',
@@ -77,7 +78,6 @@ export const docs = {
77
78
  ],
78
79
  playground: {
79
80
  defaults: {
80
- padding: 4,
81
81
  children: {
82
82
  __element: 'VStack',
83
83
  props: {gap: 2},
@@ -91,7 +91,7 @@ export const docs = {
91
91
  theming: {
92
92
  container: true,
93
93
  targets: [
94
- {className: 'astryx-card', visualProps: ['variant']},
94
+ {className: 'astryx-card', visualProps: ['variant', 'elevation']},
95
95
  ],
96
96
  vars: [
97
97
  {name: '--_card-radius', description: 'Border radius of the card', default: 'var(--radius-container)', private: true},
@@ -135,16 +135,19 @@ export const docsZh = {
135
135
  {name: 'maxWidth', type: 'SizeValue', description: '卡片最大宽度。'},
136
136
  {name: 'minHeight', type: 'SizeValue', description: '卡片最小高度。'},
137
137
  {name: 'children', type: 'ReactNode', description: '在卡片内部渲染的内容。'},
138
- {name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: '使用间距比例的内边距。', default: '4'},
138
+ {name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: '使用间距比例的内边距。省略时,卡片采用主题的卡片内边距,而不是某个步进值;传入步进值意味着覆盖主题,而不是复述默认值。', default: "the theme's card padding (spacing step 4 with no theme)"},
139
+ {name: 'variant', type: "'default' | 'transparent' | 'muted' | 'blue' | 'cyan' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'teal' | 'yellow'", description: '背景颜色变体。`default` 使用标准卡片背景;`transparent` 完全去掉背景;`muted` 使用弱化卡片的柔和背景。非语义变体使用对应的 `--color-background-<name>` 令牌。', default: "'default'"},
139
140
  {name: 'elevation', type: "'none' | 'low' | 'med' | 'high'", description: '静止阴影深度。`none` 为扁平;`low`/`med`/`high` 对应阴影令牌比例。', default: "'none'"},
140
141
  ],
141
142
  theming: {
142
143
  container: true,
143
144
  targets: [
144
- {className: 'astryx-card', visualProps: ['variant']},
145
+ {className: 'astryx-card', visualProps: ['variant', 'elevation']},
145
146
  ],
146
147
  vars: [
147
148
  {name: '--_card-radius', description: 'Border radius of the card', default: 'var(--radius-container)', private: true},
149
+ {name: '--_card-elevation', description: 'Resting shadow of the card, set from the elevation prop.', default: '0 0 transparent', private: true},
150
+ {name: '--_card-ring', description: 'Inset ring drawn in the card box-shadow list.', default: '0 0 transparent', private: true},
148
151
  ],
149
152
  derived: [
150
153
  {property: 'borderRadius', vars: ['--_card-radius']},
@@ -178,7 +181,7 @@ export const docsDense = {
178
181
  maxWidth: 'max card width',
179
182
  minHeight: 'min card height',
180
183
  children: 'content inside card',
181
- padding: 'internal padding via spacing scale',
184
+ padding: "internal padding via spacing scale; omitted = the theme's card padding, NOT a fixed step. Passing a step overrides the theme.",
182
185
  variant: 'background color variant; `default` = standard card bg, `transparent` = no background at all, `muted` = muted bg for de-emphasised cards; non-semantic variants use the corresponding `--color-background-<name>` token',
183
186
  elevation: 'resting shadow depth: none (flat) | low | med | high (shadow token scale). Raise only to float above content.',
184
187
  },