@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
@@ -0,0 +1,165 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file useFocusTrapEscapeShim.test.tsx
5
+ * @input Uses vitest, @testing-library/react, useFocusTrap, Dialog, Lightbox,
6
+ * MobileNav, Tooltip, Popover
7
+ * @output Tests that hasActiveFocusTrapEscape still means what it meant in
8
+ * 0.4.2 — an Escape-dismissible FOCUS TRAP is active, not "a layer is open"
9
+ * @position Testing; guards the deprecated public shim in useFocusTrap.ts
10
+ *
11
+ * The shim is public API. Its answer must not change now that Escape moved to
12
+ * the shared stack: `BottomSheetSwitcher` gates its own dismissal on it, so a
13
+ * shim that also counts tooltips, hover cards and dialogs tells the sheet a
14
+ * trap is above it when none is, and the sheet stops closing.
15
+ *
16
+ * SYNC: When useFocusTrap.ts changes, update tests to match new behavior
17
+ */
18
+
19
+ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
20
+ import {render} from '@testing-library/react';
21
+
22
+ import {hasActiveFocusTrapEscape, useFocusTrap} from './useFocusTrap';
23
+ import {Dialog} from '../Dialog/Dialog';
24
+ import {Lightbox} from '../Lightbox/Lightbox';
25
+ import {MobileNav} from '../MobileNav/MobileNav';
26
+ import {Popover} from '../Popover/Popover';
27
+ import {Tooltip} from '../Tooltip/Tooltip';
28
+ import {resetLayerStackForTests} from '../Layer/layerStack';
29
+
30
+ beforeEach(() => {
31
+ HTMLDialogElement.prototype.showModal = vi.fn(function (
32
+ this: HTMLDialogElement,
33
+ ) {
34
+ this.setAttribute('open', '');
35
+ });
36
+ HTMLDialogElement.prototype.close = vi.fn(function (this: HTMLDialogElement) {
37
+ this.removeAttribute('open');
38
+ });
39
+ });
40
+
41
+ afterEach(() => {
42
+ resetLayerStackForTests();
43
+ });
44
+
45
+ function Trap({
46
+ isActive = true,
47
+ hasEscape = true,
48
+ children,
49
+ }: {
50
+ isActive?: boolean;
51
+ hasEscape?: boolean;
52
+ children?: React.ReactNode;
53
+ }) {
54
+ const {containerRef} = useFocusTrap<HTMLDivElement>({
55
+ isActive,
56
+ onEscape: hasEscape ? () => {} : undefined,
57
+ });
58
+ return <div ref={containerRef}>{children}</div>;
59
+ }
60
+
61
+ describe('hasActiveFocusTrapEscape', () => {
62
+ it('is false with nothing mounted', () => {
63
+ expect(hasActiveFocusTrapEscape()).toBe(false);
64
+ });
65
+
66
+ it('is true for an active trap with an Escape handler', () => {
67
+ render(<Trap />);
68
+ expect(hasActiveFocusTrapEscape()).toBe(true);
69
+ });
70
+
71
+ it('is false for a trap with no Escape handler', () => {
72
+ render(<Trap hasEscape={false} />);
73
+ expect(hasActiveFocusTrapEscape()).toBe(false);
74
+ });
75
+
76
+ it('is false for an inactive trap', () => {
77
+ render(<Trap isActive={false} />);
78
+ expect(hasActiveFocusTrapEscape()).toBe(false);
79
+ });
80
+
81
+ it('is true for nested traps, and false again once both unmount', () => {
82
+ const {unmount} = render(
83
+ <Trap>
84
+ <Trap />
85
+ </Trap>,
86
+ );
87
+ expect(hasActiveFocusTrapEscape()).toBe(true);
88
+ unmount();
89
+ expect(hasActiveFocusTrapEscape()).toBe(false);
90
+ });
91
+
92
+ it('is true for an open Popover, which traps focus', () => {
93
+ render(
94
+ <Popover
95
+ isOpen={true}
96
+ onOpenChange={() => {}}
97
+ content="Popover body"
98
+ label="Popover">
99
+ <button type="button">Open</button>
100
+ </Popover>,
101
+ );
102
+ expect(hasActiveFocusTrapEscape()).toBe(true);
103
+ });
104
+
105
+ // The families below are all on the shared dismissal stack and none of them
106
+ // traps focus. Answering `true` for these is what broke the bottom sheet.
107
+ it('is false for an open Dialog', () => {
108
+ render(
109
+ <Dialog isOpen={true} onOpenChange={() => {}} aria-label="Dialog">
110
+ Body
111
+ </Dialog>,
112
+ );
113
+ expect(hasActiveFocusTrapEscape()).toBe(false);
114
+ });
115
+
116
+ it('is false for an open Lightbox', () => {
117
+ render(
118
+ <Lightbox
119
+ isOpen={true}
120
+ onOpenChange={() => {}}
121
+ media={{src: '/photo.jpg', alt: 'A photo'}}
122
+ />,
123
+ );
124
+ expect(hasActiveFocusTrapEscape()).toBe(false);
125
+ });
126
+
127
+ it('is false for an open MobileNav', () => {
128
+ render(
129
+ <MobileNav isOpen={true} onOpenChange={() => {}} label="Drawer">
130
+ <span>Nav</span>
131
+ </MobileNav>,
132
+ );
133
+ expect(hasActiveFocusTrapEscape()).toBe(false);
134
+ });
135
+
136
+ it('is false for a showing Tooltip', () => {
137
+ render(
138
+ <Tooltip content="Tip" isDefaultOpen={true}>
139
+ <button type="button">Trigger</button>
140
+ </Tooltip>,
141
+ );
142
+ expect(hasActiveFocusTrapEscape()).toBe(false);
143
+ });
144
+
145
+ it('is true for a Popover inside a Dialog, and false once the Popover closes', () => {
146
+ function Scene({isPopoverOpen}: {isPopoverOpen: boolean}) {
147
+ return (
148
+ <Dialog isOpen={true} onOpenChange={() => {}} aria-label="Dialog">
149
+ <Popover
150
+ isOpen={isPopoverOpen}
151
+ onOpenChange={() => {}}
152
+ content="Popover body"
153
+ label="Popover">
154
+ <button type="button">Open</button>
155
+ </Popover>
156
+ </Dialog>
157
+ );
158
+ }
159
+ const {rerender} = render(<Scene isPopoverOpen={true} />);
160
+ expect(hasActiveFocusTrapEscape()).toBe(true);
161
+
162
+ rerender(<Scene isPopoverOpen={false} />);
163
+ expect(hasActiveFocusTrapEscape()).toBe(false);
164
+ });
165
+ });
@@ -18,7 +18,8 @@
18
18
  * unless a hotkey opts in via `allowInInputs`.
19
19
  *
20
20
  * Platform-aware: `mod` maps to metaKey (⌘) on Apple platforms and
21
- * ctrlKey elsewhere — mirrors the detection used by Kbd.
21
+ * ctrlKey elsewhere, through the same isApplePlatform util Kbd reads, so
22
+ * displayed and handled shortcuts cannot disagree.
22
23
  *
23
24
  * SYNC: When modified, update:
24
25
  * - /packages/core/src/hooks/index.ts
@@ -26,6 +27,7 @@
26
27
  */
27
28
 
28
29
  import {useEffect, useRef} from 'react';
30
+ import {isApplePlatform} from '../utils/isApplePlatform';
29
31
 
30
32
  /**
31
33
  * A single keyboard shortcut registration.
@@ -71,23 +73,6 @@ const KEY_ALIASES: Record<string, string> = {
71
73
  plus: '+',
72
74
  };
73
75
 
74
- /**
75
- * Detects whether the current platform is macOS/iOS.
76
- * Prefers the User-Agent Client Hints API when available (modern Chrome/Edge),
77
- * falls back to navigator.platform (deprecated but universally supported).
78
- * Mirrors the detection used by Kbd so displayed and handled shortcuts agree.
79
- */
80
- function isApplePlatform(): boolean {
81
- if (typeof navigator === 'undefined') {
82
- return false;
83
- }
84
- const uaData = 'userAgentData' in navigator ? navigator.userAgentData : null;
85
- if (uaData && typeof uaData === 'object' && 'platform' in uaData) {
86
- return /mac/i.test((uaData as {platform: string}).platform ?? '');
87
- }
88
- return /Mac|iPhone|iPad|iPod/.test(navigator.platform ?? '');
89
- }
90
-
91
76
  /**
92
77
  * Whether the event target is a typing surface where global shortcuts
93
78
  * should stay silent by default.
@@ -0,0 +1,79 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('@astryxdesign/cli/authoring').HookDoc} */
4
+ export const docs = {
5
+ name: 'useMergedRefs',
6
+ displayName: 'useMergedRefs',
7
+ keywords: [
8
+ 'ref',
9
+ 'refs',
10
+ 'merge',
11
+ 'forwardRef',
12
+ 'callback ref',
13
+ 'stable ref',
14
+ ],
15
+ params: [
16
+ {
17
+ name: 'refs',
18
+ type: 'Array<Ref<T> | undefined>',
19
+ description: 'Up to six refs that should all receive the same element.',
20
+ required: true,
21
+ },
22
+ ],
23
+ returns: [
24
+ {
25
+ name: 'ref',
26
+ type: 'RefCallback<T>',
27
+ description:
28
+ 'A merged callback ref that remains stable until an input ref changes.',
29
+ },
30
+ ],
31
+ usage: {
32
+ description:
33
+ 'Combines multiple object or callback refs into one stable callback ref. Use it when a component must forward a consumer ref while also attaching internal refs. Unlike calling mergeRefs during render, the callback identity stays stable across unrelated rerenders, so React does not detach and reattach the element.',
34
+ bestPractices: [
35
+ {
36
+ guidance: true,
37
+ description:
38
+ 'Use useMergedRefs when one element must receive both a forwarded ref and one or more internal refs.',
39
+ },
40
+ {
41
+ guidance: false,
42
+ description:
43
+ 'Call mergeRefs directly in a JSX ref prop; that creates a new callback on every render and forces unnecessary detach and attach work.',
44
+ },
45
+ ],
46
+ },
47
+ relatedComponents: [],
48
+ relatedHooks: [],
49
+ importPath: '@astryxdesign/core/hooks',
50
+ category: 'utility',
51
+ };
52
+
53
+ /** @type {import('@astryxdesign/cli/authoring').HookTranslationDoc} */
54
+ export const docsDense = {
55
+ description:
56
+ 'Combines object/callback refs into one stable callback ref. Identity changes only when an input ref changes, avoiding detach/attach churn from inline mergeRefs calls.',
57
+ paramDescriptions: {
58
+ refs: 'refs that should all receive the same element.',
59
+ },
60
+ returnDescriptions: {
61
+ ref: 'stable merged callback ref; changes only when an input ref changes.',
62
+ },
63
+ usage: {
64
+ description:
65
+ 'Use when one element needs a forwarded consumer ref plus internal refs. Keeps the callback stable across unrelated rerenders.',
66
+ bestPractices: [
67
+ {
68
+ guidance: true,
69
+ description:
70
+ 'Use for a forwarded ref plus internal measurement, focus, or anchor refs.',
71
+ },
72
+ {
73
+ guidance: false,
74
+ description:
75
+ 'Call mergeRefs inline in JSX; it forces ref detach/attach on every render.',
76
+ },
77
+ ],
78
+ },
79
+ };
@@ -0,0 +1,62 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file useMergedRefs.test.tsx
5
+ * @input Uses vitest, @testing-library/react, useMergedRefs hook
6
+ * @output Unit tests for stable merged ref behavior
7
+ * @position Testing; validates useMergedRefs.ts
8
+ *
9
+ * SYNC: When useMergedRefs.ts changes, update tests to match new behavior
10
+ */
11
+
12
+ import {renderHook} from '@testing-library/react';
13
+ import {createRef} from 'react';
14
+ import {describe, expect, it, vi} from 'vitest';
15
+ import {useMergedRefs} from './useMergedRefs';
16
+
17
+ describe('useMergedRefs', () => {
18
+ it('forwards values to callback and object refs', () => {
19
+ const callbackRef = vi.fn();
20
+ const objectRef = createRef<HTMLDivElement>();
21
+ const {result} = renderHook(() =>
22
+ useMergedRefs<HTMLDivElement>(callbackRef, objectRef),
23
+ );
24
+ const element = document.createElement('div');
25
+
26
+ const cleanup = result.current(element);
27
+
28
+ expect(callbackRef).toHaveBeenCalledWith(element);
29
+ expect(objectRef.current).toBe(element);
30
+
31
+ cleanup?.();
32
+ expect(callbackRef).toHaveBeenLastCalledWith(null);
33
+ expect(objectRef.current).toBeNull();
34
+ });
35
+
36
+ it('keeps the merged callback stable when input refs are unchanged', () => {
37
+ const callbackRef = vi.fn();
38
+ const objectRef = createRef<HTMLDivElement>();
39
+ const {result, rerender} = renderHook(() =>
40
+ useMergedRefs<HTMLDivElement>(callbackRef, objectRef),
41
+ );
42
+ const first = result.current;
43
+
44
+ rerender();
45
+
46
+ expect(result.current).toBe(first);
47
+ });
48
+
49
+ it('updates the merged callback when an input ref changes', () => {
50
+ const firstRef = vi.fn();
51
+ const secondRef = vi.fn();
52
+ const {result, rerender} = renderHook(
53
+ ({ref}) => useMergedRefs<HTMLDivElement>(ref),
54
+ {initialProps: {ref: firstRef}},
55
+ );
56
+ const first = result.current;
57
+
58
+ rerender({ref: secondRef});
59
+
60
+ expect(result.current).not.toBe(first);
61
+ });
62
+ });
@@ -0,0 +1,36 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file useMergedRefs.ts
7
+ * @input React refs to combine into one stable callback ref
8
+ * @output Exports useMergedRefs
9
+ * @position Core hook; use when one element must receive multiple refs
10
+ *
11
+ * SYNC: When modified, update:
12
+ * - /packages/core/src/hooks/index.ts
13
+ * - /packages/core/src/hooks/useMergedRefs.doc.mjs
14
+ * - /packages/core/src/hooks/useMergedRefs.test.tsx
15
+ */
16
+
17
+ import {useMemo, type Ref, type RefCallback} from 'react';
18
+ import {mergeRefs} from '../utils/mergeRefs';
19
+
20
+ /**
21
+ * Combine up to six refs into a callback ref whose identity changes only when
22
+ * one of the input refs changes.
23
+ */
24
+ export function useMergedRefs<T>(
25
+ refA?: Ref<T>,
26
+ refB?: Ref<T>,
27
+ refC?: Ref<T>,
28
+ refD?: Ref<T>,
29
+ refE?: Ref<T>,
30
+ refF?: Ref<T>,
31
+ ): RefCallback<T> {
32
+ return useMemo(
33
+ () => mergeRefs(refA, refB, refC, refD, refE, refF),
34
+ [refA, refB, refC, refD, refE, refF],
35
+ );
36
+ }
package/src/index.ts CHANGED
@@ -55,6 +55,7 @@ export * from './NavIcon';
55
55
  export * from './NavMenu';
56
56
  export * from './Slider';
57
57
  export * from './Stack';
58
+ export * from './Stepper';
58
59
  export * from './Switch';
59
60
  export * from './DateInput';
60
61
  export * from './DateTimeInput';
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Ambient module declaration for Vite's `?raw` imports.
5
+ *
6
+ * numberParser.docblock.test.ts reads its own subject's source as text, to
7
+ * check the prose in it against the parser's behaviour. Vite serves that with
8
+ * the `?raw` query; without this declaration TypeScript fails with TS2307.
9
+ */
10
+
11
+ declare module '*?raw' {
12
+ const content: string;
13
+ export default content;
14
+ }
@@ -68,7 +68,7 @@ export const docs = {
68
68
  {
69
69
  guidance: true,
70
70
  description:
71
- 'Prefer mode="auto" when the surface color comes from a theme token. A token named "inverted" is not guaranteed to be inverted, and auto measures what was actually painted instead of trusting the name — including deciding that a surface needs no media context at all.',
71
+ 'Prefer mode="auto" when the surface color comes from a theme token. A token named "inverted" is not guaranteed to be inverted, and auto measures what was actually painted instead of trusting the name. It can even decide that a surface needs no media context at all.',
72
72
  },
73
73
  {
74
74
  guidance: true,
@@ -93,14 +93,14 @@ export const docs = {
93
93
  type: "'dark' | 'light' | 'auto' | 'off'",
94
94
  required: true,
95
95
  description:
96
- 'Surface luminance context: dark for content over dark backgrounds (light text, white-tinted interactions), light for content over light backgrounds (dark text, black-tinted interactions), auto to decide from the painted surface — no media context when the ambient text already reads on the surface (3:1), otherwise the side that reads better — and off to turn it off explicitly. The element renders either way, so a surface can switch contexts without remounting children.',
96
+ 'Surface luminance context: dark for content over dark backgrounds (light text, white-tinted interactions), light for content over light backgrounds (dark text, black-tinted interactions), auto to decide from the painted surface (no media context when the ambient text already reads on the surface at 3:1, otherwise the side that reads better), and off to turn it off explicitly. The element renders either way, so a surface can switch contexts without remounting children.',
97
97
  },
98
98
  {
99
99
  name: 'fallback',
100
100
  type: "'dark' | 'light'",
101
101
  default: "'dark'",
102
102
  description:
103
- 'Which side auto uses when the surface cannot be measured: during SSR, on the first client frame, and whenever the backdrop is not knowable from CSS — most often a background-image, whose pixels need sampling (useImageMode) rather than a computed style. Ignored unless mode is auto.',
103
+ 'Which side auto uses when the surface cannot be measured: during SSR, on the first client frame, and whenever the backdrop is not knowable from CSS, most often a background-image, whose pixels need sampling (useImageMode) rather than a computed style. Ignored unless mode is auto.',
104
104
  },
105
105
  {
106
106
  name: 'children',
@@ -126,7 +126,7 @@ export const docsDense = {
126
126
  {
127
127
  guidance: true,
128
128
  description:
129
- 'Prefer mode="auto" when surface color comes from a theme token — a token named "inverted" is not guaranteed to be; auto measures what was painted.',
129
+ 'Prefer mode="auto" when surface color comes from a theme token; a token named "inverted" is not guaranteed to be; auto measures what was painted.',
130
130
  },
131
131
  {
132
132
  guidance: true,
@@ -148,6 +148,6 @@ export const docsDense = {
148
148
  propDescriptions: {
149
149
  mode: 'surface luminance context: dark for content over dark backgrounds (light text, white-tinted interactions), light for content over light backgrounds (dark text, black-tinted interactions), auto to decide from painted surface (none if ambient text already reads at 3:1, else better-reading side), off to turn off explicitly (element still renders, so children never remount)',
150
150
  fallback:
151
- 'side auto uses when surface is unmeasurable (SSR, first frame, background-image — those need useImageMode sampling); ignored unless mode is auto',
151
+ 'side auto uses when surface is unmeasurable (SSR, first frame, background-image, which needs useImageMode sampling); ignored unless mode is auto',
152
152
  },
153
153
  };
@@ -213,6 +213,7 @@ function discoverComponents(): ComponentInfo[] {
213
213
  // ---------------------------------------------------------------------------
214
214
 
215
215
  const DIR_TO_REGISTRY_KEY: Record<string, string> = {
216
+ Avatar: 'avatar',
216
217
  Banner: 'banner',
217
218
  Button: 'button',
218
219
  Card: 'card',
@@ -221,13 +222,13 @@ const DIR_TO_REGISTRY_KEY: Record<string, string> = {
221
222
  Dialog: 'dialog',
222
223
  DropdownMenu: 'dropdown-menu',
223
224
  Field: 'field',
224
- HoverCard: 'hovercard',
225
+ HoverCard: 'hover-card',
225
226
  NumberInput: 'number-input',
226
227
  Popover: 'popover',
227
- ProgressBar: 'progressbar-mark',
228
+ ProgressBar: 'progress-bar-mark',
228
229
  Section: 'section',
229
230
  SegmentedControl: 'segmented-control',
230
- TextArea: 'textarea',
231
+ TextArea: 'text-area',
231
232
  };
232
233
 
233
234
  /**
@@ -418,6 +419,21 @@ describe('getDerivedVars', () => {
418
419
  expect(getDerivedVars('unknown', 'borderRadius')).toEqual([]);
419
420
  });
420
421
 
422
+ it('resolves a deprecated key to the entries of the key that replaced it', () => {
423
+ // A theme written against the old spelling still selects the element (the
424
+ // component emits both classes), so its derived vars must still expand —
425
+ // otherwise the rule lands and the var half of it silently does nothing.
426
+ expect(getDerivedVars('hovercard', 'borderRadius')).toEqual(
427
+ getDerivedVars('hover-card', 'borderRadius'),
428
+ );
429
+ expect(getDerivedVars('textarea', 'paddingInline')).toEqual(
430
+ getDerivedVars('text-area', 'paddingInline'),
431
+ );
432
+ expect(getDerivedVars('progressbar-mark', 'width')).toEqual(
433
+ getDerivedVars('progress-bar-mark', 'width'),
434
+ );
435
+ });
436
+
421
437
  it('returns empty for unregistered property', () => {
422
438
  expect(getDerivedVars('card', 'color')).toEqual([]);
423
439
  });
@@ -43,6 +43,7 @@ export interface DerivedVarEntry {
43
43
  * entries share the same property.
44
44
  */
45
45
  export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
46
+ avatar: [{property: 'borderRadius', vars: ['--_avatar-radius']}],
46
47
  banner: [{property: 'borderRadius', vars: ['--_banner-radius']}],
47
48
  button: [{property: 'borderRadius', vars: ['--_button-radius']}],
48
49
  card: [
@@ -66,13 +67,13 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
66
67
  {property: 'padding', vars: ['--_dropdown-menu-padding']},
67
68
  ],
68
69
  field: [{property: 'borderRadius', vars: ['--_field-radius']}],
69
- hovercard: [{property: 'borderRadius', vars: ['--_hovercard-radius']}],
70
+ 'hover-card': [{property: 'borderRadius', vars: ['--_hovercard-radius']}],
70
71
  'number-input': [
71
72
  {property: 'padding', expand: 'container'},
72
73
  {property: 'borderRadius', vars: ['--_field-radius']},
73
74
  ],
74
75
  popover: [{property: 'borderRadius', vars: ['--_popover-radius']}],
75
- 'progressbar-mark': [
76
+ 'progress-bar-mark': [
76
77
  {property: 'width', vars: ['--_progressbar-mark-width'], replaces: true},
77
78
  {property: 'height', vars: ['--_progressbar-mark-height'], replaces: true},
78
79
  ],
@@ -81,7 +82,7 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
81
82
  {property: 'borderRadius', vars: ['--_segmented-control-radius']},
82
83
  {property: 'padding', vars: ['--_segmented-control-padding']},
83
84
  ],
84
- textarea: [
85
+ 'text-area': [
85
86
  {
86
87
  property: 'paddingInline',
87
88
  vars: ['--_textarea-inline-padding'],
@@ -90,6 +91,21 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
90
91
  ],
91
92
  };
92
93
 
94
+ /**
95
+ * Deprecated component keys → the key that superseded them.
96
+ *
97
+ * A renamed target keeps emitting its old class, so a theme written against
98
+ * the old key still selects the element. Without this the rule would land but
99
+ * its derived vars would not expand, and the half that travels through a var
100
+ * (a hover card's radius, a text area's inline padding) would silently do
101
+ * nothing. Drop these with the classes, in the next major.
102
+ */
103
+ const DEPRECATED_REGISTRY_KEYS: Record<string, string> = {
104
+ hovercard: 'hover-card',
105
+ 'progressbar-mark': 'progress-bar-mark',
106
+ textarea: 'text-area',
107
+ };
108
+
93
109
  /**
94
110
  * Look up derived var entries for a component + CSS property.
95
111
  * Returns matching entries in priority order, or empty array if none.
@@ -98,7 +114,10 @@ export function getDerivedVars(
98
114
  component: string,
99
115
  property: string,
100
116
  ): DerivedVarEntry[] {
101
- const entries = derivedVarRegistry[component];
117
+ const renamedTo = DEPRECATED_REGISTRY_KEYS[component];
118
+ const entries =
119
+ derivedVarRegistry[component] ??
120
+ (renamedTo ? derivedVarRegistry[renamedTo] : undefined);
102
121
  if (!entries) {
103
122
  return [];
104
123
  }
@@ -702,3 +702,40 @@ describe('physical padding longhands', () => {
702
702
  expect(rule).not.toContain('--_dropdown-menu-padding');
703
703
  });
704
704
  });
705
+
706
+ describe('renamed theme targets', () => {
707
+ // The renamed targets emit both classes, so a rule written against either
708
+ // key selects the element. What is easy to miss is the derived-var half: a
709
+ // key the registry does not know still emits a rule, minus every var the
710
+ // component actually reads — the same silent nothing a misspelled key gives.
711
+ it('expands derived vars for a renamed key and its deprecated spelling', () => {
712
+ const rules = (component: string, styles: Record<string, string>) =>
713
+ generateThemeRules(
714
+ defineTheme({
715
+ name: `test-renamed-${component}`,
716
+ components: {[component]: {base: styles}},
717
+ }),
718
+ ).join('\n');
719
+
720
+ const hoverCard = rules('hover-card', {borderRadius: '9px'});
721
+ expect(hoverCard).toContain('.astryx-hover-card');
722
+ expect(hoverCard).toContain('--_hovercard-radius: 9px');
723
+ expect(rules('hovercard', {borderRadius: '9px'})).toContain(
724
+ '--_hovercard-radius: 9px',
725
+ );
726
+
727
+ const textArea = rules('text-area', {paddingInline: '11px'});
728
+ expect(textArea).toContain('.astryx-text-area');
729
+ expect(textArea).toContain('--_textarea-inline-padding: 11px');
730
+ expect(rules('textarea', {paddingInline: '11px'})).toContain(
731
+ '--_textarea-inline-padding: 11px',
732
+ );
733
+
734
+ const mark = rules('progress-bar-mark', {width: '3px'});
735
+ expect(mark).toContain('.astryx-progress-bar-mark');
736
+ expect(mark).toContain('--_progressbar-mark-width: 3px');
737
+ expect(rules('progressbar-mark', {width: '3px'})).toContain(
738
+ '--_progressbar-mark-width: 3px',
739
+ );
740
+ });
741
+ });
@@ -44,8 +44,11 @@ export const syntaxTokenDefaults = {
44
44
  '--color-syntax-attribute': 'var(--color-text-teal)',
45
45
  // property -> cyan text (object properties)
46
46
  '--color-syntax-property': 'var(--color-text-cyan)',
47
- // punctuation -> disabled text (brackets, semicolons)
48
- '--color-syntax-punctuation': 'var(--color-text-disabled)',
47
+ // punctuation -> secondary text (brackets, semicolons). Not disabled text:
48
+ // disabled grey is calibrated to fail AA on purpose (WCAG exempts inactive
49
+ // controls), and punctuation in a code sample is normal, always-active
50
+ // text — see #5386.
51
+ '--color-syntax-punctuation': 'var(--color-text-secondary)',
49
52
  // background -> muted surface
50
53
  '--color-syntax-background': 'var(--color-background-muted)',
51
54
  } as const;
@@ -19,6 +19,11 @@ export interface ItemGroup<T extends SearchableItem = SearchableItem> {
19
19
  items: T[];
20
20
  }
21
21
 
22
+ export interface GroupItemsOptions {
23
+ /** Place ungrouped items before named groups instead of after them. */
24
+ ungroupedFirst?: boolean;
25
+ }
26
+
22
27
  /**
23
28
  * Extract the group string from an item's auxiliaryData.
24
29
  */
@@ -52,6 +57,7 @@ export function getItemGroup(item: SearchableItem): string | undefined {
52
57
  */
53
58
  export function groupItems<T extends SearchableItem>(
54
59
  items: T[],
60
+ {ungroupedFirst = false}: GroupItemsOptions = {},
55
61
  ): ItemGroup<T>[] {
56
62
  const hasGroups = items.some(item => getItemGroup(item) != null);
57
63
 
@@ -76,14 +82,14 @@ export function groupItems<T extends SearchableItem>(
76
82
  }
77
83
  }
78
84
 
79
- const result: ItemGroup<T>[] = groupOrder.map(heading => ({
85
+ const namedGroups: ItemGroup<T>[] = groupOrder.map(heading => ({
80
86
  heading,
81
87
  items: groups.get(heading) ?? [],
82
88
  }));
89
+ const ungroupedGroup: ItemGroup<T>[] =
90
+ ungrouped.length > 0 ? [{heading: null, items: ungrouped}] : [];
83
91
 
84
- if (ungrouped.length > 0) {
85
- result.push({heading: null, items: ungrouped});
86
- }
87
-
88
- return result;
92
+ return ungroupedFirst
93
+ ? [...ungroupedGroup, ...namedGroups]
94
+ : [...namedGroups, ...ungroupedGroup];
89
95
  }
@@ -86,7 +86,7 @@ export type {
86
86
  ThemeProps,
87
87
  } from './themeProps';
88
88
  export {groupItems, getItemGroup} from './groupItems';
89
- export type {ItemGroup} from './groupItems';
89
+ export type {ItemGroup, GroupItemsOptions} from './groupItems';
90
90
  export {observeResize, unobserveResize} from './sharedResizeObserver';
91
91
  export {isRenderable} from './isRenderable';
92
92
  export {getInputARIA} from './inputAria';