@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
@@ -8,6 +8,13 @@
8
8
  * @output Exports Dialog component, DialogProps, DialogVariant, DialogPurpose types
9
9
  * @position Core implementation; consumed by index.ts, tested by Dialog.test.tsx
10
10
  *
11
+ * The standard variant treats `width` as the preferred surface width, then
12
+ * clamps it to the dynamic viewport with spacing-token gutters so narrow
13
+ * viewports keep content and controls on screen without changing the public API.
14
+ * Fullscreen dialogs add safe-area protection to the default padding fallback
15
+ * while preserving explicit prop/theme padding overrides, and fade in without
16
+ * the centered-dialog translate/scale motion.
17
+ *
11
18
  * SYNC: When modified, update these files to stay in sync:
12
19
  * - /packages/core/src/Dialog/Dialog.doc.mjs (props table, features, implementation notes)
13
20
  * - /packages/core/src/Dialog/Dialog.test.tsx (tests for new/changed behavior)
@@ -27,14 +34,15 @@ import {
27
34
  import type {BaseProps} from '../BaseProps';
28
35
  import * as stylex from '@stylexjs/stylex';
29
36
  import {useScrollLock} from '../hooks/useScrollLock';
30
- import {hasActiveFocusTrapEscape} from '../hooks/useFocusTrap';
31
- import {isImeKeyEvent} from '../utils/ime';
37
+ import {LayerDepthProvider} from '../Layer/LayerDepthContext';
38
+ import {useLayerDismissal} from '../Layer/useLayerDismissal';
32
39
  import {
33
40
  colorVars,
34
41
  radiusVars,
35
42
  durationVars,
36
43
  easeVars,
37
44
  shadowVars,
45
+ spacingVars,
38
46
  } from '../theme/tokens.stylex';
39
47
  import {container} from '../Layout/container.stylex';
40
48
  import type {SpacingToken} from '../Layout/container.stylex';
@@ -47,13 +55,14 @@ import {
47
55
  overlayPaddingReset,
48
56
  } from '../Layout/padding.stylex';
49
57
  import type {SpacingStep} from '../utils/types';
50
- import {mergeProps, mergeRefs} from '../utils';
58
+ import {mergeProps} from '../utils';
51
59
  import {devWarn} from '../utils/devWarning';
52
60
  import {DialogContext} from './DialogContext';
53
61
  import {themeProps} from '../utils/themeProps';
54
62
  import type {DialogVariantMap} from './index';
55
63
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
56
64
 
65
+ import {useMergedRefs} from '../hooks/useMergedRefs';
57
66
  /**
58
67
  * Calculate a directional translate offset for dialog entry animation.
59
68
  * Returns a normalized vector from the trigger element toward the viewport
@@ -118,6 +127,32 @@ const enterDirectional = stylex.keyframes({
118
127
  to: {opacity: 1, transform: 'translate(0, 0) scale(1)'},
119
128
  });
120
129
 
130
+ const enterFullscreen = stylex.keyframes({
131
+ from: {opacity: 0},
132
+ to: {opacity: 1},
133
+ });
134
+
135
+ const dialogFullscreenSafeAreaBlockStartPadding = `var(--astryx-dialog-padding-block-start, var(--astryx-dialog-padding, max(${spacingVars['--spacing-4']}, env(safe-area-inset-top, 0px))))`;
136
+ const dialogFullscreenSafeAreaBlockEndPadding = `var(--astryx-dialog-padding-block-end, var(--astryx-dialog-padding, max(${spacingVars['--spacing-4']}, env(safe-area-inset-bottom, 0px))))`;
137
+ const dialogFullscreenSafeAreaInlineStartPaddingLtr = `var(--astryx-dialog-padding-inline-start, var(--astryx-dialog-padding-inline, var(--astryx-dialog-padding, max(${spacingVars['--spacing-4']}, env(safe-area-inset-left, 0px)))))`;
138
+ const dialogFullscreenSafeAreaInlineStartPaddingRtl = `var(--astryx-dialog-padding-inline-start, var(--astryx-dialog-padding-inline, var(--astryx-dialog-padding, max(${spacingVars['--spacing-4']}, env(safe-area-inset-right, 0px)))))`;
139
+ const dialogFullscreenSafeAreaInlineEndPaddingLtr = `var(--astryx-dialog-padding-inline-end, var(--astryx-dialog-padding-inline, var(--astryx-dialog-padding, max(${spacingVars['--spacing-4']}, env(safe-area-inset-right, 0px)))))`;
140
+ const dialogFullscreenSafeAreaInlineEndPaddingRtl = `var(--astryx-dialog-padding-inline-end, var(--astryx-dialog-padding-inline, var(--astryx-dialog-padding, max(${spacingVars['--spacing-4']}, env(safe-area-inset-left, 0px)))))`;
141
+
142
+ /** @internal Verified by Dialog.test.tsx; not re-exported from the package entry point. */
143
+ export const dialogFullscreenSafeAreaPaddingContract = {
144
+ blockStart: dialogFullscreenSafeAreaBlockStartPadding,
145
+ blockEnd: dialogFullscreenSafeAreaBlockEndPadding,
146
+ inlineStart: {
147
+ ltr: dialogFullscreenSafeAreaInlineStartPaddingLtr,
148
+ rtl: dialogFullscreenSafeAreaInlineStartPaddingRtl,
149
+ },
150
+ inlineEnd: {
151
+ ltr: dialogFullscreenSafeAreaInlineEndPaddingLtr,
152
+ rtl: dialogFullscreenSafeAreaInlineEndPaddingRtl,
153
+ },
154
+ } as const;
155
+
121
156
  /**
122
157
  * Dialog styles using native <dialog> element
123
158
  * Uses ::backdrop pseudo-element for overlay
@@ -171,6 +206,24 @@ const styles = stylex.create({
171
206
  margin: 0,
172
207
  inset: 0,
173
208
  },
209
+ fullscreenOpen: {
210
+ animationName: {
211
+ default: enterFullscreen,
212
+ '@media (prefers-reduced-motion: reduce)': 'none',
213
+ },
214
+ },
215
+ fullscreenSafeArea: {
216
+ paddingBlockStart: dialogFullscreenSafeAreaBlockStartPadding,
217
+ paddingBlockEnd: dialogFullscreenSafeAreaBlockEndPadding,
218
+ paddingInlineStart: {
219
+ default: dialogFullscreenSafeAreaInlineStartPaddingLtr,
220
+ ':is([dir="rtl"] *)': dialogFullscreenSafeAreaInlineStartPaddingRtl,
221
+ },
222
+ paddingInlineEnd: {
223
+ default: dialogFullscreenSafeAreaInlineEndPaddingLtr,
224
+ ':is([dir="rtl"] *)': dialogFullscreenSafeAreaInlineEndPaddingRtl,
225
+ },
226
+ },
174
227
  inner: {
175
228
  display: 'flex',
176
229
  flexDirection: 'column',
@@ -194,12 +247,30 @@ const styles = stylex.create({
194
247
  },
195
248
  });
196
249
 
197
- // Dynamic styles for width, maxHeight, and position
250
+ const STANDARD_DIALOG_VIEWPORT_GUTTER = spacingVars['--spacing-4'];
251
+ const STANDARD_DIALOG_VIEWPORT_MAX_WIDTH = `calc(100dvw - ${STANDARD_DIALOG_VIEWPORT_GUTTER} - ${STANDARD_DIALOG_VIEWPORT_GUTTER})`;
252
+ const STANDARD_DIALOG_MAX_WIDTH = `min(100%, ${STANDARD_DIALOG_VIEWPORT_MAX_WIDTH})`;
253
+
254
+ function formatSizeValue(value: number | string): string {
255
+ return typeof value === 'number' ? `${value}px` : value;
256
+ }
257
+
258
+ function resolveDialogSizing(
259
+ width: number | string,
260
+ maxHeight: number | string,
261
+ ) {
262
+ return {
263
+ width: formatSizeValue(width),
264
+ maxWidth: STANDARD_DIALOG_MAX_WIDTH,
265
+ maxHeight: formatSizeValue(maxHeight),
266
+ };
267
+ }
268
+
198
269
  const dynamicStyles = stylex.create({
199
- sizing: (width: number | string, maxHeight: number | string) => ({
200
- width: typeof width === 'number' ? `${width}px` : width,
201
- maxWidth: '90vw',
202
- maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight,
270
+ sizing: (width: string, maxWidth: string, maxHeight: string) => ({
271
+ width,
272
+ maxWidth,
273
+ maxHeight,
203
274
  }),
204
275
  position: (
205
276
  top: string,
@@ -288,7 +359,7 @@ export interface DialogProps extends BaseProps<HTMLDialogElement> {
288
359
  * The actual height will be the height of its content.
289
360
  * Numbers are treated as pixels, strings are used as-is.
290
361
  * Ignored when variant is 'fullscreen'.
291
- * @default '75vh'
362
+ * @default '75dvh'
292
363
  */
293
364
  maxHeight?: number | string;
294
365
 
@@ -356,7 +427,7 @@ export function Dialog({
356
427
  isInline = false,
357
428
  onOpenChange,
358
429
  width = 400,
359
- maxHeight = '75vh',
430
+ maxHeight = '75dvh',
360
431
  position,
361
432
  variant = 'standard',
362
433
  purpose = 'info',
@@ -374,6 +445,9 @@ export function Dialog({
374
445
  const paddingToken = spacingStepToToken[effectivePadding] as SpacingToken;
375
446
 
376
447
  const isFullscreen = variant === 'fullscreen';
448
+ const standardSizing = isFullscreen
449
+ ? null
450
+ : resolveDialogSizing(width, maxHeight);
377
451
 
378
452
  // Default accessible name: publish a title id through DialogContext so a
379
453
  // DialogHeader applies it to its heading (mirrors AlertDialog's explicit
@@ -415,6 +489,8 @@ export function Dialog({
415
489
  [titleId, hasConsumerName],
416
490
  );
417
491
 
492
+ const mergedDialogRef = useMergedRefs(ref, attachDialog);
493
+
418
494
  // Capture the element that was focused when the dialog opened,
419
495
  // for directional animation origin and focus restoration on close.
420
496
  const triggerElementRef = useRef<HTMLElement | null>(null);
@@ -474,34 +550,24 @@ export function Dialog({
474
550
  // Skip for inline rendering — no modal overlay to compensate for.
475
551
  useScrollLock(isOpen && !isInline);
476
552
 
477
- // Handle Escape key — skip for inline rendering
478
- useEffect(() => {
479
- if (isInline) {
480
- return;
481
- }
482
- const dialog = dialogRef.current;
483
- if (!dialog || !isOpen) {
484
- return;
485
- }
486
-
487
- const handleKeyDown = (event: KeyboardEvent) => {
488
- if (event.key === 'Escape') {
489
- // Ignore IME composition-cancel, and defer to any popover/menu layered
490
- // on top of this dialog so a single Escape closes only the top-most
491
- // layer (the popover's own focus trap handles it and stops propagation).
492
- if (isImeKeyEvent(event) || hasActiveFocusTrapEscape()) {
493
- return;
494
- }
495
- event.preventDefault();
496
- if (allowEscape) {
497
- onOpenChange(false);
498
- }
499
- }
500
- };
501
-
502
- dialog.addEventListener('keydown', handleKeyDown);
503
- return () => dialog.removeEventListener('keydown', handleKeyDown);
504
- }, [isOpen, isInline, allowEscape, onOpenChange]);
553
+ // Join the shared layer dismissal stack. The stack owns the Escape listener
554
+ // and routes each press to the top-most layer, so this dialog does not listen
555
+ // itself — that is what stops a modal opened from inside another modal (or a
556
+ // popover opened inside this one) from closing two layers on one press.
557
+ //
558
+ // A `required` dialog registers as `block`: it must not be dismissed, and the
559
+ // press must not fall through and dismiss a layer behind it either.
560
+ //
561
+ // Inline mode opts out — it renders dialog content in normal flow, with
562
+ // nothing layered over anything.
563
+ const {shouldDismissOnCloseRequest} = useLayerDismissal({
564
+ isActive: isOpen,
565
+ isEnabled: !isInline,
566
+ escapeBehavior: allowEscape ? 'close' : 'block',
567
+ onDismiss: () => {
568
+ onOpenChange(false);
569
+ },
570
+ });
505
571
 
506
572
  // Dev-time guardrail: an open modal should always have an accessible name.
507
573
  // The header-title check reads the DOM, so this stays in an effect; the ref
@@ -537,12 +603,18 @@ export function Dialog({
537
603
  }
538
604
  };
539
605
 
540
- // Handle native cancel event (browser Escape handling)
606
+ // The native `cancel` event is the browser's own close-watcher firing: an
607
+ // Android back gesture, or a close request the stack never saw a press for.
608
+ // Escape presses the stack owns never arrive here — it preventDefault()s
609
+ // those, which suppresses the close watcher.
610
+ //
611
+ // Always preventDefault so the browser cannot close a controlled <dialog>
612
+ // behind React's back, then answer the request with the stack's own rules:
613
+ // only the top-most layer dismisses, a `required` dialog swallows it, and
614
+ // nothing dismisses while an IME composition is in progress.
541
615
  const handleCancel = (event: React.SyntheticEvent<HTMLDialogElement>) => {
542
616
  event.preventDefault();
543
- // Defer to a popover/menu layered on top of this dialog; it will dismiss
544
- // itself on the same Escape press.
545
- if (hasActiveFocusTrapEscape()) {
617
+ if (!shouldDismissOnCloseRequest()) {
546
618
  return;
547
619
  }
548
620
  if (allowEscape) {
@@ -550,7 +622,6 @@ export function Dialog({
550
622
  }
551
623
  };
552
624
 
553
- // Shared inner content wrapper
554
625
  const innerContent = (
555
626
  <div
556
627
  {...stylex.props(
@@ -559,22 +630,14 @@ export function Dialog({
559
630
  useThemeDefault
560
631
  ? {
561
632
  useThemeDefault: 'dialog',
562
- maxHeight: isFullscreen
563
- ? undefined
564
- : typeof maxHeight === 'number'
565
- ? `${maxHeight}px`
566
- : maxHeight,
633
+ maxHeight: standardSizing?.maxHeight,
567
634
  }
568
635
  : {
569
636
  paddingInnerX: paddingToken,
570
637
  paddingInnerY: paddingToken,
571
638
  paddingOuterX: paddingToken,
572
639
  paddingOuterY: paddingToken,
573
- maxHeight: isFullscreen
574
- ? undefined
575
- : typeof maxHeight === 'number'
576
- ? `${maxHeight}px`
577
- : maxHeight,
640
+ maxHeight: standardSizing?.maxHeight,
578
641
  },
579
642
  ),
580
643
  !useThemeDefault &&
@@ -589,6 +652,7 @@ export function Dialog({
589
652
  !useThemeDefault &&
590
653
  effectivePadding !== 4 &&
591
654
  containerPaddingBlockEndVarStyles[effectivePadding],
655
+ isFullscreen && useThemeDefault && styles.fullscreenSafeArea,
592
656
  )}>
593
657
  <DialogContext value={dialogContextValue}>{children}</DialogContext>
594
658
  </div>
@@ -612,7 +676,12 @@ export function Dialog({
612
676
  stylex.props(
613
677
  styles.inlineWrapper,
614
678
  overlayPaddingReset.reset,
615
- !isFullscreen && dynamicStyles.sizing(width, maxHeight),
679
+ standardSizing &&
680
+ dynamicStyles.sizing(
681
+ standardSizing.width,
682
+ standardSizing.maxWidth,
683
+ standardSizing.maxHeight,
684
+ ),
616
685
  isFullscreen && styles.fullscreen,
617
686
  xstyle,
618
687
  ),
@@ -623,7 +692,7 @@ export function Dialog({
623
692
  (props as Record<string, unknown>)['data-testid'] as
624
693
  string | undefined
625
694
  }>
626
- {innerContent}
695
+ <LayerDepthProvider>{innerContent}</LayerDepthProvider>
627
696
  </div>
628
697
  );
629
698
  }
@@ -632,7 +701,7 @@ export function Dialog({
632
701
 
633
702
  return (
634
703
  <dialog
635
- ref={mergeRefs(ref, attachDialog)}
704
+ ref={mergedDialogRef}
636
705
  {...safeProps}
637
706
  {...mergeProps(
638
707
  themeProps('dialog', {variant}),
@@ -641,7 +710,12 @@ export function Dialog({
641
710
  overlayPaddingReset.reset,
642
711
  isOpen && styles.open,
643
712
  styles.backdrop,
644
- !isFullscreen && dynamicStyles.sizing(width, maxHeight),
713
+ standardSizing &&
714
+ dynamicStyles.sizing(
715
+ standardSizing.width,
716
+ standardSizing.maxWidth,
717
+ standardSizing.maxHeight,
718
+ ),
645
719
  hasPosition &&
646
720
  (() => {
647
721
  const o = resolveDialogPositionOffsets(position);
@@ -653,6 +727,7 @@ export function Dialog({
653
727
  );
654
728
  })(),
655
729
  isFullscreen && styles.fullscreen,
730
+ isFullscreen && isOpen && styles.fullscreenOpen,
656
731
  xstyle,
657
732
  ),
658
733
  className,
@@ -665,7 +740,7 @@ export function Dialog({
665
740
  // imperatively in `attachDialog`; a consumer-provided aria-labelledby
666
741
  // flows through {...safeProps} above and wins.
667
742
  {...(purpose === 'required' ? {role: 'alertdialog'} : undefined)}>
668
- {innerContent}
743
+ <LayerDepthProvider>{innerContent}</LayerDepthProvider>
669
744
  </dialog>
670
745
  );
671
746
  }
@@ -89,6 +89,12 @@ export const docs = {
89
89
  type: '() => void',
90
90
  description: 'Callback fired when the trigger button is clicked.',
91
91
  },
92
+ {
93
+ name: 'placement',
94
+ type: "'above' | 'below' | 'start' | 'end'",
95
+ description: 'Position placement for the menu popover relative to the trigger button.',
96
+ default: "'below'",
97
+ },
92
98
  {
93
99
  name: 'hasChevron',
94
100
  type: 'boolean',
@@ -701,11 +701,14 @@ describe('DropdownMenuSubMenu theming slots', () => {
701
701
  name: /Move to/,
702
702
  hidden: true,
703
703
  });
704
- // The indicator-icon slot wraps the chevron affordance inside the trigger
705
- // row.
706
- expect(
707
- trigger.querySelector('.astryx-dropdown-menu-indicator-icon'),
708
- ).toBeInTheDocument();
704
+ // The indicator-icon slot sits on the chevron glyph itself (the element
705
+ // that carries the icon size), so a theme can restyle its size/color
706
+ // directly.
707
+ const indicator = trigger.querySelector(
708
+ '.astryx-dropdown-menu-indicator-icon',
709
+ );
710
+ expect(indicator).toBeInTheDocument();
711
+ expect(indicator).toHaveClass('astryx-icon');
709
712
  });
710
713
  });
711
714
 
@@ -476,20 +476,17 @@ export function DropdownMenuSubMenu(
476
476
  );
477
477
 
478
478
  const endAffordance = hasSpinner ? (
479
- <span
480
- {...mergeProps(
481
- themeProps('dropdown-menu-indicator-icon'),
482
- stylex.props(triggerStyles.caret),
483
- )}>
479
+ <span {...stylex.props(triggerStyles.caret)}>
484
480
  <Spinner size="sm" />
485
481
  </span>
486
482
  ) : (
487
- <span
488
- {...mergeProps(
489
- themeProps('dropdown-menu-indicator-icon'),
490
- stylex.props(triggerStyles.caret),
491
- )}>
492
- <Icon icon="chevronRight" size="sm" color="secondary" />
483
+ <span {...stylex.props(triggerStyles.caret)}>
484
+ <Icon
485
+ icon="chevronRight"
486
+ size="sm"
487
+ color="secondary"
488
+ {...themeProps('dropdown-menu-indicator-icon')}
489
+ />
493
490
  </span>
494
491
  );
495
492
 
@@ -39,8 +39,8 @@ export const docs = {
39
39
  ],
40
40
  vars: [
41
41
  {name: '--_field-radius', description: 'Border radius of input fields', default: 'var(--radius-element)', private: true},
42
- {name: '--_input-clear-hit-inset', description: 'Outset of the clear (\u2715) button\u2019s invisible hit area, applied to a ::after overlay. 0 on a fine pointer; negative on a coarse one, which grows the 20px button to the 24px touch target without changing what is drawn.', default: '0px', private: true},
43
- {name: '--_input-clear-hit-content', description: 'Whether the clear (\u2715) button\u2019s invisible hit overlay exists. `none` on a fine pointer, so no ::after is generated and hover still reaches the glyph; `""` on a coarse one, where the overlay provides the 24px touch target.', default: 'none', private: true},
42
+ {name: '--_input-clear-hit-inset', description: 'Outset of the clear (\u2715) button\'s invisible hit area, applied to a ::after overlay. 0 on a fine pointer; negative on a coarse one, which grows the 20px button to the 24px touch target without changing what is drawn.', default: '0px', private: true},
43
+ {name: '--_input-clear-hit-content', description: 'Whether the clear (\u2715) button\'s invisible hit overlay exists. `none` on a fine pointer, so no ::after is generated and hover still reaches the glyph; `""` on a coarse one, where the overlay provides the 24px touch target.', default: 'none', private: true},
44
44
  ],
45
45
  derived: [
46
46
  {property: 'borderRadius', vars: ['--_field-radius']},
@@ -60,6 +60,17 @@ export const docs = {
60
60
  description: 'ID for the input element (used for the label htmlFor attribute).',
61
61
  required: true,
62
62
  },
63
+ {
64
+ name: 'labelID',
65
+ type: 'string',
66
+ description: 'ID applied to the label element itself for group accessibility.',
67
+ },
68
+ {
69
+ name: 'isGroupLabel',
70
+ type: 'boolean',
71
+ description: 'Renders the label as a span for control groups (radiogroup, checkbox list).',
72
+ default: 'false',
73
+ },
63
74
  {
64
75
  name: 'children',
65
76
  type: 'ReactNode',
@@ -15,6 +15,7 @@ import userEvent from '@testing-library/user-event';
15
15
  import {TestIcon} from '../__tests__/TestIcon';
16
16
  import {InternationalizationProvider} from '../i18n';
17
17
  import {FieldLabel} from './FieldLabel';
18
+ import {themeProps} from '../utils/themeProps';
18
19
 
19
20
  describe('FieldLabel', () => {
20
21
  it('renders label text', () => {
@@ -197,4 +198,32 @@ describe('FieldLabel', () => {
197
198
  expect(description.closest('label')).toBeNull();
198
199
  });
199
200
  });
201
+
202
+ describe('a control can name its own label target', () => {
203
+ it('composes a passed target onto the field-label one', () => {
204
+ // How CheckboxInput and Switch reach their label: the control spreads
205
+ // its own themeProps in, and both classes end up on the same element,
206
+ // so a theme can style every label or just this kind.
207
+ render(
208
+ <FieldLabel
209
+ {...themeProps('checkbox-label')}
210
+ label="Notify me"
211
+ inputID="notify-input"
212
+ />,
213
+ );
214
+ const label = screen.getByText('Notify me').closest('label');
215
+ expect(label).toHaveClass('astryx-field-label');
216
+ expect(label).toHaveClass('astryx-checkbox-label');
217
+ });
218
+
219
+ it('describes no placement of its own', () => {
220
+ // The label cannot know how its caller arranged it, so it says nothing:
221
+ // a `data-layout` here would be a claim that is wrong for at least one
222
+ // caller (Field's horizontal-labels puts a label beside its control),
223
+ // and a consumer could set it untruthfully.
224
+ render(<FieldLabel label="Email" inputID="email-input" />);
225
+ const label = screen.getByText('Email').closest('label');
226
+ expect(label).not.toHaveAttribute('data-layout');
227
+ });
228
+ });
200
229
  });
@@ -285,6 +285,13 @@ export function FieldLabel({
285
285
  htmlFor={isGroupLabel ? undefined : inputID}
286
286
  {...rest}
287
287
  {...mergeProps(
288
+ // A control that knows what kind of label this is passes its own
289
+ // target down (CheckboxInput's `checkbox-label`, Switch's
290
+ // `switch-label`); it arrives as `className` and composes onto this
291
+ // one. The label itself does not describe its own placement — it
292
+ // cannot know it, and any encoding it guessed would be wrong for a
293
+ // caller that arranges labels differently (Field's
294
+ // `horizontal-labels`).
288
295
  themeProps('field-label'),
289
296
  stylex.props(
290
297
  styles.label,
@@ -54,13 +54,14 @@ export type {
54
54
  InputStatus as FileInputStatus,
55
55
  InputStatusType as FileInputStatusType,
56
56
  } from '../Field';
57
- import {mergeProps, mergeRefs} from '../utils';
57
+ import {mergeProps} from '../utils';
58
58
  import type {BaseProps} from '../BaseProps';
59
59
  import type {SizeValue} from '../utils/types';
60
60
  import {themeProps} from '../utils/themeProps';
61
61
  import {useTranslator} from '../i18n';
62
62
  import type {TranslatorFn} from '../i18n';
63
63
 
64
+ import {useMergedRefs} from '../hooks/useMergedRefs';
64
65
  function formatFileSize(bytes: number): string {
65
66
  if (bytes < 1024) {
66
67
  return `${bytes} B`;
@@ -827,7 +828,7 @@ export function FileInput({
827
828
  </VisuallyHidden>
828
829
  <input
829
830
  {...rest}
830
- ref={mergeRefs(ref, inputRef)}
831
+ ref={useMergedRefs(ref, inputRef)}
831
832
  id={id}
832
833
  type="file"
833
834
  accept={accept}
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import {render, screen} from '@testing-library/react';
9
- import {describe, it, expect} from 'vitest';
9
+ import {describe, it, expect, vi} from 'vitest';
10
10
  import {Heading} from './Heading';
11
11
 
12
12
  describe('Heading', () => {
@@ -16,6 +16,28 @@ describe('Heading', () => {
16
16
  expect(screen.getByText('Page Title')).toBeInTheDocument();
17
17
  });
18
18
 
19
+ it('keeps a forwarded ref attached across rerenders', () => {
20
+ const ref = vi.fn();
21
+ const {rerender} = render(
22
+ <Heading ref={ref} level={1}>
23
+ Before
24
+ </Heading>,
25
+ );
26
+
27
+ const element = screen.getByText('Before');
28
+ expect(ref).toHaveBeenLastCalledWith(element);
29
+ ref.mockClear();
30
+
31
+ rerender(
32
+ <Heading ref={ref} level={1}>
33
+ After
34
+ </Heading>,
35
+ );
36
+
37
+ expect(ref).not.toHaveBeenCalled();
38
+ expect(screen.getByText('After')).toBe(element);
39
+ });
40
+
19
41
  it('renders h1 for level 1', () => {
20
42
  render(<Heading level={1}>H1</Heading>);
21
43
  const element = screen.getByText('H1');
@@ -43,7 +43,8 @@ import {
43
43
  import {useTruncation} from '../Text/useTruncation';
44
44
  import {resolveStyleColor} from '../Text/Text';
45
45
  import type {LayerPlacement} from '../Layer';
46
- import {mergeProps, mergeRefs} from '../utils';
46
+ import {mergeProps} from '../utils';
47
+ import {useMergedRefs} from '../hooks/useMergedRefs';
47
48
  import type {BaseProps} from '../BaseProps';
48
49
  import {themeProps} from '../utils/themeProps';
49
50
 
@@ -242,13 +243,16 @@ export function Heading({
242
243
  // Ref for the heading element (used as tooltip anchor)
243
244
  const headingRef = useRef<HTMLHeadingElement>(null);
244
245
 
246
+ // Keep the merged ref stable across rerenders.
247
+ const mergedRef = useMergedRefs(ref, truncation.ref, headingRef);
248
+
245
249
  // Build inline style for -webkit-line-clamp (dynamic value)
246
250
  const inlineStyle = maxLines > 1 ? {WebkitLineClamp: maxLines} : undefined;
247
251
 
248
252
  return (
249
253
  <>
250
254
  <Component
251
- ref={mergeRefs(ref, truncation.ref, headingRef)}
255
+ ref={mergedRef}
252
256
  {...mergeProps(
253
257
  themeProps('heading', {level, color, ...(type && {type})}),
254
258
  stylex.props(
@@ -16,7 +16,10 @@ export const docs = {
16
16
  },
17
17
  theming: {
18
18
  targets: [
19
- {className: 'astryx-hovercard'},
19
+ {className: 'astryx-hover-card'},
20
+ // Still emitted beside the names above, so themes written against
21
+ // them keep working. Drop in the next major.
22
+ {className: 'astryx-hovercard', deprecatedFor: 'hover-card'},
20
23
  ],
21
24
  vars: [
22
25
  {name: '--_hovercard-radius', description: 'Border radius of the hover card', default: 'var(--radius-container)', private: true},
@@ -109,6 +112,11 @@ export const docs = {
109
112
  type: 'boolean',
110
113
  description: 'Whether the hover card should be shown on mount. Still dismissible.',
111
114
  },
115
+ {
116
+ name: 'isOpen',
117
+ type: 'boolean',
118
+ description: 'Controlled open state for the hover card.',
119
+ },
112
120
  ],
113
121
  },
114
122
  ],
@@ -139,7 +147,10 @@ export const docsZh = {
139
147
  displayName: 'Hover Card',
140
148
  theming: {
141
149
  targets: [
142
- {className: 'astryx-hovercard'},
150
+ {className: 'astryx-hover-card'},
151
+ // Still emitted beside the names above, so themes written against
152
+ // them keep working. Drop in the next major.
153
+ {className: 'astryx-hovercard', deprecatedFor: 'hover-card'},
143
154
  ],
144
155
  vars: [
145
156
  {name: '--_hovercard-radius', description: 'Border radius of the hover card', default: 'var(--radius-container)', private: true},