@parallelworks/ui 0.77.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.
- package/README.md +30 -5
- package/dist/access/AccessDrawer.d.ts +28 -7
- package/dist/access/AccessDrawer.js +216 -35
- package/dist/access/AccessList.d.ts +19 -1
- package/dist/access/AccessList.js +220 -9
- package/dist/access/GrantView.d.ts +3 -1
- package/dist/access/GrantView.js +17 -4
- package/dist/access/PrincipalPicker.js +5 -5
- package/dist/access/focus.js +1 -1
- package/dist/access/index.d.ts +2 -2
- package/dist/access/index.js +2 -2
- package/dist/access/strings.d.ts +18 -0
- package/dist/access/strings.js +20 -2
- package/dist/access/types.d.ts +26 -0
- package/dist/ai/components/AllocationSelector.js +1 -1
- package/dist/ai/components/AttachmentManager.js +5 -5
- package/dist/ai/components/AttachmentUpload.js +2 -2
- package/dist/ai/components/BranchNavigator.js +1 -1
- package/dist/ai/components/ChatActivity.js +1 -1
- package/dist/ai/components/ChatEmptyState.js +3 -3
- package/dist/ai/components/ChatInput.js +3 -5
- package/dist/ai/components/ChatLayout.js +1 -1
- package/dist/ai/components/ChatMessage.js +1 -1
- package/dist/ai/components/ChatMessageList.js +2 -2
- package/dist/ai/components/ChatSidebar.js +3 -3
- package/dist/ai/components/ChatThread.js +4 -4
- package/dist/ai/components/ComposerAddMenu.js +9 -20
- package/dist/ai/components/ModelSelector.js +3 -3
- package/dist/ai/components/PastedText.js +5 -5
- package/dist/ai/components/SessionView.js +1 -1
- package/dist/ai/components/ShareDialog.js +3 -3
- package/dist/ai/components/SlashMenu.d.ts +31 -4
- package/dist/ai/components/SlashMenu.js +36 -63
- package/dist/ai/components/agent/ActivityLine.js +1 -1
- package/dist/ai/components/agent/AgentMessageParts.js +13 -13
- package/dist/ai/components/conversationActions.js +3 -3
- package/dist/ai/core/ChatProvider.js +1 -1
- package/dist/ai/core/config.js +1 -1
- package/dist/ai/ui/ConversationSidebar.js +3 -3
- package/dist/ai/ui/sidebar.js +3 -3
- package/dist/assets/yaml.worker-DOBV2lND.js +884 -0
- package/dist/components/ActionMenu.d.ts +38 -9
- package/dist/components/ActionMenu.js +48 -22
- package/dist/components/Avatar.d.ts +66 -6
- package/dist/components/Avatar.js +130 -18
- package/dist/components/Breadcrumbs.d.ts +4 -0
- package/dist/components/Breadcrumbs.js +26 -10
- package/dist/components/Button.d.ts +3 -2
- package/dist/components/Button.js +11 -1
- package/dist/components/Callout.d.ts +3 -2
- package/dist/components/Callout.js +3 -2
- package/dist/components/Card.d.ts +33 -9
- package/dist/components/Card.js +24 -8
- package/dist/components/Checkbox.d.ts +3 -1
- package/dist/components/Checkbox.js +4 -2
- package/dist/components/ColorInput.js +1 -1
- package/dist/components/Combobox.d.ts +23 -0
- package/dist/components/Combobox.js +252 -86
- package/dist/components/ConfirmModal.d.ts +26 -2
- package/dist/components/ConfirmModal.js +81 -15
- package/dist/components/ContextMenu.d.ts +29 -2
- package/dist/components/ContextMenu.js +60 -8
- package/dist/components/CopyButton.d.ts +21 -8
- package/dist/components/CopyButton.js +29 -9
- package/dist/components/CreateModal.d.ts +16 -4
- package/dist/components/CreateModal.js +27 -16
- package/dist/components/DatePicker.d.ts +31 -1
- package/dist/components/DatePicker.js +178 -47
- package/dist/components/DescriptionList.d.ts +13 -3
- package/dist/components/DescriptionList.js +43 -11
- package/dist/components/Disclosure.d.ts +10 -2
- package/dist/components/Disclosure.js +18 -7
- package/dist/components/Drawer.js +5 -5
- package/dist/components/EmptyState.d.ts +12 -4
- package/dist/components/EmptyState.js +18 -10
- package/dist/components/ErrorPage.d.ts +40 -0
- package/dist/components/ErrorPage.js +101 -0
- package/dist/components/ExternalLink.d.ts +4 -1
- package/dist/components/ExternalLink.js +4 -5
- package/dist/components/Field.d.ts +21 -6
- package/dist/components/Field.js +32 -16
- package/dist/components/FileButton.d.ts +19 -0
- package/dist/components/FileButton.js +32 -0
- package/dist/components/HoverCard.d.ts +26 -6
- package/dist/components/HoverCard.js +11 -5
- package/dist/components/IconButton.js +4 -2
- package/dist/components/InfoTip.js +3 -3
- package/dist/components/Input.d.ts +33 -3
- package/dist/components/Input.js +149 -14
- package/dist/components/Kbd.d.ts +40 -0
- package/dist/components/Kbd.js +168 -0
- package/dist/components/Listbox.d.ts +103 -0
- package/dist/components/Listbox.js +190 -0
- package/dist/components/Loader.d.ts +8 -2
- package/dist/components/Loader.js +16 -1
- package/dist/components/Markdown.js +1 -1
- package/dist/components/MarkdownImpl.js +1 -1
- package/dist/components/Menu.d.ts +20 -2
- package/dist/components/Menu.js +48 -19
- package/dist/components/MenuEntries.d.ts +38 -2
- package/dist/components/MenuEntries.js +266 -39
- package/dist/components/Meter.d.ts +50 -11
- package/dist/components/Meter.js +71 -21
- package/dist/components/Modal.d.ts +9 -3
- package/dist/components/Modal.js +68 -29
- package/dist/components/OneTimeCodeInput.js +1 -1
- package/dist/components/PageHeader.js +111 -7
- package/dist/components/PageHeaderAction.d.ts +8 -3
- package/dist/components/PageHeaderAction.js +122 -34
- package/dist/components/Pagination.d.ts +13 -1
- package/dist/components/Pagination.js +90 -19
- package/dist/components/Popover.d.ts +13 -2
- package/dist/components/Popover.js +20 -21
- package/dist/components/Provider.d.ts +140 -3
- package/dist/components/Provider.js +142 -12
- package/dist/components/RefreshButton.d.ts +13 -6
- package/dist/components/RefreshButton.js +17 -9
- package/dist/components/RunStatusIcon.d.ts +16 -7
- package/dist/components/RunStatusIcon.js +21 -8
- package/dist/components/Section.d.ts +11 -4
- package/dist/components/Section.js +33 -22
- package/dist/components/SegmentedControl.d.ts +16 -3
- package/dist/components/SegmentedControl.js +7 -3
- package/dist/components/Select.d.ts +19 -3
- package/dist/components/Select.js +114 -68
- package/dist/components/SelectionCopy.d.ts +10 -0
- package/dist/components/SelectionCopy.js +105 -0
- package/dist/components/SettingModeOption.js +1 -1
- package/dist/components/SettingsCard.js +1 -1
- package/dist/components/Skeleton.js +1 -1
- package/dist/components/StatusBadge.d.ts +55 -10
- package/dist/components/StatusBadge.js +91 -15
- package/dist/components/StickyBar.js +1 -1
- package/dist/components/Table.d.ts +22 -4
- package/dist/components/Table.js +46 -24
- package/dist/components/Tabs.d.ts +9 -4
- package/dist/components/Tabs.js +9 -4
- package/dist/components/Tag.d.ts +49 -0
- package/dist/components/Tag.js +199 -0
- package/dist/components/ThemeEditor.js +1 -1
- package/dist/components/Toast.js +1 -1
- package/dist/components/ToggleGroup.d.ts +4 -1
- package/dist/components/ToggleGroup.js +30 -13
- package/dist/components/Tooltip.d.ts +9 -3
- package/dist/components/Tooltip.js +55 -39
- package/dist/components/buttonClasses.d.ts +5 -2
- package/dist/components/buttonClasses.js +11 -10
- package/dist/components/chart.d.ts +69 -0
- package/dist/components/chart.js +145 -0
- package/dist/components/comboboxItems.d.ts +7 -1
- package/dist/components/comboboxItems.js +6 -2
- package/dist/components/dismiss.d.ts +5 -1
- package/dist/components/dismiss.js +6 -2
- package/dist/components/floating.d.ts +4 -4
- package/dist/components/floating.js +5 -5
- package/dist/components/headerActionsFit.d.ts +37 -0
- package/dist/components/headerActionsFit.js +81 -0
- package/dist/components/pageHeaderStore.d.ts +3 -0
- package/dist/components/pageHeaderStore.js +3 -0
- package/dist/components/pathBreaks.js +2 -2
- package/dist/components/popupContainer.d.ts +17 -0
- package/dist/components/popupContainer.js +69 -0
- package/dist/components/relativeTime.d.ts +21 -10
- package/dist/components/relativeTime.js +50 -22
- package/dist/components/segmented.d.ts +18 -4
- package/dist/components/segmented.js +48 -6
- package/dist/components/typedDate.d.ts +5 -0
- package/dist/components/typedDate.js +50 -0
- package/dist/components/useClosingValue.d.ts +4 -0
- package/dist/components/useClosingValue.js +12 -0
- package/dist/components/useCopy.d.ts +6 -0
- package/dist/components/useCopy.js +3 -3
- package/dist/components/useNarrow.d.ts +2 -0
- package/dist/components/useNarrow.js +16 -0
- package/dist/editor/Editor.js +1 -1
- package/dist/editor/FormCodePanel.js +1 -1
- package/dist/editor/Monaco.js +1 -1
- package/dist/editor/workers.js +1 -1
- package/dist/file-explorer/FileExplorer.js +16 -15
- package/dist/file-explorer/FileExplorerContext.js +2 -2
- package/dist/file-explorer/FilePreview/Viewer.js +3 -3
- package/dist/file-explorer/FilePreview/index.js +2 -2
- package/dist/file-explorer/FileRowsWindow.js +3 -3
- package/dist/file-explorer/FileTable.js +1 -1
- package/dist/file-explorer/LoadMoreRow.js +1 -1
- package/dist/file-explorer/TreeView.js +5 -5
- package/dist/file-explorer/helpers.js +2 -2
- package/dist/file-explorer/toasts.js +2 -2
- package/dist/form/Fields/CheckboxGroupField.js +1 -1
- package/dist/form/Fields/DropdownField.js +1 -1
- package/dist/form/Fields/DurationField.js +2 -2
- package/dist/form/Fields/MultiDropdownField.js +1 -1
- package/dist/form/Fields/NumberField.js +1 -1
- package/dist/form/Fields/ObjectField.js +1 -1
- package/dist/form/Fields/RangeField.js +1 -1
- package/dist/form/Fields/StringField.js +1 -1
- package/dist/form/Form.js +3 -3
- package/dist/form/FormLayout.js +1 -1
- package/dist/form/Wizard/WizardContainer.js +1 -1
- package/dist/form/Wizard/WizardNavigation.js +1 -1
- package/dist/form/Wizard/WizardStepContent.js +1 -1
- package/dist/form/fieldRegistry.js +1 -1
- package/dist/form/formEditing.js +1 -1
- package/dist/format.d.ts +17 -7
- package/dist/format.js +39 -16
- package/dist/graph/AnnotationBanner.js +2 -2
- package/dist/graph/Connectors.js +5 -5
- package/dist/graph/DependencyGraph.js +10 -9
- package/dist/graph/GraphEditor.js +4 -4
- package/dist/graph/GraphEditorDialogs.js +13 -12
- package/dist/graph/GraphNode.js +1 -1
- package/dist/graph/InputDialog.js +5 -5
- package/dist/graph/InputsEditor.js +7 -7
- package/dist/graph/MatrixGroup.js +2 -2
- package/dist/graph/ProblemsButton.js +3 -3
- package/dist/graph/Reveal.js +1 -1
- package/dist/graph/RunWarningsList.js +1 -1
- package/dist/graph/ShortcutsButton.js +25 -8
- package/dist/graph/StepSummaries.js +1 -1
- package/dist/graph/TreeView.js +2 -2
- package/dist/graph/WorkflowSettingsDialog.js +3 -3
- package/dist/graph/editorFields.js +3 -3
- package/dist/graph/editorPrimitives.js +1 -1
- package/dist/graph/editorRows.js +5 -5
- package/dist/graph/fieldProblems.js +2 -2
- package/dist/graph/inputRefs.js +7 -6
- package/dist/graph/stepWith.js +2 -2
- package/dist/index.d.ts +30 -21
- package/dist/index.js +20 -12
- package/dist/list/ActionToolbar.d.ts +4 -0
- package/dist/list/ActionToolbar.js +35 -12
- package/dist/list/ListFilterBar.d.ts +42 -0
- package/dist/list/ListFilterBar.js +789 -0
- package/dist/list/ListPage.d.ts +42 -4
- package/dist/list/ListPage.js +56 -22
- package/dist/list/ListTable.d.ts +27 -3
- package/dist/list/ListTable.js +48 -23
- package/dist/list/ListToolbar.d.ts +31 -0
- package/dist/list/ListToolbar.js +43 -0
- package/dist/list/ListViewControls.d.ts +8 -4
- package/dist/list/ListViewControls.js +22 -14
- package/dist/list/UserHoverCard.d.ts +8 -2
- package/dist/list/UserHoverCard.js +26 -13
- package/dist/list/filterModel.d.ts +122 -0
- package/dist/list/filterModel.js +308 -0
- package/dist/list/index.d.ts +6 -2
- package/dist/list/index.js +6 -2
- package/dist/list/listSearch.d.ts +1 -1
- package/dist/list/listSearch.js +8 -4
- package/dist/list/listView.d.ts +24 -2
- package/dist/list/listView.js +47 -45
- package/dist/list/rowMenu.d.ts +10 -5
- package/dist/list/rowMenu.js +17 -7
- package/dist/list/useListFilters.d.ts +68 -0
- package/dist/list/useListFilters.js +252 -0
- package/dist/logviewer/LogViewer.js +4 -4
- package/dist/styles/theme.css +94 -0
- package/dist/styles.css +1 -1
- package/package.json +11 -11
- package/dist/assets/yaml.worker-k9AdOqzf.js +0 -1441
- package/dist/components/fullscreen.d.ts +0 -4
- package/dist/components/fullscreen.js +0 -18
package/dist/list/ListPage.d.ts
CHANGED
|
@@ -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
|
|
16
|
-
* trail and actions
|
|
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
|
|
23
|
-
export
|
|
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. */
|
package/dist/list/ListPage.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
40
|
-
|
|
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: [
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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,
|
package/dist/list/ListTable.d.ts
CHANGED
|
@@ -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
|
-
|
|
55
|
-
|
|
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;
|
package/dist/list/ListTable.js
CHANGED
|
@@ -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
|
|
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__ */
|
|
65
|
+
return /* @__PURE__ */ jsx(Table.Item, {
|
|
61
66
|
className: "py-2.5",
|
|
62
|
-
children:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
}),
|
|
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
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
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:
|
|
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
|
|
168
|
-
*
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
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 ??
|
|
177
|
+
label: label ?? t.filterButton(state.count),
|
|
177
178
|
dot: active,
|
|
178
179
|
shortcut: "f"
|
|
179
|
-
})
|
|
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
|
-
|
|
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;
|