@astryxdesign/core 0.4.7 → 0.5.0-canary.32a62fd

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 (554) hide show
  1. package/CHANGELOG.md +161 -1
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +3 -2
  4. package/dist/AspectRatio/AspectRatio.d.ts +24 -0
  5. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  6. package/dist/AspectRatio/AspectRatio.js +23 -4
  7. package/dist/Avatar/Avatar.d.ts +25 -1
  8. package/dist/Avatar/Avatar.d.ts.map +1 -1
  9. package/dist/Avatar/Avatar.js +58 -19
  10. package/dist/Avatar/index.d.ts +2 -2
  11. package/dist/Avatar/index.d.ts.map +1 -1
  12. package/dist/Avatar/index.js +1 -1
  13. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  14. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  15. package/dist/AvatarGroup/AvatarGroup.js +8 -4
  16. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  17. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  19. package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
  20. package/dist/Banner/Banner.d.ts +40 -15
  21. package/dist/Banner/Banner.d.ts.map +1 -1
  22. package/dist/Banner/Banner.js +51 -18
  23. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  24. package/dist/BottomSheet/BottomSheet.js +17 -4
  25. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  26. package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
  27. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  28. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
  29. package/dist/Button/Button.d.ts.map +1 -1
  30. package/dist/Button/Button.js +5 -4
  31. package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
  32. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  33. package/dist/ButtonGroup/ButtonGroup.js +26 -7
  34. package/dist/Calendar/Calendar.d.ts +3 -1
  35. package/dist/Calendar/Calendar.d.ts.map +1 -1
  36. package/dist/Calendar/Calendar.js +13 -14
  37. package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
  38. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
  39. package/dist/Calendar/getInitialFocusDate.js +62 -0
  40. package/dist/Carousel/Carousel.d.ts.map +1 -1
  41. package/dist/Carousel/Carousel.js +3 -3
  42. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  43. package/dist/Chat/ChatComposerInput.js +2 -3
  44. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  45. package/dist/Chat/ChatLayout.js +3 -3
  46. package/dist/Chat/ChatMessageList.d.ts +22 -3
  47. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  48. package/dist/Chat/ChatMessageList.js +6 -3
  49. package/dist/Chat/ChatTokenizedText.d.ts +2 -0
  50. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  51. package/dist/Chat/ChatTokenizedText.js +11 -6
  52. package/dist/Chat/useChatComposerTokens.js +1 -1
  53. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  54. package/dist/CheckboxInput/CheckboxInput.js +10 -3
  55. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  56. package/dist/ClickableCard/ClickableCard.js +3 -3
  57. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  58. package/dist/CodeBlock/CodeBlock.js +15 -4
  59. package/dist/CodeBlock/highlightRanges.js +1 -1
  60. package/dist/CodeBlock/highlightStyles.js +13 -13
  61. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  62. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  63. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  64. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  65. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  66. package/dist/ContextMenu/ContextMenu.js +4 -3
  67. package/dist/DateInput/DateInput.d.ts +43 -0
  68. package/dist/DateInput/DateInput.d.ts.map +1 -1
  69. package/dist/DateInput/DateInput.js +22 -2
  70. package/dist/DateInput/NativeDateField.d.ts +10 -0
  71. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  72. package/dist/DateInput/NativeDateField.js +477 -0
  73. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  74. package/dist/DateInput/TouchDateField.js +38 -4
  75. package/dist/DateInput/index.d.ts +1 -1
  76. package/dist/DateInput/index.d.ts.map +1 -1
  77. package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
  78. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  79. package/dist/DateTimeInput/DateTimeInput.js +406 -12
  80. package/dist/DateTimeInput/index.d.ts +1 -1
  81. package/dist/DateTimeInput/index.d.ts.map +1 -1
  82. package/dist/Dialog/Dialog.d.ts +7 -1
  83. package/dist/Dialog/Dialog.d.ts.map +1 -1
  84. package/dist/Dialog/Dialog.js +89 -58
  85. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  86. package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
  87. package/dist/Field/FieldLabel.d.ts.map +1 -1
  88. package/dist/Field/FieldLabel.js +9 -1
  89. package/dist/FileInput/FileInput.d.ts.map +1 -1
  90. package/dist/FileInput/FileInput.js +3 -2
  91. package/dist/Heading/Heading.d.ts.map +1 -1
  92. package/dist/Heading/Heading.js +6 -2
  93. package/dist/HoverCard/HoverCard.d.ts +6 -0
  94. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  95. package/dist/HoverCard/HoverCard.js +52 -3
  96. package/dist/HoverCard/useHoverCard.d.ts +16 -2
  97. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  98. package/dist/HoverCard/useHoverCard.js +74 -26
  99. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  100. package/dist/Indicator/CheckboxIndicator.js +6 -2
  101. package/dist/Item/Item.d.ts.map +1 -1
  102. package/dist/Item/Item.js +4 -2
  103. package/dist/Kbd/Kbd.d.ts.map +1 -1
  104. package/dist/Kbd/Kbd.js +2 -19
  105. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  106. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  107. package/dist/Layer/LayerDepthContext.js +66 -0
  108. package/dist/Layer/index.d.ts +3 -0
  109. package/dist/Layer/index.d.ts.map +1 -1
  110. package/dist/Layer/index.js +4 -0
  111. package/dist/Layer/layerStack.d.ts +98 -0
  112. package/dist/Layer/layerStack.d.ts.map +1 -0
  113. package/dist/Layer/layerStack.js +306 -0
  114. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  115. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  116. package/dist/Layer/useLayerDismissal.js +91 -0
  117. package/dist/Lightbox/Lightbox.d.ts +1 -0
  118. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  119. package/dist/Lightbox/Lightbox.js +103 -81
  120. package/dist/Markdown/index.d.ts +1 -1
  121. package/dist/Markdown/index.d.ts.map +1 -1
  122. package/dist/Markdown/parser.d.ts +38 -1
  123. package/dist/Markdown/parser.d.ts.map +1 -1
  124. package/dist/Markdown/parser.js +177 -29
  125. package/dist/MobileNav/MobileNav.d.ts +6 -1
  126. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  127. package/dist/MobileNav/MobileNav.js +61 -36
  128. package/dist/MultiSelector/MultiSelector.d.ts +15 -1
  129. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  130. package/dist/MultiSelector/MultiSelector.js +17 -6
  131. package/dist/MultiSelector/index.d.ts +1 -1
  132. package/dist/MultiSelector/index.d.ts.map +1 -1
  133. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  134. package/dist/NavIcon/NavIcon.js +5 -1
  135. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  136. package/dist/NavMenu/NavHeadingMenu.js +3 -2
  137. package/dist/NumberInput/NumberInput.d.ts +1 -0
  138. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  139. package/dist/NumberInput/NumberInput.js +27 -37
  140. package/dist/NumberInput/numberParser.d.ts +43 -0
  141. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  142. package/dist/NumberInput/numberParser.js +293 -0
  143. package/dist/Outline/Outline.d.ts.map +1 -1
  144. package/dist/Outline/Outline.js +3 -2
  145. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  146. package/dist/OverflowList/OverflowList.js +3 -2
  147. package/dist/Overlay/Overlay.d.ts.map +1 -1
  148. package/dist/Overlay/Overlay.js +3 -2
  149. package/dist/Popover/usePopover.d.ts.map +1 -1
  150. package/dist/Popover/usePopover.js +20 -17
  151. package/dist/PowerSearch/PowerSearch.d.ts +8 -2
  152. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  153. package/dist/PowerSearch/PowerSearch.js +19 -6
  154. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
  155. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  156. package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
  157. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
  158. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  159. package/dist/PowerSearch/PowerSearchValueEditor.js +19 -9
  160. package/dist/PowerSearch/types.d.ts +2 -0
  161. package/dist/PowerSearch/types.d.ts.map +1 -1
  162. package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
  163. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  164. package/dist/PowerSearch/usePowerSearchSource.js +14 -5
  165. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  166. package/dist/ProgressBar/ProgressBar.js +18 -5
  167. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  168. package/dist/Resizable/ResizeHandle.js +3 -2
  169. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  170. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  171. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  172. package/dist/SelectableCard/SelectableCard.js +3 -3
  173. package/dist/Selector/Selector.d.ts.map +1 -1
  174. package/dist/Selector/Selector.js +5 -0
  175. package/dist/SideNav/SideNav.d.ts.map +1 -1
  176. package/dist/SideNav/SideNav.js +4 -3
  177. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  178. package/dist/SideNav/SideNavHeading.js +8 -7
  179. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  180. package/dist/SideNav/SideNavItem.js +4 -3
  181. package/dist/Slider/Slider.d.ts.map +1 -1
  182. package/dist/Slider/Slider.js +3 -3
  183. package/dist/Spinner/Spinner.d.ts +3 -3
  184. package/dist/Spinner/Spinner.d.ts.map +1 -1
  185. package/dist/Spinner/Spinner.js +130 -78
  186. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  187. package/dist/StatusDot/StatusDot.js +6 -1
  188. package/dist/Stepper/Step.d.ts +140 -0
  189. package/dist/Stepper/Step.d.ts.map +1 -0
  190. package/dist/Stepper/Step.js +1045 -0
  191. package/dist/Stepper/StepStatus.d.ts +24 -0
  192. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  193. package/dist/Stepper/StepStatus.js +1 -0
  194. package/dist/Stepper/Stepper.d.ts +93 -0
  195. package/dist/Stepper/Stepper.d.ts.map +1 -0
  196. package/dist/Stepper/Stepper.js +184 -0
  197. package/dist/Stepper/StepperContext.d.ts +41 -0
  198. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  199. package/dist/Stepper/StepperContext.js +34 -0
  200. package/dist/Stepper/index.d.ts +8 -0
  201. package/dist/Stepper/index.d.ts.map +1 -0
  202. package/dist/Stepper/index.js +7 -0
  203. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  204. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  205. package/dist/Stepper/stepper.stylex.js +20 -0
  206. package/dist/Switch/Switch.d.ts.map +1 -1
  207. package/dist/Switch/Switch.js +8 -3
  208. package/dist/TabList/Tab.d.ts +15 -2
  209. package/dist/TabList/Tab.d.ts.map +1 -1
  210. package/dist/TabList/Tab.js +32 -7
  211. package/dist/TabList/TabList.d.ts +46 -7
  212. package/dist/TabList/TabList.d.ts.map +1 -1
  213. package/dist/TabList/TabList.js +353 -23
  214. package/dist/TabList/TabListContext.d.ts +11 -1
  215. package/dist/TabList/TabListContext.d.ts.map +1 -1
  216. package/dist/TabList/TabListContext.js +11 -2
  217. package/dist/TabList/TabMenu.d.ts.map +1 -1
  218. package/dist/TabList/TabMenu.js +3 -2
  219. package/dist/TabList/index.d.ts +2 -2
  220. package/dist/TabList/index.d.ts.map +1 -1
  221. package/dist/Table/BaseTable.d.ts.map +1 -1
  222. package/dist/Table/BaseTable.js +10 -2
  223. package/dist/Table/Table.d.ts.map +1 -1
  224. package/dist/Table/Table.js +3 -6
  225. package/dist/Table/TableRow.d.ts +16 -5
  226. package/dist/Table/TableRow.d.ts.map +1 -1
  227. package/dist/Table/TableRow.js +16 -5
  228. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  229. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
  230. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  231. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  232. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  233. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  234. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  235. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  236. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  237. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  238. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  239. package/dist/Table/plugins/selection/useTableSelection.js +19 -5
  240. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  241. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  242. package/dist/Table/types.d.ts +22 -4
  243. package/dist/Table/types.d.ts.map +1 -1
  244. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  245. package/dist/Table/useBaseTablePlugins.js +5 -0
  246. package/dist/Text/Text.d.ts.map +1 -1
  247. package/dist/Text/Text.js +6 -2
  248. package/dist/TextArea/TextArea.d.ts.map +1 -1
  249. package/dist/TextArea/TextArea.js +9 -3
  250. package/dist/TextInput/TextInput.d.ts.map +1 -1
  251. package/dist/TextInput/TextInput.js +3 -2
  252. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  253. package/dist/TimeInput/TimeInput.js +3 -2
  254. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  255. package/dist/Timestamp/Timestamp.js +5 -3
  256. package/dist/Token/TokenLink.d.ts.map +1 -1
  257. package/dist/Token/TokenLink.js +2 -2
  258. package/dist/Tokenizer/Tokenizer.d.ts +3 -1
  259. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  260. package/dist/Tokenizer/Tokenizer.js +2 -0
  261. package/dist/Tooltip/Tooltip.d.ts +5 -0
  262. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  263. package/dist/Tooltip/useTooltip.d.ts +5 -0
  264. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  265. package/dist/Tooltip/useTooltip.js +39 -24
  266. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  267. package/dist/TopNav/TopNavHeading.js +5 -4
  268. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  269. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  270. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  271. package/dist/TopNav/TopNavMenu.js +4 -3
  272. package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
  273. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  274. package/dist/Typeahead/BaseTypeahead.js +68 -29
  275. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  276. package/dist/Typeahead/Typeahead.js +3 -2
  277. package/dist/astryx.css +94 -7
  278. package/dist/hooks/index.d.ts +1 -0
  279. package/dist/hooks/index.d.ts.map +1 -1
  280. package/dist/hooks/index.js +1 -0
  281. package/dist/hooks/useFocusTrap.d.ts +7 -4
  282. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  283. package/dist/hooks/useFocusTrap.js +60 -95
  284. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  285. package/dist/hooks/useHotkeys.js +3 -18
  286. package/dist/hooks/useMergedRefs.d.ts +18 -0
  287. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  288. package/dist/hooks/useMergedRefs.js +25 -0
  289. package/dist/index.d.ts +1 -0
  290. package/dist/index.d.ts.map +1 -1
  291. package/dist/index.js +1 -0
  292. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  293. package/dist/theme/derivedVarRegistry.js +24 -4
  294. package/dist/theme/syntax/tokens.d.ts +1 -1
  295. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  296. package/dist/theme/syntax/tokens.js +5 -2
  297. package/dist/utils/groupItems.d.ts +5 -1
  298. package/dist/utils/groupItems.d.ts.map +1 -1
  299. package/dist/utils/groupItems.js +9 -9
  300. package/dist/utils/index.d.ts +1 -1
  301. package/dist/utils/index.d.ts.map +1 -1
  302. package/dist/utils/isApplePlatform.d.ts +18 -0
  303. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  304. package/dist/utils/isApplePlatform.js +37 -0
  305. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  306. package/dist/utils/sharedResizeObserver.js +10 -1
  307. package/dist/utils/timeParser.d.ts +1 -1
  308. package/dist/utils/timeParser.d.ts.map +1 -1
  309. package/dist/utils/timeParser.js +26 -12
  310. package/locales/en.json +31 -7
  311. package/locales/pseudo.json +18 -0
  312. package/package.json +8 -3
  313. package/src/AppShell/AppShell.tsx +3 -2
  314. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  315. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  316. package/src/AspectRatio/AspectRatio.tsx +40 -1
  317. package/src/Avatar/Avatar.doc.mjs +14 -3
  318. package/src/Avatar/Avatar.test.tsx +97 -0
  319. package/src/Avatar/Avatar.tsx +125 -52
  320. package/src/Avatar/index.ts +2 -2
  321. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  322. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  323. package/src/AvatarGroup/AvatarGroup.tsx +15 -6
  324. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  325. package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
  326. package/src/Banner/Banner.doc.mjs +13 -11
  327. package/src/Banner/Banner.test.tsx +102 -15
  328. package/src/Banner/Banner.tsx +72 -25
  329. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  330. package/src/BottomSheet/BottomSheet.tsx +17 -4
  331. package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
  332. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  333. package/src/Button/Button.doc.mjs +22 -0
  334. package/src/Button/Button.test.tsx +13 -0
  335. package/src/Button/Button.tsx +5 -4
  336. package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
  337. package/src/ButtonGroup/ButtonGroup.test.tsx +391 -1
  338. package/src/ButtonGroup/ButtonGroup.tsx +23 -5
  339. package/src/Calendar/Calendar.doc.mjs +4 -3
  340. package/src/Calendar/Calendar.test.tsx +52 -0
  341. package/src/Calendar/Calendar.tsx +18 -15
  342. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  343. package/src/Calendar/getInitialFocusDate.ts +93 -0
  344. package/src/Carousel/Carousel.tsx +3 -2
  345. package/src/Chat/ChatComposerInput.tsx +5 -1
  346. package/src/Chat/ChatLayout.tsx +3 -2
  347. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  348. package/src/Chat/ChatMessageList.test.tsx +46 -0
  349. package/src/Chat/ChatMessageList.tsx +28 -4
  350. package/src/Chat/ChatTokenizedText.tsx +17 -10
  351. package/src/Chat/useChatComposerTokens.ts +1 -1
  352. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  353. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  354. package/src/CheckboxInput/CheckboxInput.tsx +8 -2
  355. package/src/ClickableCard/ClickableCard.tsx +3 -2
  356. package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
  357. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  358. package/src/CodeBlock/CodeBlock.tsx +20 -4
  359. package/src/CodeBlock/highlightRanges.ts +1 -1
  360. package/src/CodeBlock/highlightStyles.ts +13 -13
  361. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  362. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  363. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  364. package/src/ContextMenu/ContextMenu.tsx +4 -3
  365. package/src/DateInput/DateInput.doc.mjs +16 -0
  366. package/src/DateInput/DateInput.tsx +55 -2
  367. package/src/DateInput/DateInputTouch.test.tsx +68 -9
  368. package/src/DateInput/NativeDateField.test.tsx +565 -0
  369. package/src/DateInput/NativeDateField.tsx +623 -0
  370. package/src/DateInput/TouchDateField.tsx +38 -4
  371. package/src/DateInput/index.ts +1 -0
  372. package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
  373. package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
  374. package/src/DateTimeInput/DateTimeInput.tsx +556 -24
  375. package/src/DateTimeInput/index.ts +1 -0
  376. package/src/Dialog/Dialog.doc.mjs +8 -3
  377. package/src/Dialog/Dialog.test.tsx +261 -1
  378. package/src/Dialog/Dialog.tsx +109 -58
  379. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  380. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
  381. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
  382. package/src/Field/Field.doc.mjs +13 -2
  383. package/src/Field/FieldLabel.test.tsx +29 -0
  384. package/src/Field/FieldLabel.tsx +7 -0
  385. package/src/FileInput/FileInput.tsx +3 -2
  386. package/src/Heading/Heading.test.tsx +23 -1
  387. package/src/Heading/Heading.tsx +6 -2
  388. package/src/HoverCard/HoverCard.doc.mjs +13 -2
  389. package/src/HoverCard/HoverCard.test.tsx +101 -4
  390. package/src/HoverCard/HoverCard.tsx +71 -3
  391. package/src/HoverCard/useHoverCard.tsx +101 -33
  392. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  393. package/src/Indicator/Indicator.doc.mjs +2 -0
  394. package/src/Item/Item.tsx +5 -4
  395. package/src/Kbd/Kbd.tsx +2 -19
  396. package/src/Layer/LayerDepthContext.tsx +62 -0
  397. package/src/Layer/index.ts +9 -0
  398. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  399. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  400. package/src/Layer/layerStack.ts +362 -0
  401. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  402. package/src/Layer/useLayerDismissal.ts +173 -0
  403. package/src/Layout/Layout.doc.mjs +2 -2
  404. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  405. package/src/Lightbox/Lightbox.tsx +124 -102
  406. package/src/Link/Link.doc.mjs +39 -0
  407. package/src/Markdown/Markdown.doc.mjs +5 -0
  408. package/src/Markdown/incremental.test.ts +16 -2
  409. package/src/Markdown/index.ts +1 -0
  410. package/src/Markdown/parser.perf.test.ts +96 -1
  411. package/src/Markdown/parser.test.ts +145 -2
  412. package/src/Markdown/parser.ts +244 -29
  413. package/src/MobileNav/MobileNav.tsx +62 -36
  414. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  415. package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
  416. package/src/MultiSelector/MultiSelector.test.tsx +106 -0
  417. package/src/MultiSelector/MultiSelector.tsx +50 -6
  418. package/src/MultiSelector/index.ts +1 -0
  419. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  420. package/src/NavIcon/NavIcon.test.tsx +9 -0
  421. package/src/NavIcon/NavIcon.tsx +5 -1
  422. package/src/NavMenu/NavHeadingMenu.tsx +3 -2
  423. package/src/NumberInput/NumberInput.doc.mjs +20 -0
  424. package/src/NumberInput/NumberInput.tsx +28 -29
  425. package/src/NumberInput/numberParser.test.ts +137 -0
  426. package/src/NumberInput/numberParser.ts +346 -0
  427. package/src/Outline/Outline.tsx +3 -2
  428. package/src/OverflowList/OverflowList.tsx +3 -2
  429. package/src/Overlay/Overlay.tsx +3 -2
  430. package/src/Popover/usePopover.tsx +31 -28
  431. package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
  432. package/src/PowerSearch/PowerSearch.test.tsx +240 -1
  433. package/src/PowerSearch/PowerSearch.tsx +34 -5
  434. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +201 -0
  435. package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
  436. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +47 -1
  437. package/src/PowerSearch/PowerSearchValueEditor.tsx +15 -0
  438. package/src/PowerSearch/types.ts +2 -0
  439. package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
  440. package/src/PowerSearch/usePowerSearchSource.ts +13 -3
  441. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  442. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  443. package/src/ProgressBar/ProgressBar.tsx +28 -8
  444. package/src/Resizable/ResizeHandle.tsx +3 -2
  445. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  446. package/src/SelectableCard/SelectableCard.tsx +3 -2
  447. package/src/Selector/Selector.doc.mjs +12 -1
  448. package/src/Selector/Selector.test.tsx +45 -1
  449. package/src/Selector/Selector.tsx +11 -1
  450. package/src/SideNav/SideNav.doc.mjs +6 -6
  451. package/src/SideNav/SideNav.tsx +4 -2
  452. package/src/SideNav/SideNavHeading.tsx +12 -12
  453. package/src/SideNav/SideNavItem.tsx +4 -2
  454. package/src/Slider/Slider.tsx +3 -2
  455. package/src/Spinner/Spinner.test.tsx +147 -1
  456. package/src/Spinner/Spinner.tsx +120 -101
  457. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  458. package/src/StatusDot/StatusDot.test.tsx +9 -0
  459. package/src/StatusDot/StatusDot.tsx +7 -1
  460. package/src/Stepper/Step.doc.mjs +98 -0
  461. package/src/Stepper/Step.tsx +1638 -0
  462. package/src/Stepper/StepStatus.ts +26 -0
  463. package/src/Stepper/Stepper.doc.mjs +370 -0
  464. package/src/Stepper/Stepper.test.tsx +1024 -0
  465. package/src/Stepper/Stepper.tsx +258 -0
  466. package/src/Stepper/StepperContext.ts +71 -0
  467. package/src/Stepper/index.ts +18 -0
  468. package/src/Stepper/stepper.stylex.ts +19 -0
  469. package/src/Switch/Switch.doc.mjs +2 -0
  470. package/src/Switch/Switch.test.tsx +10 -0
  471. package/src/Switch/Switch.tsx +6 -2
  472. package/src/TabList/Tab.doc.mjs +13 -1
  473. package/src/TabList/Tab.tsx +67 -7
  474. package/src/TabList/TabList.doc.mjs +22 -6
  475. package/src/TabList/TabList.test.tsx +559 -0
  476. package/src/TabList/TabList.tsx +490 -22
  477. package/src/TabList/TabListContext.ts +13 -2
  478. package/src/TabList/TabMenu.tsx +3 -2
  479. package/src/TabList/index.ts +6 -2
  480. package/src/Table/BaseTable.tsx +12 -4
  481. package/src/Table/Table.doc.mjs +9 -2
  482. package/src/Table/Table.test.tsx +132 -14
  483. package/src/Table/Table.tsx +3 -8
  484. package/src/Table/TableBody.doc.mjs +40 -0
  485. package/src/Table/TableFooter.doc.mjs +40 -0
  486. package/src/Table/TableHeader.doc.mjs +40 -0
  487. package/src/Table/TableRow.tsx +16 -5
  488. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  489. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  490. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
  491. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  492. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  493. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  494. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  495. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  496. package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
  497. package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
  498. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  499. package/src/Table/types.ts +22 -4
  500. package/src/Table/useBaseTablePlugins.ts +5 -0
  501. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  502. package/src/Table/useTablePagination.doc.mjs +7 -0
  503. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  504. package/src/Table/useTableSelection.doc.mjs +31 -0
  505. package/src/Text/Text.test.tsx +23 -1
  506. package/src/Text/Text.tsx +6 -2
  507. package/src/TextArea/TextArea.doc.mjs +8 -2
  508. package/src/TextArea/TextArea.test.tsx +11 -0
  509. package/src/TextArea/TextArea.tsx +15 -8
  510. package/src/TextInput/TextInput.doc.mjs +10 -0
  511. package/src/TextInput/TextInput.tsx +3 -2
  512. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  513. package/src/TimeInput/TimeInput.tsx +2 -2
  514. package/src/Timestamp/Timestamp.tsx +4 -2
  515. package/src/Toast/Toast.doc.mjs +6 -0
  516. package/src/Token/TokenLink.tsx +2 -2
  517. package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
  518. package/src/Tokenizer/Tokenizer.tsx +4 -0
  519. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  520. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  521. package/src/Tooltip/Tooltip.test.tsx +32 -0
  522. package/src/Tooltip/Tooltip.tsx +5 -0
  523. package/src/Tooltip/useTooltip.tsx +47 -24
  524. package/src/TopNav/TopNavHeading.tsx +5 -4
  525. package/src/TopNav/TopNavMegaMenu.tsx +3 -2
  526. package/src/TopNav/TopNavMenu.tsx +4 -3
  527. package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
  528. package/src/Typeahead/BaseTypeahead.tsx +85 -33
  529. package/src/Typeahead/Typeahead.doc.mjs +5 -0
  530. package/src/Typeahead/Typeahead.test.tsx +49 -0
  531. package/src/Typeahead/Typeahead.tsx +3 -2
  532. package/src/hooks/index.ts +2 -0
  533. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  534. package/src/hooks/useFocusTrap.test.tsx +14 -0
  535. package/src/hooks/useFocusTrap.ts +62 -111
  536. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  537. package/src/hooks/useHotkeys.ts +3 -18
  538. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  539. package/src/hooks/useMergedRefs.test.tsx +62 -0
  540. package/src/hooks/useMergedRefs.ts +36 -0
  541. package/src/index.ts +1 -0
  542. package/src/theme/MediaTheme.doc.mjs +5 -5
  543. package/src/theme/derivedVarRegistry.test.ts +19 -3
  544. package/src/theme/derivedVarRegistry.ts +23 -4
  545. package/src/theme/generateThemeRules.test.ts +37 -0
  546. package/src/theme/syntax/tokens.ts +5 -2
  547. package/src/utils/groupItems.ts +12 -6
  548. package/src/utils/index.ts +1 -1
  549. package/src/utils/isApplePlatform.test.ts +61 -0
  550. package/src/utils/isApplePlatform.ts +37 -0
  551. package/src/utils/sharedResizeObserver.ts +10 -2
  552. package/src/utils/timeParser.test.ts +6 -1
  553. package/src/utils/timeParser.ts +35 -13
  554. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -12,6 +12,8 @@ import {
12
12
  } from 'vitest';
13
13
  import {render, screen, fireEvent, act} from '@testing-library/react';
14
14
  import React, {useState} from 'react';
15
+ import * as stylex from '@stylexjs/stylex';
16
+ import {spacingVars} from '../theme/tokens.stylex';
15
17
  import {PowerSearch} from './PowerSearch';
16
18
  import {PowerSearchEditPopover} from './PowerSearchEditPopover';
17
19
  import {useInternalConfig} from './useInternalConfig';
@@ -326,3 +328,202 @@ describe('PowerSearch', () => {
326
328
  expect(onSave).toHaveBeenCalledTimes(1);
327
329
  });
328
330
  });
331
+
332
+ // =============================================================================
333
+ // Narrow-width layout (#4761)
334
+ // =============================================================================
335
+
336
+ // jsdom performs no real layout (and never matches @container conditions), so
337
+ // these tests assert the declarations that produce the narrow-width behavior
338
+ // rather than measured geometry, via StyleX probe classes: one deterministic
339
+ // atomic class per property/value/condition, so an element carries a probe's
340
+ // classes exactly when it has the same declaration. The dev debug class
341
+ // (contains "__") is excluded.
342
+ const CHIP_ROW_COLLAPSE = '@container (max-width: 399px)';
343
+
344
+ const probe = stylex.create({
345
+ responsiveLayerMinWidth: {
346
+ minWidth: `min(400px, calc(100% - ${spacingVars['--spacing-4']}))`,
347
+ },
348
+ fixedLayerMinWidth: {minWidth: 400},
349
+ queryContainer: {containerType: 'inline-size'},
350
+ responsiveWrap: {
351
+ flexWrap: {default: 'nowrap', [CHIP_ROW_COLLAPSE]: 'wrap'},
352
+ },
353
+ cellMaxWidth: {maxWidth: '100%'},
354
+ nestedFieldCellWidth: {width: 200},
355
+ });
356
+
357
+ function atomicClasses(style: (typeof probe)[keyof typeof probe]): string[] {
358
+ const {className = ''} = stylex.props(style);
359
+ const classes = className
360
+ .split(' ')
361
+ .filter(c => c !== '' && !c.includes('__'));
362
+ // A probe resolving to no atomic classes would make every assertion built
363
+ // on it vacuous, including the not-toHaveClass loops; fail loudly instead.
364
+ expect(classes.length).toBeGreaterThan(0);
365
+ return classes;
366
+ }
367
+
368
+ function expectProbeClasses(
369
+ el: HTMLElement,
370
+ style: (typeof probe)[keyof typeof probe],
371
+ ) {
372
+ for (const cls of atomicClasses(style)) {
373
+ expect(el).toHaveClass(cls);
374
+ }
375
+ }
376
+
377
+ describe('narrow-width layout (#4761)', () => {
378
+ function EditHarness() {
379
+ const internalConfig = useInternalConfig(testConfig);
380
+ return (
381
+ <PowerSearchEditPopover
382
+ config={internalConfig}
383
+ filter={{
384
+ field: 'status',
385
+ operator: 'is',
386
+ value: {type: 'string', value: 'open'},
387
+ }}
388
+ mode="edit"
389
+ onSave={() => {}}
390
+ onCancel={() => {}}
391
+ />
392
+ );
393
+ }
394
+
395
+ function getChipRow(container: HTMLElement): HTMLElement {
396
+ // Locate the chip row by its collapse declaration, then sanity-check it
397
+ // really is the row holding the field / operator / value cells.
398
+ const [rowCls] = atomicClasses(probe.responsiveWrap);
399
+ const row = container.querySelector(`.${rowCls}`) as HTMLElement;
400
+ expect(row).not.toBeNull();
401
+ expect(row).toHaveClass('astryx-stack');
402
+ expect(row.children).toHaveLength(3);
403
+ return row;
404
+ }
405
+
406
+ it('popover root establishes the container the collapse query measures', () => {
407
+ const {container} = render(<EditHarness />);
408
+
409
+ // Without inline-size containment on the root, no @container condition
410
+ // in this file can match and the chip rows would never wrap.
411
+ const root = container.firstElementChild as HTMLElement;
412
+ expect(root).not.toBeNull();
413
+ expectProbeClasses(root, probe.queryContainer);
414
+ });
415
+
416
+ it('filter chip row wraps below the collapse width instead of overflowing', () => {
417
+ const {container} = render(<EditHarness />);
418
+
419
+ const row = getChipRow(container);
420
+ expectProbeClasses(row, probe.responsiveWrap);
421
+ });
422
+
423
+ it('operator cell is capped at the row width', () => {
424
+ const {container} = render(<EditHarness />);
425
+
426
+ // Capped so a long translated operator label truncates inside the
427
+ // Selector trigger instead of pushing the row wider than the popover.
428
+ const operatorCell = getChipRow(container).children[1] as HTMLElement;
429
+ expectProbeClasses(operatorCell, probe.cellMaxWidth);
430
+ });
431
+
432
+ it('nested sub-filter rows wrap instead of overflowing on one line', () => {
433
+ const nestedConfig: PowerSearchConfig = {
434
+ name: 'test-nested',
435
+ fields: [
436
+ {
437
+ key: 'group',
438
+ label: 'Group',
439
+ operators: [
440
+ {key: 'all_of', label: 'all of', value: {type: 'nested'}},
441
+ ],
442
+ },
443
+ {
444
+ key: 'status',
445
+ label: 'Status',
446
+ operators: [{key: 'is', label: 'is', value: {type: 'string'}}],
447
+ },
448
+ ],
449
+ };
450
+
451
+ function NestedHarness() {
452
+ const internalConfig = useInternalConfig(nestedConfig);
453
+ return (
454
+ <PowerSearchEditPopover
455
+ config={internalConfig}
456
+ filter={{
457
+ field: 'group',
458
+ operator: 'all_of',
459
+ value: {
460
+ type: 'nested',
461
+ value: [
462
+ {
463
+ field: 'status',
464
+ operator: 'is',
465
+ value: {type: 'string', value: 'open'},
466
+ },
467
+ ],
468
+ },
469
+ }}
470
+ mode="edit"
471
+ onSave={() => {}}
472
+ onCancel={() => {}}
473
+ />
474
+ );
475
+ }
476
+
477
+ const {container} = render(<NestedHarness />);
478
+
479
+ // Locate the sub-filter row through its fixed-width field cell.
480
+ const [cellCls] = atomicClasses(probe.nestedFieldCellWidth);
481
+ const fieldCell = container.querySelector(`.${cellCls}`) as HTMLElement;
482
+ expect(fieldCell).not.toBeNull();
483
+ const row = fieldCell.parentElement as HTMLElement;
484
+ expect(row).toHaveClass('astryx-stack');
485
+ expectProbeClasses(row, probe.responsiveWrap);
486
+
487
+ // The fixed-width cells are capped so they cannot clip in containers
488
+ // narrower than their design width (or under deep TreeList indentation).
489
+ expectProbeClasses(fieldCell, probe.cellMaxWidth);
490
+ const operatorCell = row.children[1] as HTMLElement;
491
+ expectProbeClasses(operatorCell, probe.cellMaxWidth);
492
+ });
493
+
494
+ it('edit popover layer yields to viewports narrower than its 400px floor', () => {
495
+ const filters: PowerSearchFilter[] = [
496
+ {field: 'status', operator: 'is', value: {type: 'string', value: 'open'}},
497
+ ];
498
+
499
+ function Harness() {
500
+ const [currentFilters, setCurrentFilters] = useState(filters);
501
+ return (
502
+ <PowerSearch
503
+ config={testConfig}
504
+ filters={currentFilters}
505
+ onChange={newFilters => setCurrentFilters([...newFilters])}
506
+ />
507
+ );
508
+ }
509
+
510
+ render(<Harness />);
511
+
512
+ act(() => {
513
+ fireEvent.click(screen.getByText('Status: is'));
514
+ flushRAF();
515
+ });
516
+
517
+ const layer = screen
518
+ .getByText('Cancel')
519
+ .closest('[popover]') as HTMLElement;
520
+ expect(layer).not.toBeNull();
521
+
522
+ // The fixed 400px floor is replaced by one clamped to the available
523
+ // inline space, so the popover never opens wider than the screen.
524
+ expectProbeClasses(layer, probe.responsiveLayerMinWidth);
525
+ for (const cls of atomicClasses(probe.fixedLayerMinWidth)) {
526
+ expect(layer).not.toHaveClass(cls);
527
+ }
528
+ });
529
+ });
@@ -32,13 +32,23 @@ import type {
32
32
  OperatorValue,
33
33
  } from './types';
34
34
 
35
+ // Below the popover layer's 400px floor (see popoverLayerStyles in
36
+ // PowerSearch.tsx) the chip rows collapse from one line to wrapped lines.
37
+ // A container query, not a viewport one, so the rows track the width the
38
+ // popover actually got (#4761).
39
+ const CHIP_ROW_COLLAPSE = '@container (max-width: 399px)';
40
+
35
41
  const styles = stylex.create({
36
42
  container: {
37
43
  overflow: 'hidden',
44
+ containerType: 'inline-size',
38
45
  },
39
46
  content: {
40
47
  padding: spacingVars['--spacing-4'],
41
48
  },
49
+ chipRow: {
50
+ flexWrap: {default: 'nowrap', [CHIP_ROW_COLLAPSE]: 'wrap'},
51
+ },
42
52
  footer: {
43
53
  padding: spacingVars['--spacing-3'],
44
54
  paddingTop: 0,
@@ -51,6 +61,9 @@ const styles = stylex.create({
51
61
  operatorSelector: {
52
62
  flexGrow: 1,
53
63
  flexShrink: 0,
64
+ // Long translated operator labels truncate in the Selector trigger
65
+ // instead of pushing the row wider than the popover (#4761).
66
+ maxWidth: '100%',
54
67
  },
55
68
  valueEditor: {
56
69
  flexGrow: 2,
@@ -63,10 +76,12 @@ const styles = stylex.create({
63
76
  nestedFieldSelector: {
64
77
  flexShrink: 0,
65
78
  width: 200,
79
+ maxWidth: '100%',
66
80
  },
67
81
  nestedOperatorSelector: {
68
82
  flexShrink: 0,
69
83
  width: 180,
84
+ maxWidth: '100%',
70
85
  },
71
86
  nestedRow: {
72
87
  width: '100%',
@@ -90,6 +105,8 @@ export interface PowerSearchEditPopoverProps {
90
105
  onCancel: () => void;
91
106
  /** Label for the save button. @default 'Apply' */
92
107
  saveButtonLabel?: string;
108
+ /** Max suggestions in string and entity value typeaheads. */
109
+ maxMenuItems?: number;
93
110
  /** Whether the filter is read-only. */
94
111
  isReadOnly?: boolean;
95
112
  }
@@ -232,6 +249,7 @@ interface NestedSubFilterRowProps {
232
249
  config: InternalConfig;
233
250
  subFilter: EditablePartialFilter;
234
251
  onChange: (subFilter: EditablePartialFilter) => void;
252
+ maxMenuItems?: number;
235
253
  isReadOnly: boolean;
236
254
  }
237
255
 
@@ -239,6 +257,7 @@ function NestedSubFilterRow({
239
257
  config,
240
258
  subFilter,
241
259
  onChange,
260
+ maxMenuItems,
242
261
  isReadOnly,
243
262
  }: NestedSubFilterRowProps) {
244
263
  const t = useTranslator();
@@ -309,7 +328,7 @@ function NestedSubFilterRow({
309
328
  );
310
329
 
311
330
  return (
312
- <HStack gap={2} vAlign="center">
331
+ <HStack gap={2} vAlign="center" xstyle={styles.chipRow}>
313
332
  <div {...stylex.props(styles.nestedFieldSelector)}>
314
333
  <Selector
315
334
  label={t('@astryx.powersearch.editor.field')}
@@ -341,6 +360,7 @@ function NestedSubFilterRow({
341
360
  filterValue={subFilter.value}
342
361
  onChange={handleValueChange}
343
362
  config={config}
363
+ maxMenuItems={maxMenuItems}
344
364
  isDisabled={isReadOnly}
345
365
  />
346
366
  </div>
@@ -359,6 +379,7 @@ interface NestedEditorProps {
359
379
  operatorOptions: {value: string; label: string}[];
360
380
  onOperatorChange: (operatorKey: string) => void;
361
381
  onPartialFilterChange: (filter: PartialFilter) => void;
382
+ maxMenuItems?: number;
362
383
  isReadOnly: boolean;
363
384
  }
364
385
 
@@ -368,6 +389,7 @@ function NestedEditor({
368
389
  operatorOptions,
369
390
  onOperatorChange,
370
391
  onPartialFilterChange,
392
+ maxMenuItems,
371
393
  isReadOnly,
372
394
  }: NestedEditorProps) {
373
395
  const t = useTranslator();
@@ -489,6 +511,7 @@ function NestedEditor({
489
511
  config={config}
490
512
  subFilter={sf}
491
513
  onChange={updated => handleUpdate(itemPath, updated)}
514
+ maxMenuItems={maxMenuItems}
492
515
  isReadOnly={isReadOnly}
493
516
  />
494
517
  ),
@@ -515,6 +538,7 @@ function NestedEditor({
515
538
  config={config}
516
539
  subFilter={sf}
517
540
  onChange={updated => handleUpdate(itemPath, updated)}
541
+ maxMenuItems={maxMenuItems}
518
542
  isReadOnly={isReadOnly}
519
543
  />
520
544
  ),
@@ -593,6 +617,7 @@ export function PowerSearchEditPopover({
593
617
  onSave,
594
618
  onCancel,
595
619
  saveButtonLabel: saveButtonLabelFromProps,
620
+ maxMenuItems,
596
621
  isReadOnly = false,
597
622
  }: PowerSearchEditPopoverProps) {
598
623
  const t = useTranslator();
@@ -762,6 +787,7 @@ export function PowerSearchEditPopover({
762
787
  operatorOptions={operatorOptions}
763
788
  onOperatorChange={handleOperatorChange}
764
789
  onPartialFilterChange={setPartialFilter}
790
+ maxMenuItems={maxMenuItems}
765
791
  isReadOnly={isReadOnly}
766
792
  />
767
793
  </VStack>
@@ -802,7 +828,7 @@ export function PowerSearchEditPopover({
802
828
  return (
803
829
  <div {...stylex.props(styles.container)} onKeyDown={handleKeyDown}>
804
830
  <div {...stylex.props(styles.content)}>
805
- <HStack gap={2}>
831
+ <HStack gap={2} xstyle={styles.chipRow}>
806
832
  <div {...stylex.props(styles.fieldSelector)}>
807
833
  <Selector
808
834
  label={t('@astryx.powersearch.editor.field')}
@@ -835,6 +861,7 @@ export function PowerSearchEditPopover({
835
861
  onChange={handleValueChange}
836
862
  onEnter={handleSave}
837
863
  config={config}
864
+ maxMenuItems={maxMenuItems}
838
865
  isDisabled={isReadOnly}
839
866
  />
840
867
  </div>
@@ -10,7 +10,11 @@
10
10
  import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
11
11
  import {render, screen, fireEvent, act} from '@testing-library/react';
12
12
  import {PowerSearchValueEditor} from './PowerSearchValueEditor';
13
- import type {FilterValueEntityList, PowerSearchEntity} from './types';
13
+ import type {
14
+ FilterValueEntityList,
15
+ OperatorValue,
16
+ PowerSearchEntity,
17
+ } from './types';
14
18
  import type {InternalConfig} from './useInternalConfig';
15
19
  import type {SearchableItem, SearchSource} from '../Typeahead/types';
16
20
 
@@ -404,3 +408,45 @@ describe('StringListEditor (#1107)', () => {
404
408
  expect(screen.getByRole('combobox')).toBeInTheDocument();
405
409
  });
406
410
  });
411
+
412
+ describe('maxMenuItems', () => {
413
+ const source = createSearchSource(
414
+ Array.from({length: 6}, (_, index) => ({
415
+ id: `option-${index}`,
416
+ label: `Option ${index}`,
417
+ })),
418
+ );
419
+
420
+ async function expectCapped(operatorValue: OperatorValue) {
421
+ render(
422
+ <PowerSearchValueEditor
423
+ operatorValue={operatorValue}
424
+ filterValue={undefined}
425
+ onChange={vi.fn()}
426
+ config={stubConfig}
427
+ maxMenuItems={2}
428
+ />,
429
+ );
430
+
431
+ await act(async () => {
432
+ fireEvent.change(screen.getByRole('combobox'), {
433
+ target: {value: 'Option'},
434
+ });
435
+ await new Promise(resolve => setTimeout(resolve, 200));
436
+ });
437
+
438
+ expect(screen.getAllByRole('option', {hidden: true})).toHaveLength(2);
439
+ }
440
+
441
+ it('caps string suggestions', async () => {
442
+ await expectCapped({type: 'string', searchSource: source});
443
+ });
444
+
445
+ it('caps string-list suggestions', async () => {
446
+ await expectCapped({type: 'string_list', searchSource: source});
447
+ });
448
+
449
+ it('caps entity-list suggestions', async () => {
450
+ await expectCapped({type: 'entity_list', searchSource: source});
451
+ });
452
+ });
@@ -40,6 +40,8 @@ export interface PowerSearchValueEditorProps {
40
40
  onChange: (value: FilterValue, shouldSave?: boolean) => void;
41
41
  onEnter?: () => void;
42
42
  config: InternalConfig;
43
+ /** Max suggestions in string and entity value typeaheads. */
44
+ maxMenuItems?: number;
43
45
  isDisabled?: boolean;
44
46
  timezoneID?: string;
45
47
  }
@@ -80,11 +82,13 @@ function StringEditor({
80
82
  filterValue,
81
83
  onChange,
82
84
  onEnter: _onEnter,
85
+ maxMenuItems,
83
86
  }: {
84
87
  operatorValue: OperatorValue & {type: 'string'};
85
88
  filterValue: FilterValue | undefined;
86
89
  onChange: (value: FilterValue, shouldSave?: boolean) => void;
87
90
  onEnter?: () => void;
91
+ maxMenuItems?: number;
88
92
  }) {
89
93
  const t = useTranslator();
90
94
  const currentValue = filterValue?.type === 'string' ? filterValue.value : '';
@@ -111,6 +115,7 @@ function StringEditor({
111
115
  }}
112
116
  placeholder={t('@astryx.powersearch.valueEditor.searchPlaceholder')}
113
117
  debounceMs={150}
118
+ maxMenuItems={maxMenuItems}
114
119
  />
115
120
  );
116
121
  }
@@ -132,10 +137,12 @@ function StringListEditor({
132
137
  operatorValue,
133
138
  filterValue,
134
139
  onChange,
140
+ maxMenuItems,
135
141
  }: {
136
142
  operatorValue: OperatorValue & {type: 'string_list'};
137
143
  filterValue: FilterValue | undefined;
138
144
  onChange: (value: FilterValue) => void;
145
+ maxMenuItems?: number;
139
146
  }) {
140
147
  const t = useTranslator();
141
148
  const currentValue: SearchableItem[] = useMemo(() => {
@@ -176,6 +183,7 @@ function StringListEditor({
176
183
  placeholder={t('@astryx.powersearch.valueEditor.addValuesPlaceholder')}
177
184
  debounceMs={operatorValue.searchSource ? 150 : 0}
178
185
  hasCreate={hasCreate}
186
+ maxMenuItems={maxMenuItems}
179
187
  />
180
188
  );
181
189
  }
@@ -537,10 +545,12 @@ function EntityListEditor({
537
545
  operatorValue,
538
546
  filterValue,
539
547
  onChange,
548
+ maxMenuItems,
540
549
  }: {
541
550
  operatorValue: OperatorValue & {type: 'entity_list'};
542
551
  filterValue: FilterValue | undefined;
543
552
  onChange: (value: FilterValue) => void;
553
+ maxMenuItems?: number;
544
554
  }) {
545
555
  const t = useTranslator();
546
556
  const source = useMemo<SearchSource<SearchableItem>>(() => {
@@ -588,6 +598,7 @@ function EntityListEditor({
588
598
  renderItem={operatorValue.renderItem}
589
599
  placeholder={t('@astryx.powersearch.valueEditor.searchPlaceholder')}
590
600
  debounceMs={operatorValue.searchSource ? 150 : 0}
601
+ maxMenuItems={maxMenuItems}
591
602
  />
592
603
  );
593
604
  }
@@ -631,6 +642,7 @@ export function PowerSearchValueEditor({
631
642
  filterValue,
632
643
  onChange,
633
644
  onEnter,
645
+ maxMenuItems,
634
646
  isDisabled,
635
647
  }: PowerSearchValueEditorProps) {
636
648
  switch (operatorValue.type) {
@@ -644,6 +656,7 @@ export function PowerSearchValueEditor({
644
656
  filterValue={filterValue}
645
657
  onChange={onChange}
646
658
  onEnter={onEnter}
659
+ maxMenuItems={maxMenuItems}
647
660
  />
648
661
  );
649
662
 
@@ -653,6 +666,7 @@ export function PowerSearchValueEditor({
653
666
  operatorValue={operatorValue}
654
667
  filterValue={filterValue}
655
668
  onChange={onChange}
669
+ maxMenuItems={maxMenuItems}
656
670
  />
657
671
  );
658
672
 
@@ -734,6 +748,7 @@ export function PowerSearchValueEditor({
734
748
  operatorValue={operatorValue}
735
749
  filterValue={filterValue}
736
750
  onChange={onChange}
751
+ maxMenuItems={maxMenuItems}
737
752
  />
738
753
  );
739
754
 
@@ -384,6 +384,8 @@ export interface PowerSearchAuxData {
384
384
  readonly filterValue?: FilterValue;
385
385
  /** Index in the filters array (for editing/removing). */
386
386
  readonly filterIndex?: number;
387
+ /** Section heading for field-browser entries. */
388
+ readonly group?: string;
387
389
  }
388
390
 
389
391
  export type PowerSearchItem = SearchableItem<PowerSearchAuxData>;
@@ -21,10 +21,15 @@ import type {
21
21
  // Helpers
22
22
  // =============================================================================
23
23
 
24
- function createSource(config: PowerSearchConfig) {
24
+ function createSource(
25
+ config: PowerSearchConfig,
26
+ // Uncapped by default so these tests exercise matching and ranking rather
27
+ // than the typed-result cap, which has its own test below.
28
+ maxTypedResults: number = Number.POSITIVE_INFINITY,
29
+ ) {
25
30
  const {result} = renderHook(() => {
26
31
  const internal = useInternalConfig(config);
27
- return usePowerSearchSource(internal);
32
+ return usePowerSearchSource(internal, maxTypedResults);
28
33
  });
29
34
  return result.current;
30
35
  }
@@ -92,6 +97,27 @@ const configWithContentSearch: PowerSearchConfig = {
92
97
  contentSearchFieldKey: 'title',
93
98
  };
94
99
 
100
+ const groupedConfig: PowerSearchConfig = {
101
+ name: 'GroupedSearch',
102
+ fields: [
103
+ field('team_a', 'Field Team A', 'Team'),
104
+ field('plain_a', 'Field Plain A'),
105
+ field('time_a', 'Field Time A', 'Time'),
106
+ field('team_b', 'Field Team B', 'Team'),
107
+ field('plain_b', 'Field Plain B'),
108
+ field('time_b', 'Field Time B', 'Time'),
109
+ ],
110
+ };
111
+
112
+ function field(key: string, label: string, group?: string) {
113
+ return {
114
+ key,
115
+ label,
116
+ group,
117
+ operators: [{key: 'is', label: 'is', value: {type: 'string'} as const}],
118
+ };
119
+ }
120
+
95
121
  // =============================================================================
96
122
  // Tests
97
123
  // =============================================================================
@@ -125,6 +151,21 @@ describe('usePowerSearchSource', () => {
125
151
  const source = createSource(baseConfig);
126
152
  expect(syncSearch(source, '')).toEqual(syncBootstrap(source));
127
153
  });
154
+
155
+ it('orders ungrouped fields before named groups', () => {
156
+ const items = syncBootstrap(createSource(groupedConfig));
157
+ expect(items.map(item => item.label)).toEqual([
158
+ 'Field Plain A',
159
+ 'Field Plain B',
160
+ 'Field Team A',
161
+ 'Field Team B',
162
+ 'Field Time A',
163
+ 'Field Time B',
164
+ ]);
165
+ expect(
166
+ items.map(item => (item.auxiliaryData as PowerSearchAuxData).group),
167
+ ).toEqual([undefined, undefined, 'Team', 'Team', 'Time', 'Time']);
168
+ });
128
169
  });
129
170
 
130
171
  describe('search (with query)', () => {
@@ -176,6 +217,23 @@ describe('usePowerSearchSource', () => {
176
217
  const aux = isItem?.auxiliaryData as PowerSearchAuxData;
177
218
  expect(aux.operatorKey).toBe('is');
178
219
  });
220
+
221
+ it('leaves ranked results flat and in relevance order', () => {
222
+ const results = syncSearch(createSource(groupedConfig), 'field');
223
+ expect(results.slice(0, 6).map(item => item.label)).toEqual([
224
+ 'Field Team A',
225
+ 'Field Team A is',
226
+ 'Field Plain A',
227
+ 'Field Plain A is',
228
+ 'Field Time A',
229
+ 'Field Time A is',
230
+ ]);
231
+ expect(
232
+ results.every(
233
+ item => (item.auxiliaryData as PowerSearchAuxData).group == null,
234
+ ),
235
+ ).toBe(true);
236
+ });
179
237
  });
180
238
 
181
239
  describe('contentSearchFieldKey', () => {
@@ -539,3 +597,25 @@ describe('usePowerSearchSource', () => {
539
597
  });
540
598
  });
541
599
  });
600
+
601
+ describe('typed-result cap', () => {
602
+ const manyFields: PowerSearchConfig = {
603
+ name: 'many',
604
+ fields: Array.from({length: 25}, (_, i) => ({
605
+ key: `field_${i}`,
606
+ label: `Zebra ${String(i).padStart(2, '0')}`,
607
+ operators: [{key: 'is', label: 'is', value: {type: 'string'} as const}],
608
+ })),
609
+ };
610
+
611
+ it('caps results for a typed query', () => {
612
+ const source = createSource(manyFields, 10);
613
+ expect(source.search('zebra')).toHaveLength(10);
614
+ });
615
+
616
+ it('never caps the field list for an empty query', () => {
617
+ const source = createSource(manyFields, 10);
618
+ expect(syncBootstrap(source)).toHaveLength(25);
619
+ expect(source.search('')).toHaveLength(25);
620
+ });
621
+ });
@@ -14,13 +14,20 @@
14
14
 
15
15
  import {useMemo} from 'react';
16
16
  import type {SearchSource} from '../Typeahead/types';
17
+ import {groupItems} from '../utils';
17
18
  import {useTranslator} from '../i18n';
18
19
  import {resolveOperatorLabel} from './resolveOperatorLabel';
19
20
  import type {InternalConfig} from './useInternalConfig';
20
21
  import type {PowerSearchItem, PowerSearchOperator, FilterValue} from './types';
21
22
 
23
+ /**
24
+ * @param maxTypedResults Cap applied to ranked results for a non-empty query.
25
+ * The source never truncates empty-query browsing; PowerSearch's view applies
26
+ * a separate 1,000-row safety ceiling.
27
+ */
22
28
  export function usePowerSearchSource(
23
29
  config: InternalConfig,
30
+ maxTypedResults: number,
24
31
  ): SearchSource<PowerSearchItem> {
25
32
  const t = useTranslator();
26
33
  return useMemo(() => {
@@ -198,14 +205,14 @@ export function usePowerSearchSource(
198
205
  }
199
206
  }
200
207
 
201
- return results;
208
+ return results.slice(0, maxTypedResults);
202
209
  },
203
210
 
204
211
  bootstrap(): PowerSearchItem[] {
205
212
  return allItems;
206
213
  },
207
214
  };
208
- }, [config, t]);
215
+ }, [config, t, maxTypedResults]);
209
216
  }
210
217
 
211
218
  interface ValueMatch {
@@ -282,9 +289,12 @@ function buildFieldItems(config: InternalConfig): PowerSearchItem[] {
282
289
  auxiliaryData: {
283
290
  fieldKey: field.key,
284
291
  operatorKey: defaultOp?.key,
292
+ group: field.group,
285
293
  },
286
294
  });
287
295
  }
288
296
 
289
- return items;
297
+ return groupItems(items, {ungroupedFirst: true}).flatMap(
298
+ group => group.items,
299
+ );
290
300
  }