@astryxdesign/core 0.4.6 → 0.4.7-canary.20bae6c

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 (377) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +3 -2
  4. package/dist/AspectRatio/AspectRatio.d.ts +24 -0
  5. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  6. package/dist/AspectRatio/AspectRatio.js +23 -4
  7. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  8. package/dist/AvatarGroup/AvatarGroup.js +3 -2
  9. package/dist/BottomSheet/BottomSheet.d.ts +1 -0
  10. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  11. package/dist/BottomSheet/BottomSheet.js +54 -15
  12. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts +6 -0
  13. package/dist/BottomSheet/BottomSheetEdgeTint.d.ts.map +1 -0
  14. package/dist/BottomSheet/BottomSheetEdgeTint.js +62 -0
  15. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  16. package/dist/BottomSheet/BottomSheetPanel.js +1 -0
  17. package/dist/BottomSheet/BottomSheetSwitcher.d.ts +1 -0
  18. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  19. package/dist/BottomSheet/BottomSheetSwitcher.js +13 -6
  20. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  21. package/dist/BottomSheet/useSheetGestures.js +23 -5
  22. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  23. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
  24. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  25. package/dist/ButtonGroup/ButtonGroup.js +12 -4
  26. package/dist/Calendar/Calendar.d.ts +3 -1
  27. package/dist/Calendar/Calendar.d.ts.map +1 -1
  28. package/dist/Calendar/Calendar.js +13 -14
  29. package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
  30. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
  31. package/dist/Calendar/getInitialFocusDate.js +62 -0
  32. package/dist/Carousel/Carousel.d.ts.map +1 -1
  33. package/dist/Carousel/Carousel.js +3 -3
  34. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  35. package/dist/Chat/ChatLayout.js +3 -3
  36. package/dist/Chat/ChatMessageList.d.ts +22 -3
  37. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  38. package/dist/Chat/ChatMessageList.js +6 -3
  39. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  40. package/dist/CheckboxInput/CheckboxInput.js +3 -2
  41. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  42. package/dist/ClickableCard/ClickableCard.js +3 -3
  43. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  44. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  45. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  46. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  47. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  48. package/dist/ContextMenu/ContextMenu.js +4 -3
  49. package/dist/DateInput/DateInput.d.ts.map +1 -1
  50. package/dist/DateInput/DateInput.js +3 -2
  51. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  52. package/dist/DateInput/TouchDateField.js +34 -1
  53. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  54. package/dist/DateTimeInput/DateTimeInput.js +3 -2
  55. package/dist/Dialog/Dialog.d.ts +7 -1
  56. package/dist/Dialog/Dialog.d.ts.map +1 -1
  57. package/dist/Dialog/Dialog.js +89 -58
  58. package/dist/FileInput/FileInput.d.ts.map +1 -1
  59. package/dist/FileInput/FileInput.js +3 -2
  60. package/dist/Heading/Heading.d.ts.map +1 -1
  61. package/dist/Heading/Heading.js +6 -2
  62. package/dist/HoverCard/HoverCard.d.ts +6 -0
  63. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  64. package/dist/HoverCard/useHoverCard.d.ts +5 -0
  65. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  66. package/dist/HoverCard/useHoverCard.js +67 -25
  67. package/dist/Item/Item.d.ts.map +1 -1
  68. package/dist/Item/Item.js +4 -2
  69. package/dist/Kbd/Kbd.d.ts.map +1 -1
  70. package/dist/Kbd/Kbd.js +10 -3
  71. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  72. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  73. package/dist/Layer/LayerDepthContext.js +66 -0
  74. package/dist/Layer/index.d.ts +3 -0
  75. package/dist/Layer/index.d.ts.map +1 -1
  76. package/dist/Layer/index.js +4 -0
  77. package/dist/Layer/layerStack.d.ts +98 -0
  78. package/dist/Layer/layerStack.d.ts.map +1 -0
  79. package/dist/Layer/layerStack.js +306 -0
  80. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  81. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  82. package/dist/Layer/useLayerDismissal.js +91 -0
  83. package/dist/Lightbox/Lightbox.d.ts +1 -0
  84. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  85. package/dist/Lightbox/Lightbox.js +103 -81
  86. package/dist/Markdown/index.d.ts +1 -1
  87. package/dist/Markdown/index.d.ts.map +1 -1
  88. package/dist/Markdown/parser.d.ts +38 -1
  89. package/dist/Markdown/parser.d.ts.map +1 -1
  90. package/dist/Markdown/parser.js +149 -23
  91. package/dist/MobileNav/MobileNav.d.ts +6 -1
  92. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  93. package/dist/MobileNav/MobileNav.js +61 -36
  94. package/dist/MultiSelector/MultiSelector.d.ts +15 -1
  95. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  96. package/dist/MultiSelector/MultiSelector.js +17 -6
  97. package/dist/MultiSelector/index.d.ts +1 -1
  98. package/dist/MultiSelector/index.d.ts.map +1 -1
  99. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  100. package/dist/NavMenu/NavHeadingMenu.js +3 -2
  101. package/dist/Outline/Outline.d.ts.map +1 -1
  102. package/dist/Outline/Outline.js +3 -2
  103. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  104. package/dist/OverflowList/OverflowList.js +3 -2
  105. package/dist/Overlay/Overlay.d.ts.map +1 -1
  106. package/dist/Overlay/Overlay.js +3 -2
  107. package/dist/Popover/usePopover.d.ts.map +1 -1
  108. package/dist/Popover/usePopover.js +20 -17
  109. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  110. package/dist/PowerSearch/PowerSearch.js +3 -4
  111. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  112. package/dist/Resizable/ResizeHandle.js +3 -2
  113. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  114. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  115. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  116. package/dist/SelectableCard/SelectableCard.js +3 -3
  117. package/dist/Selector/Selector.d.ts.map +1 -1
  118. package/dist/Selector/Selector.js +5 -0
  119. package/dist/SideNav/SideNav.d.ts.map +1 -1
  120. package/dist/SideNav/SideNav.js +4 -3
  121. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  122. package/dist/SideNav/SideNavItem.js +4 -3
  123. package/dist/Slider/Slider.d.ts.map +1 -1
  124. package/dist/Slider/Slider.js +3 -3
  125. package/dist/Stepper/Step.d.ts +140 -0
  126. package/dist/Stepper/Step.d.ts.map +1 -0
  127. package/dist/Stepper/Step.js +1045 -0
  128. package/dist/Stepper/StepStatus.d.ts +24 -0
  129. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  130. package/dist/Stepper/StepStatus.js +1 -0
  131. package/dist/Stepper/Stepper.d.ts +93 -0
  132. package/dist/Stepper/Stepper.d.ts.map +1 -0
  133. package/dist/Stepper/Stepper.js +184 -0
  134. package/dist/Stepper/StepperContext.d.ts +41 -0
  135. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  136. package/dist/Stepper/StepperContext.js +34 -0
  137. package/dist/Stepper/index.d.ts +8 -0
  138. package/dist/Stepper/index.d.ts.map +1 -0
  139. package/dist/Stepper/index.js +7 -0
  140. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  141. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  142. package/dist/Stepper/stepper.stylex.js +20 -0
  143. package/dist/Switch/Switch.d.ts.map +1 -1
  144. package/dist/Switch/Switch.js +3 -2
  145. package/dist/TabList/Tab.d.ts.map +1 -1
  146. package/dist/TabList/Tab.js +5 -1
  147. package/dist/TabList/TabList.d.ts.map +1 -1
  148. package/dist/TabList/TabList.js +3 -3
  149. package/dist/Table/BaseTable.d.ts.map +1 -1
  150. package/dist/Table/BaseTable.js +4 -1
  151. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  152. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
  153. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  154. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  155. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  156. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  157. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  158. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  159. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  160. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  161. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  162. package/dist/Table/plugins/selection/useTableSelection.js +19 -5
  163. package/dist/Table/types.d.ts +22 -4
  164. package/dist/Table/types.d.ts.map +1 -1
  165. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  166. package/dist/Table/useBaseTablePlugins.js +5 -0
  167. package/dist/Text/Text.d.ts.map +1 -1
  168. package/dist/Text/Text.js +6 -2
  169. package/dist/TextArea/TextArea.d.ts.map +1 -1
  170. package/dist/TextArea/TextArea.js +3 -2
  171. package/dist/TextInput/TextInput.d.ts.map +1 -1
  172. package/dist/TextInput/TextInput.js +3 -2
  173. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  174. package/dist/TimeInput/TimeInput.js +3 -2
  175. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  176. package/dist/Timestamp/Timestamp.js +5 -3
  177. package/dist/Token/TokenLink.d.ts.map +1 -1
  178. package/dist/Token/TokenLink.js +2 -2
  179. package/dist/Tooltip/Tooltip.d.ts +5 -0
  180. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  181. package/dist/Tooltip/useTooltip.d.ts +5 -0
  182. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  183. package/dist/Tooltip/useTooltip.js +39 -24
  184. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  185. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  186. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  187. package/dist/Typeahead/BaseTypeahead.js +3 -3
  188. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  189. package/dist/Typeahead/Typeahead.js +3 -2
  190. package/dist/astryx.css +43 -1
  191. package/dist/hooks/index.d.ts +1 -0
  192. package/dist/hooks/index.d.ts.map +1 -1
  193. package/dist/hooks/index.js +1 -0
  194. package/dist/hooks/useFocusTrap.d.ts +7 -4
  195. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  196. package/dist/hooks/useFocusTrap.js +52 -91
  197. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  198. package/dist/hooks/useHotkeys.js +10 -3
  199. package/dist/hooks/useListFocus.d.ts +5 -2
  200. package/dist/hooks/useListFocus.d.ts.map +1 -1
  201. package/dist/hooks/useListFocus.js +12 -6
  202. package/dist/hooks/useMergedRefs.d.ts +18 -0
  203. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  204. package/dist/hooks/useMergedRefs.js +25 -0
  205. package/dist/index.d.ts +1 -0
  206. package/dist/index.d.ts.map +1 -1
  207. package/dist/index.js +1 -0
  208. package/dist/utils/timeParser.d.ts +1 -1
  209. package/dist/utils/timeParser.d.ts.map +1 -1
  210. package/dist/utils/timeParser.js +26 -12
  211. package/locales/en.json +27 -7
  212. package/locales/pseudo.json +15 -0
  213. package/package.json +8 -3
  214. package/src/AppShell/AppShell.tsx +3 -2
  215. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  216. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  217. package/src/AspectRatio/AspectRatio.tsx +40 -1
  218. package/src/Avatar/Avatar.doc.mjs +2 -1
  219. package/src/AvatarGroup/AvatarGroup.tsx +3 -2
  220. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  221. package/src/BottomSheet/BottomSheet.tsx +36 -4
  222. package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +225 -0
  223. package/src/BottomSheet/BottomSheetEdgeTint.tsx +82 -0
  224. package/src/BottomSheet/BottomSheetPanel.test.tsx +66 -0
  225. package/src/BottomSheet/BottomSheetPanel.tsx +19 -0
  226. package/src/BottomSheet/BottomSheetSwitcher.tsx +16 -2
  227. package/src/BottomSheet/useSheetGestures.test.ts +27 -0
  228. package/src/BottomSheet/useSheetGestures.ts +25 -5
  229. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  230. package/src/Button/Button.doc.mjs +22 -0
  231. package/src/ButtonGroup/ButtonGroup.doc.mjs +7 -1
  232. package/src/ButtonGroup/ButtonGroup.test.tsx +185 -1
  233. package/src/ButtonGroup/ButtonGroup.tsx +11 -3
  234. package/src/Calendar/Calendar.doc.mjs +4 -3
  235. package/src/Calendar/Calendar.test.tsx +52 -0
  236. package/src/Calendar/Calendar.tsx +18 -15
  237. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  238. package/src/Calendar/getInitialFocusDate.ts +93 -0
  239. package/src/Carousel/Carousel.tsx +3 -2
  240. package/src/Chat/ChatLayout.tsx +3 -2
  241. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  242. package/src/Chat/ChatMessageList.test.tsx +46 -0
  243. package/src/Chat/ChatMessageList.tsx +28 -4
  244. package/src/CheckboxInput/CheckboxInput.tsx +3 -2
  245. package/src/ClickableCard/ClickableCard.tsx +3 -2
  246. package/src/CodeBlock/CodeBlock.doc.mjs +6 -0
  247. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  248. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  249. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  250. package/src/ContextMenu/ContextMenu.tsx +4 -3
  251. package/src/DateInput/DateInput.tsx +3 -2
  252. package/src/DateInput/DateInputTouch.test.tsx +36 -0
  253. package/src/DateInput/TouchDateField.tsx +35 -1
  254. package/src/DateTimeInput/DateTimeInput.tsx +2 -2
  255. package/src/Dialog/Dialog.doc.mjs +8 -3
  256. package/src/Dialog/Dialog.test.tsx +261 -1
  257. package/src/Dialog/Dialog.tsx +109 -58
  258. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  259. package/src/Field/Field.doc.mjs +13 -2
  260. package/src/FileInput/FileInput.tsx +3 -2
  261. package/src/Heading/Heading.test.tsx +23 -1
  262. package/src/Heading/Heading.tsx +6 -2
  263. package/src/HoverCard/HoverCard.doc.mjs +5 -0
  264. package/src/HoverCard/HoverCard.tsx +6 -0
  265. package/src/HoverCard/useHoverCard.tsx +81 -30
  266. package/src/Item/Item.tsx +5 -4
  267. package/src/Kbd/Kbd.test.tsx +17 -0
  268. package/src/Kbd/Kbd.tsx +10 -3
  269. package/src/Layer/LayerDepthContext.tsx +62 -0
  270. package/src/Layer/index.ts +9 -0
  271. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  272. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  273. package/src/Layer/layerStack.ts +362 -0
  274. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  275. package/src/Layer/useLayerDismissal.ts +173 -0
  276. package/src/Layout/Layout.doc.mjs +2 -2
  277. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  278. package/src/Lightbox/Lightbox.tsx +124 -102
  279. package/src/Link/Link.doc.mjs +39 -0
  280. package/src/Markdown/index.ts +1 -0
  281. package/src/Markdown/parser.perf.test.ts +71 -1
  282. package/src/Markdown/parser.test.ts +145 -2
  283. package/src/Markdown/parser.ts +208 -22
  284. package/src/MobileNav/MobileNav.tsx +62 -36
  285. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  286. package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
  287. package/src/MultiSelector/MultiSelector.test.tsx +105 -0
  288. package/src/MultiSelector/MultiSelector.tsx +50 -6
  289. package/src/MultiSelector/index.ts +1 -0
  290. package/src/NavMenu/NavHeadingMenu.tsx +3 -2
  291. package/src/NumberInput/NumberInput.doc.mjs +5 -0
  292. package/src/Outline/Outline.tsx +3 -2
  293. package/src/OverflowList/OverflowList.tsx +3 -2
  294. package/src/Overlay/Overlay.tsx +3 -2
  295. package/src/Popover/Popover.test.tsx +27 -1
  296. package/src/Popover/usePopover.tsx +31 -28
  297. package/src/PowerSearch/PowerSearch.doc.mjs +26 -0
  298. package/src/PowerSearch/PowerSearch.tsx +5 -2
  299. package/src/Resizable/ResizeHandle.tsx +3 -2
  300. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  301. package/src/SelectableCard/SelectableCard.tsx +3 -2
  302. package/src/Selector/Selector.doc.mjs +12 -1
  303. package/src/Selector/Selector.test.tsx +21 -0
  304. package/src/Selector/Selector.tsx +11 -1
  305. package/src/SideNav/SideNav.doc.mjs +6 -6
  306. package/src/SideNav/SideNav.tsx +4 -2
  307. package/src/SideNav/SideNavItem.tsx +4 -2
  308. package/src/Slider/Slider.tsx +3 -2
  309. package/src/Stepper/Step.doc.mjs +98 -0
  310. package/src/Stepper/Step.tsx +1638 -0
  311. package/src/Stepper/StepStatus.ts +26 -0
  312. package/src/Stepper/Stepper.doc.mjs +370 -0
  313. package/src/Stepper/Stepper.test.tsx +1024 -0
  314. package/src/Stepper/Stepper.tsx +258 -0
  315. package/src/Stepper/StepperContext.ts +71 -0
  316. package/src/Stepper/index.ts +18 -0
  317. package/src/Stepper/stepper.stylex.ts +19 -0
  318. package/src/Switch/Switch.tsx +3 -2
  319. package/src/TabList/Tab.tsx +5 -1
  320. package/src/TabList/TabList.test.tsx +21 -4
  321. package/src/TabList/TabList.tsx +3 -2
  322. package/src/Table/BaseTable.tsx +6 -3
  323. package/src/Table/Table.test.tsx +35 -0
  324. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  325. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  326. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
  327. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  328. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  329. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  330. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  331. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  332. package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
  333. package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
  334. package/src/Table/types.ts +22 -4
  335. package/src/Table/useBaseTablePlugins.ts +5 -0
  336. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  337. package/src/Table/useTablePagination.doc.mjs +7 -0
  338. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  339. package/src/Table/useTableSelection.doc.mjs +31 -0
  340. package/src/Text/Text.test.tsx +23 -1
  341. package/src/Text/Text.tsx +6 -2
  342. package/src/TextArea/TextArea.tsx +3 -2
  343. package/src/TextInput/TextInput.doc.mjs +10 -0
  344. package/src/TextInput/TextInput.tsx +3 -2
  345. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  346. package/src/TimeInput/TimeInput.tsx +2 -2
  347. package/src/Timestamp/Timestamp.tsx +4 -2
  348. package/src/Toast/Toast.doc.mjs +6 -0
  349. package/src/Token/TokenLink.tsx +2 -2
  350. package/src/Tokenizer/Tokenizer.doc.mjs +16 -0
  351. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  352. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  353. package/src/Tooltip/Tooltip.test.tsx +32 -0
  354. package/src/Tooltip/Tooltip.tsx +5 -0
  355. package/src/Tooltip/useTooltip.tsx +47 -24
  356. package/src/TopNav/TopNavMegaMenu.tsx +3 -2
  357. package/src/Typeahead/BaseTypeahead.tsx +3 -2
  358. package/src/Typeahead/Typeahead.doc.mjs +5 -0
  359. package/src/Typeahead/Typeahead.tsx +3 -2
  360. package/src/__tests__/complexComponentContract.test.tsx +81 -0
  361. package/src/hooks/index.ts +2 -0
  362. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  363. package/src/hooks/useFocusTrap.ts +54 -107
  364. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  365. package/src/hooks/useHotkeys.test.ts +18 -0
  366. package/src/hooks/useHotkeys.ts +10 -3
  367. package/src/hooks/useListFocus.doc.mjs +2 -2
  368. package/src/hooks/useListFocus.test.tsx +65 -3
  369. package/src/hooks/useListFocus.ts +15 -7
  370. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  371. package/src/hooks/useMergedRefs.test.tsx +62 -0
  372. package/src/hooks/useMergedRefs.ts +36 -0
  373. package/src/index.ts +1 -0
  374. package/src/theme/MediaTheme.doc.mjs +5 -5
  375. package/src/utils/timeParser.test.ts +6 -1
  376. package/src/utils/timeParser.ts +35 -13
  377. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -14,6 +14,8 @@
14
14
  *
15
15
  * SYNC: When modified, update:
16
16
  * - /packages/core/src/hooks/index.ts
17
+ * - /packages/core/src/hooks/useListFocus.doc.mjs
18
+ * - /packages/core/src/hooks/useListFocus.test.tsx
17
19
  */
18
20
 
19
21
  import {useCallback, useRef} from 'react';
@@ -64,7 +66,9 @@ export interface UseListFocusOptions {
64
66
  wrap?: boolean;
65
67
 
66
68
  /**
67
- * Callback when Escape key is pressed.
69
+ * Callback when Escape key is pressed. Supplying it also makes the list
70
+ * consume the key (`preventDefault`); without it Escape passes through to
71
+ * the surrounding layer.
68
72
  */
69
73
  onEscape?: () => void;
70
74
 
@@ -277,7 +281,8 @@ function shouldDeferToCaret(target: EventTarget | null, key: string): boolean {
277
281
  * - ArrowUp/ArrowLeft: Move to previous item (wraps to last)
278
282
  * - Home: Move to first item
279
283
  * - End: Move to last item
280
- * - Escape: Custom callback (e.g., close menu)
284
+ * - Escape: runs `onEscape` and consumes the key. With no `onEscape` the key
285
+ * is left alone, so a surrounding layer can still dismiss on it.
281
286
  *
282
287
  * By default the hook only *moves* focus and leaves `tabindex` management to
283
288
  * the caller. Opt into {@link UseListFocusOptions.hasRovingTabIndex} for a hook
@@ -557,12 +562,15 @@ export function useListFocus<T extends HTMLElement = HTMLElement>(
557
562
  return;
558
563
  }
559
564
 
560
- // Escape is handled regardless of orientation. Preserve the historical
561
- // behavior of always consuming Escape here (preventDefault) so consumers
562
- // that relied on it are unaffected.
565
+ // Escape is handled regardless of orientation, but only *consumed* when
566
+ // a handler asked for it: a list with no dismissal to perform must leave
567
+ // the key to whatever host layer does have one, and those defer to
568
+ // `defaultPrevented` (see `useFocusTrap`) or to the native popover.
563
569
  if (e.key === 'Escape') {
564
- e.preventDefault();
565
- onEscape?.();
570
+ if (onEscape) {
571
+ e.preventDefault();
572
+ onEscape();
573
+ }
566
574
  return;
567
575
  }
568
576
 
@@ -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';
@@ -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
  };
@@ -135,6 +135,9 @@ describe('parseTimeInput', () => {
135
135
  it('parses compact formats', () => {
136
136
  expect(parseTimeInput('1430')).toBe('14:30');
137
137
  expect(parseTimeInput('0000')).toBe('00:00');
138
+ expect(parseTimeInput('0230pm')).toBe('14:30');
139
+ expect(parseTimeInput('1230am')).toBe('00:30');
140
+ expect(parseTimeInput('023045pm', true)).toBe('14:30:45');
138
141
  });
139
142
 
140
143
  it('parses hour-only with meridiem', () => {
@@ -259,7 +262,9 @@ describe('adjustTime', () => {
259
262
 
260
263
  it('wraps large negative deltas in constant time', () => {
261
264
  expect(adjustTime('10:00' as ISOTimeString, -1440 * 1e7)).toBe('10:00');
262
- expect(adjustTime('10:00' as ISOTimeString, -1440 * 1e7 - 30)).toBe('09:30');
265
+ expect(adjustTime('10:00' as ISOTimeString, -1440 * 1e7 - 30)).toBe(
266
+ '09:30',
267
+ );
263
268
  });
264
269
 
265
270
  it('adds minutes', () => {
@@ -4,7 +4,7 @@
4
4
  * @file timeParser.ts
5
5
  * @input Uses string parsing
6
6
  * @output Exports time parsing and formatting utilities
7
- * @position Shared utility; used by TimePicker
7
+ * @position Shared utility; used by TimeInput and DateTimeInput
8
8
  *
9
9
  * SYNC: When modified, update this header
10
10
  */
@@ -175,16 +175,29 @@ export function parseTimeInput(
175
175
  // Remove AM/PM suffix
176
176
  const timeStr = trimmed.replace(/\s*[ap]\.?m?\.?\s*$/i, '').trim();
177
177
 
178
+ const convertHourTo24Hour = (hour: number): number | null => {
179
+ if (!hasMeridiem) {
180
+ return hour;
181
+ }
182
+ if (hour < 1 || hour > 12) {
183
+ return null;
184
+ }
185
+ if (isPM && hour !== 12) {
186
+ return hour + 12;
187
+ }
188
+ if (isAM && hour === 12) {
189
+ return 0;
190
+ }
191
+ return hour;
192
+ };
193
+
178
194
  // Handle formats like "2pm" -> "2"
179
195
  if (/^\d{1,2}$/.test(timeStr)) {
180
196
  const hour = parseInt(timeStr, 10);
181
- if (hour >= 1 && hour <= 12 && hasMeridiem) {
182
- let hour24 = hour;
183
- if (isPM && hour !== 12) {
184
- hour24 = hour + 12;
185
- }
186
- if (isAM && hour === 12) {
187
- hour24 = 0;
197
+ if (hasMeridiem) {
198
+ const hour24 = convertHourTo24Hour(hour);
199
+ if (hour24 === null) {
200
+ return null;
188
201
  }
189
202
  return formatISOTime(
190
203
  {hour: hour24, minute: 0, second: 0},
@@ -201,8 +214,15 @@ export function parseTimeInput(
201
214
  if (/^\d{4}$/.test(timeStr)) {
202
215
  const hour = parseInt(timeStr.slice(0, 2), 10);
203
216
  const minute = parseInt(timeStr.slice(2, 4), 10);
204
- if (hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59) {
205
- return formatISOTime({hour, minute, second: 0}, includeSeconds);
217
+ const hour24 = convertHourTo24Hour(hour);
218
+ if (
219
+ hour24 !== null &&
220
+ hour24 >= 0 &&
221
+ hour24 <= 23 &&
222
+ minute >= 0 &&
223
+ minute <= 59
224
+ ) {
225
+ return formatISOTime({hour: hour24, minute, second: 0}, includeSeconds);
206
226
  }
207
227
  return null;
208
228
  }
@@ -212,15 +232,17 @@ export function parseTimeInput(
212
232
  const hour = parseInt(timeStr.slice(0, 2), 10);
213
233
  const minute = parseInt(timeStr.slice(2, 4), 10);
214
234
  const second = parseInt(timeStr.slice(4, 6), 10);
235
+ const hour24 = convertHourTo24Hour(hour);
215
236
  if (
216
- hour >= 0 &&
217
- hour <= 23 &&
237
+ hour24 !== null &&
238
+ hour24 >= 0 &&
239
+ hour24 <= 23 &&
218
240
  minute >= 0 &&
219
241
  minute <= 59 &&
220
242
  second >= 0 &&
221
243
  second <= 59
222
244
  ) {
223
- return formatISOTime({hour, minute, second}, includeSeconds);
245
+ return formatISOTime({hour: hour24, minute, second}, includeSeconds);
224
246
  }
225
247
  return null;
226
248
  }
@@ -1,69 +0,0 @@
1
- // Copyright (c) Meta Platforms, Inc. and affiliates.
2
-
3
- import {describe, it, expect} from 'vitest';
4
-
5
- import {docs as CheckboxInputDocs} from '../CheckboxInput/CheckboxInput.doc.mjs';
6
- import {docs as CheckboxListDocs} from '../CheckboxList/CheckboxList.doc.mjs';
7
- import {docs as DateInputDocs} from '../DateInput/DateInput.doc.mjs';
8
- import {docs as DateRangeInputDocs} from '../DateRangeInput/DateRangeInput.doc.mjs';
9
- import {docs as DateTimeInputDocs} from '../DateTimeInput/DateTimeInput.doc.mjs';
10
- import {docs as FileInputDocs} from '../FileInput/FileInput.doc.mjs';
11
- import {docs as MultiSelectorDocs} from '../MultiSelector/MultiSelector.doc.mjs';
12
- import {docs as NumberInputDocs} from '../NumberInput/NumberInput.doc.mjs';
13
- import {docs as RadioListDocs} from '../RadioList/RadioList.doc.mjs';
14
- import {docs as SelectorDocs} from '../Selector/Selector.doc.mjs';
15
- import {docs as SliderDocs} from '../Slider/Slider.doc.mjs';
16
- import {docs as SwitchDocs} from '../Switch/Switch.doc.mjs';
17
- import {docs as TextAreaDocs} from '../TextArea/TextArea.doc.mjs';
18
- import {docs as TextInputDocs} from '../TextInput/TextInput.doc.mjs';
19
- import {docs as TimeInputDocs} from '../TimeInput/TimeInput.doc.mjs';
20
- import {docs as TokenizerDocs} from '../Tokenizer/Tokenizer.doc.mjs';
21
- import {docs as TypeaheadDocs} from '../Typeahead/Typeahead.doc.mjs';
22
-
23
- const inputDocsSuite = [
24
- {name: 'CheckboxInput', docs: CheckboxInputDocs},
25
- {name: 'CheckboxList', docs: CheckboxListDocs},
26
- {name: 'DateInput', docs: DateInputDocs},
27
- {name: 'DateRangeInput', docs: DateRangeInputDocs},
28
- {name: 'DateTimeInput', docs: DateTimeInputDocs},
29
- {name: 'FileInput', docs: FileInputDocs},
30
- {name: 'MultiSelector', docs: MultiSelectorDocs},
31
- {name: 'NumberInput', docs: NumberInputDocs},
32
- {name: 'RadioList', docs: RadioListDocs},
33
- {name: 'Selector', docs: SelectorDocs},
34
- {name: 'Slider', docs: SliderDocs},
35
- {name: 'Switch', docs: SwitchDocs},
36
- {name: 'TextArea', docs: TextAreaDocs},
37
- {name: 'TextInput', docs: TextInputDocs},
38
- {name: 'TimeInput', docs: TimeInputDocs},
39
- {name: 'Tokenizer', docs: TokenizerDocs},
40
- {name: 'Typeahead', docs: TypeaheadDocs},
41
- ];
42
-
43
- describe('Input Family width Prop Contract (#4163)', () => {
44
- inputDocsSuite.forEach(({name, docs}) => {
45
- it(`documents the width prop for ${name}`, () => {
46
- // `docs` is the ComponentDoc union (single vs multi component); narrow it
47
- // for structural access to either the top-level props or the first
48
- // sub-component's props.
49
- const doc = docs as {
50
- props?: {name: string; type: string}[];
51
- components?: {props?: {name: string; type: string}[]}[];
52
- };
53
- const propsList = (doc.props || doc.components?.[0]?.props) as {
54
- name: string;
55
- type: string;
56
- }[];
57
- expect(
58
- propsList,
59
- `${name}.doc.mjs must expose a props array`,
60
- ).toBeDefined();
61
- const widthProp = propsList.find(p => p.name === 'width');
62
- expect(
63
- widthProp,
64
- `${name}.doc.mjs must document the width prop`,
65
- ).toBeDefined();
66
- expect(widthProp?.type).toBe('SizeValue');
67
- });
68
- });
69
- });