@astryxdesign/core 0.5.0 → 0.5.1-canary.046f6ea

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 (622) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +45 -20
  5. package/dist/AspectRatio/AspectRatio.d.ts +6 -6
  6. package/dist/Avatar/Avatar.d.ts +25 -1
  7. package/dist/Avatar/Avatar.d.ts.map +1 -1
  8. package/dist/Avatar/Avatar.js +43 -9
  9. package/dist/Avatar/index.d.ts +2 -2
  10. package/dist/Avatar/index.d.ts.map +1 -1
  11. package/dist/Avatar/index.js +1 -1
  12. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  13. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  14. package/dist/AvatarGroup/AvatarGroup.js +5 -2
  15. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  16. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  17. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroupOverflow.js +11 -7
  19. package/dist/Badge/Badge.d.ts.map +1 -1
  20. package/dist/Badge/Badge.js +26 -2
  21. package/dist/Banner/Banner.d.ts +10 -1
  22. package/dist/Banner/Banner.d.ts.map +1 -1
  23. package/dist/Banner/Banner.js +11 -2
  24. package/dist/Button/Button.d.ts.map +1 -1
  25. package/dist/Button/Button.js +8 -7
  26. package/dist/Calendar/Calendar.d.ts +4 -2
  27. package/dist/Calendar/Calendar.d.ts.map +1 -1
  28. package/dist/Calendar/Calendar.js +15 -21
  29. package/dist/Calendar/hooks/useCalendarDays.js +4 -6
  30. package/dist/Calendar/hooks/useCalendarNavigation.js +4 -6
  31. package/dist/Calendar/styles.d.ts +5 -20
  32. package/dist/Calendar/styles.d.ts.map +1 -1
  33. package/dist/Calendar/styles.js +15 -17
  34. package/dist/Card/Card.d.ts +12 -12
  35. package/dist/Card/Card.d.ts.map +1 -1
  36. package/dist/Card/Card.js +17 -9
  37. package/dist/Card/index.d.ts +35 -1
  38. package/dist/Card/index.d.ts.map +1 -1
  39. package/dist/Card/index.js +21 -1
  40. package/dist/Carousel/Carousel.d.ts.map +1 -1
  41. package/dist/Carousel/Carousel.js +108 -7
  42. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  43. package/dist/CheckboxInput/CheckboxInput.js +7 -1
  44. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  45. package/dist/CodeBlock/CodeBlock.js +15 -4
  46. package/dist/CodeBlock/highlightRanges.js +1 -1
  47. package/dist/CodeBlock/highlightStyles.js +13 -13
  48. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  49. package/dist/CommandPalette/CommandPaletteItem.js +2 -7
  50. package/dist/ComplexSelector/ComplexSelector.d.ts +10 -2
  51. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  52. package/dist/ComplexSelector/ComplexSelector.js +14 -7
  53. package/dist/DateInput/DateInput.d.ts +43 -0
  54. package/dist/DateInput/DateInput.d.ts.map +1 -1
  55. package/dist/DateInput/DateInput.js +22 -5
  56. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  57. package/dist/DateInput/MonthScroller.js +5 -3
  58. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
  59. package/dist/DateInput/MonthYearWheels.js +6 -4
  60. package/dist/DateInput/NativeDateField.d.ts +10 -0
  61. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  62. package/dist/DateInput/NativeDateField.js +494 -0
  63. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  64. package/dist/DateInput/TouchDateField.js +52 -25
  65. package/dist/DateInput/Wheel.d.ts.map +1 -1
  66. package/dist/DateInput/Wheel.js +1 -0
  67. package/dist/DateInput/index.d.ts +1 -1
  68. package/dist/DateInput/index.d.ts.map +1 -1
  69. package/dist/DateInput/nativeDateSegments.d.ts +22 -0
  70. package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
  71. package/dist/DateInput/nativeDateSegments.js +111 -0
  72. package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
  73. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  74. package/dist/DateRangeInput/DateRangeInput.js +3 -5
  75. package/dist/DateTimeInput/DateTimeInput.d.ts +23 -24
  76. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  77. package/dist/DateTimeInput/DateTimeInput.js +35 -10
  78. package/dist/DateTimeInput/TouchDateTimeField.d.ts +6 -0
  79. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -0
  80. package/dist/DateTimeInput/TouchDateTimeField.js +1021 -0
  81. package/dist/Dialog/Dialog.d.ts +16 -2
  82. package/dist/Dialog/Dialog.d.ts.map +1 -1
  83. package/dist/Dialog/Dialog.js +28 -7
  84. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  85. package/dist/DropdownMenu/DropdownMenu.js +4 -13
  86. package/dist/Field/FieldLabel.d.ts.map +1 -1
  87. package/dist/Field/FieldLabel.js +9 -1
  88. package/dist/Field/InputClearButton.d.ts +9 -3
  89. package/dist/Field/InputClearButton.d.ts.map +1 -1
  90. package/dist/Field/InputClearButton.js +14 -3
  91. package/dist/Heading/Heading.d.ts.map +1 -1
  92. package/dist/Heading/Heading.js +0 -1
  93. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  94. package/dist/HoverCard/HoverCard.js +104 -3
  95. package/dist/HoverCard/useHoverCard.d.ts +14 -2
  96. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  97. package/dist/HoverCard/useHoverCard.js +7 -1
  98. package/dist/Icon/Icon.d.ts +4 -2
  99. package/dist/Icon/Icon.d.ts.map +1 -1
  100. package/dist/Icon/defaultIcons.d.ts +3 -2
  101. package/dist/Icon/defaultIcons.d.ts.map +1 -1
  102. package/dist/Icon/defaultIcons.js +7 -0
  103. package/dist/Icon/globalIconRegistry.d.ts +13 -0
  104. package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
  105. package/dist/Icon/globalIconRegistry.js +34 -6
  106. package/dist/Icon/index.d.ts +1 -1
  107. package/dist/Icon/index.d.ts.map +1 -1
  108. package/dist/Icon/useIcon.d.ts +5 -2
  109. package/dist/Icon/useIcon.d.ts.map +1 -1
  110. package/dist/Icon/useIcon.js +3 -0
  111. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  112. package/dist/Indicator/CheckboxIndicator.js +6 -2
  113. package/dist/Item/Item.d.ts.map +1 -1
  114. package/dist/Item/Item.js +2 -2
  115. package/dist/Kbd/Kbd.d.ts.map +1 -1
  116. package/dist/Kbd/Kbd.js +2 -26
  117. package/dist/Layer/gestureCounter.d.ts +8 -0
  118. package/dist/Layer/gestureCounter.d.ts.map +1 -0
  119. package/dist/Layer/gestureCounter.js +53 -0
  120. package/dist/Layer/useLayer.d.ts +23 -13
  121. package/dist/Layer/useLayer.d.ts.map +1 -1
  122. package/dist/Layer/useLayer.js +146 -24
  123. package/dist/List/List.d.ts +1 -1
  124. package/dist/List/List.d.ts.map +1 -1
  125. package/dist/List/List.js +15 -4
  126. package/dist/Markdown/Markdown.d.ts +1 -1
  127. package/dist/Markdown/Markdown.d.ts.map +1 -1
  128. package/dist/Markdown/Markdown.js +20 -7
  129. package/dist/Markdown/parser.d.ts.map +1 -1
  130. package/dist/Markdown/parser.js +5 -3
  131. package/dist/MetadataList/MetadataListItem.d.ts +1 -1
  132. package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
  133. package/dist/MetadataList/MetadataListItem.js +4 -1
  134. package/dist/MultiSelector/MultiSelector.d.ts +18 -1
  135. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  136. package/dist/MultiSelector/MultiSelector.js +58 -11
  137. package/dist/MultiSelector/hooks.d.ts +7 -1
  138. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  139. package/dist/MultiSelector/hooks.js +3 -2
  140. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  141. package/dist/NavIcon/NavIcon.js +5 -1
  142. package/dist/NavItem/navItemStyles.stylex.d.ts +0 -8
  143. package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
  144. package/dist/NavItem/navItemStyles.stylex.js +0 -2
  145. package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
  146. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  147. package/dist/NavMenu/NavHeadingMenu.js +7 -4
  148. package/dist/NumberInput/NumberInput.d.ts +6 -1
  149. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  150. package/dist/NumberInput/NumberInput.js +95 -126
  151. package/dist/NumberInput/numberInputCommit.d.ts +34 -0
  152. package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
  153. package/dist/NumberInput/numberInputCommit.js +71 -0
  154. package/dist/NumberInput/numberParser.d.ts +64 -0
  155. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  156. package/dist/NumberInput/numberParser.js +350 -0
  157. package/dist/Outline/Outline.d.ts.map +1 -1
  158. package/dist/Outline/Outline.js +2 -3
  159. package/dist/OverflowList/OverflowList.d.ts +41 -1
  160. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  161. package/dist/OverflowList/OverflowList.js +43 -2
  162. package/dist/Popover/Popover.d.ts.map +1 -1
  163. package/dist/Popover/Popover.js +8 -14
  164. package/dist/Popover/usePopover.d.ts +15 -41
  165. package/dist/Popover/usePopover.d.ts.map +1 -1
  166. package/dist/Popover/usePopover.js +26 -7
  167. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchValueEditor.js +91 -18
  169. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  170. package/dist/PowerSearch/formatFilterValue.js +4 -2
  171. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  172. package/dist/ProgressBar/ProgressBar.js +18 -5
  173. package/dist/Resizable/useResizable.d.ts +19 -1
  174. package/dist/Resizable/useResizable.d.ts.map +1 -1
  175. package/dist/Resizable/useResizable.js +104 -38
  176. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  177. package/dist/SelectableCard/SelectableCard.js +9 -0
  178. package/dist/Selector/Selector.d.ts +18 -1
  179. package/dist/Selector/Selector.d.ts.map +1 -1
  180. package/dist/Selector/Selector.js +92 -21
  181. package/dist/Selector/hooks.d.ts +7 -1
  182. package/dist/Selector/hooks.d.ts.map +1 -1
  183. package/dist/Selector/hooks.js +3 -2
  184. package/dist/SideNav/SideNav.d.ts +6 -1
  185. package/dist/SideNav/SideNav.d.ts.map +1 -1
  186. package/dist/SideNav/SideNav.js +57 -27
  187. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  188. package/dist/SideNav/SideNavHeading.js +5 -4
  189. package/dist/SideNav/SideNavItem.d.ts +29 -4
  190. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  191. package/dist/SideNav/SideNavItem.js +75 -20
  192. package/dist/Slider/Slider.d.ts.map +1 -1
  193. package/dist/Slider/Slider.js +34 -2
  194. package/dist/Spinner/Spinner.d.ts +3 -1
  195. package/dist/Spinner/Spinner.d.ts.map +1 -1
  196. package/dist/Spinner/Spinner.js +199 -20
  197. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  198. package/dist/StatusDot/StatusDot.js +6 -1
  199. package/dist/Stepper/Step.d.ts.map +1 -1
  200. package/dist/Stepper/Step.js +7 -6
  201. package/dist/Switch/Switch.d.ts.map +1 -1
  202. package/dist/Switch/Switch.js +5 -1
  203. package/dist/Table/BaseTable.d.ts.map +1 -1
  204. package/dist/Table/BaseTable.js +6 -1
  205. package/dist/Table/Table.d.ts.map +1 -1
  206. package/dist/Table/Table.js +3 -6
  207. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  208. package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
  209. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
  210. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  211. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +34 -3
  212. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  213. package/dist/Table/plugins/selection/useTableSelection.js +25 -1
  214. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  215. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  216. package/dist/Text/Text.d.ts.map +1 -1
  217. package/dist/Text/Text.js +0 -1
  218. package/dist/TextArea/TextArea.d.ts.map +1 -1
  219. package/dist/TextArea/TextArea.js +13 -8
  220. package/dist/Timestamp/Timestamp.d.ts +1 -1
  221. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  222. package/dist/Timestamp/Timestamp.js +10 -18
  223. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  224. package/dist/Timestamp/formatInstant.js +10 -5
  225. package/dist/Toast/Toast.d.ts +17 -2
  226. package/dist/Toast/Toast.d.ts.map +1 -1
  227. package/dist/Toast/Toast.js +77 -11
  228. package/dist/Toast/ToastViewport.d.ts +1 -0
  229. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  230. package/dist/Toast/ToastViewport.js +76 -21
  231. package/dist/Toast/index.d.ts +1 -1
  232. package/dist/Toast/index.d.ts.map +1 -1
  233. package/dist/Toast/types.d.ts +38 -0
  234. package/dist/Toast/types.d.ts.map +1 -1
  235. package/dist/Toast/useToastGesture.d.ts +26 -0
  236. package/dist/Toast/useToastGesture.d.ts.map +1 -0
  237. package/dist/Toast/useToastGesture.js +223 -0
  238. package/dist/Token/Token.d.ts +1 -1
  239. package/dist/Token/Token.d.ts.map +1 -1
  240. package/dist/Token/Token.js +23 -12
  241. package/dist/Token/TokenLink.d.ts +1 -1
  242. package/dist/Token/TokenLink.d.ts.map +1 -1
  243. package/dist/Token/TokenLink.js +5 -2
  244. package/dist/Tokenizer/Tokenizer.d.ts +12 -1
  245. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  246. package/dist/Tokenizer/Tokenizer.js +31 -21
  247. package/dist/TopNav/TopNavHeading.js +2 -2
  248. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  249. package/dist/TopNav/TopNavItem.js +3 -3
  250. package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
  251. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  252. package/dist/TopNav/TopNavMegaMenu.js +30 -9
  253. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  254. package/dist/TopNav/TopNavMegaMenuItem.js +3 -3
  255. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  256. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  257. package/dist/TopNav/TopNavMenu.js +21 -6
  258. package/dist/TreeList/TreeList.d.ts +1 -1
  259. package/dist/TreeList/TreeList.d.ts.map +1 -1
  260. package/dist/TreeList/TreeList.js +7 -2
  261. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  262. package/dist/TreeList/TreeListItem.js +2 -2
  263. package/dist/Typeahead/BaseTypeahead.d.ts +33 -0
  264. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  265. package/dist/Typeahead/BaseTypeahead.js +51 -8
  266. package/dist/Typeahead/Typeahead.d.ts +8 -1
  267. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  268. package/dist/Typeahead/Typeahead.js +2 -0
  269. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  270. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  271. package/dist/Typeahead/TypeaheadItem.js +7 -2
  272. package/dist/astryx.css +87 -22
  273. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  274. package/dist/hooks/useHotkeys.js +3 -25
  275. package/dist/hooks/useOverflow.d.ts.map +1 -1
  276. package/dist/hooks/useOverflow.js +14 -4
  277. package/dist/i18n/InternationalizationContext.d.ts +2 -0
  278. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  279. package/dist/i18n/InternationalizationContext.js +3 -1
  280. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  281. package/dist/i18n/InternationalizationProvider.js +3 -1
  282. package/dist/i18n/resolve.d.ts +1 -1
  283. package/dist/i18n/resolve.d.ts.map +1 -1
  284. package/dist/i18n/resolve.js +37 -38
  285. package/dist/i18n/useTranslator.d.ts.map +1 -1
  286. package/dist/i18n/useTranslator.js +2 -3
  287. package/dist/index.d.ts +1 -1
  288. package/dist/index.d.ts.map +1 -1
  289. package/dist/theme/Theme.d.ts.map +1 -1
  290. package/dist/theme/Theme.js +46 -10
  291. package/dist/theme/defineTheme.d.ts +9 -3
  292. package/dist/theme/defineTheme.d.ts.map +1 -1
  293. package/dist/theme/defineTheme.js +5 -0
  294. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  295. package/dist/theme/derivedVarRegistry.js +24 -4
  296. package/dist/theme/generateThemeRules.d.ts +21 -0
  297. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  298. package/dist/theme/generateThemeRules.js +26 -0
  299. package/dist/theme/syntax/tokens.d.ts +1 -1
  300. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  301. package/dist/theme/syntax/tokens.js +5 -2
  302. package/dist/theme/useTheme.d.ts.map +1 -1
  303. package/dist/theme/useTheme.js +6 -7
  304. package/dist/utils/dateParser.d.ts +5 -8
  305. package/dist/utils/dateParser.d.ts.map +1 -1
  306. package/dist/utils/dateParser.js +10 -11
  307. package/dist/utils/focusOutline.stylex.d.ts +25 -0
  308. package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
  309. package/dist/utils/focusOutline.stylex.js +15 -0
  310. package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
  311. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
  312. package/dist/utils/interactionOverlay.stylex.js +42 -0
  313. package/dist/utils/isApplePlatform.d.ts +18 -0
  314. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  315. package/dist/utils/isApplePlatform.js +37 -0
  316. package/dist/utils/plainDate.d.ts +11 -0
  317. package/dist/utils/plainDate.d.ts.map +1 -1
  318. package/dist/utils/plainDate.js +20 -4
  319. package/locales/af-ZA.json +7 -7
  320. package/locales/ar-SA.json +7 -7
  321. package/locales/ca-ES.json +6 -6
  322. package/locales/cs-CZ.json +7 -7
  323. package/locales/da-DK.json +7 -7
  324. package/locales/de-DE.json +7 -7
  325. package/locales/el-GR.json +7 -7
  326. package/locales/en.json +178 -6
  327. package/locales/es-ES.json +6 -6
  328. package/locales/fi-FI.json +7 -7
  329. package/locales/fr-FR.json +7 -7
  330. package/locales/he-IL.json +7 -7
  331. package/locales/hu-HU.json +7 -7
  332. package/locales/it-IT.json +7 -7
  333. package/locales/ja-JP.json +7 -7
  334. package/locales/ko-KR.json +7 -7
  335. package/locales/nl-NL.json +7 -7
  336. package/locales/no-NO.json +7 -7
  337. package/locales/pl-PL.json +7 -7
  338. package/locales/pseudo.json +130 -1
  339. package/locales/pt-BR.json +7 -7
  340. package/locales/pt-PT.json +7 -7
  341. package/locales/ro-RO.json +7 -7
  342. package/locales/ru-RU.json +7 -7
  343. package/locales/sr-SP.json +7 -7
  344. package/locales/sv-SE.json +7 -7
  345. package/locales/tr-TR.json +7 -7
  346. package/locales/uk-UA.json +7 -7
  347. package/locales/vi-VN.json +7 -7
  348. package/locales/zh-CN.json +7 -7
  349. package/locales/zh-TW.json +7 -7
  350. package/package.json +4 -5
  351. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  352. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  353. package/src/AlertDialog/AlertDialog.tsx +62 -20
  354. package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
  355. package/src/AspectRatio/AspectRatio.tsx +6 -6
  356. package/src/Avatar/Avatar.doc.mjs +12 -2
  357. package/src/Avatar/Avatar.test.tsx +80 -0
  358. package/src/Avatar/Avatar.tsx +64 -14
  359. package/src/Avatar/index.ts +2 -2
  360. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  361. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  362. package/src/AvatarGroup/AvatarGroup.tsx +12 -4
  363. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  364. package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
  365. package/src/Badge/Badge.doc.mjs +3 -2
  366. package/src/Badge/Badge.test.tsx +32 -3
  367. package/src/Badge/Badge.tsx +42 -1
  368. package/src/Banner/Banner.doc.mjs +9 -0
  369. package/src/Banner/Banner.test.tsx +76 -11
  370. package/src/Banner/Banner.tsx +21 -2
  371. package/src/Button/Button.doc.mjs +2 -1
  372. package/src/Button/Button.test.tsx +19 -4
  373. package/src/Button/Button.tsx +9 -29
  374. package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
  375. package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
  376. package/src/Calendar/Calendar.doc.mjs +4 -4
  377. package/src/Calendar/Calendar.test.tsx +112 -0
  378. package/src/Calendar/Calendar.tsx +18 -16
  379. package/src/Calendar/hooks/useCalendarDays.ts +4 -4
  380. package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
  381. package/src/Calendar/styles.ts +48 -42
  382. package/src/Card/Card.doc.mjs +10 -7
  383. package/src/Card/Card.test.tsx +113 -19
  384. package/src/Card/Card.tsx +67 -89
  385. package/src/Card/index.ts +36 -1
  386. package/src/Carousel/Carousel.doc.mjs +3 -0
  387. package/src/Carousel/Carousel.test.tsx +360 -0
  388. package/src/Carousel/Carousel.tsx +116 -15
  389. package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -1
  390. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  391. package/src/CheckboxInput/CheckboxInput.tsx +5 -0
  392. package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
  393. package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
  394. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  395. package/src/CodeBlock/CodeBlock.tsx +20 -4
  396. package/src/CodeBlock/highlightRanges.ts +1 -1
  397. package/src/CodeBlock/highlightStyles.ts +13 -13
  398. package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
  399. package/src/ComplexSelector/ComplexSelector.doc.mjs +9 -2
  400. package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
  401. package/src/ComplexSelector/ComplexSelector.tsx +22 -12
  402. package/src/DateInput/DateInput.doc.mjs +17 -1
  403. package/src/DateInput/DateInput.test.tsx +9 -4
  404. package/src/DateInput/DateInput.tsx +54 -3
  405. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  406. package/src/DateInput/MonthScroller.tsx +5 -1
  407. package/src/DateInput/MonthYearWheels.tsx +7 -4
  408. package/src/DateInput/NativeDateField.test.tsx +635 -0
  409. package/src/DateInput/NativeDateField.tsx +641 -0
  410. package/src/DateInput/TouchDateField.tsx +83 -33
  411. package/src/DateInput/Wheel.tsx +1 -0
  412. package/src/DateInput/index.ts +1 -0
  413. package/src/DateInput/nativeDateSegments.ts +127 -0
  414. package/src/DateRangeInput/DateRangeInput.doc.mjs +3 -3
  415. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
  416. package/src/DateRangeInput/DateRangeInput.tsx +8 -13
  417. package/src/DateTimeInput/DateTimeInput.doc.mjs +39 -22
  418. package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
  419. package/src/DateTimeInput/DateTimeInput.tsx +54 -20
  420. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
  421. package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
  422. package/src/Dialog/Dialog.test.tsx +185 -18
  423. package/src/Dialog/Dialog.tsx +35 -11
  424. package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
  425. package/src/DropdownMenu/DropdownMenu.tsx +4 -13
  426. package/src/Field/Field.doc.mjs +1 -1
  427. package/src/Field/FieldLabel.test.tsx +29 -0
  428. package/src/Field/FieldLabel.tsx +7 -0
  429. package/src/Field/InputClearButton.test.tsx +15 -1
  430. package/src/Field/InputClearButton.tsx +28 -4
  431. package/src/FieldStatus/FieldStatus.doc.mjs +1 -1
  432. package/src/FileInput/FileInput.doc.mjs +1 -1
  433. package/src/Heading/Heading.tsx +0 -1
  434. package/src/HoverCard/HoverCard.doc.mjs +8 -2
  435. package/src/HoverCard/HoverCard.test.tsx +154 -4
  436. package/src/HoverCard/HoverCard.tsx +137 -3
  437. package/src/HoverCard/useHoverCard.tsx +23 -3
  438. package/src/Icon/Icon.test.tsx +55 -1
  439. package/src/Icon/Icon.tsx +5 -3
  440. package/src/Icon/defaultIcons.tsx +11 -2
  441. package/src/Icon/globalIconRegistry.test.tsx +16 -3
  442. package/src/Icon/globalIconRegistry.tsx +37 -6
  443. package/src/Icon/index.ts +1 -0
  444. package/src/Icon/useIcon.ts +9 -2
  445. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  446. package/src/Indicator/Indicator.doc.mjs +3 -1
  447. package/src/InputGroup/InputGroup.doc.mjs +1 -1
  448. package/src/Item/Item.tsx +2 -7
  449. package/src/Kbd/Kbd.test.tsx +0 -17
  450. package/src/Kbd/Kbd.tsx +2 -26
  451. package/src/Layer/gestureCounter.ts +57 -0
  452. package/src/Layer/useLayer.test.tsx +368 -16
  453. package/src/Layer/useLayer.tsx +208 -35
  454. package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
  455. package/src/List/List.test.tsx +38 -0
  456. package/src/List/List.tsx +8 -1
  457. package/src/Markdown/Markdown.test.tsx +37 -0
  458. package/src/Markdown/Markdown.tsx +16 -5
  459. package/src/Markdown/parser.test.ts +33 -0
  460. package/src/Markdown/parser.ts +9 -3
  461. package/src/MetadataList/MetadataList.test.tsx +75 -2
  462. package/src/MetadataList/MetadataListItem.tsx +5 -2
  463. package/src/MultiSelector/MultiSelector.doc.mjs +23 -2
  464. package/src/MultiSelector/MultiSelector.test.tsx +205 -0
  465. package/src/MultiSelector/MultiSelector.tsx +103 -16
  466. package/src/MultiSelector/hooks.ts +9 -2
  467. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  468. package/src/NavIcon/NavIcon.test.tsx +9 -0
  469. package/src/NavIcon/NavIcon.tsx +5 -1
  470. package/src/NavItem/navItemStyles.stylex.ts +0 -8
  471. package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
  472. package/src/NavMenu/NavHeadingMenu.tsx +7 -4
  473. package/src/NumberInput/NumberInput.doc.mjs +27 -8
  474. package/src/NumberInput/NumberInput.test.tsx +563 -8
  475. package/src/NumberInput/NumberInput.tsx +77 -131
  476. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  477. package/src/NumberInput/numberInputCommit.ts +103 -0
  478. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  479. package/src/NumberInput/numberParser.test.ts +222 -0
  480. package/src/NumberInput/numberParser.ts +403 -0
  481. package/src/Outline/Outline.tsx +2 -4
  482. package/src/OverflowList/OverflowList.doc.mjs +102 -21
  483. package/src/OverflowList/OverflowList.test.tsx +550 -4
  484. package/src/OverflowList/OverflowList.tsx +100 -2
  485. package/src/Pagination/Pagination.test.tsx +3 -2
  486. package/src/Popover/Popover.doc.mjs +2 -2
  487. package/src/Popover/Popover.test.tsx +38 -0
  488. package/src/Popover/Popover.tsx +28 -66
  489. package/src/Popover/usePopover.tsx +44 -5
  490. package/src/PowerSearch/PowerSearch.doc.mjs +1 -1
  491. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
  492. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
  493. package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
  494. package/src/PowerSearch/formatFilterValue.test.ts +16 -1
  495. package/src/PowerSearch/formatFilterValue.ts +2 -0
  496. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  497. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  498. package/src/ProgressBar/ProgressBar.tsx +28 -8
  499. package/src/RadioList/RadioList.doc.mjs +1 -1
  500. package/src/Resizable/Resizable.doc.mjs +2 -2
  501. package/src/Resizable/useResizable.doc.mjs +21 -2
  502. package/src/Resizable/useResizable.test.ts +421 -0
  503. package/src/Resizable/useResizable.ts +133 -48
  504. package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
  505. package/src/SelectableCard/SelectableCard.tsx +16 -0
  506. package/src/Selector/Selector.doc.mjs +15 -1
  507. package/src/Selector/Selector.source-build.test.mjs +65 -0
  508. package/src/Selector/Selector.test.tsx +301 -0
  509. package/src/Selector/Selector.tsx +145 -32
  510. package/src/Selector/hooks.ts +17 -2
  511. package/src/SideNav/SideNav.doc.mjs +2 -2
  512. package/src/SideNav/SideNav.test.tsx +1069 -6
  513. package/src/SideNav/SideNav.tsx +109 -38
  514. package/src/SideNav/SideNavHeading.tsx +5 -2
  515. package/src/SideNav/SideNavItem.doc.mjs +24 -3
  516. package/src/SideNav/SideNavItem.tsx +134 -44
  517. package/src/Slider/Slider.doc.mjs +2 -2
  518. package/src/Slider/Slider.test.tsx +106 -1
  519. package/src/Slider/Slider.tsx +52 -1
  520. package/src/Spinner/Spinner.doc.mjs +17 -5
  521. package/src/Spinner/Spinner.test.tsx +164 -0
  522. package/src/Spinner/Spinner.tsx +252 -22
  523. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  524. package/src/StatusDot/StatusDot.test.tsx +9 -0
  525. package/src/StatusDot/StatusDot.tsx +7 -1
  526. package/src/Stepper/Step.doc.mjs +1 -1
  527. package/src/Stepper/Step.tsx +7 -14
  528. package/src/Switch/Switch.doc.mjs +3 -1
  529. package/src/Switch/Switch.test.tsx +10 -0
  530. package/src/Switch/Switch.tsx +3 -0
  531. package/src/Table/BaseTable.tsx +6 -1
  532. package/src/Table/Table.doc.mjs +5 -3
  533. package/src/Table/Table.tsx +3 -8
  534. package/src/Table/TableBody.doc.mjs +2 -2
  535. package/src/Table/TableFooter.doc.mjs +1 -1
  536. package/src/Table/TableHeader.doc.mjs +1 -1
  537. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  538. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  539. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
  540. package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
  541. package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
  542. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  543. package/src/Table/useTableGroupedRows.doc.mjs +3 -3
  544. package/src/Table/useTablePagination.doc.mjs +1 -1
  545. package/src/Table/useTableSelection.doc.mjs +1 -1
  546. package/src/Text/Text.test.tsx +44 -0
  547. package/src/Text/Text.tsx +0 -1
  548. package/src/TextArea/TextArea.doc.mjs +13 -3
  549. package/src/TextArea/TextArea.test.tsx +11 -0
  550. package/src/TextArea/TextArea.tsx +34 -22
  551. package/src/TextInput/TextInput.doc.mjs +1 -1
  552. package/src/TimeInput/TimeInput.doc.mjs +1 -1
  553. package/src/Timestamp/Timestamp.test.tsx +89 -0
  554. package/src/Timestamp/Timestamp.tsx +8 -8
  555. package/src/Timestamp/formatInstant.ts +5 -0
  556. package/src/Toast/Toast.doc.mjs +213 -44
  557. package/src/Toast/Toast.tsx +118 -23
  558. package/src/Toast/ToastViewport.test.tsx +1434 -8
  559. package/src/Toast/ToastViewport.tsx +85 -14
  560. package/src/Toast/index.ts +2 -0
  561. package/src/Toast/types.ts +43 -5
  562. package/src/Toast/useToastGesture.ts +361 -0
  563. package/src/Token/Token.test.tsx +95 -0
  564. package/src/Token/Token.tsx +19 -17
  565. package/src/Token/TokenLink.tsx +12 -3
  566. package/src/Tokenizer/Tokenizer.doc.mjs +17 -4
  567. package/src/Tokenizer/Tokenizer.test.tsx +161 -0
  568. package/src/Tokenizer/Tokenizer.tsx +49 -24
  569. package/src/TopNav/TopNavHeading.tsx +2 -2
  570. package/src/TopNav/TopNavItem.tsx +3 -7
  571. package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
  572. package/src/TopNav/TopNavMegaMenu.tsx +47 -4
  573. package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
  574. package/src/TopNav/TopNavMenu.test.tsx +133 -1
  575. package/src/TopNav/TopNavMenu.tsx +38 -5
  576. package/src/TreeList/TreeList.test.tsx +49 -0
  577. package/src/TreeList/TreeList.tsx +7 -2
  578. package/src/TreeList/TreeListItem.tsx +2 -7
  579. package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
  580. package/src/Typeahead/BaseTypeahead.tsx +96 -6
  581. package/src/Typeahead/Typeahead.doc.mjs +7 -1
  582. package/src/Typeahead/Typeahead.test.tsx +154 -0
  583. package/src/Typeahead/Typeahead.tsx +9 -0
  584. package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
  585. package/src/Typeahead/TypeaheadItem.tsx +8 -1
  586. package/src/hooks/useAnnounce.doc.mjs +96 -0
  587. package/src/hooks/useDevWarning.doc.mjs +96 -0
  588. package/src/hooks/useHotkeys.test.ts +0 -18
  589. package/src/hooks/useHotkeys.ts +3 -25
  590. package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
  591. package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
  592. package/src/hooks/useInteractiveRole.doc.mjs +119 -0
  593. package/src/hooks/useLongPress.doc.mjs +123 -0
  594. package/src/hooks/useOverflow.doc.mjs +58 -17
  595. package/src/hooks/useOverflow.ts +16 -4
  596. package/src/hooks/useTypeahead.doc.mjs +153 -0
  597. package/src/i18n/InternationalizationContext.ts +3 -0
  598. package/src/i18n/InternationalizationProvider.tsx +8 -1
  599. package/src/i18n/__tests__/resolve.test.ts +23 -1
  600. package/src/i18n/resolve.ts +46 -49
  601. package/src/i18n/useTranslator.ts +2 -7
  602. package/src/index.ts +2 -0
  603. package/src/raw-import.d.ts +14 -0
  604. package/src/theme/Theme.test.tsx +104 -2
  605. package/src/theme/Theme.tsx +49 -14
  606. package/src/theme/defineTheme.test.ts +23 -0
  607. package/src/theme/defineTheme.ts +12 -3
  608. package/src/theme/derivedVarRegistry.test.ts +87 -3
  609. package/src/theme/derivedVarRegistry.ts +23 -4
  610. package/src/theme/generateThemeRules.test.ts +99 -1
  611. package/src/theme/generateThemeRules.ts +28 -0
  612. package/src/theme/syntax/tokens.ts +5 -2
  613. package/src/theme/useTheme.test.tsx +10 -0
  614. package/src/theme/useTheme.ts +16 -10
  615. package/src/utils/dateParser.test.ts +34 -2
  616. package/src/utils/dateParser.ts +11 -14
  617. package/src/utils/focusOutline.stylex.ts +50 -0
  618. package/src/utils/interactionOverlay.stylex.ts +74 -0
  619. package/src/utils/isApplePlatform.test.ts +61 -0
  620. package/src/utils/isApplePlatform.ts +37 -0
  621. package/src/utils/plainDate.test.ts +46 -0
  622. package/src/utils/plainDate.ts +18 -3
@@ -12,8 +12,87 @@
12
12
  import {readFileSync} from 'node:fs';
13
13
  import {describe, it, expect, vi, beforeEach} from 'vitest';
14
14
  import {render, screen, fireEvent} from '@testing-library/react';
15
- import {Dialog, resolveDialogPositionOffsets} from './Dialog';
15
+ import {
16
+ Dialog,
17
+ dialogFullscreenSafeAreaPaddingContract,
18
+ resolveDialogPositionOffsets,
19
+ } from './Dialog';
16
20
  import {DialogHeader} from './DialogHeader';
21
+ import {defineTheme, generateThemeCSS} from '../theme';
22
+
23
+ function generateThemeTestCSS(
24
+ theme: Parameters<typeof generateThemeCSS>[0],
25
+ ): string {
26
+ return Object.values(generateThemeCSS(theme)).join('\n');
27
+ }
28
+
29
+ function extractConstDeclaration(source: string, name: string): string {
30
+ const start = source.indexOf(`const ${name} = stylex.keyframes({`);
31
+ if (start === -1) {
32
+ throw new Error(`Missing ${name} keyframes`);
33
+ }
34
+
35
+ const bodyStart = source.indexOf('{', start);
36
+ let depth = 0;
37
+ for (let index = bodyStart; index < source.length; index += 1) {
38
+ const char = source[index];
39
+ if (char === '{') {
40
+ depth += 1;
41
+ } else if (char === '}') {
42
+ depth -= 1;
43
+ if (depth === 0) {
44
+ return source.slice(start, index + 3);
45
+ }
46
+ }
47
+ }
48
+
49
+ throw new Error(`Unterminated ${name} keyframes`);
50
+ }
51
+
52
+ function extractThemeVars(css: string): Map<string, string> {
53
+ const vars = new Map<string, string>();
54
+ for (const match of css.matchAll(/(--astryx-dialog-[\w-]+):\s*([^;]+);/g)) {
55
+ vars.set(match[1], match[2].trim());
56
+ }
57
+ return vars;
58
+ }
59
+
60
+ function resolveCSSVarFallback(
61
+ value: string,
62
+ vars: ReadonlyMap<string, string>,
63
+ ): string {
64
+ const trimmed = value.trim();
65
+ if (!trimmed.startsWith('var(') || !trimmed.endsWith(')')) {
66
+ return trimmed;
67
+ }
68
+
69
+ const inner = trimmed.slice(4, -1);
70
+ let depth = 0;
71
+ let commaIndex = -1;
72
+ for (let index = 0; index < inner.length; index += 1) {
73
+ const char = inner[index];
74
+ if (char === '(') {
75
+ depth += 1;
76
+ } else if (char === ')') {
77
+ depth -= 1;
78
+ } else if (char === ',' && depth === 0) {
79
+ commaIndex = index;
80
+ break;
81
+ }
82
+ }
83
+
84
+ const varName = (
85
+ commaIndex === -1 ? inner : inner.slice(0, commaIndex)
86
+ ).trim();
87
+ const fallback = commaIndex === -1 ? '' : inner.slice(commaIndex + 1).trim();
88
+ return vars.has(varName)
89
+ ? vars.get(varName)!
90
+ : resolveCSSVarFallback(fallback, vars);
91
+ }
92
+
93
+ function normalizeCSSValue(value: string): string {
94
+ return value.replace(/\s+/g, '');
95
+ }
17
96
 
18
97
  // Mock showModal and close methods since they're not fully implemented in jsdom
19
98
  beforeEach(() => {
@@ -396,36 +475,57 @@ describe('Dialog', () => {
396
475
  expect(inlineStyle).toContain('--x-maxHeight: 70dvh');
397
476
  });
398
477
 
399
- it('uses a fullscreen-specific fade animation instead of centered dialog movement', () => {
478
+ it('uses opacity-only fullscreen keyframes while standard dialogs keep directional movement', () => {
400
479
  const source = readFileSync(
401
480
  'packages/core/src/Dialog/Dialog.tsx',
402
481
  'utf8',
403
482
  );
404
- const standardOpen = source.slice(
405
- source.indexOf(' open: {'),
406
- source.indexOf(' // Backdrop using ::backdrop'),
483
+ const enterDirectional = extractConstDeclaration(
484
+ source,
485
+ 'enterDirectional',
486
+ );
487
+ const enterFullscreen = extractConstDeclaration(
488
+ source,
489
+ 'enterFullscreen',
407
490
  );
408
491
  const fullscreenOpen = source.slice(
409
492
  source.indexOf(' fullscreenOpen: {'),
410
493
  source.indexOf(' fullscreenSafeArea: {'),
411
494
  );
412
- const modalStyleOrder = source.slice(
413
- source.indexOf('focusOutlineProps.focusVisible('),
414
- source.indexOf(
415
- ' xstyle,',
416
- source.indexOf('focusOutlineProps.focusVisible('),
417
- ),
418
- );
419
495
 
420
- expect(standardOpen).toContain('enterDirectional');
496
+ expect(enterDirectional).toContain('transform');
497
+ expect(enterDirectional).toContain('translate(var(--dialog-dir-x');
498
+ expect(enterDirectional).toContain('scale(0.95)');
499
+ expect(enterFullscreen).toContain('opacity');
500
+ expect(enterFullscreen).not.toContain('transform');
501
+ expect(enterFullscreen).not.toContain('translate');
502
+ expect(enterFullscreen).not.toContain('scale(');
421
503
  expect(fullscreenOpen).toContain('enterFullscreen');
422
504
  expect(fullscreenOpen).not.toContain('enterDirectional');
423
- expect(modalStyleOrder.indexOf('styles.open')).toBeLessThan(
424
- modalStyleOrder.indexOf('styles.fullscreenOpen'),
505
+ });
506
+
507
+ it('maps fullscreen safe-area insets to logical sides in LTR and RTL', () => {
508
+ expect(dialogFullscreenSafeAreaPaddingContract.inlineStart.ltr).toContain(
509
+ 'safe-area-inset-left',
510
+ );
511
+ expect(dialogFullscreenSafeAreaPaddingContract.inlineEnd.ltr).toContain(
512
+ 'safe-area-inset-right',
513
+ );
514
+ expect(dialogFullscreenSafeAreaPaddingContract.inlineStart.rtl).toContain(
515
+ 'safe-area-inset-right',
516
+ );
517
+ expect(dialogFullscreenSafeAreaPaddingContract.inlineEnd.rtl).toContain(
518
+ 'safe-area-inset-left',
519
+ );
520
+ expect(dialogFullscreenSafeAreaPaddingContract.inlineStart.rtl).not.toBe(
521
+ dialogFullscreenSafeAreaPaddingContract.inlineStart.ltr,
522
+ );
523
+ expect(dialogFullscreenSafeAreaPaddingContract.inlineEnd.rtl).not.toBe(
524
+ dialogFullscreenSafeAreaPaddingContract.inlineEnd.ltr,
425
525
  );
426
526
  });
427
527
 
428
- it('protects fullscreen content with safe-area padding', () => {
528
+ it('protects default fullscreen content with safe-area padding', () => {
429
529
  render(
430
530
  <Dialog
431
531
  isOpen={true}
@@ -438,10 +538,77 @@ describe('Dialog', () => {
438
538
 
439
539
  const wrapper = screen.getByTestId('child').parentElement!;
440
540
  const computed = window.getComputedStyle(wrapper);
441
- expect(computed.paddingInlineStart).toContain('safe-area-inset-left');
442
- expect(computed.paddingInlineEnd).toContain('safe-area-inset-right');
541
+ expect(normalizeCSSValue(computed.paddingInlineStart)).toBe(
542
+ normalizeCSSValue(
543
+ dialogFullscreenSafeAreaPaddingContract.inlineStart.ltr,
544
+ ),
545
+ );
546
+ expect(normalizeCSSValue(computed.paddingInlineEnd)).toBe(
547
+ normalizeCSSValue(
548
+ dialogFullscreenSafeAreaPaddingContract.inlineEnd.ltr,
549
+ ),
550
+ );
443
551
  expect(wrapper.parentElement!.tagName).toBe('DIALOG');
444
552
  });
553
+
554
+ it('applies RTL fullscreen safe-area padding to the opposite logical edges', () => {
555
+ render(
556
+ <div dir="rtl">
557
+ <Dialog
558
+ isOpen={true}
559
+ onOpenChange={() => {}}
560
+ variant="fullscreen"
561
+ aria-label="Fullscreen RTL dialog">
562
+ <div data-testid="rtl-child">Content</div>
563
+ </Dialog>
564
+ </div>,
565
+ );
566
+
567
+ const wrapper = screen.getByTestId('rtl-child').parentElement!;
568
+ const computed = window.getComputedStyle(wrapper);
569
+ expect(normalizeCSSValue(computed.paddingInlineStart)).toBe(
570
+ normalizeCSSValue(
571
+ dialogFullscreenSafeAreaPaddingContract.inlineStart.rtl,
572
+ ),
573
+ );
574
+ expect(normalizeCSSValue(computed.paddingInlineEnd)).toBe(
575
+ normalizeCSSValue(
576
+ dialogFullscreenSafeAreaPaddingContract.inlineEnd.rtl,
577
+ ),
578
+ );
579
+ });
580
+
581
+ it('resolves theme zero padding before the default fullscreen safe-area fallback', () => {
582
+ const zeroPaddingTheme = defineTheme({
583
+ name: 'dialog-zero-padding-test',
584
+ components: {
585
+ dialog: {
586
+ base: {padding: '0'},
587
+ },
588
+ },
589
+ });
590
+
591
+ const vars = extractThemeVars(generateThemeTestCSS(zeroPaddingTheme));
592
+ expect(vars.get('--astryx-dialog-padding')).toBe('0');
593
+ expect(
594
+ resolveCSSVarFallback(
595
+ dialogFullscreenSafeAreaPaddingContract.blockStart,
596
+ vars,
597
+ ),
598
+ ).toBe('0');
599
+ expect(
600
+ resolveCSSVarFallback(
601
+ dialogFullscreenSafeAreaPaddingContract.inlineStart.ltr,
602
+ vars,
603
+ ),
604
+ ).toBe('0');
605
+ expect(
606
+ resolveCSSVarFallback(
607
+ dialogFullscreenSafeAreaPaddingContract.inlineEnd.rtl,
608
+ vars,
609
+ ),
610
+ ).toBe('0');
611
+ });
445
612
  });
446
613
 
447
614
  describe('position prop', () => {
@@ -11,8 +11,9 @@
11
11
  * The standard variant treats `width` as the preferred surface width, then
12
12
  * clamps it to the dynamic viewport with spacing-token gutters so narrow
13
13
  * viewports keep content and controls on screen without changing the public API.
14
- * Fullscreen dialogs preserve the same padding floor while honoring safe-area
15
- * insets, and fade in without the centered-dialog translate/scale motion.
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.
16
17
  *
17
18
  * SYNC: When modified, update these files to stay in sync:
18
19
  * - /packages/core/src/Dialog/Dialog.doc.mjs (props table, features, implementation notes)
@@ -131,6 +132,27 @@ const enterFullscreen = stylex.keyframes({
131
132
  to: {opacity: 1},
132
133
  });
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
+
134
156
  /**
135
157
  * Dialog styles using native <dialog> element
136
158
  * Uses ::backdrop pseudo-element for overlay
@@ -191,14 +213,16 @@ const styles = stylex.create({
191
213
  },
192
214
  },
193
215
  fullscreenSafeArea: {
194
- paddingBlockStart:
195
- 'max(var(--container-padding-block-start), env(safe-area-inset-top, 0px))',
196
- paddingBlockEnd:
197
- 'max(var(--container-padding-block-end), env(safe-area-inset-bottom, 0px))',
198
- paddingInlineStart:
199
- 'max(var(--container-padding-inline-start), env(safe-area-inset-left, 0px))',
200
- paddingInlineEnd:
201
- 'max(var(--container-padding-inline-end), env(safe-area-inset-right, 0px))',
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
+ },
202
226
  },
203
227
  inner: {
204
228
  display: 'flex',
@@ -628,7 +652,7 @@ export function Dialog({
628
652
  !useThemeDefault &&
629
653
  effectivePadding !== 4 &&
630
654
  containerPaddingBlockEndVarStyles[effectivePadding],
631
- isFullscreen && styles.fullscreenSafeArea,
655
+ isFullscreen && useThemeDefault && styles.fullscreenSafeArea,
632
656
  )}>
633
657
  <DialogContext value={dialogContextValue}>{children}</DialogContext>
634
658
  </div>
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import {describe, it, expect, vi, beforeEach} from 'vitest';
13
- import {render, screen, fireEvent, waitFor} from '@testing-library/react';
13
+ import {render, screen, fireEvent, waitFor, act} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {useState} from 'react';
16
16
  import {DropdownMenu} from './DropdownMenu';
@@ -315,10 +315,7 @@ describe('DropdownMenu', () => {
315
315
  });
316
316
 
317
317
  describe('DropdownMenu light-dismiss race', () => {
318
- it('does not re-open the menu when a click follows a hide within the guard window', () => {
319
- // Reproduces the iOS Safari race: pointerdown fires light-dismiss before
320
- // the subsequent click on the trigger; without the guard, the click would
321
- // immediately re-open the menu in the same tap.
318
+ function openMenu() {
322
319
  render(
323
320
  <DropdownMenu
324
321
  button={{label: 'Actions'}}
@@ -326,13 +323,50 @@ describe('DropdownMenu light-dismiss race', () => {
326
323
  data-testid="astryx-dropdown-menu"
327
324
  />,
328
325
  );
329
-
330
326
  const trigger = screen.getByTestId('astryx-dropdown-menu');
331
- fireEvent.click(trigger); // open
332
- fireEvent.click(trigger); // close (stamps guard)
333
- fireEvent.click(trigger); // would re-open without guard
327
+ fireEvent.pointerDown(trigger);
328
+ fireEvent.click(trigger);
334
329
  expect(HTMLElement.prototype.showPopover).toHaveBeenCalledTimes(1);
335
- expect(HTMLElement.prototype.hidePopover).toHaveBeenCalledTimes(1);
330
+ return trigger;
331
+ }
332
+
333
+ /**
334
+ * The browser dismisses the menu on pointerup and queues the `toggle` event;
335
+ * on the engines that lose the race it reaches React before the trigger's
336
+ * own click, which then reads a closed menu.
337
+ */
338
+ function lightDismiss() {
339
+ const popover = document.querySelector('[popover]') as HTMLElement;
340
+ act(() => {
341
+ popover.dispatchEvent(
342
+ Object.assign(new Event('toggle'), {
343
+ oldState: 'open',
344
+ newState: 'closed',
345
+ }),
346
+ );
347
+ });
348
+ }
349
+
350
+ it('does not re-open when the trigger click follows its own light dismiss', () => {
351
+ const trigger = openMenu();
352
+
353
+ fireEvent.pointerDown(trigger);
354
+ lightDismiss();
355
+ fireEvent.click(trigger);
356
+
357
+ expect(HTMLElement.prototype.showPopover).toHaveBeenCalledTimes(1);
358
+ });
359
+
360
+ it('re-opens on a press of its own after a light dismiss', () => {
361
+ const trigger = openMenu();
362
+
363
+ fireEvent.pointerDown(trigger);
364
+ lightDismiss();
365
+ fireEvent.click(trigger);
366
+ fireEvent.pointerDown(trigger);
367
+ fireEvent.click(trigger);
368
+
369
+ expect(HTMLElement.prototype.showPopover).toHaveBeenCalledTimes(2);
336
370
  });
337
371
  });
338
372
 
@@ -37,7 +37,7 @@ import React, {
37
37
  type ReactNode,
38
38
  } from 'react';
39
39
  import * as stylex from '@stylexjs/stylex';
40
- import {usePopover} from '../Popover/usePopover';
40
+ import {usePopoverInternal} from '../Popover/usePopover';
41
41
  import {Button, type ButtonProps} from '../Button';
42
42
  import {Icon} from '../Icon';
43
43
 
@@ -261,14 +261,8 @@ export function DropdownMenu({
261
261
  const isControlled = controlledIsOpen !== undefined;
262
262
  const isOpen = isControlled ? controlledIsOpen : internalIsOpen;
263
263
 
264
- // Track when the menu was last hidden so a near-simultaneous trigger
265
- // click — e.g. on iOS Safari where pointerdown fires light-dismiss
266
- // before the trigger's click event — can't immediately re-open it.
267
- const lastHideTimeRef = useRef(0);
268
-
269
264
  // Close menu + return focus to trigger
270
265
  const handleLayerHide = useCallback(() => {
271
- lastHideTimeRef.current = Date.now();
272
266
  onOpenChange?.(false);
273
267
  if (!isControlled) {
274
268
  setInternalIsOpen(false);
@@ -294,7 +288,7 @@ export function DropdownMenu({
294
288
  }
295
289
  }, [isControlled, onOpenChange]);
296
290
 
297
- const popover = usePopover({
291
+ const popover = usePopoverInternal({
298
292
  onHide: handleLayerHide,
299
293
  onShow: handleLayerShow,
300
294
  hasLightDismiss: true,
@@ -422,11 +416,8 @@ export function DropdownMenu({
422
416
 
423
417
  const handleButtonClick = useCallback(
424
418
  (e: React.MouseEvent<HTMLButtonElement>) => {
425
- // If the menu was just closed by light dismiss (e.g. iOS Safari fires
426
- // pointerdown → hide before the trigger's click), the click would
427
- // otherwise immediately re-open it. Short-circuit within the guard
428
- // window.
429
- if (Date.now() - lastHideTimeRef.current < 50) {
419
+ // The click that light-dismissed the menu is not a request to reopen it.
420
+ if (popover.wasJustDismissed()) {
430
421
  return;
431
422
  }
432
423
  onClick?.();
@@ -6,7 +6,7 @@ export const docs = {
6
6
  name: 'Field',
7
7
  displayName: 'Field',
8
8
  group: 'Field',
9
- category: 'Data Input',
9
+ category: 'Form Controls',
10
10
  keywords: ["field","formfield","formgroup","formcontrol","label","input","required","optional","helpertext","hint"],
11
11
  playground: {
12
12
  defaults: {
@@ -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,
@@ -15,7 +15,7 @@ import {readFileSync} from 'node:fs';
15
15
  import path from 'node:path';
16
16
  import {describe, it, expect, vi} from 'vitest';
17
17
  import {render, screen, fireEvent} from '@testing-library/react';
18
- import {InputClearButton} from './InputClearButton';
18
+ import {InputClearButton, type InputClearButtonProps} from './InputClearButton';
19
19
  import {Icon} from '../Icon';
20
20
  import {defineTheme} from '../theme/defineTheme';
21
21
  import {generateThemeCSS} from '../theme/generateThemeRules';
@@ -67,6 +67,20 @@ const getGlyph = (): HTMLElement => {
67
67
  return icon as HTMLElement;
68
68
  };
69
69
 
70
+ describe('InputClearButton public props', () => {
71
+ it('keep popup invoker handlers internal', () => {
72
+ const hasPointerDown: 'onPointerDown' extends keyof InputClearButtonProps
73
+ ? true
74
+ : false = false;
75
+ const hasClickCapture: 'onClickCapture' extends keyof InputClearButtonProps
76
+ ? true
77
+ : false = false;
78
+
79
+ expect(hasPointerDown).toBe(false);
80
+ expect(hasClickCapture).toBe(false);
81
+ });
82
+ });
83
+
70
84
  describe('InputClearButton', () => {
71
85
  it('renders a real button with the given accessible label', () => {
72
86
  render(<InputClearButton label="Clear" onClick={() => {}} />);
@@ -5,8 +5,7 @@
5
5
  /**
6
6
  * @file InputClearButton.tsx
7
7
  * @input Uses React, Button, Icon
8
- * @output Exports InputClearButton, the shared clear (✕) button rendered by
9
- * every clearable input in the family.
8
+ * @output Exports the public InputClearButton and an internal popup-aware variant.
10
9
  * @position Shared primitive. Every input that renders a clear affordance —
11
10
  * TextInput, NumberInput, TimeInput, DateInput, DateTimeInput,
12
11
  * DateRangeInput, Selector, MultiSelector, Typeahead, Tokenizer, FileInput —
@@ -80,12 +79,24 @@ export interface InputClearButtonProps {
80
79
  iconClassName?: string;
81
80
  }
82
81
 
83
- export function InputClearButton({
82
+ interface InternalInputClearButtonProps extends InputClearButtonProps {
83
+ onPointerDown: React.PointerEventHandler<HTMLElement>;
84
+ onClickCapture: React.MouseEventHandler<HTMLElement>;
85
+ }
86
+
87
+ type InputClearButtonRenderProps = InputClearButtonProps &
88
+ Partial<
89
+ Pick<InternalInputClearButtonProps, 'onPointerDown' | 'onClickCapture'>
90
+ >;
91
+
92
+ function renderInputClearButton({
84
93
  label,
85
94
  onClick,
95
+ onPointerDown,
96
+ onClickCapture,
86
97
  xstyle,
87
98
  iconClassName,
88
- }: InputClearButtonProps): ReactNode {
99
+ }: InputClearButtonRenderProps): ReactNode {
89
100
  const {className: iconTargetClassName} = themeProps('input-clear-icon');
90
101
  const {className: buttonTargetClassName} = themeProps('input-clear-button');
91
102
  return (
@@ -107,10 +118,23 @@ export function InputClearButton({
107
118
  />
108
119
  }
109
120
  onClick={onClick}
121
+ onPointerDown={onPointerDown}
122
+ onClickCapture={onClickCapture}
110
123
  isIconOnly
111
124
  xstyle={[styles.button, xstyle]}
112
125
  />
113
126
  );
114
127
  }
115
128
 
129
+ export function InputClearButton(props: InputClearButtonProps): ReactNode {
130
+ return renderInputClearButton(props);
131
+ }
132
+
133
+ /** Internal variant used while popup-aware clear behavior is rolled out. */
134
+ export function InternalInputClearButton(
135
+ props: InternalInputClearButtonProps,
136
+ ): ReactNode {
137
+ return renderInputClearButton(props);
138
+ }
139
+
116
140
  InputClearButton.displayName = 'InputClearButton';
@@ -5,7 +5,7 @@ export const docs = {
5
5
  name: 'FieldStatus',
6
6
  displayName: 'Field Status',
7
7
  group: 'Field',
8
- category: 'Data Input',
8
+ category: 'Form Controls',
9
9
  isHiddenFromOverview: true,
10
10
  description:
11
11
  'Status message component for form field validation feedback. Messages are announced to screen readers through persistent live regions (assertive for errors, polite otherwise), so conditional mounting is safe.',
@@ -5,7 +5,7 @@
5
5
  export const docs = {
6
6
  name: 'FileInput',
7
7
  displayName: 'File Input',
8
- category: 'Data Input',
8
+ category: 'Form Controls',
9
9
  keywords: ["fileinput","file","upload","drag","drop","dropzone","attachment","browse"],
10
10
  props: [
11
11
  {
@@ -281,7 +281,6 @@ export function Heading({
281
281
  className,
282
282
  {...style, ...inlineStyle},
283
283
  )}
284
- title={tooltipEnabled ? truncation.fullText : undefined}
285
284
  {...ariaProps}
286
285
  {...props}>
287
286
  {children}
@@ -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},
@@ -144,7 +147,10 @@ export const docsZh = {
144
147
  displayName: 'Hover Card',
145
148
  theming: {
146
149
  targets: [
147
- {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'},
148
154
  ],
149
155
  vars: [
150
156
  {name: '--_hovercard-radius', description: 'Border radius of the hover card', default: 'var(--radius-container)', private: true},