@astryxdesign/core 0.5.0 → 0.5.1-canary.f64186a

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 +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/index.d.ts +1 -1
  278. package/dist/index.d.ts.map +1 -1
  279. package/dist/theme/Theme.d.ts.map +1 -1
  280. package/dist/theme/Theme.js +46 -10
  281. package/dist/theme/defineTheme.d.ts +9 -3
  282. package/dist/theme/defineTheme.d.ts.map +1 -1
  283. package/dist/theme/defineTheme.js +5 -0
  284. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  285. package/dist/theme/derivedVarRegistry.js +24 -4
  286. package/dist/theme/generateThemeRules.d.ts +21 -0
  287. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  288. package/dist/theme/generateThemeRules.js +26 -0
  289. package/dist/theme/syntax/tokens.d.ts +1 -1
  290. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  291. package/dist/theme/syntax/tokens.js +5 -2
  292. package/dist/theme/useTheme.d.ts.map +1 -1
  293. package/dist/theme/useTheme.js +6 -7
  294. package/dist/utils/dateParser.d.ts +5 -8
  295. package/dist/utils/dateParser.d.ts.map +1 -1
  296. package/dist/utils/dateParser.js +10 -11
  297. package/dist/utils/focusOutline.stylex.d.ts +25 -0
  298. package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
  299. package/dist/utils/focusOutline.stylex.js +15 -0
  300. package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
  301. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
  302. package/dist/utils/interactionOverlay.stylex.js +42 -0
  303. package/dist/utils/isApplePlatform.d.ts +18 -0
  304. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  305. package/dist/utils/isApplePlatform.js +37 -0
  306. package/dist/utils/plainDate.d.ts +11 -0
  307. package/dist/utils/plainDate.d.ts.map +1 -1
  308. package/dist/utils/plainDate.js +20 -4
  309. package/locales/af-ZA.json +7 -7
  310. package/locales/ar-SA.json +7 -7
  311. package/locales/ca-ES.json +6 -6
  312. package/locales/cs-CZ.json +7 -7
  313. package/locales/da-DK.json +7 -7
  314. package/locales/de-DE.json +7 -7
  315. package/locales/el-GR.json +7 -7
  316. package/locales/en.json +178 -6
  317. package/locales/es-ES.json +6 -6
  318. package/locales/fi-FI.json +7 -7
  319. package/locales/fr-FR.json +7 -7
  320. package/locales/he-IL.json +7 -7
  321. package/locales/hu-HU.json +7 -7
  322. package/locales/it-IT.json +7 -7
  323. package/locales/ja-JP.json +7 -7
  324. package/locales/ko-KR.json +7 -7
  325. package/locales/nl-NL.json +7 -7
  326. package/locales/no-NO.json +7 -7
  327. package/locales/pl-PL.json +7 -7
  328. package/locales/pseudo.json +130 -1
  329. package/locales/pt-BR.json +7 -7
  330. package/locales/pt-PT.json +7 -7
  331. package/locales/ro-RO.json +7 -7
  332. package/locales/ru-RU.json +7 -7
  333. package/locales/sr-SP.json +7 -7
  334. package/locales/sv-SE.json +7 -7
  335. package/locales/tr-TR.json +7 -7
  336. package/locales/uk-UA.json +7 -7
  337. package/locales/vi-VN.json +7 -7
  338. package/locales/zh-CN.json +7 -7
  339. package/locales/zh-TW.json +7 -7
  340. package/package.json +4 -5
  341. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  342. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  343. package/src/AlertDialog/AlertDialog.tsx +62 -20
  344. package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
  345. package/src/AspectRatio/AspectRatio.tsx +6 -6
  346. package/src/Avatar/Avatar.doc.mjs +12 -2
  347. package/src/Avatar/Avatar.test.tsx +80 -0
  348. package/src/Avatar/Avatar.tsx +64 -14
  349. package/src/Avatar/index.ts +2 -2
  350. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  351. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  352. package/src/AvatarGroup/AvatarGroup.tsx +12 -4
  353. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  354. package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
  355. package/src/Badge/Badge.doc.mjs +3 -2
  356. package/src/Badge/Badge.test.tsx +32 -3
  357. package/src/Badge/Badge.tsx +42 -1
  358. package/src/Banner/Banner.doc.mjs +9 -0
  359. package/src/Banner/Banner.test.tsx +76 -11
  360. package/src/Banner/Banner.tsx +21 -2
  361. package/src/Button/Button.doc.mjs +2 -1
  362. package/src/Button/Button.test.tsx +19 -4
  363. package/src/Button/Button.tsx +9 -29
  364. package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
  365. package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
  366. package/src/Calendar/Calendar.doc.mjs +3 -3
  367. package/src/Calendar/Calendar.test.tsx +112 -0
  368. package/src/Calendar/Calendar.tsx +18 -16
  369. package/src/Calendar/hooks/useCalendarDays.ts +4 -4
  370. package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
  371. package/src/Calendar/styles.ts +48 -42
  372. package/src/Card/Card.doc.mjs +10 -7
  373. package/src/Card/Card.test.tsx +113 -19
  374. package/src/Card/Card.tsx +67 -89
  375. package/src/Card/index.ts +36 -1
  376. package/src/Carousel/Carousel.doc.mjs +3 -0
  377. package/src/Carousel/Carousel.test.tsx +360 -0
  378. package/src/Carousel/Carousel.tsx +116 -15
  379. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  380. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  381. package/src/CheckboxInput/CheckboxInput.tsx +5 -0
  382. package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
  383. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  384. package/src/CodeBlock/CodeBlock.tsx +20 -4
  385. package/src/CodeBlock/highlightRanges.ts +1 -1
  386. package/src/CodeBlock/highlightStyles.ts +13 -13
  387. package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
  388. package/src/ComplexSelector/ComplexSelector.doc.mjs +7 -0
  389. package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
  390. package/src/ComplexSelector/ComplexSelector.tsx +22 -12
  391. package/src/DateInput/DateInput.doc.mjs +16 -0
  392. package/src/DateInput/DateInput.test.tsx +9 -4
  393. package/src/DateInput/DateInput.tsx +54 -3
  394. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  395. package/src/DateInput/MonthScroller.tsx +5 -1
  396. package/src/DateInput/MonthYearWheels.tsx +7 -4
  397. package/src/DateInput/NativeDateField.test.tsx +635 -0
  398. package/src/DateInput/NativeDateField.tsx +641 -0
  399. package/src/DateInput/TouchDateField.tsx +83 -33
  400. package/src/DateInput/Wheel.tsx +1 -0
  401. package/src/DateInput/index.ts +1 -0
  402. package/src/DateInput/nativeDateSegments.ts +127 -0
  403. package/src/DateRangeInput/DateRangeInput.doc.mjs +2 -2
  404. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
  405. package/src/DateRangeInput/DateRangeInput.tsx +8 -13
  406. package/src/DateTimeInput/DateTimeInput.doc.mjs +38 -21
  407. package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
  408. package/src/DateTimeInput/DateTimeInput.tsx +54 -20
  409. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
  410. package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
  411. package/src/Dialog/Dialog.test.tsx +185 -18
  412. package/src/Dialog/Dialog.tsx +35 -11
  413. package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
  414. package/src/DropdownMenu/DropdownMenu.tsx +4 -13
  415. package/src/Field/FieldLabel.test.tsx +29 -0
  416. package/src/Field/FieldLabel.tsx +7 -0
  417. package/src/Field/InputClearButton.test.tsx +15 -1
  418. package/src/Field/InputClearButton.tsx +28 -4
  419. package/src/Heading/Heading.tsx +0 -1
  420. package/src/HoverCard/HoverCard.doc.mjs +8 -2
  421. package/src/HoverCard/HoverCard.test.tsx +154 -4
  422. package/src/HoverCard/HoverCard.tsx +137 -3
  423. package/src/HoverCard/useHoverCard.tsx +23 -3
  424. package/src/Icon/Icon.test.tsx +55 -1
  425. package/src/Icon/Icon.tsx +5 -3
  426. package/src/Icon/defaultIcons.tsx +11 -2
  427. package/src/Icon/globalIconRegistry.test.tsx +16 -3
  428. package/src/Icon/globalIconRegistry.tsx +37 -6
  429. package/src/Icon/index.ts +1 -0
  430. package/src/Icon/useIcon.ts +9 -2
  431. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  432. package/src/Indicator/Indicator.doc.mjs +2 -0
  433. package/src/Item/Item.tsx +2 -7
  434. package/src/Kbd/Kbd.test.tsx +0 -17
  435. package/src/Kbd/Kbd.tsx +2 -26
  436. package/src/Layer/gestureCounter.ts +57 -0
  437. package/src/Layer/useLayer.test.tsx +368 -16
  438. package/src/Layer/useLayer.tsx +208 -35
  439. package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
  440. package/src/List/List.test.tsx +38 -0
  441. package/src/List/List.tsx +8 -1
  442. package/src/Markdown/Markdown.test.tsx +37 -0
  443. package/src/Markdown/Markdown.tsx +16 -5
  444. package/src/Markdown/parser.test.ts +33 -0
  445. package/src/Markdown/parser.ts +9 -3
  446. package/src/MetadataList/MetadataList.test.tsx +75 -2
  447. package/src/MetadataList/MetadataListItem.tsx +5 -2
  448. package/src/MultiSelector/MultiSelector.doc.mjs +22 -1
  449. package/src/MultiSelector/MultiSelector.test.tsx +205 -0
  450. package/src/MultiSelector/MultiSelector.tsx +103 -16
  451. package/src/MultiSelector/hooks.ts +9 -2
  452. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  453. package/src/NavIcon/NavIcon.test.tsx +9 -0
  454. package/src/NavIcon/NavIcon.tsx +5 -1
  455. package/src/NavItem/navItemStyles.stylex.ts +0 -8
  456. package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
  457. package/src/NavMenu/NavHeadingMenu.tsx +7 -4
  458. package/src/NumberInput/NumberInput.doc.mjs +26 -7
  459. package/src/NumberInput/NumberInput.test.tsx +563 -8
  460. package/src/NumberInput/NumberInput.tsx +77 -131
  461. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  462. package/src/NumberInput/numberInputCommit.ts +103 -0
  463. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  464. package/src/NumberInput/numberParser.test.ts +222 -0
  465. package/src/NumberInput/numberParser.ts +403 -0
  466. package/src/Outline/Outline.tsx +2 -4
  467. package/src/OverflowList/OverflowList.doc.mjs +102 -21
  468. package/src/OverflowList/OverflowList.test.tsx +550 -4
  469. package/src/OverflowList/OverflowList.tsx +100 -2
  470. package/src/Pagination/Pagination.test.tsx +3 -2
  471. package/src/Popover/Popover.doc.mjs +2 -2
  472. package/src/Popover/Popover.test.tsx +38 -0
  473. package/src/Popover/Popover.tsx +28 -66
  474. package/src/Popover/usePopover.tsx +44 -5
  475. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
  476. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
  477. package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
  478. package/src/PowerSearch/formatFilterValue.test.ts +16 -1
  479. package/src/PowerSearch/formatFilterValue.ts +2 -0
  480. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  481. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  482. package/src/ProgressBar/ProgressBar.tsx +28 -8
  483. package/src/Resizable/Resizable.doc.mjs +2 -2
  484. package/src/Resizable/useResizable.doc.mjs +21 -2
  485. package/src/Resizable/useResizable.test.ts +421 -0
  486. package/src/Resizable/useResizable.ts +133 -48
  487. package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
  488. package/src/SelectableCard/SelectableCard.tsx +16 -0
  489. package/src/Selector/Selector.doc.mjs +14 -0
  490. package/src/Selector/Selector.source-build.test.mjs +65 -0
  491. package/src/Selector/Selector.test.tsx +301 -0
  492. package/src/Selector/Selector.tsx +145 -32
  493. package/src/Selector/hooks.ts +17 -2
  494. package/src/SideNav/SideNav.doc.mjs +2 -2
  495. package/src/SideNav/SideNav.test.tsx +1069 -6
  496. package/src/SideNav/SideNav.tsx +109 -38
  497. package/src/SideNav/SideNavHeading.tsx +5 -2
  498. package/src/SideNav/SideNavItem.doc.mjs +24 -3
  499. package/src/SideNav/SideNavItem.tsx +134 -44
  500. package/src/Slider/Slider.test.tsx +106 -1
  501. package/src/Slider/Slider.tsx +52 -1
  502. package/src/Spinner/Spinner.doc.mjs +17 -5
  503. package/src/Spinner/Spinner.test.tsx +164 -0
  504. package/src/Spinner/Spinner.tsx +252 -22
  505. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  506. package/src/StatusDot/StatusDot.test.tsx +9 -0
  507. package/src/StatusDot/StatusDot.tsx +7 -1
  508. package/src/Stepper/Step.doc.mjs +1 -1
  509. package/src/Stepper/Step.tsx +7 -14
  510. package/src/Switch/Switch.doc.mjs +2 -0
  511. package/src/Switch/Switch.test.tsx +10 -0
  512. package/src/Switch/Switch.tsx +3 -0
  513. package/src/Table/BaseTable.tsx +6 -1
  514. package/src/Table/Table.doc.mjs +5 -3
  515. package/src/Table/Table.tsx +3 -8
  516. package/src/Table/TableBody.doc.mjs +2 -2
  517. package/src/Table/TableFooter.doc.mjs +1 -1
  518. package/src/Table/TableHeader.doc.mjs +1 -1
  519. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  520. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  521. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
  522. package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
  523. package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
  524. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  525. package/src/Table/useTableGroupedRows.doc.mjs +3 -3
  526. package/src/Table/useTablePagination.doc.mjs +1 -1
  527. package/src/Table/useTableSelection.doc.mjs +1 -1
  528. package/src/Text/Text.test.tsx +44 -0
  529. package/src/Text/Text.tsx +0 -1
  530. package/src/TextArea/TextArea.doc.mjs +12 -2
  531. package/src/TextArea/TextArea.test.tsx +11 -0
  532. package/src/TextArea/TextArea.tsx +34 -22
  533. package/src/Timestamp/Timestamp.test.tsx +89 -0
  534. package/src/Timestamp/Timestamp.tsx +8 -8
  535. package/src/Timestamp/formatInstant.ts +5 -0
  536. package/src/Toast/Toast.doc.mjs +213 -44
  537. package/src/Toast/Toast.tsx +118 -23
  538. package/src/Toast/ToastViewport.test.tsx +1434 -8
  539. package/src/Toast/ToastViewport.tsx +85 -14
  540. package/src/Toast/index.ts +2 -0
  541. package/src/Toast/types.ts +43 -5
  542. package/src/Toast/useToastGesture.ts +361 -0
  543. package/src/Token/Token.test.tsx +95 -0
  544. package/src/Token/Token.tsx +19 -17
  545. package/src/Token/TokenLink.tsx +12 -3
  546. package/src/Tokenizer/Tokenizer.doc.mjs +16 -3
  547. package/src/Tokenizer/Tokenizer.test.tsx +161 -0
  548. package/src/Tokenizer/Tokenizer.tsx +49 -24
  549. package/src/TopNav/TopNavHeading.tsx +2 -2
  550. package/src/TopNav/TopNavItem.tsx +3 -7
  551. package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
  552. package/src/TopNav/TopNavMegaMenu.tsx +47 -4
  553. package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
  554. package/src/TopNav/TopNavMenu.test.tsx +133 -1
  555. package/src/TopNav/TopNavMenu.tsx +38 -5
  556. package/src/TreeList/TreeList.test.tsx +49 -0
  557. package/src/TreeList/TreeList.tsx +7 -2
  558. package/src/TreeList/TreeListItem.tsx +2 -7
  559. package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
  560. package/src/Typeahead/BaseTypeahead.tsx +96 -6
  561. package/src/Typeahead/Typeahead.doc.mjs +6 -0
  562. package/src/Typeahead/Typeahead.test.tsx +154 -0
  563. package/src/Typeahead/Typeahead.tsx +9 -0
  564. package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
  565. package/src/Typeahead/TypeaheadItem.tsx +8 -1
  566. package/src/hooks/useAnnounce.doc.mjs +96 -0
  567. package/src/hooks/useDevWarning.doc.mjs +96 -0
  568. package/src/hooks/useHotkeys.test.ts +0 -18
  569. package/src/hooks/useHotkeys.ts +3 -25
  570. package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
  571. package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
  572. package/src/hooks/useInteractiveRole.doc.mjs +119 -0
  573. package/src/hooks/useLongPress.doc.mjs +123 -0
  574. package/src/hooks/useOverflow.doc.mjs +58 -17
  575. package/src/hooks/useOverflow.ts +16 -4
  576. package/src/hooks/useTypeahead.doc.mjs +153 -0
  577. package/src/index.ts +2 -0
  578. package/src/raw-import.d.ts +14 -0
  579. package/src/theme/Theme.test.tsx +104 -2
  580. package/src/theme/Theme.tsx +49 -14
  581. package/src/theme/defineTheme.test.ts +23 -0
  582. package/src/theme/defineTheme.ts +12 -3
  583. package/src/theme/derivedVarRegistry.test.ts +87 -3
  584. package/src/theme/derivedVarRegistry.ts +23 -4
  585. package/src/theme/generateThemeRules.test.ts +99 -1
  586. package/src/theme/generateThemeRules.ts +28 -0
  587. package/src/theme/syntax/tokens.ts +5 -2
  588. package/src/theme/useTheme.test.tsx +10 -0
  589. package/src/theme/useTheme.ts +16 -10
  590. package/src/utils/dateParser.test.ts +34 -2
  591. package/src/utils/dateParser.ts +11 -14
  592. package/src/utils/focusOutline.stylex.ts +50 -0
  593. package/src/utils/interactionOverlay.stylex.ts +74 -0
  594. package/src/utils/isApplePlatform.test.ts +61 -0
  595. package/src/utils/isApplePlatform.ts +37 -0
  596. package/src/utils/plainDate.test.ts +46 -0
  597. package/src/utils/plainDate.ts +18 -3
@@ -18,12 +18,20 @@
18
18
  * - /packages/cli/assets/templates/blocks/components/OverflowList/ (showcase blocks)
19
19
  */
20
20
 
21
- import {type ReactNode, type ReactElement, Children} from 'react';
21
+ import {
22
+ type ReactNode,
23
+ type ReactElement,
24
+ Children,
25
+ useCallback,
26
+ useRef,
27
+ useState,
28
+ } from 'react';
22
29
  import type {BaseProps} from '../BaseProps';
23
30
  import type {SpacingStep} from '../utils/types';
24
31
  import * as stylex from '@stylexjs/stylex';
25
32
  import {mergeProps} from '../utils';
26
33
  import {useOverflow} from '../hooks/useOverflow';
34
+ import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
27
35
  import {spacingVars} from '../theme/tokens.stylex';
28
36
  import {themeProps} from '../utils/themeProps';
29
37
 
@@ -187,6 +195,47 @@ export interface OverflowListProps extends BaseProps<HTMLDivElement> {
187
195
  * ```
188
196
  */
189
197
  overflowRenderer?: (overflowItems: OverflowItem[]) => ReactNode;
198
+
199
+ /**
200
+ * Called with the items that are currently collapsed, whenever that set
201
+ * changes.
202
+ *
203
+ * Use it when the collapsed items belong in a menu the surrounding UI
204
+ * already renders (a row that already has its own "…" button), so the list
205
+ * does not grow a second anchor beside it. `overflowRenderer` cannot serve
206
+ * that case: it is only rendered while items overflow, and its measurement
207
+ * copy always receives every item.
208
+ *
209
+ * The contract:
210
+ * - It fires once measurement has collapsed something, and again with an
211
+ * empty array once the row widens back out and everything fits.
212
+ * - It is **silent while nothing overflows** — including on mount, so a list
213
+ * that fits from the start never calls it. There is no report of the
214
+ * pre-measurement state, which would always be an empty set whether or not
215
+ * the row actually overflows. Hold the collapsed set in state initialised
216
+ * to `[]` and it is correct at every moment; if you remount the list while
217
+ * keeping that state, reset it yourself.
218
+ * - Reports are keyed on the collapsed items' original indices and React
219
+ * keys. Membership and order changes report even when the count stays the
220
+ * same; unrelated re-renders and callback identity changes do not.
221
+ *
222
+ * Give dynamic children stable React keys. Items include their current
223
+ * original `index`; use it to look up your own data rather than storing
224
+ * `child`.
225
+ *
226
+ * @example
227
+ * ```
228
+ * const [hidden, setHidden] = useState<OverflowItem[]>([]);
229
+ * <>
230
+ * <OverflowList onOverflowChange={setHidden}>{items}</OverflowList>
231
+ * <DropdownMenu
232
+ * button={{label: 'More', variant: 'ghost'}}
233
+ * items={[...alwaysThere, ...hidden.map(({index}) => actions[index])]}
234
+ * />
235
+ * </>
236
+ * ```
237
+ */
238
+ onOverflowChange?: (overflowItems: OverflowItem[]) => void;
190
239
  }
191
240
 
192
241
  /**
@@ -219,6 +268,7 @@ export function OverflowList({
219
268
  collapseFrom = 'end',
220
269
  behavior = 'observeSelf',
221
270
  overflowRenderer,
271
+ onOverflowChange,
222
272
  xstyle,
223
273
  className,
224
274
  style,
@@ -263,11 +313,59 @@ export function OverflowList({
263
313
  // so the indicator renders at its maximum possible width.
264
314
  const measureIndicator = overflowRenderer?.(allItems);
265
315
 
316
+ // Re-run measurement when keyed children change without resizing the row.
317
+ // The measured key delays reporting until that measurement has committed.
318
+ // Lists without the callback skip all identity work.
319
+ const measurementKey = onOverflowChange
320
+ ? JSON.stringify({
321
+ children: childArray.map((child, index) => [index, child.key]),
322
+ gap,
323
+ minVisibleItems,
324
+ maxVisibleItems,
325
+ maxRows,
326
+ collapseFrom,
327
+ behavior,
328
+ })
329
+ : '';
330
+ const [measuredKey, setMeasuredKey] = useState(measurementKey);
331
+ const reportMeasureRef = useCallback(
332
+ (element: HTMLElement | null) => {
333
+ measureRef(element);
334
+ if (element) {
335
+ setMeasuredKey(measurementKey);
336
+ }
337
+ },
338
+ [measureRef, measurementKey],
339
+ );
340
+
341
+ // Report after measurement, before paint, so a standing menu updates in the
342
+ // same frame as the visible row. Keys distinguish membership and order while
343
+ // suppressing callback-only or unrelated re-renders. The initial empty key
344
+ // suppresses the optimistic pre-measurement render.
345
+ const overflowKey = onOverflowChange
346
+ ? JSON.stringify(overflowItems.map(({child, index}) => [index, child.key]))
347
+ : '[]';
348
+ const reportedKeyRef = useRef('[]');
349
+ const overflowItemsRef = useRef(overflowItems);
350
+ overflowItemsRef.current = overflowItems;
351
+
352
+ useIsomorphicLayoutEffect(() => {
353
+ if (
354
+ !onOverflowChange ||
355
+ measuredKey !== measurementKey ||
356
+ reportedKeyRef.current === overflowKey
357
+ ) {
358
+ return;
359
+ }
360
+ reportedKeyRef.current = overflowKey;
361
+ onOverflowChange(overflowItemsRef.current);
362
+ }, [measuredKey, measurementKey, overflowKey, onOverflowChange]);
363
+
266
364
  return (
267
365
  <>
268
366
  {/* Hidden measurement container */}
269
367
  <div
270
- ref={measureRef}
368
+ ref={reportMeasureRef}
271
369
  aria-hidden="true"
272
370
  inert
273
371
  {...stylex.props(styles.measureContainer, gapStyles[gap])}>
@@ -613,7 +613,7 @@ describe('Pagination', () => {
613
613
  expect(box).toHaveAttribute('aria-valuemax', '10');
614
614
  });
615
615
 
616
- it('commits a typed page on Enter and rejects an over-range entry', async () => {
616
+ it('commits a typed page on Enter and clamps an over-range entry', async () => {
617
617
  const user = userEvent.setup();
618
618
  const onChange = vi.fn();
619
619
  render(
@@ -633,9 +633,10 @@ describe('Pagination', () => {
633
633
  onChange.mockClear();
634
634
  await user.clear(box);
635
635
  // The box is a NumberInput bounded to [1, totalPages]: an over-max entry
636
- // is rejected and never navigates past the last page.
636
+ // lands on the last page rather than navigating past it.
637
637
  await user.type(box, '99{Enter}');
638
638
  expect(onChange).not.toHaveBeenCalledWith(99);
639
+ expect(onChange).toHaveBeenCalledWith(10);
639
640
  });
640
641
 
641
642
  it('commits on blur', async () => {
@@ -136,7 +136,7 @@ export const docs = {
136
136
  {className: 'astryx-popover-surface'},
137
137
  ],
138
138
  vars: [
139
- {name: '--_popover-radius', description: 'Border radius of the popover', default: 'var(--radius-element)', private: true},
139
+ {name: '--_popover-radius', description: 'Border radius of the popover surface', default: 'var(--radius-container)', private: true},
140
140
  ],
141
141
  derived: [
142
142
  {property: 'borderRadius', vars: ['--_popover-radius']},
@@ -281,7 +281,7 @@ export const docsZh = {
281
281
  {className: 'astryx-popover-surface'},
282
282
  ],
283
283
  vars: [
284
- {name: '--_popover-radius', description: 'Border radius of the popover', default: 'var(--radius-element)', private: true},
284
+ {name: '--_popover-radius', description: 'Border radius of the popover surface', default: 'var(--radius-container)', private: true},
285
285
  ],
286
286
  derived: [
287
287
  {property: 'borderRadius', vars: ['--_popover-radius']},
@@ -14,6 +14,7 @@ import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
14
14
  import {render, screen, fireEvent} from '@testing-library/react';
15
15
  import React, {useRef} from 'react';
16
16
  import {Popover} from './Popover';
17
+ import type {UsePopoverReturn} from './usePopover';
17
18
  import {Dialog} from '../Dialog';
18
19
  import {SegmentedControl, SegmentedControlItem} from '../SegmentedControl';
19
20
 
@@ -55,6 +56,19 @@ afterAll(() => {
55
56
  (HTMLElement.prototype as any).matches = originalMatches;
56
57
  });
57
58
 
59
+ describe('usePopover public return type', () => {
60
+ it('keeps dismissal internals out of the public contract', () => {
61
+ const hasKeepOpenProps: 'keepOpenProps' extends keyof UsePopoverReturn
62
+ ? true
63
+ : false = false;
64
+ const hasDismissalGuard: 'wasJustDismissed' extends keyof UsePopoverReturn
65
+ ? true
66
+ : false = false;
67
+ expect(hasKeepOpenProps).toBe(false);
68
+ expect(hasDismissalGuard).toBe(false);
69
+ });
70
+ });
71
+
58
72
  describe('Popover', () => {
59
73
  it('renders trigger element', () => {
60
74
  render(
@@ -486,4 +500,28 @@ describe('Popover', () => {
486
500
  expect(trigger).toHaveFocus();
487
501
  });
488
502
  });
503
+
504
+ it('puts the theme target and styling escape hatches on the popup surface', () => {
505
+ render(
506
+ <Popover
507
+ isOpen
508
+ content={<span data-testid="content">Popover content</span>}
509
+ label="Test popover"
510
+ data-testid="popover"
511
+ className="consumer-popover"
512
+ style={{padding: 0}}>
513
+ <button type="button">Open</button>
514
+ </Popover>,
515
+ );
516
+
517
+ const target = document.querySelector('.astryx-popover');
518
+ expect(target).not.toBeNull();
519
+ // The surface paints background, radius and elevation; a target on the
520
+ // content box inside it would style a box that paints nothing.
521
+ expect(target).toHaveClass('astryx-popover-surface');
522
+ expect(target).toHaveClass('consumer-popover');
523
+ expect(target).toHaveStyle({padding: '0'});
524
+ expect(target).toContainElement(screen.getByTestId('content'));
525
+ expect(screen.getByTestId('popover')).not.toHaveClass('consumer-popover');
526
+ });
489
527
  });
@@ -25,7 +25,6 @@ import React, {
25
25
  } from 'react';
26
26
  import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
27
27
  import * as stylex from '@stylexjs/stylex';
28
- import {mergeProps} from '../utils';
29
28
  import {devWarn} from '../utils/devWarning';
30
29
  import type {BaseProps} from '../BaseProps';
31
30
  import {usePopover} from './usePopover';
@@ -33,7 +32,6 @@ import type {LayerAlignment, LayerPlacement} from '../Layer/useLayer';
33
32
  import {layerAnimations} from '../Layer/layerAnimations.stylex';
34
33
  import {spacingVars} from '../theme/tokens.stylex';
35
34
  import {InteractiveRoleContext} from '../InteractiveRoleContext/InteractiveRoleContext';
36
- import {themeProps} from '../utils/themeProps';
37
35
 
38
36
  // =============================================================================
39
37
  // Helpers
@@ -243,7 +241,8 @@ const styles = stylex.create({
243
241
  anchorWrapper: {
244
242
  display: 'inline-flex',
245
243
  },
246
- // Visual styles for the inner content container
244
+ // Content padding, applied to the popup surface so a theme's `padding`
245
+ // replaces it instead of nesting inside it.
247
246
  contentPadding: {
248
247
  paddingBlockStart: spacingVars['--spacing-3'],
249
248
  paddingBlockEnd: spacingVars['--spacing-3'],
@@ -322,16 +321,12 @@ export function Popover({
322
321
  }: PopoverProps): ReactElement {
323
322
  const wrapperRef = useRef<HTMLDivElement>(null);
324
323
  const isControlled = isOpen !== undefined;
325
- // Track when the popover was last hidden by light dismiss to prevent
326
- // the trigger click from immediately re-opening it.
327
- const lastHideTimeRef = useRef(0);
328
324
 
329
325
  const handlePopoverShow = useCallback(() => {
330
326
  onOpenChange?.(true);
331
327
  }, [onOpenChange]);
332
328
 
333
329
  const handlePopoverHide = useCallback(() => {
334
- lastHideTimeRef.current = Date.now();
335
330
  onOpenChange?.(false);
336
331
  }, [onOpenChange]);
337
332
 
@@ -344,6 +339,13 @@ export function Popover({
344
339
  hasCloseButton,
345
340
  closeButtonLabel,
346
341
  hasAutoFocus,
342
+ // The surface is the box that paints background, radius and elevation, so
343
+ // it is the element the `popover` theme target has to sit on — a target on
344
+ // the content div inside it styles a box that paints nothing.
345
+ surfaceTarget: 'popover',
346
+ xstyle: [styles.contentPadding, xstyle],
347
+ className,
348
+ style,
347
349
  onShow: handlePopoverShow,
348
350
  onHide: handlePopoverHide,
349
351
  });
@@ -353,11 +355,7 @@ export function Popover({
353
355
  if (!isEnabled) {
354
356
  return;
355
357
  }
356
- // If the popover was just closed by light dismiss (clicking outside),
357
- // the trigger click fires in the same event — skip re-opening.
358
- if (Date.now() - lastHideTimeRef.current < 50) {
359
- return;
360
- }
358
+ // `toggle` absorbs a click that belongs to its own light dismiss.
361
359
  popover.toggle();
362
360
  }, [isEnabled, popover]);
363
361
 
@@ -511,24 +509,12 @@ export function Popover({
511
509
  if (anchorRef && children == null) {
512
510
  return (
513
511
  <>
514
- {popover.render(
515
- <div
516
- data-testid={testId}
517
- {...mergeProps(
518
- themeProps('popover'),
519
- stylex.props(styles.contentPadding, xstyle),
520
- className,
521
- style,
522
- )}>
523
- {content}
524
- </div>,
525
- {
526
- placement,
527
- alignment,
528
- offset: spacingVars['--spacing-1'],
529
- xstyle: [popoverXstyle, layerAnimations[placement]],
530
- },
531
- )}
512
+ {popover.render(<div data-testid={testId}>{content}</div>, {
513
+ placement,
514
+ alignment,
515
+ offset: spacingVars['--spacing-1'],
516
+ xstyle: [popoverXstyle, layerAnimations[placement]],
517
+ })}
532
518
  </>
533
519
  );
534
520
  }
@@ -548,24 +534,12 @@ export function Popover({
548
534
  return (
549
535
  <>
550
536
  {children(triggerProps)}
551
- {popover.render(
552
- <div
553
- data-testid={testId}
554
- {...mergeProps(
555
- themeProps('popover'),
556
- stylex.props(styles.contentPadding, xstyle),
557
- className,
558
- style,
559
- )}>
560
- {content}
561
- </div>,
562
- {
563
- placement,
564
- alignment,
565
- offset: spacingVars['--spacing-1'],
566
- xstyle: [popoverXstyle, layerAnimations[placement]],
567
- },
568
- )}
537
+ {popover.render(<div data-testid={testId}>{content}</div>, {
538
+ placement,
539
+ alignment,
540
+ offset: spacingVars['--spacing-1'],
541
+ xstyle: [popoverXstyle, layerAnimations[placement]],
542
+ })}
569
543
  </>
570
544
  );
571
545
  }
@@ -578,24 +552,12 @@ export function Popover({
578
552
  {children}
579
553
  </div>
580
554
  </InteractiveRoleContext>
581
- {popover.render(
582
- <div
583
- data-testid={testId}
584
- {...mergeProps(
585
- themeProps('popover'),
586
- stylex.props(styles.contentPadding, xstyle),
587
- className,
588
- style,
589
- )}>
590
- {content}
591
- </div>,
592
- {
593
- placement,
594
- alignment,
595
- offset: spacingVars['--spacing-1'],
596
- xstyle: [popoverXstyle, layerAnimations[placement]],
597
- },
598
- )}
555
+ {popover.render(<div data-testid={testId}>{content}</div>, {
556
+ placement,
557
+ alignment,
558
+ offset: spacingVars['--spacing-1'],
559
+ xstyle: [popoverXstyle, layerAnimations[placement]],
560
+ })}
599
561
  </>
600
562
  );
601
563
  }
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * @file usePopover.tsx
7
7
  * @input Uses useLayer, useFocusTrap, React hooks
8
- * @output Exports usePopover hook for popover dialogs with focus trapping
8
+ * @output Exports usePopover and a package-internal trigger-aware variant.
9
9
  * @position Higher-level layer utility; used by DatePicker, Combobox, etc.
10
10
  *
11
11
  * Combines popover layer behavior with focus trap for dialog-like popovers.
@@ -17,7 +17,7 @@
17
17
 
18
18
  import React, {useCallback, useEffect, useRef, type ReactNode} from 'react';
19
19
  import * as stylex from '@stylexjs/stylex';
20
- import {useLayer, type ContextRenderProps} from '../Layer/useLayer';
20
+ import {useLayerInternal, type ContextRenderProps} from '../Layer/useLayer';
21
21
  import {useFocusTrap} from '../hooks/useFocusTrap';
22
22
  import {LayerDepthProvider} from '../Layer/LayerDepthContext';
23
23
  import type {StyleXStyles} from '@stylexjs/stylex';
@@ -41,7 +41,8 @@ const styles = stylex.create({
41
41
  // Consumers that need a raw positioned layer should use useLayer instead.
42
42
  surface: {
43
43
  backgroundColor: colorVars['--color-background-popover'],
44
- borderRadius: radiusVars['--radius-container'],
44
+ '--_popover-radius': radiusVars['--radius-container'],
45
+ borderRadius: 'var(--_popover-radius)',
45
46
  boxShadow: shadowVars['--shadow-low'],
46
47
  },
47
48
  // Focus trap container
@@ -111,6 +112,16 @@ export interface UsePopoverOptions {
111
112
  */
112
113
  xstyle?: StyleXStyles;
113
114
 
115
+ /**
116
+ * Additional class name applied to the painted popover surface.
117
+ */
118
+ className?: string;
119
+
120
+ /**
121
+ * Inline styles applied to the painted popover surface.
122
+ */
123
+ style?: React.CSSProperties;
124
+
114
125
  /**
115
126
  * Whether clicking outside should dismiss the popover.
116
127
  * @default true
@@ -283,6 +294,10 @@ export interface UsePopoverReturn {
283
294
  };
284
295
  }
285
296
 
297
+ interface InternalUsePopoverReturn extends UsePopoverReturn {
298
+ wasJustDismissed: () => boolean;
299
+ }
300
+
286
301
  /**
287
302
  * Hook for creating popover dialogs with focus trapping.
288
303
  *
@@ -323,11 +338,15 @@ export interface UsePopoverReturn {
323
338
  * }
324
339
  * ```
325
340
  */
326
- export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
341
+ function usePopoverImplementation(
342
+ options: UsePopoverOptions = {},
343
+ ): InternalUsePopoverReturn {
327
344
  const {
328
345
  onShow,
329
346
  onHide,
330
347
  xstyle,
348
+ className,
349
+ style,
331
350
  hasLightDismiss = true,
332
351
  hasEscapeDismiss = true,
333
352
  hasAutoFocus = true,
@@ -351,7 +370,7 @@ export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
351
370
  const skipAutoFocusRef = useRef(false);
352
371
 
353
372
  // Core layer for popover positioning
354
- const layer = useLayer({
373
+ const layer = useLayerInternal({
355
374
  mode: 'context',
356
375
  lightDismiss: hasLightDismiss,
357
376
  onShow,
@@ -400,6 +419,9 @@ export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
400
419
 
401
420
  // Toggle function
402
421
  const toggle = useCallback(() => {
422
+ if (layer.wasJustDismissed()) {
423
+ return;
424
+ }
403
425
  if (layer.isOpen) {
404
426
  layer.hide();
405
427
  } else {
@@ -450,6 +472,8 @@ export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
450
472
  hasSurface && styles.surface,
451
473
  xstyle,
452
474
  ),
475
+ className,
476
+ style,
453
477
  )}>
454
478
  {children}
455
479
  {hasCloseButton && (
@@ -475,6 +499,8 @@ export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
475
499
  hasCloseButton,
476
500
  hasSurface,
477
501
  surfaceTarget,
502
+ className,
503
+ style,
478
504
  closeButtonLabel,
479
505
  contentRef,
480
506
  dialogLabel,
@@ -491,9 +517,22 @@ export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
491
517
  show,
492
518
  hide: layer.hide,
493
519
  toggle,
520
+ wasJustDismissed: layer.wasJustDismissed,
494
521
  isOpen: layer.isOpen,
495
522
  id: layer.id,
496
523
  render,
497
524
  triggerProps,
498
525
  };
499
526
  }
527
+
528
+ export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
529
+ const {wasJustDismissed: _, ...popover} = usePopoverImplementation(options);
530
+ return popover;
531
+ }
532
+
533
+ /** @internal Used by trigger components; not exported from package barrels. */
534
+ export function usePopoverInternal(
535
+ options: UsePopoverOptions = {},
536
+ ): InternalUsePopoverReturn {
537
+ return usePopoverImplementation(options);
538
+ }
@@ -286,6 +286,93 @@ describe('PowerSearch', () => {
286
286
  expect(onSave).not.toHaveBeenCalled();
287
287
  });
288
288
 
289
+ it('saves the freshly committed numeric value on Enter', () => {
290
+ const numericConfig: PowerSearchConfig = {
291
+ name: 'test-number',
292
+ fields: [
293
+ {
294
+ key: 'level',
295
+ label: 'Level',
296
+ operators: [
297
+ {key: 'equals', label: 'equals', value: {type: 'integer'}},
298
+ ],
299
+ },
300
+ ],
301
+ };
302
+ const onSave = vi.fn();
303
+
304
+ function NumericValueHarness() {
305
+ const internalConfig = useInternalConfig(numericConfig);
306
+ return (
307
+ <PowerSearchEditPopover
308
+ config={internalConfig}
309
+ filter={{
310
+ field: 'level',
311
+ operator: 'equals',
312
+ value: {type: 'integer', value: 5},
313
+ }}
314
+ mode="edit"
315
+ onSave={onSave}
316
+ onCancel={() => {}}
317
+ />
318
+ );
319
+ }
320
+
321
+ render(<NumericValueHarness />);
322
+ const input = screen.getByRole('spinbutton');
323
+ fireEvent.focus(input);
324
+ fireEvent.input(input, {target: {value: '42'}});
325
+ fireEvent.keyDown(input, {key: 'Enter'});
326
+
327
+ expect(onSave).toHaveBeenCalledWith({
328
+ field: 'level',
329
+ operator: 'equals',
330
+ value: {type: 'integer', value: 42},
331
+ });
332
+ });
333
+
334
+ it('does not save an invalid numeric draft on Enter', () => {
335
+ const numericConfig: PowerSearchConfig = {
336
+ name: 'test-number',
337
+ fields: [
338
+ {
339
+ key: 'level',
340
+ label: 'Level',
341
+ operators: [
342
+ {key: 'equals', label: 'equals', value: {type: 'integer'}},
343
+ ],
344
+ },
345
+ ],
346
+ };
347
+ const onSave = vi.fn();
348
+
349
+ function NumericValueHarness() {
350
+ const internalConfig = useInternalConfig(numericConfig);
351
+ return (
352
+ <PowerSearchEditPopover
353
+ config={internalConfig}
354
+ filter={{
355
+ field: 'level',
356
+ operator: 'equals',
357
+ value: {type: 'integer', value: 5},
358
+ }}
359
+ mode="edit"
360
+ onSave={onSave}
361
+ onCancel={() => {}}
362
+ />
363
+ );
364
+ }
365
+
366
+ render(<NumericValueHarness />);
367
+ const input = screen.getByRole('spinbutton');
368
+ fireEvent.focus(input);
369
+ fireEvent.input(input, {target: {value: '1·234'}});
370
+ fireEvent.keyDown(input, {key: 'Enter'});
371
+
372
+ expect(onSave).not.toHaveBeenCalled();
373
+ expect(input).toHaveValue('1·234');
374
+ });
375
+
289
376
  it('does not save/close on a composing Enter while typing a filter value (#4828)', () => {
290
377
  const onSave = vi.fn();
291
378
  const onCancel = vi.fn();
@@ -182,6 +182,70 @@ describe('StringEditor (#1103)', () => {
182
182
  });
183
183
  });
184
184
 
185
+ describe('numeric editor commit timing', () => {
186
+ it('saves the committed number when Enter finishes the edit', () => {
187
+ const onChange = vi.fn();
188
+ const onEnter = vi.fn();
189
+ render(
190
+ <PowerSearchValueEditor
191
+ operatorValue={{type: 'integer'}}
192
+ filterValue={{type: 'integer', value: 5}}
193
+ onChange={onChange}
194
+ onEnter={onEnter}
195
+ config={stubConfig}
196
+ />,
197
+ );
198
+ const input = screen.getByRole('spinbutton');
199
+ fireEvent.focus(input);
200
+ fireEvent.input(input, {target: {value: '42'}});
201
+ fireEvent.keyDown(input, {key: 'Enter'});
202
+
203
+ expect(onChange).toHaveBeenLastCalledWith(
204
+ {type: 'integer', value: 42},
205
+ true,
206
+ );
207
+ expect(onEnter).not.toHaveBeenCalled();
208
+ });
209
+
210
+ it('does not save an invalid numeric draft on Enter', () => {
211
+ const onChange = vi.fn();
212
+ const onEnter = vi.fn();
213
+ render(
214
+ <PowerSearchValueEditor
215
+ operatorValue={{type: 'integer'}}
216
+ filterValue={{type: 'integer', value: 5}}
217
+ onChange={onChange}
218
+ onEnter={onEnter}
219
+ config={stubConfig}
220
+ />,
221
+ );
222
+ const input = screen.getByRole('spinbutton');
223
+ fireEvent.focus(input);
224
+ fireEvent.input(input, {target: {value: '1·234'}});
225
+ fireEvent.keyDown(input, {key: 'Enter'});
226
+
227
+ expect(onChange).not.toHaveBeenCalled();
228
+ expect(onEnter).not.toHaveBeenCalled();
229
+ expect(input).toHaveValue('1·234');
230
+ });
231
+
232
+ it('keeps the existing Enter callback when there is no pending edit', () => {
233
+ const onEnter = vi.fn();
234
+ render(
235
+ <PowerSearchValueEditor
236
+ operatorValue={{type: 'float'}}
237
+ filterValue={{type: 'float', value: 1.5}}
238
+ onChange={() => {}}
239
+ onEnter={onEnter}
240
+ config={stubConfig}
241
+ />,
242
+ );
243
+
244
+ fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'Enter'});
245
+ expect(onEnter).toHaveBeenCalledTimes(1);
246
+ });
247
+ });
248
+
185
249
  // =============================================================================
186
250
  // #1106 — EntityListEditor drops photo, no renderItem
187
251
  // =============================================================================