@parallelworks/ui 0.76.0 → 0.78.0

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 (270) hide show
  1. package/README.md +30 -5
  2. package/dist/access/AccessDrawer.d.ts +28 -7
  3. package/dist/access/AccessDrawer.js +216 -35
  4. package/dist/access/AccessList.d.ts +19 -1
  5. package/dist/access/AccessList.js +220 -9
  6. package/dist/access/GrantView.d.ts +3 -1
  7. package/dist/access/GrantView.js +17 -4
  8. package/dist/access/PrincipalPicker.js +5 -5
  9. package/dist/access/focus.js +1 -1
  10. package/dist/access/index.d.ts +2 -2
  11. package/dist/access/index.js +2 -2
  12. package/dist/access/strings.d.ts +18 -0
  13. package/dist/access/strings.js +20 -2
  14. package/dist/access/types.d.ts +26 -0
  15. package/dist/ai/adapter/types.d.ts +1 -0
  16. package/dist/ai/components/AllocationSelector.js +1 -1
  17. package/dist/ai/components/AttachmentManager.js +5 -5
  18. package/dist/ai/components/AttachmentUpload.js +2 -2
  19. package/dist/ai/components/BranchNavigator.js +1 -1
  20. package/dist/ai/components/ChatActivity.d.ts +2 -0
  21. package/dist/ai/components/ChatActivity.js +31 -0
  22. package/dist/ai/components/ChatEmptyState.js +3 -3
  23. package/dist/ai/components/ChatInput.js +3 -5
  24. package/dist/ai/components/ChatLayout.js +1 -1
  25. package/dist/ai/components/ChatMessage.js +1 -1
  26. package/dist/ai/components/ChatMessageList.js +2 -2
  27. package/dist/ai/components/ChatSidebar.js +3 -3
  28. package/dist/ai/components/ChatThread.js +4 -4
  29. package/dist/ai/components/ComposerAddMenu.js +9 -20
  30. package/dist/ai/components/ModelSelector.js +3 -3
  31. package/dist/ai/components/PastedText.js +5 -5
  32. package/dist/ai/components/SessionView.js +5 -2
  33. package/dist/ai/components/ShareDialog.js +3 -3
  34. package/dist/ai/components/SlashMenu.d.ts +31 -4
  35. package/dist/ai/components/SlashMenu.js +36 -63
  36. package/dist/ai/components/agent/ActivityLine.js +1 -1
  37. package/dist/ai/components/agent/AgentMessageParts.d.ts +1 -1
  38. package/dist/ai/components/agent/AgentMessageParts.js +44 -18
  39. package/dist/ai/components/conversationActions.js +3 -3
  40. package/dist/ai/core/ChatProvider.js +11 -2
  41. package/dist/ai/core/config.d.ts +10 -1
  42. package/dist/ai/core/config.js +1 -1
  43. package/dist/ai/index.d.ts +1 -1
  44. package/dist/ai/strings.d.ts +2 -0
  45. package/dist/ai/strings.js +2 -1
  46. package/dist/ai/types.d.ts +3 -0
  47. package/dist/ai/ui/ConversationSidebar.js +3 -3
  48. package/dist/ai/ui/sidebar.js +3 -3
  49. package/dist/assets/yaml.worker-DOBV2lND.js +884 -0
  50. package/dist/components/ActionMenu.d.ts +38 -9
  51. package/dist/components/ActionMenu.js +48 -22
  52. package/dist/components/Avatar.d.ts +66 -6
  53. package/dist/components/Avatar.js +130 -18
  54. package/dist/components/Breadcrumbs.d.ts +4 -0
  55. package/dist/components/Breadcrumbs.js +26 -10
  56. package/dist/components/Button.d.ts +3 -2
  57. package/dist/components/Button.js +11 -1
  58. package/dist/components/Callout.d.ts +3 -2
  59. package/dist/components/Callout.js +3 -2
  60. package/dist/components/Card.d.ts +33 -9
  61. package/dist/components/Card.js +24 -8
  62. package/dist/components/Checkbox.d.ts +3 -1
  63. package/dist/components/Checkbox.js +4 -2
  64. package/dist/components/ColorInput.js +1 -1
  65. package/dist/components/Combobox.d.ts +23 -0
  66. package/dist/components/Combobox.js +252 -86
  67. package/dist/components/ConfirmModal.d.ts +26 -2
  68. package/dist/components/ConfirmModal.js +81 -15
  69. package/dist/components/ContextMenu.d.ts +29 -2
  70. package/dist/components/ContextMenu.js +60 -8
  71. package/dist/components/CopyButton.d.ts +21 -8
  72. package/dist/components/CopyButton.js +29 -9
  73. package/dist/components/CreateModal.d.ts +16 -4
  74. package/dist/components/CreateModal.js +27 -16
  75. package/dist/components/DatePicker.d.ts +31 -1
  76. package/dist/components/DatePicker.js +178 -47
  77. package/dist/components/DescriptionList.d.ts +13 -3
  78. package/dist/components/DescriptionList.js +43 -11
  79. package/dist/components/Disclosure.d.ts +10 -2
  80. package/dist/components/Disclosure.js +18 -7
  81. package/dist/components/Drawer.js +5 -5
  82. package/dist/components/EmptyState.d.ts +12 -4
  83. package/dist/components/EmptyState.js +18 -10
  84. package/dist/components/ErrorPage.d.ts +40 -0
  85. package/dist/components/ErrorPage.js +101 -0
  86. package/dist/components/ExternalLink.d.ts +4 -1
  87. package/dist/components/ExternalLink.js +4 -5
  88. package/dist/components/Field.d.ts +21 -6
  89. package/dist/components/Field.js +32 -16
  90. package/dist/components/FileButton.d.ts +19 -0
  91. package/dist/components/FileButton.js +32 -0
  92. package/dist/components/HoverCard.d.ts +26 -6
  93. package/dist/components/HoverCard.js +11 -5
  94. package/dist/components/IconButton.js +4 -2
  95. package/dist/components/InfoTip.js +3 -3
  96. package/dist/components/Input.d.ts +33 -3
  97. package/dist/components/Input.js +149 -14
  98. package/dist/components/Kbd.d.ts +40 -0
  99. package/dist/components/Kbd.js +168 -0
  100. package/dist/components/Listbox.d.ts +103 -0
  101. package/dist/components/Listbox.js +190 -0
  102. package/dist/components/Loader.d.ts +8 -2
  103. package/dist/components/Loader.js +16 -1
  104. package/dist/components/Markdown.js +1 -1
  105. package/dist/components/MarkdownImpl.js +1 -1
  106. package/dist/components/Menu.d.ts +20 -2
  107. package/dist/components/Menu.js +48 -19
  108. package/dist/components/MenuEntries.d.ts +38 -2
  109. package/dist/components/MenuEntries.js +266 -39
  110. package/dist/components/Meter.d.ts +50 -11
  111. package/dist/components/Meter.js +71 -21
  112. package/dist/components/Modal.d.ts +9 -3
  113. package/dist/components/Modal.js +68 -29
  114. package/dist/components/OneTimeCodeInput.js +1 -1
  115. package/dist/components/PageHeader.js +111 -7
  116. package/dist/components/PageHeaderAction.d.ts +8 -3
  117. package/dist/components/PageHeaderAction.js +122 -34
  118. package/dist/components/Pagination.d.ts +13 -1
  119. package/dist/components/Pagination.js +90 -19
  120. package/dist/components/Popover.d.ts +13 -2
  121. package/dist/components/Popover.js +20 -21
  122. package/dist/components/Provider.d.ts +140 -3
  123. package/dist/components/Provider.js +142 -12
  124. package/dist/components/RefreshButton.d.ts +13 -6
  125. package/dist/components/RefreshButton.js +17 -9
  126. package/dist/components/RunStatusIcon.d.ts +16 -7
  127. package/dist/components/RunStatusIcon.js +21 -8
  128. package/dist/components/Section.d.ts +11 -4
  129. package/dist/components/Section.js +33 -22
  130. package/dist/components/SegmentedControl.d.ts +16 -3
  131. package/dist/components/SegmentedControl.js +7 -3
  132. package/dist/components/Select.d.ts +19 -3
  133. package/dist/components/Select.js +114 -68
  134. package/dist/components/SelectionCopy.d.ts +10 -0
  135. package/dist/components/SelectionCopy.js +105 -0
  136. package/dist/components/SettingModeOption.js +1 -1
  137. package/dist/components/SettingsCard.js +1 -1
  138. package/dist/components/Skeleton.js +1 -1
  139. package/dist/components/StatusBadge.d.ts +55 -10
  140. package/dist/components/StatusBadge.js +91 -15
  141. package/dist/components/StickyBar.js +1 -1
  142. package/dist/components/Table.d.ts +22 -4
  143. package/dist/components/Table.js +46 -24
  144. package/dist/components/Tabs.d.ts +9 -4
  145. package/dist/components/Tabs.js +9 -4
  146. package/dist/components/Tag.d.ts +49 -0
  147. package/dist/components/Tag.js +199 -0
  148. package/dist/components/ThemeEditor.js +1 -1
  149. package/dist/components/Toast.js +1 -1
  150. package/dist/components/ToggleGroup.d.ts +4 -1
  151. package/dist/components/ToggleGroup.js +30 -13
  152. package/dist/components/Tooltip.d.ts +9 -3
  153. package/dist/components/Tooltip.js +55 -39
  154. package/dist/components/buttonClasses.d.ts +5 -2
  155. package/dist/components/buttonClasses.js +11 -10
  156. package/dist/components/chart.d.ts +69 -0
  157. package/dist/components/chart.js +145 -0
  158. package/dist/components/comboboxItems.d.ts +7 -1
  159. package/dist/components/comboboxItems.js +6 -2
  160. package/dist/components/dismiss.d.ts +5 -1
  161. package/dist/components/dismiss.js +6 -2
  162. package/dist/components/floating.d.ts +4 -4
  163. package/dist/components/floating.js +5 -5
  164. package/dist/components/headerActionsFit.d.ts +37 -0
  165. package/dist/components/headerActionsFit.js +81 -0
  166. package/dist/components/pageHeaderStore.d.ts +3 -0
  167. package/dist/components/pageHeaderStore.js +3 -0
  168. package/dist/components/pathBreaks.js +2 -2
  169. package/dist/components/popupContainer.d.ts +17 -0
  170. package/dist/components/popupContainer.js +69 -0
  171. package/dist/components/relativeTime.d.ts +21 -10
  172. package/dist/components/relativeTime.js +50 -22
  173. package/dist/components/segmented.d.ts +18 -4
  174. package/dist/components/segmented.js +48 -6
  175. package/dist/components/typedDate.d.ts +5 -0
  176. package/dist/components/typedDate.js +50 -0
  177. package/dist/components/useClosingValue.d.ts +4 -0
  178. package/dist/components/useClosingValue.js +12 -0
  179. package/dist/components/useCopy.d.ts +6 -0
  180. package/dist/components/useCopy.js +3 -3
  181. package/dist/components/useNarrow.d.ts +2 -0
  182. package/dist/components/useNarrow.js +16 -0
  183. package/dist/editor/Editor.js +1 -1
  184. package/dist/editor/FormCodePanel.js +1 -1
  185. package/dist/editor/Monaco.js +1 -1
  186. package/dist/editor/workers.js +1 -1
  187. package/dist/file-explorer/FileExplorer.js +16 -15
  188. package/dist/file-explorer/FileExplorerContext.js +2 -2
  189. package/dist/file-explorer/FilePreview/Viewer.js +3 -3
  190. package/dist/file-explorer/FilePreview/index.js +2 -2
  191. package/dist/file-explorer/FileRowsWindow.js +3 -3
  192. package/dist/file-explorer/FileTable.js +1 -1
  193. package/dist/file-explorer/LoadMoreRow.js +1 -1
  194. package/dist/file-explorer/TreeView.js +5 -5
  195. package/dist/file-explorer/helpers.js +2 -2
  196. package/dist/file-explorer/toasts.js +2 -2
  197. package/dist/form/Fields/CheckboxGroupField.js +1 -1
  198. package/dist/form/Fields/DropdownField.js +1 -1
  199. package/dist/form/Fields/DurationField.js +2 -2
  200. package/dist/form/Fields/MultiDropdownField.js +1 -1
  201. package/dist/form/Fields/NumberField.js +1 -1
  202. package/dist/form/Fields/ObjectField.js +1 -1
  203. package/dist/form/Fields/RangeField.js +1 -1
  204. package/dist/form/Fields/StringField.js +1 -1
  205. package/dist/form/Form.js +3 -3
  206. package/dist/form/FormLayout.js +1 -1
  207. package/dist/form/Wizard/WizardContainer.js +1 -1
  208. package/dist/form/Wizard/WizardNavigation.js +1 -1
  209. package/dist/form/Wizard/WizardStepContent.js +1 -1
  210. package/dist/form/fieldRegistry.js +1 -1
  211. package/dist/form/formEditing.js +1 -1
  212. package/dist/format.d.ts +17 -7
  213. package/dist/format.js +39 -16
  214. package/dist/graph/AnnotationBanner.js +2 -2
  215. package/dist/graph/Connectors.js +5 -5
  216. package/dist/graph/DependencyGraph.js +10 -9
  217. package/dist/graph/GraphEditor.js +4 -4
  218. package/dist/graph/GraphEditorDialogs.js +13 -12
  219. package/dist/graph/GraphNode.js +1 -1
  220. package/dist/graph/InputDialog.js +5 -5
  221. package/dist/graph/InputsEditor.js +7 -7
  222. package/dist/graph/MatrixGroup.js +2 -2
  223. package/dist/graph/ProblemsButton.js +3 -3
  224. package/dist/graph/Reveal.js +1 -1
  225. package/dist/graph/RunWarningsList.js +1 -1
  226. package/dist/graph/ShortcutsButton.js +25 -8
  227. package/dist/graph/StepSummaries.js +1 -1
  228. package/dist/graph/TreeView.js +2 -2
  229. package/dist/graph/WorkflowSettingsDialog.js +3 -3
  230. package/dist/graph/editorFields.js +3 -3
  231. package/dist/graph/editorPrimitives.js +1 -1
  232. package/dist/graph/editorRows.js +5 -5
  233. package/dist/graph/fieldProblems.js +2 -2
  234. package/dist/graph/inputRefs.js +7 -6
  235. package/dist/graph/stepWith.js +2 -2
  236. package/dist/index.d.ts +30 -21
  237. package/dist/index.js +20 -12
  238. package/dist/list/ActionToolbar.d.ts +4 -0
  239. package/dist/list/ActionToolbar.js +35 -12
  240. package/dist/list/ListFilterBar.d.ts +42 -0
  241. package/dist/list/ListFilterBar.js +789 -0
  242. package/dist/list/ListPage.d.ts +42 -4
  243. package/dist/list/ListPage.js +56 -22
  244. package/dist/list/ListTable.d.ts +27 -3
  245. package/dist/list/ListTable.js +48 -23
  246. package/dist/list/ListToolbar.d.ts +31 -0
  247. package/dist/list/ListToolbar.js +43 -0
  248. package/dist/list/ListViewControls.d.ts +8 -4
  249. package/dist/list/ListViewControls.js +22 -14
  250. package/dist/list/UserHoverCard.d.ts +8 -2
  251. package/dist/list/UserHoverCard.js +26 -13
  252. package/dist/list/filterModel.d.ts +122 -0
  253. package/dist/list/filterModel.js +308 -0
  254. package/dist/list/index.d.ts +6 -2
  255. package/dist/list/index.js +6 -2
  256. package/dist/list/listSearch.d.ts +1 -1
  257. package/dist/list/listSearch.js +8 -4
  258. package/dist/list/listView.d.ts +24 -2
  259. package/dist/list/listView.js +47 -45
  260. package/dist/list/rowMenu.d.ts +10 -5
  261. package/dist/list/rowMenu.js +17 -7
  262. package/dist/list/useListFilters.d.ts +68 -0
  263. package/dist/list/useListFilters.js +252 -0
  264. package/dist/logviewer/LogViewer.js +4 -4
  265. package/dist/styles/theme.css +94 -0
  266. package/dist/styles.css +1 -1
  267. package/package.json +11 -11
  268. package/dist/assets/yaml.worker-k9AdOqzf.js +0 -1441
  269. package/dist/components/fullscreen.d.ts +0 -4
  270. package/dist/components/fullscreen.js +0 -18
@@ -12,15 +12,53 @@ export interface ListPageProps {
12
12
  * edges, for a host whose page container is padded. A list runs edge to
13
13
  * edge so its rows' hover and dividers span the page. */
14
14
  bleed?: boolean | undefined;
15
- /** The list's search, filters and view controls, above the rows. The page's
16
- * trail and actions go in its `PageHeader`. */
15
+ /** The list's search, filters and view controls, above the rows, such as a
16
+ * `ListToolbar`. The page's trail and actions, "+ Add" among them, go in
17
+ * its `PageHeader`. With `total`, it hides while the list is empty. */
17
18
  toolbar?: ReactNode;
19
+ /** Under the toolbar: the chips of the list's active filters. By default the view's own
20
+ * `ListFilterBar`, shown while a filter is on; pass one to add a trailing slot, such as Save
21
+ * view, or `null` to leave it out. */
22
+ filterBar?: ReactNode;
18
23
  /** Omit on pages without a list view — rows show all actions by default. */
19
24
  view?: ListViewChrome | undefined;
25
+ /** Still loading: a sketch of rows in place of the list. */
26
+ loading?: boolean | undefined;
27
+ /** Why the list couldn't load. Shown only while there is nothing to show
28
+ * from before, so a failed refresh keeps the rows on screen. */
29
+ error?: unknown;
30
+ /** What failed to load, as the error names it: "Couldn't load clusters". */
31
+ errorNoun?: string | undefined;
32
+ /** How many rows there are before any search or filter. Given, the page
33
+ * picks its body: the rows, `empty` while there are none, and `noMatches`
34
+ * while a search or filter leaves none. */
35
+ total?: number | undefined;
36
+ /** How many rows the search and filters leave; `total` by default. */
37
+ matches?: number | undefined;
38
+ /** What shows while there is nothing in the list yet. */
39
+ empty?: ListPageEmpty | undefined;
40
+ /** What shows while a search or filter leaves nothing, such as "No clusters
41
+ * match". */
42
+ noMatches?: ReactNode;
43
+ /** Keeps the toolbar while the list is empty, for one whose controls still
44
+ * matter then, such as a filter set by default that hides everything. */
45
+ toolbarWhenEmpty?: boolean | undefined;
20
46
  children: ReactNode;
21
47
  }
22
- /** A list filling the page: its toolbar stays put while only the rows scroll. */
23
- export declare function ListPage({ bleed, toolbar, view, children }: ListPageProps): import("react").JSX.Element;
48
+ /** A list's empty state: what is missing, and what to do about it. */
49
+ export interface ListPageEmpty {
50
+ /** A glyph for what the list holds, drawn faded above the title. */
51
+ icon?: ReactNode;
52
+ title: ReactNode;
53
+ description?: ReactNode;
54
+ /** Such as a link to the docs; the page's "+ Add" stays in its header. */
55
+ action?: ReactNode;
56
+ }
57
+ /** A list filling the page: its toolbar stays put while only the rows scroll.
58
+ * Given `total`, it also shows the list's states in one shared look: a
59
+ * sketch while loading, the error when loading failed, the empty state with
60
+ * the toolbar hidden, the no-matches state, or the rows. */
61
+ export declare function ListPage({ bleed, toolbar, filterBar, view, loading, error, errorNoun, total, matches, empty, noMatches, toolbarWhenEmpty, children, }: ListPageProps): import("react").JSX.Element;
24
62
  export declare function ListRow({ href, onActivate, items, goTo, openMenu, pinnedActions, selected, selectionActive, onRowSelect, leading, className, children, }: {
25
63
  /** Where the row goes. Its `NameCell` with the same href becomes a link
26
64
  * covering the row; a click the link doesn't catch still goes there. */
@@ -1,13 +1,15 @@
1
1
  import { cx } from "../cx.js";
2
+ import { EmptyState } from "../components/EmptyState.js";
2
3
  import { Tooltip } from "../components/Tooltip.js";
3
4
  import { useNavigation } from "../components/Provider.js";
4
5
  import { AppLink, isPlainClick } from "../components/AppLink.js";
5
- import { isMenuDivider, isMenuSubmenu, useRunAction, warnIfInert } from "../components/MenuEntries.js";
6
+ import { isMenuDivider, isMenuGroup, isMenuSubmenu, useRunAction, warnIfInert } from "../components/MenuEntries.js";
6
7
  import { Table } from "../components/Table.js";
7
- import { ListActionsHeader, StretchRowLinkContext } from "./ListTable.js";
8
+ import { ListFilterBar } from "./ListFilterBar.js";
9
+ import { ListActionsHeader, ListError, ListSkeleton, StretchRowLinkContext } from "./ListTable.js";
8
10
  import { MoreButton, rowContextMenuProps, useRowMenuActive } from "./rowMenu.js";
9
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
11
  import { Children, cloneElement, createContext, isValidElement, useContext, useMemo } from "react";
12
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
13
  //#region src/list/ListPage.tsx
12
14
  /** Defaults mean rows outside a ListView fully show actions (no view = show everything). */
13
15
  var RowActionsContext = createContext({
@@ -36,20 +38,51 @@ function ListRowActionsProvider({ view, children }) {
36
38
  children
37
39
  });
38
40
  }
39
- /** A list filling the page: its toolbar stays put while only the rows scroll. */
40
- function ListPage({ bleed = false, toolbar, view, children }) {
41
+ var STAYS_BESIDE_STACK = "@max-[36rem]:align-top @max-[36rem]:pt-2.5";
42
+ /** A list filling the page: its toolbar stays put while only the rows scroll.
43
+ * Given `total`, it also shows the list's states in one shared look: a
44
+ * sketch while loading, the error when loading failed, the empty state with
45
+ * the toolbar hidden, the no-matches state, or the rows. */
46
+ function ListPage({ bleed = false, toolbar, filterBar, view, loading = false, error, errorNoun, total, matches, empty, noMatches, toolbarWhenEmpty = false, children }) {
47
+ const failed = !loading && error !== void 0 && error !== null && !total;
48
+ const known = total !== void 0 && !loading && !failed;
49
+ const isEmpty = known && total === 0;
50
+ const noneMatch = known && !isEmpty && (matches ?? total) === 0;
51
+ const controls = total === void 0 || toolbarWhenEmpty || known && total > 0;
52
+ const bar = filterBar === void 0 ? view?.filterState && view.filterState.fields.length > 0 ? /* @__PURE__ */ jsx(ListFilterBar, { filters: view.filterState }) : null : filterBar;
53
+ let body = children;
54
+ if (loading) body = /* @__PURE__ */ jsx(ListSkeleton, {});
55
+ else if (failed) body = /* @__PURE__ */ jsx(ListError, {
56
+ error,
57
+ noun: errorNoun
58
+ });
59
+ else if (isEmpty && empty) body = /* @__PURE__ */ jsx(EmptyState, {
60
+ variant: "plain",
61
+ ...empty
62
+ });
63
+ else if (noneMatch && noMatches) body = /* @__PURE__ */ jsx(EmptyState, {
64
+ variant: "plain",
65
+ title: noMatches
66
+ });
41
67
  return /* @__PURE__ */ jsxs("div", {
42
68
  className: cx("flex h-full min-h-0 flex-col", bleed && "-m-4"),
43
- children: [toolbar && /* @__PURE__ */ jsx("div", {
44
- className: "shrink-0 px-4",
45
- children: toolbar
46
- }), /* @__PURE__ */ jsx("div", {
47
- className: "relative @container min-h-0 flex-1 overflow-auto",
48
- children: /* @__PURE__ */ jsx(ListRowActionsProvider, {
49
- view,
50
- children
69
+ children: [
70
+ !!toolbar && controls && /* @__PURE__ */ jsx("div", {
71
+ className: "shrink-0 px-4",
72
+ children: toolbar
73
+ }),
74
+ !!bar && controls && /* @__PURE__ */ jsx("div", {
75
+ className: "shrink-0 px-4",
76
+ children: bar
77
+ }),
78
+ /* @__PURE__ */ jsx("div", {
79
+ className: "relative @container min-h-0 flex-1 overflow-auto",
80
+ children: /* @__PURE__ */ jsx(ListRowActionsProvider, {
81
+ view,
82
+ children: body
83
+ })
51
84
  })
52
- })]
85
+ ]
53
86
  });
54
87
  }
55
88
  function ListRow({ href, onActivate, items, goTo, openMenu, pinnedActions, selected, selectionActive, onRowSelect, leading, className, children }) {
@@ -62,19 +95,20 @@ function ListRow({ href, onActivate, items, goTo, openMenu, pinnedActions, selec
62
95
  return Children.toArray(content).length > 0 ? [content] : [];
63
96
  });
64
97
  const styledCells = cells.map((child, i) => {
65
- const cls = columnClasses[i];
98
+ const cls = cx(columnClasses[i], i > 0 && stacked.length > 0 && !columnStacks[i] && STAYS_BESIDE_STACK);
66
99
  if (!isValidElement(child) || !cls && !(i === 0 && stacked.length > 0)) return child;
67
100
  const el = child;
68
101
  if (i === 0 && stacked.length > 0) return cloneElement(el, {
69
102
  className: cx(el.props.className, cls),
70
- children: /* @__PURE__ */ jsxs(Fragment, { children: [el.props.children, stacked.map((content, j) => /* @__PURE__ */ jsx("div", {
71
- className: "mt-1 @[36rem]:hidden",
103
+ children: /* @__PURE__ */ jsxs(Fragment$1, { children: [el.props.children, stacked.map((content, j) => /* @__PURE__ */ jsx("div", {
104
+ className: "mt-1 flex min-w-0 items-center @[36rem]:hidden",
72
105
  "data-stacked": true,
73
106
  children: content
74
107
  }, j))] })
75
108
  });
76
109
  return cloneElement(el, { className: cx(el.props.className, cls) });
77
110
  });
111
+ const floating = !alwaysShowActions && !(pinnedActions && pinnedActions.length > 0);
78
112
  const stretch = !!href && !selectionActive;
79
113
  const handleRowClick = (e) => {
80
114
  if (e.target.closest("a,button,input,label")) return;
@@ -87,7 +121,7 @@ function ListRow({ href, onActivate, items, goTo, openMenu, pinnedActions, selec
87
121
  } else onActivate?.();
88
122
  };
89
123
  const pinnedLabels = new Set((pinnedActions ?? []).map((a) => a.label));
90
- const hasOverflowItems = items.some((item) => !isMenuDivider(item) && (isMenuSubmenu(item) || !pinnedLabels.has(item.label)));
124
+ const hasOverflowItems = items.some((item) => !isMenuDivider(item) && (isMenuSubmenu(item) || isMenuGroup(item) || !pinnedLabels.has(item.label)));
91
125
  return /* @__PURE__ */ jsxs("tr", {
92
126
  className: cx("group", selected ? "bg-(--theme-accent-subtle)/60" : menuActive ? "theme-hover" : "hover:theme-hover", (href || onActivate || selectionActive) && "cursor-pointer", stretch && "relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:z-[1]", className),
93
127
  onClick: handleRowClick,
@@ -99,9 +133,9 @@ function ListRow({ href, onActivate, items, goTo, openMenu, pinnedActions, selec
99
133
  children: styledCells
100
134
  }),
101
135
  showActions && /* @__PURE__ */ jsx(Table.Item, {
102
- className: "relative py-2.5",
136
+ className: cx("relative py-2.5", floating && "pointer-fine:w-0! pointer-fine:min-w-0! pointer-fine:pl-0! pointer-fine:pr-1!"),
103
137
  children: /* @__PURE__ */ jsxs("div", {
104
- className: "absolute inset-y-0 right-0 flex items-center gap-0.5 pr-4",
138
+ className: cx("absolute inset-y-0 right-0 flex items-center gap-0.5 pr-4", floating && !menuActive && "pointer-fine:opacity-0 pointer-fine:group-hover:opacity-100 pointer-fine:focus-within:opacity-100", floating && "pointer-fine:bg-linear-to-l pointer-fine:from-(--theme-hover) pointer-fine:from-70% pointer-fine:to-transparent pointer-fine:pl-6"),
105
139
  children: [pinnedActions && pinnedActions.length > 0 && /* @__PURE__ */ jsx("span", {
106
140
  className: "hidden items-center gap-0.5 @[44rem]:flex",
107
141
  children: pinnedActions.map((action) => /* @__PURE__ */ jsx(PinnedActionButton, {
@@ -110,7 +144,7 @@ function ListRow({ href, onActivate, items, goTo, openMenu, pinnedActions, selec
110
144
  }, action.key))
111
145
  }), /* @__PURE__ */ jsx(MoreButton, {
112
146
  open: menuActive,
113
- visible: menuActive || alwaysShowActions,
147
+ visible: menuActive || alwaysShowActions || floating,
114
148
  onOpen: (button) => openRowMenu(button, items),
115
149
  className: hasOverflowItems ? void 0 : "@[44rem]:hidden"
116
150
  })]
@@ -159,7 +193,7 @@ function columnSort(view, orderBy) {
159
193
  * cells still size the columns, but nobody sees or hears them, as with any
160
194
  * other display option that is off. */
161
195
  function ListColumns({ view }) {
162
- return /* @__PURE__ */ jsxs(Fragment, { children: [view.visibleColumns.map((col, i) => {
196
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [view.visibleColumns.map((col, i) => {
163
197
  const orderBy = view.orderBys.some((o) => o.value === col.orderBy) ? col.orderBy : void 0;
164
198
  return /* @__PURE__ */ jsx(Table.Header, {
165
199
  caps: false,
@@ -33,8 +33,11 @@ export declare const STRETCHED_LINK = "after:absolute after:inset-0 after:conten
33
33
  * raised above the link so they keep their own clicks. A checkbox is a
34
34
  * `role="checkbox"` span, not an input, so the role names it. */
35
35
  export declare const STRETCHED_LINK_ROW = "relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:z-[1]";
36
- export declare function NameCell({ icon, name, subtitle, href, badge, title, children, }: {
36
+ export declare function NameCell({ icon, iconTile, name, subtitle, href, badge, title, children, }: {
37
37
  icon: ReactNode;
38
+ /** Sets the icon in a small bordered tile, so rows whose icons differ in
39
+ * weight, such as kinds of token or runner, still line up. */
40
+ iconTile?: boolean | undefined;
38
41
  name: string;
39
42
  subtitle?: string | undefined;
40
43
  /** The name's link. Inside a `ListRow` with an `href`, the whole row is
@@ -46,15 +49,29 @@ export declare function NameCell({ icon, name, subtitle, href, badge, title, chi
46
49
  * narrow container (see `ColumnDef.stack`). */
47
50
  children?: ReactNode;
48
51
  }): import("react").JSX.Element;
52
+ /** A row's column text: muted 13px, or monospace for an ID, a path or a
53
+ * hash. The style sits on the text rather than the cell, so it carries over
54
+ * when a narrow list stacks the column under the name. */
55
+ export declare function ListCellText({ mono, className, children, }: {
56
+ mono?: boolean | undefined;
57
+ className?: string | undefined;
58
+ children: ReactNode;
59
+ }): import("react").JSX.Element;
49
60
  export declare function GroupRow({ label, count, colSpan, }: {
50
61
  label: string;
51
62
  count: number;
52
63
  colSpan: number;
53
64
  }): import("react").JSX.Element;
54
- export declare function ListError({ error, noun, }: {
55
- error: unknown;
65
+ /** Says a list couldn't load. It never shows the error's own text, which is
66
+ * the server's words, in its language and not written for the reader. */
67
+ export declare function ListError({ noun, message, }: {
68
+ /** What failed. It is not shown: pass `message` to say what went wrong. */
69
+ error?: unknown;
56
70
  /** What failed to load, as the heading names it: "Couldn't load clusters". */
57
71
  noun?: string | undefined;
72
+ /** What went wrong, in the reader's words, such as the host's own text for the error.
73
+ * Defaults to a generic line from the strings. */
74
+ message?: ReactNode;
58
75
  }): import("react").JSX.Element;
59
76
  export declare function ListSkeleton({ rows }: {
60
77
  rows?: number;
@@ -63,6 +80,12 @@ export declare function ListSkeleton({ rows }: {
63
80
  export declare const NAME_MIN_WIDTH_PX = 200;
64
81
  /** Width the trailing actions column reserves for `count` always-visible
65
82
  * buttons plus the hover `⋯` trigger. */
83
+ /** The lane of a row whose only action is a `⋯` shown on hover. With a mouse
84
+ * it claims no width: the `⋯` floats over the row's end while hovered, so
85
+ * the last column ends at the list's edge as the first starts at it, and the
86
+ * lane's 4px makes up that column's padding to the edge's 16px. On a touch
87
+ * screen, where the `⋯` always shows, the lane keeps its width. */
88
+ export declare const FLOATING_ACTIONS_LANE = "pointer-fine:w-0! pointer-fine:min-w-0! pointer-fine:pl-0! pointer-fine:pr-1!";
66
89
  export declare function actionsColumnWidth(count: number): number;
67
90
  /** Shared leading selection checkbox for multi-select rows: stops the row-click
68
91
  * and suppresses shift-click text selection. Wrap in <Table.Item> for `leading`. */
@@ -90,6 +113,7 @@ export declare function ListActionsHeader({ view, actionCount, className, }: {
90
113
  view?: {
91
114
  showActions: boolean;
92
115
  actionsWidth: number;
116
+ alwaysShowActions?: boolean;
93
117
  };
94
118
  actionCount?: number;
95
119
  className?: string;
@@ -1,13 +1,13 @@
1
1
  import { cx } from "../cx.js";
2
2
  import { ErrorIcon } from "../icons.js";
3
- import { positionKeys } from "../components/keys.js";
4
3
  import { useStrings } from "../components/Provider.js";
5
4
  import { AppLink } from "../components/AppLink.js";
5
+ import { positionKeys } from "../components/keys.js";
6
6
  import { LoadingRegion, Skeleton } from "../components/Skeleton.js";
7
7
  import { Checkbox } from "../components/Checkbox.js";
8
8
  import { Table } from "../components/Table.js";
9
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
9
  import { createContext, useContext } from "react";
10
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/list/ListTable.tsx
12
12
  var NAME_TEXT = "font-medium text-[13px] leading-tight text-(--theme-app) truncate";
13
13
  var SUBTITLE_TEXT = "text-xs leading-tight text-(--theme-muted-text-color) truncate";
@@ -41,9 +41,14 @@ var STRETCHED_LINK = "after:absolute after:inset-0 after:content-[''] focus-visi
41
41
  * raised above the link so they keep their own clicks. A checkbox is a
42
42
  * `role="checkbox"` span, not an input, so the role names it. */
43
43
  var STRETCHED_LINK_ROW = "relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:relative [&_:is(a,button,input,label,[role=checkbox]):not([data-row-link])]:z-[1]";
44
- function NameCell({ icon, name, subtitle, href, badge, title, children }) {
44
+ function NameCell({ icon, iconTile = false, name, subtitle, href, badge, title, children }) {
45
45
  const stretch = useContext(StretchRowLinkContext);
46
- const inner = /* @__PURE__ */ jsxs(Fragment, { children: [icon, /* @__PURE__ */ jsxs("div", {
46
+ const hasIcon = icon !== null && icon !== void 0 && icon !== false;
47
+ const columns = hasIcon ? "col-span-2 grid grid-cols-subgrid items-center" : "flex items-center";
48
+ const inner = /* @__PURE__ */ jsxs(Fragment$1, { children: [hasIcon && (iconTile ? /* @__PURE__ */ jsx("span", {
49
+ className: "flex size-7 shrink-0 items-center justify-center rounded-md border border-(--theme-border) text-(--theme-muted-text-color) [&>svg]:size-3.5",
50
+ children: icon
51
+ }) : icon), /* @__PURE__ */ jsxs("div", {
47
52
  className: "min-w-0",
48
53
  children: [/* @__PURE__ */ jsxs("div", {
49
54
  className: "flex min-w-0 items-center gap-1.5",
@@ -57,20 +62,32 @@ function NameCell({ icon, name, subtitle, href, badge, title, children }) {
57
62
  children: subtitle
58
63
  })]
59
64
  })] });
60
- return /* @__PURE__ */ jsxs(Table.Item, {
65
+ return /* @__PURE__ */ jsx(Table.Item, {
61
66
  className: "py-2.5",
62
- children: [href ? /* @__PURE__ */ jsx(AppLink, {
63
- href,
64
- "data-row-link": stretch || void 0,
65
- className: cx("group/namecell flex items-center gap-2.5 min-w-0 cursor-pointer", stretch && "after:absolute after:inset-0 after:content-[''] focus-visible:outline-none focus-visible:after:outline-2 focus-visible:after:-outline-offset-2 focus-visible:after:outline-(--theme-link)"),
66
- children: inner
67
- }) : /* @__PURE__ */ jsx("div", {
68
- className: "flex items-center gap-2.5 min-w-0",
69
- children: inner
70
- }), children && /* @__PURE__ */ jsx("div", {
71
- className: "pl-[1.875rem]",
72
- children
73
- })]
67
+ children: /* @__PURE__ */ jsxs("div", {
68
+ className: cx("grid min-w-0", hasIcon ? "grid-cols-[auto_minmax(0,1fr)] gap-x-2.5" : "grid-cols-[minmax(0,1fr)]"),
69
+ children: [href ? /* @__PURE__ */ jsx(AppLink, {
70
+ href,
71
+ "data-row-link": stretch || void 0,
72
+ className: cx("group/namecell min-w-0 cursor-pointer", columns, stretch && "after:absolute after:inset-0 after:content-[''] focus-visible:outline-none focus-visible:after:outline-2 focus-visible:after:-outline-offset-2 focus-visible:after:outline-(--theme-link)"),
73
+ children: inner
74
+ }) : /* @__PURE__ */ jsx("div", {
75
+ className: cx("min-w-0", columns),
76
+ children: inner
77
+ }), !!children && /* @__PURE__ */ jsx("div", {
78
+ className: hasIcon ? "col-start-2 min-w-0" : "min-w-0",
79
+ children
80
+ })]
81
+ })
82
+ });
83
+ }
84
+ /** A row's column text: muted 13px, or monospace for an ID, a path or a
85
+ * hash. The style sits on the text rather than the cell, so it carries over
86
+ * when a narrow list stacks the column under the name. */
87
+ function ListCellText({ mono = false, className, children }) {
88
+ return /* @__PURE__ */ jsx("span", {
89
+ className: cx("text-(--theme-muted-text-color)", mono ? "font-mono text-xs" : "text-[13px]", className),
90
+ children
74
91
  });
75
92
  }
76
93
  function GroupRow({ label, count, colSpan }) {
@@ -93,9 +110,10 @@ function GroupRow({ label, count, colSpan }) {
93
110
  ]
94
111
  }) });
95
112
  }
96
- function ListError({ error, noun }) {
113
+ /** Says a list couldn't load. It never shows the error's own text, which is
114
+ * the server's words, in its language and not written for the reader. */
115
+ function ListError({ noun, message }) {
97
116
  const { list: t } = useStrings();
98
- const message = error && typeof error === "object" && "message" in error ? String(error.message) : void 0;
99
117
  return /* @__PURE__ */ jsxs("div", {
100
118
  role: "alert",
101
119
  className: "flex flex-col items-center justify-center gap-3 py-20 text-center",
@@ -107,9 +125,9 @@ function ListError({ error, noun }) {
107
125
  children: [/* @__PURE__ */ jsx("p", {
108
126
  className: "text-sm font-medium text-(--theme-app)",
109
127
  children: t.couldNotLoad(noun ?? t.data)
110
- }), message && /* @__PURE__ */ jsx("p", {
128
+ }), /* @__PURE__ */ jsx("p", {
111
129
  className: "max-w-md text-xs text-(--theme-muted-text-color)",
112
- children: message
130
+ children: message ?? t.couldNotLoadHint
113
131
  })]
114
132
  })]
115
133
  });
@@ -151,6 +169,12 @@ var ACTION_GAP_PX = 2;
151
169
  var ACTIONS_CELL_PAD_PX = 28;
152
170
  /** Width the trailing actions column reserves for `count` always-visible
153
171
  * buttons plus the hover `⋯` trigger. */
172
+ /** The lane of a row whose only action is a `⋯` shown on hover. With a mouse
173
+ * it claims no width: the `⋯` floats over the row's end while hovered, so
174
+ * the last column ends at the list's edge as the first starts at it, and the
175
+ * lane's 4px makes up that column's padding to the edge's 16px. On a touch
176
+ * screen, where the `⋯` always shows, the lane keeps its width. */
177
+ var FLOATING_ACTIONS_LANE = "pointer-fine:w-0! pointer-fine:min-w-0! pointer-fine:pl-0! pointer-fine:pr-1!";
154
178
  function actionsColumnWidth(count) {
155
179
  const buttons = count + 1;
156
180
  return buttons * ACTION_BUTTON_PX + (buttons - 1) * ACTION_GAP_PX + ACTIONS_CELL_PAD_PX;
@@ -192,13 +216,14 @@ function ListActionsHeader({ view, actionCount = 0, className }) {
192
216
  const { common } = useStrings();
193
217
  if (view && !view.showActions) return null;
194
218
  const width = view ? view.actionsWidth : actionsColumnWidth(actionCount);
219
+ const floating = !!view && !view.alwaysShowActions && view.actionsWidth === actionsColumnWidth(0);
195
220
  return /* @__PURE__ */ jsx(Table.Header, {
196
221
  caps: false,
197
222
  style: {
198
223
  width,
199
224
  minWidth: width
200
225
  },
201
- className: cx("relative py-2 text-right @max-[44rem]:w-[52px]! @max-[44rem]:min-w-[52px]!", className),
226
+ className: cx("relative py-2 text-right @max-[44rem]:w-[52px]! @max-[44rem]:min-w-[52px]!", floating && "pointer-fine:w-0! pointer-fine:min-w-0! pointer-fine:pl-0! pointer-fine:pr-1!", className),
202
227
  children: /* @__PURE__ */ jsx("span", {
203
228
  className: "sr-only",
204
229
  children: common.actions
@@ -207,4 +232,4 @@ function ListActionsHeader({ view, actionCount = 0, className }) {
207
232
  }
208
233
  ListActionsHeader.isTableHeader = true;
209
234
  //#endregion
210
- export { GroupRow, HEADERS_OFF, ListActionsHeader, ListError, ListSelectAllHeader, ListSkeleton, NAME_MIN_WIDTH_PX, NameCell, RowSelectCheckbox, STRETCHED_LINK, STRETCHED_LINK_ROW, StretchRowLinkContext, actionsColumnWidth, listTableFixedProps, listTableProps };
235
+ export { FLOATING_ACTIONS_LANE, GroupRow, HEADERS_OFF, ListActionsHeader, ListCellText, ListError, ListSelectAllHeader, ListSkeleton, NAME_MIN_WIDTH_PX, NameCell, RowSelectCheckbox, STRETCHED_LINK, STRETCHED_LINK_ROW, StretchRowLinkContext, actionsColumnWidth, listTableFixedProps, listTableProps };
@@ -0,0 +1,31 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type ListSearch } from './listSearch.js';
3
+ import type { ListView } from './listView.js';
4
+ export interface ListToolbarProps<T> {
5
+ /** What the count says: how many there are and, while a search or filter
6
+ * is on, how many match. `filterActive` defaults to whether the search or
7
+ * the view's filters narrow the list. */
8
+ count: {
9
+ total: number;
10
+ matches: number;
11
+ filterActive?: boolean | undefined;
12
+ noun: string;
13
+ nounPlural: string;
14
+ };
15
+ /** Adds its filter menu, when it has facets, and its display options. */
16
+ view?: ListView<T> | undefined;
17
+ search?: ListSearch | undefined;
18
+ /** Names the search for assistive technology; the strings' "Search" by default. */
19
+ searchLabel?: string | undefined;
20
+ /** The search field's placeholder; the label by default. */
21
+ searchPlaceholder?: string | undefined;
22
+ /** After the search, such as a control that acts on the whole list. A list
23
+ * page's "+ Add" belongs in its `PageHeader`. */
24
+ action?: ReactNode;
25
+ /** More controls, before the filter and display menus. */
26
+ children?: ReactNode;
27
+ }
28
+ /** A list page's toolbar in the shared order: the count on the left; then
29
+ * the page's own controls, the filter menu, the display options, the search
30
+ * and an action on the right. Give it to `ListPage` as its `toolbar`. */
31
+ export declare function ListToolbar<T>({ count, view, search, searchLabel, searchPlaceholder, action, children, }: ListToolbarProps<T>): import("react").JSX.Element;
@@ -0,0 +1,43 @@
1
+ import { useStrings } from "../components/Provider.js";
2
+ import { ListDisplayMenu, ListFilterMenu } from "./ListViewControls.js";
3
+ import { ListCount, ListSearchControl } from "./listSearch.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/list/ListToolbar.tsx
6
+ /** A list page's toolbar in the shared order: the count on the left; then
7
+ * the page's own controls, the filter menu, the display options, the search
8
+ * and an action on the right. Give it to `ListPage` as its `toolbar`. */
9
+ function ListToolbar({ count, view, search, searchLabel, searchPlaceholder, action, children }) {
10
+ const { common } = useStrings();
11
+ const filterActive = count.filterActive ?? (search !== void 0 && (search.filter.trim() !== "" || search.terms.length > 0) || (view?.activeFilterCount ?? 0) > 0);
12
+ return /* @__PURE__ */ jsxs("div", {
13
+ className: "flex min-h-10 items-center justify-between gap-3 py-1",
14
+ children: [/* @__PURE__ */ jsx("div", {
15
+ className: "shrink-0 whitespace-nowrap",
16
+ children: /* @__PURE__ */ jsx(ListCount, {
17
+ total: count.total,
18
+ matches: count.matches,
19
+ filterActive,
20
+ noun: count.noun,
21
+ nounPlural: count.nounPlural
22
+ })
23
+ }), /* @__PURE__ */ jsxs("div", {
24
+ className: "flex min-w-0 items-center gap-1",
25
+ children: [
26
+ children,
27
+ view && /* @__PURE__ */ jsx(ListFilterMenu, { view }),
28
+ view && /* @__PURE__ */ jsx(ListDisplayMenu, { view }),
29
+ search && /* @__PURE__ */ jsx(ListSearchControl, {
30
+ search,
31
+ label: searchLabel,
32
+ placeholder: searchPlaceholder ?? searchLabel ?? common.search
33
+ }),
34
+ !!action && /* @__PURE__ */ jsx("span", {
35
+ className: "ml-1 flex",
36
+ children: action
37
+ })
38
+ ]
39
+ })]
40
+ });
41
+ }
42
+ //#endregion
43
+ export { ListToolbar };
@@ -1,11 +1,15 @@
1
1
  import type { ListView } from './listView.js';
2
+ import type { ListFilters } from './useListFilters.js';
2
3
  export declare function ListDisplayMenu<T>({ view, label }: {
3
4
  view: ListView<T>;
4
5
  label?: string;
5
6
  }): import("react").JSX.Element;
6
- /** The Filter button's menu: a submenu for each facet, whose options toggle
7
- * without closing it. F opens it. */
8
- export declare function ListFilterMenu<T>({ view, label }: {
9
- view: ListView<T>;
7
+ /** The toolbar's Filter button, which F presses. Beside a chip row (`ListFilterBar`, which
8
+ * `ListPage` shows), it opens the Add filter menu: picking a field adds its chip and opens its
9
+ * value picker there. Without one, it keeps a submenu of values for each facet. */
10
+ export declare function ListFilterMenu<T>({ view, filters, label, }: {
11
+ view?: ListView<T> | undefined;
12
+ /** For a page whose filters come from `useListFilters` rather than a list view. */
13
+ filters?: ListFilters | undefined;
10
14
  label?: string;
11
15
  }): import("react").JSX.Element | null;
@@ -9,9 +9,10 @@ import { Popover } from "../components/Popover.js";
9
9
  import { InfoTip } from "../components/InfoTip.js";
10
10
  import { Switch } from "../components/Switch.js";
11
11
  import { Select } from "../components/Select.js";
12
+ import { AddFilterMenu } from "./ListFilterBar.js";
12
13
  import { Menu } from "@base-ui/react/menu";
13
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
14
  import { useState } from "react";
15
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
15
16
  import { Toggle } from "@base-ui/react/toggle";
16
17
  //#region src/list/ListViewControls.tsx
17
18
  /** A toggle pill, for the Display panel's column and pinned-action pickers. */
@@ -154,9 +155,7 @@ function OptionSelect({ label, options, value, onSelect }) {
154
155
  "aria-label": label,
155
156
  items: options,
156
157
  value,
157
- onValueChange: (next) => {
158
- if (next !== null) onSelect(next);
159
- },
158
+ onValueChange: onSelect,
160
159
  trigger: /* @__PURE__ */ jsxs("button", {
161
160
  type: "button",
162
161
  className: "flex items-center gap-1.5 rounded-md border border-(--theme-border) px-2 py-1 text-[12px] text-(--theme-app) hover:bg-(--theme-muted-panel-bg)",
@@ -164,19 +163,28 @@ function OptionSelect({ label, options, value, onSelect }) {
164
163
  })
165
164
  });
166
165
  }
167
- /** The Filter button's menu: a submenu for each facet, whose options toggle
168
- * without closing it. F opens it. */
169
- function ListFilterMenu({ view, label }) {
170
- const { common } = useStrings();
171
- if (view.facets.length === 0) return null;
172
- const active = view.activeFilterCount > 0;
173
- return /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsx(Menu.Trigger, { render: /* @__PURE__ */ jsx(IconButton, {
166
+ /** The toolbar's Filter button, which F presses. Beside a chip row (`ListFilterBar`, which
167
+ * `ListPage` shows), it opens the Add filter menu: picking a field adds its chip and opens its
168
+ * value picker there. Without one, it keeps a submenu of values for each facet. */
169
+ function ListFilterMenu({ view, filters, label }) {
170
+ const { common, filters: t } = useStrings();
171
+ const state = filters ?? view?.filterState;
172
+ if (!state || state.fields.length === 0) return null;
173
+ const active = state.count > 0;
174
+ const button = /* @__PURE__ */ jsx(IconButton, {
174
175
  variant: "outline",
175
176
  icon: /* @__PURE__ */ jsx(FilterIcon, {}),
176
- label: label ?? common.filter,
177
+ label: label ?? t.filterButton(state.count),
177
178
  dot: active,
178
179
  shortcut: "f"
179
- }) }), /* @__PURE__ */ jsxs(MenuPopup, {
180
+ });
181
+ if (state.barMounted) return /* @__PURE__ */ jsx(AddFilterMenu, {
182
+ filters: state,
183
+ trigger: button,
184
+ align: "end"
185
+ });
186
+ if (!view || view.facets.length === 0) return null;
187
+ return /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsx(Menu.Trigger, { render: button }), /* @__PURE__ */ jsxs(MenuPopup, {
180
188
  align: "end",
181
189
  className: "w-56",
182
190
  children: [/* @__PURE__ */ jsxs("div", {
@@ -217,7 +225,7 @@ function FacetSubmenu({ view, facet }) {
217
225
  children: selected.length
218
226
  })] }), /* @__PURE__ */ jsxs(MenuPopup, {
219
227
  side: "inline-start",
220
- children: [facet.searchable ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
228
+ children: [facet.searchable ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
221
229
  className: "sticky top-0 z-[1] border-b border-(--theme-border) bg-(--theme-app-bg) px-3 pb-1.5 pt-0.5",
222
230
  children: /* @__PURE__ */ jsx(Menu.Input, {
223
231
  placeholder: strings.list.searchOptions,
@@ -19,8 +19,9 @@ export interface UserHoverCardProps {
19
19
  }
20
20
  export declare function UserHoverCard({ username, name, avatarSrc, badge, href, linkComponent, loading, children, }: UserHoverCardProps): import("react").JSX.Element;
21
21
  /** One detail line of a hover card: a leading icon and its content. With
22
- * `onClick` the line is a button. */
23
- export declare function HoverCardRow({ icon, children, title, align, truncate, onClick, }: {
22
+ * `onClick` the line is a button; with `copy` it is a button that copies a value,
23
+ * such as the email address it shows, its icon turning into a check for a moment. */
24
+ export declare function HoverCardRow({ icon, children, title, align, truncate, onClick, copy, }: {
24
25
  icon: ReactNode;
25
26
  children: ReactNode;
26
27
  title?: string | undefined;
@@ -28,4 +29,9 @@ export declare function HoverCardRow({ icon, children, title, align, truncate, o
28
29
  align?: 'center' | 'start' | undefined;
29
30
  truncate?: boolean | undefined;
30
31
  onClick?: (() => void) | undefined;
32
+ /** Copies `text` when pressed, named by `label`: "Copy email", then a toast "Copied email". */
33
+ copy?: {
34
+ text: string;
35
+ label: string;
36
+ } | undefined;
31
37
  }): import("react").JSX.Element;