@zvk/composite 0.1.1 → 0.1.2
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/CHANGELOG.md +7 -0
- package/README.md +410 -0
- package/dist/activity/activity-feed.d.ts +27 -0
- package/dist/activity/activity-feed.js +30 -0
- package/dist/ai/conversation-directory.d.ts +31 -0
- package/dist/ai/conversation-directory.js +44 -0
- package/dist/ai/provider-model-selector.d.ts +31 -0
- package/dist/ai/provider-model-selector.js +41 -0
- package/dist/ai/sticky-composer.d.ts +14 -0
- package/dist/ai/sticky-composer.js +13 -0
- package/dist/data/data-table-control-bar.d.ts +13 -0
- package/dist/data/data-table-control-bar.js +11 -0
- package/dist/detail/detail-inspector-panel.d.ts +21 -0
- package/dist/detail/detail-inspector-panel.js +18 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +16 -0
- package/dist/integrations/integration-status-card.d.ts +20 -0
- package/dist/integrations/integration-status-card.js +15 -0
- package/dist/layout/feature-shell.d.ts +13 -0
- package/dist/layout/feature-shell.js +7 -0
- package/dist/navigation/command-palette-shell.d.ts +31 -0
- package/dist/navigation/command-palette-shell.js +45 -0
- package/dist/navigation/entity-switcher-menu.d.ts +38 -0
- package/dist/navigation/entity-switcher-menu.js +56 -0
- package/dist/navigation/link-action.d.ts +11 -0
- package/dist/navigation/link-action.js +41 -0
- package/dist/navigation/sectioned-workspace-shell.d.ts +2 -1
- package/dist/navigation/sectioned-workspace-shell.js +2 -2
- package/dist/settings/parameter-editor.d.ts +27 -0
- package/dist/settings/parameter-editor.js +12 -0
- package/dist/settings/settings-section-stack.d.ts +20 -0
- package/dist/settings/settings-section-stack.js +10 -0
- package/dist/state/route-state-frame.d.ts +10 -0
- package/dist/state/route-state-frame.js +31 -0
- package/dist/styles.css +2138 -99
- package/dist/workflows/process-list-panel.d.ts +26 -0
- package/dist/workflows/process-list-panel.js +24 -0
- package/dist/workflows/workflow-status-card.d.ts +20 -0
- package/dist/workflows/workflow-status-card.js +46 -0
- package/package.json +112 -17
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Spinner } from "@zvk/ui/spinner";
|
|
5
|
+
import { cn } from "../utils/cn.js";
|
|
6
|
+
function hasValue(value) {
|
|
7
|
+
return value !== null && value !== undefined && value !== false;
|
|
8
|
+
}
|
|
9
|
+
function renderNode(value) {
|
|
10
|
+
return hasValue(value) ? value : null;
|
|
11
|
+
}
|
|
12
|
+
export function ProviderModelSelector({ advancedSettings, className, empty = "No provider models available.", groups, loading = false, onGroupSelect, onItemSelect, ref, search, selectedGroupId, selectedItemId, selectedSummary, ...props }) {
|
|
13
|
+
const selectedGroup = groups.find((group) => group.id === selectedGroupId);
|
|
14
|
+
const selectedItems = selectedGroup?.items ?? [];
|
|
15
|
+
const hasGroups = groups.length > 0;
|
|
16
|
+
const hasSelectedGroup = selectedGroup !== undefined;
|
|
17
|
+
const hasSelectedItems = selectedItems.length > 0;
|
|
18
|
+
const selectedGroupUnavailable = selectedGroup?.disabled === true;
|
|
19
|
+
const showLoader = loading;
|
|
20
|
+
const showEmptyRootState = !loading && !hasGroups;
|
|
21
|
+
const showItemEmptyState = !loading && hasGroups && (!hasSelectedGroup || !hasSelectedItems);
|
|
22
|
+
return (_jsxs("div", { ...props, ref: ref, "aria-busy": loading ? true : props["aria-busy"], className: cn("zvk-composite-provider-model-selector", className), "data-empty": showEmptyRootState ? "" : undefined, "data-loading": loading ? "" : undefined, children: [_jsxs("div", { className: "zvk-composite-provider-model-selector__header", children: [hasValue(search) ? _jsx("div", { className: "zvk-composite-provider-model-selector__search", children: search }) : null, hasValue(selectedSummary) ? (_jsx("div", { className: "zvk-composite-provider-model-selector__summary", children: selectedSummary })) : null] }), showLoader ? (_jsxs("div", { className: "zvk-composite-provider-model-selector__state", "data-state": "loading", children: [_jsx(Spinner, { label: "Loading provider models", size: "sm", tone: "muted" }), _jsx("span", { children: "Loading provider models..." })] })) : null, showEmptyRootState ? (_jsx("div", { className: "zvk-composite-provider-model-selector__state", "data-state": "empty", children: renderNode(empty) })) : null, !showLoader && hasGroups ? (_jsxs("div", { className: "zvk-composite-provider-model-selector__columns", children: [_jsxs("section", { "aria-label": "Providers", className: "zvk-composite-provider-model-selector__panel", "data-state": selectedGroupUnavailable ? "unavailable" : "ready", "data-unavailable": selectedGroupUnavailable ? "" : undefined, children: [_jsx("div", { className: "zvk-composite-provider-model-selector__panel-header", children: _jsx("div", { className: "zvk-composite-provider-model-selector__panel-copy", children: _jsx("h3", { className: "zvk-composite-provider-model-selector__panel-title", children: "Providers" }) }) }), _jsx("ul", { className: "zvk-composite-provider-model-selector__list", children: groups.map((group) => {
|
|
23
|
+
const isSelected = group.id === selectedGroupId;
|
|
24
|
+
const isDisabled = group.disabled === true;
|
|
25
|
+
return (_jsx("li", { className: "zvk-composite-provider-model-selector__list-item", children: _jsx("button", { "aria-pressed": isSelected, className: "zvk-composite-provider-model-selector__choice zvk-composite-provider-model-selector__group-choice", "data-disabled": isDisabled ? "" : undefined, "data-selected": isSelected ? "" : undefined, disabled: isDisabled, type: "button", onClick: () => {
|
|
26
|
+
if (isDisabled) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
onGroupSelect?.(group);
|
|
30
|
+
}, children: _jsxs("span", { className: "zvk-composite-provider-model-selector__choice-copy", children: [_jsxs("span", { className: "zvk-composite-provider-model-selector__choice-heading", children: [_jsx("span", { className: "zvk-composite-provider-model-selector__choice-label", children: group.label }), hasValue(group.badge) ? (_jsx("span", { className: "zvk-composite-provider-model-selector__choice-badge", children: group.badge })) : null] }), hasValue(group.description) ? (_jsx("span", { className: "zvk-composite-provider-model-selector__choice-description", children: group.description })) : null] }) }) }, group.id));
|
|
31
|
+
}) })] }), _jsxs("section", { "aria-label": "Models", className: "zvk-composite-provider-model-selector__panel", "data-state": showItemEmptyState || selectedGroupUnavailable ? "unavailable" : "ready", "data-unavailable": showItemEmptyState || selectedGroupUnavailable ? "" : undefined, children: [_jsx("div", { className: "zvk-composite-provider-model-selector__panel-header", children: _jsxs("div", { className: "zvk-composite-provider-model-selector__panel-copy", children: [_jsx("h3", { className: "zvk-composite-provider-model-selector__panel-title", children: "Models" }), hasSelectedGroup ? (_jsxs("p", { className: "zvk-composite-provider-model-selector__panel-description", children: [selectedGroup?.label, hasValue(selectedGroup?.description) ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "zvk-composite-provider-model-selector__panel-description-separator", children: [" ", _jsx("span", { "aria-hidden": "true", children: "\u00B7" }), " "] }), selectedGroup?.description] })) : null] })) : null] }) }), !showItemEmptyState && hasSelectedGroup ? (_jsx("ul", { className: "zvk-composite-provider-model-selector__list", children: selectedItems.map((item) => {
|
|
32
|
+
const isSelected = item.id === selectedItemId;
|
|
33
|
+
const isDisabled = item.disabled === true || selectedGroupUnavailable;
|
|
34
|
+
return (_jsx("li", { className: "zvk-composite-provider-model-selector__list-item", children: _jsx("button", { "aria-pressed": isSelected, className: "zvk-composite-provider-model-selector__choice zvk-composite-provider-model-selector__item-choice", "data-disabled": isDisabled ? "" : undefined, "data-selected": isSelected ? "" : undefined, disabled: isDisabled, type: "button", onClick: () => {
|
|
35
|
+
if (isDisabled) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
onItemSelect?.(item, selectedGroup);
|
|
39
|
+
}, children: _jsxs("span", { className: "zvk-composite-provider-model-selector__choice-copy", children: [_jsxs("span", { className: "zvk-composite-provider-model-selector__choice-heading", children: [_jsx("span", { className: "zvk-composite-provider-model-selector__choice-label", children: item.label }), hasValue(item.badge) ? (_jsx("span", { className: "zvk-composite-provider-model-selector__choice-badge", children: item.badge })) : null] }), hasValue(item.description) ? (_jsx("span", { className: "zvk-composite-provider-model-selector__choice-description", children: item.description })) : null, hasValue(item.metadata) ? (_jsx("span", { className: "zvk-composite-provider-model-selector__choice-metadata", children: item.metadata })) : null] }) }) }, item.id));
|
|
40
|
+
}) })) : null, showItemEmptyState ? (_jsx("div", { className: "zvk-composite-provider-model-selector__state", "data-state": "empty", children: renderNode(empty) })) : null, hasValue(advancedSettings) ? (_jsx("div", { className: "zvk-composite-provider-model-selector__advanced-settings", children: advancedSettings })) : null] })] })) : null, hasValue(advancedSettings) && !hasGroups && !showLoader ? (_jsx("div", { className: "zvk-composite-provider-model-selector__advanced-settings", children: advancedSettings })) : null] }));
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface StickyComposerProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>, "children"> {
|
|
3
|
+
readonly input: React.ReactNode;
|
|
4
|
+
readonly leadingTools?: React.ReactNode;
|
|
5
|
+
readonly trailingTools?: React.ReactNode;
|
|
6
|
+
readonly submit?: React.ReactNode;
|
|
7
|
+
readonly status?: React.ReactNode;
|
|
8
|
+
readonly error?: React.ReactNode;
|
|
9
|
+
readonly footer?: React.ReactNode;
|
|
10
|
+
readonly loading?: boolean;
|
|
11
|
+
readonly disabled?: boolean;
|
|
12
|
+
readonly ref?: React.Ref<HTMLFormElement>;
|
|
13
|
+
}
|
|
14
|
+
export declare function StickyComposer({ className, disabled, error, footer, input, leadingTools, loading, ref, status, submit, trailingTools, ...props }: StickyComposerProps): React.JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
function hasValue(value) {
|
|
6
|
+
return value !== null && value !== undefined && value !== false;
|
|
7
|
+
}
|
|
8
|
+
export function StickyComposer({ className, disabled = false, error, footer, input, leadingTools, loading = false, ref, status, submit, trailingTools, ...props }) {
|
|
9
|
+
const controlsDisabled = disabled || loading;
|
|
10
|
+
const hasToolbar = hasValue(leadingTools) || hasValue(trailingTools) || hasValue(submit);
|
|
11
|
+
const hasMeta = hasValue(status) || hasValue(error);
|
|
12
|
+
return (_jsxs("form", { ...props, ref: ref, "aria-busy": loading ? true : props["aria-busy"], "aria-disabled": controlsDisabled ? true : props["aria-disabled"], className: cn("zvk-composite-sticky-composer", className), "data-disabled": controlsDisabled ? "" : undefined, "data-loading": loading ? "" : undefined, children: [_jsxs("div", { className: "zvk-composite-sticky-composer__body", children: [_jsx("div", { className: "zvk-composite-sticky-composer__input", children: input }), hasToolbar ? (_jsxs("div", { className: "zvk-composite-sticky-composer__toolbar", children: [hasValue(leadingTools) ? (_jsx("div", { className: "zvk-composite-sticky-composer__tools", "data-slot": "leading", children: leadingTools })) : null, hasValue(trailingTools) ? (_jsx("div", { className: "zvk-composite-sticky-composer__tools", "data-slot": "trailing", children: trailingTools })) : null, hasValue(submit) ? _jsx("div", { className: "zvk-composite-sticky-composer__submit", children: submit }) : null] })) : null, hasMeta ? (_jsxs("div", { className: "zvk-composite-sticky-composer__meta", children: [hasValue(status) ? _jsx("div", { className: "zvk-composite-sticky-composer__status", children: status }) : null, hasValue(error) ? (_jsx("div", { className: "zvk-composite-sticky-composer__error", role: "alert", children: error })) : null] })) : null] }), hasValue(footer) ? _jsx("div", { className: "zvk-composite-sticky-composer__footer", children: footer }) : null] }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface DataTableControlBarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
readonly search?: React.ReactNode;
|
|
4
|
+
readonly filters?: React.ReactNode;
|
|
5
|
+
readonly savedView?: React.ReactNode;
|
|
6
|
+
readonly densityControl?: React.ReactNode;
|
|
7
|
+
readonly columnControl?: React.ReactNode;
|
|
8
|
+
readonly selectionSummary?: React.ReactNode;
|
|
9
|
+
readonly bulkActions?: React.ReactNode;
|
|
10
|
+
readonly actions?: React.ReactNode;
|
|
11
|
+
readonly ref?: React.Ref<HTMLDivElement>;
|
|
12
|
+
}
|
|
13
|
+
export declare function DataTableControlBar({ actions, bulkActions, className, columnControl, densityControl, filters, children: _children, ref, savedView, search, selectionSummary, ...props }: DataTableControlBarProps): React.JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../utils/cn.js";
|
|
4
|
+
function hasValue(value) {
|
|
5
|
+
return value !== null && value !== undefined && value !== false;
|
|
6
|
+
}
|
|
7
|
+
export function DataTableControlBar({ actions, bulkActions, className, columnControl, densityControl, filters, children: _children, ref, savedView, search, selectionSummary, ...props }) {
|
|
8
|
+
const hasPrimaryControls = hasValue(search) || hasValue(filters) || hasValue(savedView) || hasValue(densityControl) || hasValue(columnControl);
|
|
9
|
+
const hasSecondaryControls = hasValue(selectionSummary) || hasValue(bulkActions) || hasValue(actions);
|
|
10
|
+
return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-data-table-control-bar", className), children: [hasPrimaryControls ? (_jsxs("div", { className: "zvk-composite-data-table-control-bar__primary", children: [hasValue(search) ? _jsx("div", { className: "zvk-composite-data-table-control-bar__search", children: search }) : null, hasValue(filters) ? _jsx("div", { className: "zvk-composite-data-table-control-bar__filters", children: filters }) : null, hasValue(savedView) ? _jsx("div", { className: "zvk-composite-data-table-control-bar__saved-view", children: savedView }) : null, hasValue(densityControl) ? (_jsx("div", { className: "zvk-composite-data-table-control-bar__density-control", children: densityControl })) : null, hasValue(columnControl) ? (_jsx("div", { className: "zvk-composite-data-table-control-bar__column-control", children: columnControl })) : null] })) : null, hasSecondaryControls ? (_jsxs("div", { className: "zvk-composite-data-table-control-bar__secondary", children: [hasValue(selectionSummary) ? (_jsx("div", { className: "zvk-composite-data-table-control-bar__selection-summary", children: selectionSummary })) : null, hasValue(bulkActions) || hasValue(actions) ? (_jsxs("div", { className: "zvk-composite-data-table-control-bar__actions", children: [hasValue(bulkActions) ? (_jsx("div", { className: "zvk-composite-data-table-control-bar__bulk-actions", children: bulkActions })) : null, hasValue(actions) ? _jsx("div", { className: "zvk-composite-data-table-control-bar__actions-slot", children: actions }) : null] })) : null] })) : null] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface DetailInspectorSection {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly title?: React.ReactNode;
|
|
5
|
+
readonly description?: React.ReactNode;
|
|
6
|
+
readonly content: React.ReactNode;
|
|
7
|
+
readonly actions?: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface DetailInspectorPanelProps extends Omit<React.ComponentPropsWithoutRef<"aside">, "title" | "children"> {
|
|
10
|
+
readonly title: React.ReactNode;
|
|
11
|
+
readonly description?: React.ReactNode;
|
|
12
|
+
readonly status?: React.ReactNode;
|
|
13
|
+
readonly metadata?: React.ReactNode;
|
|
14
|
+
readonly actions?: React.ReactNode;
|
|
15
|
+
readonly sections: readonly DetailInspectorSection[];
|
|
16
|
+
readonly empty?: React.ReactNode;
|
|
17
|
+
readonly loading?: boolean;
|
|
18
|
+
readonly footer?: React.ReactNode;
|
|
19
|
+
readonly ref?: React.Ref<HTMLElement>;
|
|
20
|
+
}
|
|
21
|
+
export declare function DetailInspectorPanel({ actions, className, description, empty, footer, loading, metadata, ref, sections, status, title, ...props }: DetailInspectorPanelProps): React.JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Spinner } from "@zvk/ui/spinner";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
function hasValue(value) {
|
|
6
|
+
return value !== null && value !== undefined && value !== false;
|
|
7
|
+
}
|
|
8
|
+
export function DetailInspectorPanel({ actions, className, description, empty, footer, loading = false, metadata, ref, sections, status, title, ...props }) {
|
|
9
|
+
const sectionIdBase = React.useId();
|
|
10
|
+
const hasSections = sections.length > 0;
|
|
11
|
+
const showEmpty = !loading && !hasSections;
|
|
12
|
+
const hasHeaderAside = hasValue(status) || hasValue(metadata) || hasValue(actions);
|
|
13
|
+
return (_jsxs("aside", { ...props, ref: ref, "aria-busy": loading ? true : props["aria-busy"], className: cn("zvk-composite-detail-inspector-panel", className), "data-empty": showEmpty ? "" : undefined, "data-loading": loading ? "" : undefined, "data-state": loading ? "loading" : showEmpty ? "empty" : "ready", children: [_jsxs("header", { className: "zvk-composite-detail-inspector-panel__header", children: [_jsxs("div", { className: "zvk-composite-detail-inspector-panel__copy", children: [_jsx("h2", { className: "zvk-composite-detail-inspector-panel__title", children: title }), hasValue(description) ? (_jsx("p", { className: "zvk-composite-detail-inspector-panel__description", children: description })) : null] }), hasHeaderAside ? (_jsxs("div", { className: "zvk-composite-detail-inspector-panel__aside", children: [hasValue(status) ? _jsx("div", { className: "zvk-composite-detail-inspector-panel__status", children: status }) : null, hasValue(metadata) ? (_jsx("div", { className: "zvk-composite-detail-inspector-panel__metadata", children: metadata })) : null, hasValue(actions) ? _jsx("div", { className: "zvk-composite-detail-inspector-panel__actions", children: actions }) : null] })) : null] }), loading ? (_jsxs("div", { className: "zvk-composite-detail-inspector-panel__state", "data-state": "loading", role: "status", children: [_jsx(Spinner, { label: "Loading details", size: "sm", tone: "muted" }), _jsx("span", { children: "Loading details..." })] })) : showEmpty ? (_jsx("div", { className: "zvk-composite-detail-inspector-panel__state", "data-state": "empty", children: empty ?? "Select an item to inspect details." })) : (_jsx("div", { className: "zvk-composite-detail-inspector-panel__sections", children: sections.map((section, index) => {
|
|
14
|
+
const sectionTitleId = `${sectionIdBase}-section-${index}-title`;
|
|
15
|
+
const hasSectionHeader = hasValue(section.title) || hasValue(section.description) || hasValue(section.actions);
|
|
16
|
+
return (_jsxs("section", { "aria-labelledby": hasValue(section.title) ? sectionTitleId : undefined, className: "zvk-composite-detail-inspector-panel__section", children: [hasSectionHeader ? (_jsxs("div", { className: "zvk-composite-detail-inspector-panel__section-header", children: [_jsxs("div", { className: "zvk-composite-detail-inspector-panel__section-copy", children: [hasValue(section.title) ? (_jsx("h3", { className: "zvk-composite-detail-inspector-panel__section-title", id: sectionTitleId, children: section.title })) : null, hasValue(section.description) ? (_jsx("p", { className: "zvk-composite-detail-inspector-panel__section-description", children: section.description })) : null] }), hasValue(section.actions) ? (_jsx("div", { className: "zvk-composite-detail-inspector-panel__section-actions", children: section.actions })) : null] })) : null, _jsx("div", { className: "zvk-composite-detail-inspector-panel__section-content", children: section.content })] }, section.id));
|
|
17
|
+
}) })), hasValue(footer) ? _jsx("footer", { className: "zvk-composite-detail-inspector-panel__footer", children: footer }) : null] }));
|
|
18
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
|
+
export { ActivityFeed } from "./activity/activity-feed.js";
|
|
2
|
+
export type { ActivityFeedGroup, ActivityFeedItem, ActivityFeedProps, ActivityFeedTone } from "./activity/activity-feed.js";
|
|
1
3
|
export { PageScaffold } from "./layout/page-scaffold.js";
|
|
2
4
|
export type { PageScaffoldMaxWidth, PageScaffoldProps } from "./layout/page-scaffold.js";
|
|
5
|
+
export { FeatureShell } from "./layout/feature-shell.js";
|
|
6
|
+
export type { FeatureShellProps } from "./layout/feature-shell.js";
|
|
3
7
|
export { AppWorkspaceShell } from "./navigation/app-workspace-shell.js";
|
|
4
8
|
export type { AppWorkspaceShellProps } from "./navigation/app-workspace-shell.js";
|
|
9
|
+
export { CommandPaletteShell } from "./navigation/command-palette-shell.js";
|
|
10
|
+
export type { CommandPaletteCommand, CommandPaletteGroup, CommandPaletteShellProps } from "./navigation/command-palette-shell.js";
|
|
11
|
+
export { EntitySwitcherMenu } from "./navigation/entity-switcher-menu.js";
|
|
12
|
+
export type { EntitySwitcherGroup, EntitySwitcherItem, EntitySwitcherMenuProps, EntitySwitcherMenuSize } from "./navigation/entity-switcher-menu.js";
|
|
5
13
|
export { BreadcrumbPageHeader, WorkspaceHeader } from "./navigation/workspace-header.js";
|
|
6
14
|
export type { BreadcrumbPageHeaderProps, BreadcrumbPageHeaderItem, WorkspaceHeaderAlign, WorkspaceHeaderHeadingLevel, WorkspaceHeaderProps } from "./navigation/workspace-header.js";
|
|
7
15
|
export { SectionedWorkspaceShell } from "./navigation/sectioned-workspace-shell.js";
|
|
8
16
|
export type { SectionedWorkspaceItem, SectionedWorkspaceSection, SectionedWorkspaceShellProps } from "./navigation/sectioned-workspace-shell.js";
|
|
9
17
|
export { StateSurface } from "./state/state-surface.js";
|
|
10
18
|
export type { StateSurfaceAlign, StateSurfaceProps, StateSurfaceSize, StateSurfaceState } from "./state/state-surface.js";
|
|
19
|
+
export { RouteStateFrame } from "./state/route-state-frame.js";
|
|
20
|
+
export type { RouteStateFrameProps, RouteStateFrameStatus } from "./state/route-state-frame.js";
|
|
11
21
|
export { EntityCard } from "./lists/entity-card.js";
|
|
12
22
|
export type { EntityCardProps } from "./lists/entity-card.js";
|
|
13
23
|
export { EntityListSection } from "./lists/entity-list-section.js";
|
|
@@ -20,5 +30,27 @@ export { ConfirmActionDialog } from "./forms/confirm-action-dialog.js";
|
|
|
20
30
|
export type { ConfirmActionDialogProps, ConfirmActionDialogTone } from "./forms/confirm-action-dialog.js";
|
|
21
31
|
export { FormSurface } from "./forms/form-surface.js";
|
|
22
32
|
export type { FormSurfaceProps } from "./forms/form-surface.js";
|
|
33
|
+
export { IntegrationStatusCard } from "./integrations/integration-status-card.js";
|
|
34
|
+
export type { IntegrationStatusCardProps, IntegrationStatusTone } from "./integrations/integration-status-card.js";
|
|
35
|
+
export { WorkflowStatusCard } from "./workflows/workflow-status-card.js";
|
|
36
|
+
export type { WorkflowStatusCardProps, WorkflowStatusTone } from "./workflows/workflow-status-card.js";
|
|
37
|
+
export { ProcessListPanel } from "./workflows/process-list-panel.js";
|
|
38
|
+
export type { ProcessListPanelItem, ProcessListPanelProps } from "./workflows/process-list-panel.js";
|
|
39
|
+
export { ParameterEditor } from "./settings/parameter-editor.js";
|
|
40
|
+
export type { ParameterEditorDensity, ParameterEditorGroup, ParameterEditorProps, ParameterEditorRow } from "./settings/parameter-editor.js";
|
|
41
|
+
export { SettingsSectionStack } from "./settings/settings-section-stack.js";
|
|
42
|
+
export type { SettingsSection, SettingsSectionStackProps } from "./settings/settings-section-stack.js";
|
|
43
|
+
export { ProviderModelSelector } from "./ai/provider-model-selector.js";
|
|
44
|
+
export type { ProviderModelGroup, ProviderModelItem, ProviderModelSelectorProps } from "./ai/provider-model-selector.js";
|
|
45
|
+
export { ConversationDirectory } from "./ai/conversation-directory.js";
|
|
46
|
+
export type { ConversationDirectoryGroup, ConversationDirectoryItem, ConversationDirectoryProps } from "./ai/conversation-directory.js";
|
|
47
|
+
export { StickyComposer } from "./ai/sticky-composer.js";
|
|
48
|
+
export type { StickyComposerProps } from "./ai/sticky-composer.js";
|
|
49
|
+
export { DetailInspectorPanel } from "./detail/detail-inspector-panel.js";
|
|
50
|
+
export type { DetailInspectorPanelProps, DetailInspectorSection } from "./detail/detail-inspector-panel.js";
|
|
23
51
|
export { DataTablePageFrame } from "./data/data-table-page-frame.js";
|
|
52
|
+
export { DataTableControlBar } from "./data/data-table-control-bar.js";
|
|
53
|
+
export { LinkAction } from "./navigation/link-action.js";
|
|
54
|
+
export type { LinkActionProps } from "./navigation/link-action.js";
|
|
55
|
+
export type { DataTableControlBarProps } from "./data/data-table-control-bar.js";
|
|
24
56
|
export type { DataTablePageFrameProps } from "./data/data-table-page-frame.js";
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
+
export { ActivityFeed } from "./activity/activity-feed.js";
|
|
1
2
|
export { PageScaffold } from "./layout/page-scaffold.js";
|
|
3
|
+
export { FeatureShell } from "./layout/feature-shell.js";
|
|
2
4
|
export { AppWorkspaceShell } from "./navigation/app-workspace-shell.js";
|
|
5
|
+
export { CommandPaletteShell } from "./navigation/command-palette-shell.js";
|
|
6
|
+
export { EntitySwitcherMenu } from "./navigation/entity-switcher-menu.js";
|
|
3
7
|
export { BreadcrumbPageHeader, WorkspaceHeader } from "./navigation/workspace-header.js";
|
|
4
8
|
export { SectionedWorkspaceShell } from "./navigation/sectioned-workspace-shell.js";
|
|
5
9
|
export { StateSurface } from "./state/state-surface.js";
|
|
10
|
+
export { RouteStateFrame } from "./state/route-state-frame.js";
|
|
6
11
|
export { EntityCard } from "./lists/entity-card.js";
|
|
7
12
|
export { EntityListSection } from "./lists/entity-list-section.js";
|
|
8
13
|
export { SummaryMetricGrid } from "./lists/summary-metric-grid.js";
|
|
9
14
|
export { SettingsHubList } from "./lists/settings-hub-list.js";
|
|
10
15
|
export { ConfirmActionDialog } from "./forms/confirm-action-dialog.js";
|
|
11
16
|
export { FormSurface } from "./forms/form-surface.js";
|
|
17
|
+
export { IntegrationStatusCard } from "./integrations/integration-status-card.js";
|
|
18
|
+
export { WorkflowStatusCard } from "./workflows/workflow-status-card.js";
|
|
19
|
+
export { ProcessListPanel } from "./workflows/process-list-panel.js";
|
|
20
|
+
export { ParameterEditor } from "./settings/parameter-editor.js";
|
|
21
|
+
export { SettingsSectionStack } from "./settings/settings-section-stack.js";
|
|
22
|
+
export { ProviderModelSelector } from "./ai/provider-model-selector.js";
|
|
23
|
+
export { ConversationDirectory } from "./ai/conversation-directory.js";
|
|
24
|
+
export { StickyComposer } from "./ai/sticky-composer.js";
|
|
25
|
+
export { DetailInspectorPanel } from "./detail/detail-inspector-panel.js";
|
|
12
26
|
export { DataTablePageFrame } from "./data/data-table-page-frame.js";
|
|
27
|
+
export { DataTableControlBar } from "./data/data-table-control-bar.js";
|
|
28
|
+
export { LinkAction } from "./navigation/link-action.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type IntegrationStatusTone = "neutral" | "success" | "warning" | "danger" | "info";
|
|
3
|
+
export interface IntegrationStatusCardProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
|
|
4
|
+
title: React.ReactNode;
|
|
5
|
+
description?: React.ReactNode;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
status?: React.ReactNode;
|
|
8
|
+
statusTone?: IntegrationStatusTone;
|
|
9
|
+
badges?: React.ReactNode;
|
|
10
|
+
metadata?: React.ReactNode;
|
|
11
|
+
metrics?: React.ReactNode;
|
|
12
|
+
actions?: React.ReactNode;
|
|
13
|
+
footer?: React.ReactNode;
|
|
14
|
+
selected?: boolean;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
error?: React.ReactNode;
|
|
18
|
+
ref?: React.Ref<HTMLElement>;
|
|
19
|
+
}
|
|
20
|
+
export declare function IntegrationStatusCard({ actions, badges, className, description, disabled, error, footer, icon, loading, metadata, metrics, ref, selected, status, statusTone, title, ...props }: IntegrationStatusCardProps): React.JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Badge } from "@zvk/ui/badge";
|
|
4
|
+
import { Spinner } from "@zvk/ui/spinner";
|
|
5
|
+
import { cn } from "../utils/cn.js";
|
|
6
|
+
function hasValue(value) {
|
|
7
|
+
return value !== null && value !== undefined && value !== false;
|
|
8
|
+
}
|
|
9
|
+
function getBadgeTone(tone) {
|
|
10
|
+
return tone === "danger" ? "destructive" : tone;
|
|
11
|
+
}
|
|
12
|
+
export function IntegrationStatusCard({ actions, badges, className, description, disabled = false, error, footer, icon, loading = false, metadata, metrics, ref, selected = false, status, statusTone = "neutral", title, ...props }) {
|
|
13
|
+
const showHeaderAside = hasValue(status) || loading || hasValue(actions);
|
|
14
|
+
return (_jsxs("article", { ...props, ref: ref, "aria-busy": loading ? true : props["aria-busy"], "aria-disabled": disabled ? true : props["aria-disabled"], className: cn("zvk-composite-integration-status-card", className), "data-disabled": disabled ? "" : undefined, "data-loading": loading ? "" : undefined, "data-selected": selected ? "" : undefined, "data-tone": statusTone, children: [_jsxs("div", { className: "zvk-composite-integration-status-card__main", children: [hasValue(icon) ? _jsx("div", { className: "zvk-composite-integration-status-card__icon", children: icon }) : null, _jsxs("div", { className: "zvk-composite-integration-status-card__body", children: [_jsxs("div", { className: "zvk-composite-integration-status-card__header", children: [_jsxs("div", { className: "zvk-composite-integration-status-card__copy", children: [_jsx("h3", { className: "zvk-composite-integration-status-card__title", children: title }), hasValue(description) ? (_jsx("p", { className: "zvk-composite-integration-status-card__description", children: description })) : null] }), showHeaderAside ? (_jsxs("div", { className: "zvk-composite-integration-status-card__aside", children: [loading ? _jsx(Spinner, { label: "Loading integration status", size: "sm", tone: "muted" }) : null, hasValue(status) ? (_jsx(Badge, { tone: getBadgeTone(statusTone), variant: "soft", children: status })) : null, hasValue(actions) ? _jsx("div", { className: "zvk-composite-integration-status-card__actions", children: actions }) : null] })) : null] }), hasValue(badges) ? _jsx("div", { className: "zvk-composite-integration-status-card__badges", children: badges }) : null, hasValue(metadata) ? _jsx("div", { className: "zvk-composite-integration-status-card__metadata", children: metadata }) : null, hasValue(metrics) ? _jsx("div", { className: "zvk-composite-integration-status-card__metrics", children: metrics }) : null, hasValue(error) ? (_jsx("div", { className: "zvk-composite-integration-status-card__error", role: "alert", children: error })) : null] })] }), hasValue(footer) ? _jsx("div", { className: "zvk-composite-integration-status-card__footer", children: footer }) : null] }));
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface FeatureShellProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
|
|
3
|
+
readonly title: React.ReactNode;
|
|
4
|
+
readonly description?: React.ReactNode;
|
|
5
|
+
readonly eyebrow?: React.ReactNode;
|
|
6
|
+
readonly actions?: React.ReactNode;
|
|
7
|
+
readonly metadata?: React.ReactNode;
|
|
8
|
+
readonly toolbar?: React.ReactNode;
|
|
9
|
+
readonly children: React.ReactNode;
|
|
10
|
+
readonly className?: string;
|
|
11
|
+
readonly ref?: React.Ref<HTMLDivElement>;
|
|
12
|
+
}
|
|
13
|
+
export declare function FeatureShell({ actions, children, className, description, eyebrow, metadata, ref, title, toolbar, ...props }: FeatureShellProps): React.JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { PageScaffold } from "../layout/page-scaffold.js";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
export function FeatureShell({ actions, children, className, description, eyebrow, metadata, ref, title, toolbar, ...props }) {
|
|
6
|
+
return (_jsx(PageScaffold, { ...props, ref: ref, actions: actions, className: cn("zvk-composite-feature-shell", className), description: description, eyebrow: eyebrow, status: metadata, title: title, toolbar: toolbar, children: children }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CommandPaletteCommand {
|
|
3
|
+
description?: React.ReactNode | undefined;
|
|
4
|
+
disabled?: boolean | undefined;
|
|
5
|
+
icon?: React.ReactNode | undefined;
|
|
6
|
+
id: string;
|
|
7
|
+
keywords?: readonly string[] | undefined;
|
|
8
|
+
label: React.ReactNode;
|
|
9
|
+
shortcut?: React.ReactNode | undefined;
|
|
10
|
+
}
|
|
11
|
+
export interface CommandPaletteGroup {
|
|
12
|
+
commands: readonly CommandPaletteCommand[];
|
|
13
|
+
id: string;
|
|
14
|
+
label?: React.ReactNode | undefined;
|
|
15
|
+
}
|
|
16
|
+
export interface CommandPaletteShellProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
17
|
+
defaultQuery?: string | undefined;
|
|
18
|
+
empty?: React.ReactNode | undefined;
|
|
19
|
+
footer?: React.ReactNode | undefined;
|
|
20
|
+
groups: readonly CommandPaletteGroup[];
|
|
21
|
+
label?: React.ReactNode | undefined;
|
|
22
|
+
loading?: boolean | undefined;
|
|
23
|
+
onCommandSelect?: ((command: CommandPaletteCommand) => void) | undefined;
|
|
24
|
+
onOpenChange: (open: boolean) => void;
|
|
25
|
+
onQueryChange?: ((query: string) => void) | undefined;
|
|
26
|
+
open: boolean;
|
|
27
|
+
placeholder?: string | undefined;
|
|
28
|
+
query?: string | undefined;
|
|
29
|
+
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
30
|
+
}
|
|
31
|
+
export declare function CommandPaletteShell({ className, defaultQuery, empty, footer, groups, label, loading, onCommandSelect, onOpenChange, onQueryChange, open, placeholder, query, ref, ...props }: CommandPaletteShellProps): React.JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createElement as _createElement } from "react";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { Command } from "@zvk/ui/command";
|
|
6
|
+
import { Dialog } from "@zvk/ui/dialog";
|
|
7
|
+
import { cn } from "../utils/cn.js";
|
|
8
|
+
function useControllableValue({ defaultValue, onChange, value }) {
|
|
9
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
10
|
+
const resolvedValue = value ?? uncontrolledValue;
|
|
11
|
+
const setValue = React.useCallback((nextValue) => {
|
|
12
|
+
if (value === undefined) {
|
|
13
|
+
setUncontrolledValue(nextValue);
|
|
14
|
+
}
|
|
15
|
+
onChange?.(nextValue);
|
|
16
|
+
}, [onChange, value]);
|
|
17
|
+
return [resolvedValue, setValue];
|
|
18
|
+
}
|
|
19
|
+
export function CommandPaletteShell({ className, defaultQuery = "", empty = "No commands found.", footer, groups, label = "Command menu", loading = false, onCommandSelect, onOpenChange, onQueryChange, open, placeholder = "Search commands...", query, ref, ...props }) {
|
|
20
|
+
const [resolvedQuery, setResolvedQuery] = useControllableValue({
|
|
21
|
+
defaultValue: defaultQuery,
|
|
22
|
+
...(onQueryChange ? { onChange: onQueryChange } : {}),
|
|
23
|
+
...(query !== undefined ? { value: query } : {})
|
|
24
|
+
});
|
|
25
|
+
const hasCommands = groups.some((group) => group.commands.length > 0);
|
|
26
|
+
const dialogProps = {
|
|
27
|
+
...(ref !== undefined ? { ref } : {})
|
|
28
|
+
};
|
|
29
|
+
const handleSelect = React.useCallback((command) => {
|
|
30
|
+
onCommandSelect?.(command);
|
|
31
|
+
onOpenChange(false);
|
|
32
|
+
}, [onCommandSelect, onOpenChange]);
|
|
33
|
+
return (_jsx(Dialog, { ...props, ...dialogProps, className: cn("zvk-composite-command-palette-shell", className), onOpenChange: onOpenChange, open: open, children: _jsxs(Dialog.Content, { className: "zvk-composite-command-palette-shell__content", children: [_jsx(Dialog.Title, { className: "zvk-composite-command-palette-shell__title", children: label }), _jsxs(Command, { className: "zvk-composite-command-palette-shell__command", onValueChange: setResolvedQuery, value: resolvedQuery, children: [_jsx(Command.Input, { className: "zvk-composite-command-palette-shell__search", placeholder: placeholder }), _jsxs(Command.List, { className: "zvk-composite-command-palette-shell__list", children: [loading ? (_jsx("div", { className: "zvk-composite-command-palette-shell__state", "data-state": "loading", children: "Loading..." })) : null, !loading && !hasCommands ? (_jsx("div", { className: "zvk-composite-command-palette-shell__state", "data-state": "empty", children: empty })) : null, !loading && hasCommands ? _jsx(Command.Empty, { children: empty }) : null, !loading
|
|
34
|
+
? groups.map((group) => (_jsx(Command.Group, { className: "zvk-composite-command-palette-shell__group", heading: group.label, children: group.commands.map((command) => {
|
|
35
|
+
const commandProps = {
|
|
36
|
+
...(command.disabled !== undefined ? { disabled: command.disabled } : {}),
|
|
37
|
+
...(command.keywords !== undefined ? { keywords: command.keywords } : {})
|
|
38
|
+
};
|
|
39
|
+
return (_createElement(Command.Item, { ...commandProps, className: "zvk-composite-command-palette-shell__item", key: command.id, onSelect: () => handleSelect(command), value: command.id },
|
|
40
|
+
command.icon ? (_jsx("span", { className: "zvk-composite-command-palette-shell__item-icon", "aria-hidden": "true", children: command.icon })) : null,
|
|
41
|
+
_jsxs("span", { className: "zvk-composite-command-palette-shell__item-content", children: [_jsx("span", { className: "zvk-composite-command-palette-shell__item-label", children: command.label }), command.description ? (_jsx("span", { className: "zvk-composite-command-palette-shell__item-description", children: command.description })) : null] }),
|
|
42
|
+
command.shortcut ? (_jsx(Command.Shortcut, { className: "zvk-composite-command-palette-shell__shortcut", children: command.shortcut })) : null));
|
|
43
|
+
}) }, group.id)))
|
|
44
|
+
: null] }), footer ? _jsx("div", { className: "zvk-composite-command-palette-shell__footer", children: footer }) : null] })] }) }));
|
|
45
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type EntitySwitcherMenuSize = "sm" | "md";
|
|
3
|
+
export interface EntitySwitcherItem {
|
|
4
|
+
badge?: React.ReactNode | undefined;
|
|
5
|
+
description?: React.ReactNode | undefined;
|
|
6
|
+
disabled?: boolean | undefined;
|
|
7
|
+
icon?: React.ReactNode | undefined;
|
|
8
|
+
id: string;
|
|
9
|
+
keywords?: readonly string[] | undefined;
|
|
10
|
+
label: React.ReactNode;
|
|
11
|
+
meta?: React.ReactNode | undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface EntitySwitcherGroup {
|
|
14
|
+
id: string;
|
|
15
|
+
items: readonly EntitySwitcherItem[];
|
|
16
|
+
label?: React.ReactNode | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface EntitySwitcherMenuProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
19
|
+
createAction?: React.ReactNode | undefined;
|
|
20
|
+
current?: EntitySwitcherItem | undefined;
|
|
21
|
+
defaultOpen?: boolean | undefined;
|
|
22
|
+
defaultQuery?: string | undefined;
|
|
23
|
+
empty?: React.ReactNode | undefined;
|
|
24
|
+
groups: readonly EntitySwitcherGroup[];
|
|
25
|
+
label: React.ReactNode;
|
|
26
|
+
loading?: boolean | undefined;
|
|
27
|
+
loadingLabel?: React.ReactNode | undefined;
|
|
28
|
+
manageAction?: React.ReactNode | undefined;
|
|
29
|
+
onOpenChange?: ((open: boolean) => void) | undefined;
|
|
30
|
+
onQueryChange?: ((query: string) => void) | undefined;
|
|
31
|
+
onSelect?: ((item: EntitySwitcherItem) => void) | undefined;
|
|
32
|
+
open?: boolean | undefined;
|
|
33
|
+
placeholder?: string | undefined;
|
|
34
|
+
query?: string | undefined;
|
|
35
|
+
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
36
|
+
size?: EntitySwitcherMenuSize | undefined;
|
|
37
|
+
}
|
|
38
|
+
export declare function EntitySwitcherMenu({ className, createAction, current, defaultOpen, defaultQuery, empty, groups, label, loading, loadingLabel, manageAction, onOpenChange, onQueryChange, onSelect, open, placeholder, query, ref, size, ...props }: EntitySwitcherMenuProps): React.JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createElement as _createElement } from "react";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { Button } from "@zvk/ui/button";
|
|
6
|
+
import { Command } from "@zvk/ui/command";
|
|
7
|
+
import { Popover } from "@zvk/ui/popover";
|
|
8
|
+
import { cn } from "../utils/cn.js";
|
|
9
|
+
function useControllableValue({ defaultValue, onChange, value }) {
|
|
10
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
11
|
+
const resolvedValue = value ?? uncontrolledValue;
|
|
12
|
+
const setValue = React.useCallback((nextValue) => {
|
|
13
|
+
if (value === undefined) {
|
|
14
|
+
setUncontrolledValue(nextValue);
|
|
15
|
+
}
|
|
16
|
+
onChange?.(nextValue);
|
|
17
|
+
}, [onChange, value]);
|
|
18
|
+
return [resolvedValue, setValue];
|
|
19
|
+
}
|
|
20
|
+
function hasRenderableNode(value) {
|
|
21
|
+
return value !== undefined && value !== null && value !== false;
|
|
22
|
+
}
|
|
23
|
+
export function EntitySwitcherMenu({ className, createAction, current, defaultOpen = false, defaultQuery = "", empty = "No entities found.", groups, label, loading = false, loadingLabel = "Loading...", manageAction, onOpenChange, onQueryChange, onSelect, open, placeholder = "Search...", query, ref, size = "md", ...props }) {
|
|
24
|
+
const [resolvedOpen, setResolvedOpen] = useControllableValue({
|
|
25
|
+
defaultValue: defaultOpen,
|
|
26
|
+
...(onOpenChange ? { onChange: onOpenChange } : {}),
|
|
27
|
+
...(open !== undefined ? { value: open } : {})
|
|
28
|
+
});
|
|
29
|
+
const [resolvedQuery, setResolvedQuery] = useControllableValue({
|
|
30
|
+
defaultValue: defaultQuery,
|
|
31
|
+
...(onQueryChange ? { onChange: onQueryChange } : {}),
|
|
32
|
+
...(query !== undefined ? { value: query } : {})
|
|
33
|
+
});
|
|
34
|
+
const hasActions = hasRenderableNode(createAction) || hasRenderableNode(manageAction);
|
|
35
|
+
const hasItems = groups.some((group) => group.items.length > 0);
|
|
36
|
+
const popoverProps = {
|
|
37
|
+
...(ref !== undefined ? { ref } : {})
|
|
38
|
+
};
|
|
39
|
+
const handleSelect = React.useCallback((item) => {
|
|
40
|
+
onSelect?.(item);
|
|
41
|
+
setResolvedOpen(false);
|
|
42
|
+
}, [onSelect, setResolvedOpen]);
|
|
43
|
+
return (_jsxs(Popover, { ...props, ...popoverProps, className: cn("zvk-composite-entity-switcher-menu", className), "data-size": size, onOpenChange: setResolvedOpen, open: resolvedOpen, placement: "bottom-start", children: [_jsx(Popover.Trigger, { asChild: true, children: _jsxs(Button, { className: "zvk-composite-entity-switcher-menu__trigger", "data-state": resolvedOpen ? "open" : "closed", type: "button", variant: "outline", children: [_jsxs("span", { className: "zvk-composite-entity-switcher-menu__trigger-content", children: [_jsx("span", { className: "zvk-composite-entity-switcher-menu__label", children: label }), _jsxs("span", { className: "zvk-composite-entity-switcher-menu__current", children: [current?.icon ? (_jsx("span", { className: "zvk-composite-entity-switcher-menu__current-icon", "aria-hidden": "true", children: current.icon })) : null, current ? (_jsxs("span", { className: "zvk-composite-entity-switcher-menu__current-text", children: [_jsx("span", { className: "zvk-composite-entity-switcher-menu__current-label", children: current.label }), current.description ? (_jsx("span", { className: "zvk-composite-entity-switcher-menu__current-description", children: current.description })) : null] })) : null] })] }), _jsx("span", { className: "zvk-composite-entity-switcher-menu__chevron", "aria-hidden": "true", children: "v" })] }) }), _jsx(Popover.Content, { align: "start", className: "zvk-composite-entity-switcher-menu__content", matchTriggerWidth: true, side: "bottom", sideOffset: 8, children: _jsxs(Command, { className: "zvk-composite-entity-switcher-menu__command", onValueChange: setResolvedQuery, value: resolvedQuery, children: [_jsx(Command.Input, { className: "zvk-composite-entity-switcher-menu__search", placeholder: placeholder }), _jsxs(Command.List, { className: "zvk-composite-entity-switcher-menu__list", children: [loading ? (_jsx("div", { className: "zvk-composite-entity-switcher-menu__state", "data-state": "loading", children: loadingLabel })) : null, !loading && !hasItems ? (_jsx("div", { className: "zvk-composite-entity-switcher-menu__state", "data-state": "empty", children: empty })) : null, !loading && hasItems ? _jsx(Command.Empty, { children: empty }) : null, !loading
|
|
44
|
+
? groups.map((group) => (_jsx(Command.Group, { className: "zvk-composite-entity-switcher-menu__group", heading: group.label, children: group.items.map((item) => {
|
|
45
|
+
const itemProps = {
|
|
46
|
+
...(item.disabled !== undefined ? { disabled: item.disabled } : {}),
|
|
47
|
+
...(item.keywords !== undefined ? { keywords: item.keywords } : {})
|
|
48
|
+
};
|
|
49
|
+
return (_createElement(Command.Item, { ...itemProps, className: "zvk-composite-entity-switcher-menu__item", "data-current": current && item.id === current.id ? "true" : undefined, key: item.id, onSelect: () => handleSelect(item), value: item.id },
|
|
50
|
+
item.icon ? (_jsx("span", { className: "zvk-composite-entity-switcher-menu__item-icon", "aria-hidden": "true", children: item.icon })) : null,
|
|
51
|
+
_jsxs("span", { className: "zvk-composite-entity-switcher-menu__item-content", children: [_jsx("span", { className: "zvk-composite-entity-switcher-menu__item-label", children: item.label }), item.description ? (_jsx("span", { className: "zvk-composite-entity-switcher-menu__item-description", children: item.description })) : null] }),
|
|
52
|
+
item.meta ? (_jsx("span", { className: "zvk-composite-entity-switcher-menu__item-meta", children: item.meta })) : null,
|
|
53
|
+
item.badge ? (_jsx("span", { className: "zvk-composite-entity-switcher-menu__item-badge", children: item.badge })) : null));
|
|
54
|
+
}) }, group.id)))
|
|
55
|
+
: null] }), hasActions ? (_jsxs("div", { className: "zvk-composite-entity-switcher-menu__actions", children: [createAction ? (_jsx("div", { className: "zvk-composite-entity-switcher-menu__action", "data-action": "create", children: createAction })) : null, manageAction ? (_jsx("div", { className: "zvk-composite-entity-switcher-menu__action", "data-action": "manage", children: manageAction })) : null] })) : null] }) })] }));
|
|
56
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { ButtonSize, ButtonVariant } from "@zvk/ui/button";
|
|
3
|
+
export interface LinkActionProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "disabled"> {
|
|
4
|
+
readonly disabled?: boolean;
|
|
5
|
+
readonly leadingIcon?: React.ReactNode;
|
|
6
|
+
readonly ref?: React.Ref<HTMLAnchorElement>;
|
|
7
|
+
readonly size?: ButtonSize;
|
|
8
|
+
readonly trailingIcon?: React.ReactNode;
|
|
9
|
+
readonly variant?: ButtonVariant;
|
|
10
|
+
}
|
|
11
|
+
export declare function LinkAction({ children, className, disabled, leadingIcon, onClickCapture, onKeyDownCapture, ["aria-disabled"]: ariaDisabled, ref, size, trailingIcon, variant, ...props }: LinkActionProps): React.JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
function hasRenderableNode(value) {
|
|
6
|
+
if (value === null || value === undefined || value === false) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint") {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
if (React.isValidElement(value)) {
|
|
13
|
+
const props = value.props;
|
|
14
|
+
if (props["aria-hidden"] === true || props["aria-hidden"] === "true") {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (typeof props["aria-label"] === "string" && props["aria-label"].trim() !== "") {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (typeof props["aria-labelledby"] === "string" && props["aria-labelledby"].trim() !== "") {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (typeof props["title"] === "string" && props["title"].trim() !== "") {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return React.Children.toArray(props.children).some(hasRenderableNode);
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
export function LinkAction({ children, className, disabled, leadingIcon, onClickCapture, onKeyDownCapture, ["aria-disabled"]: ariaDisabled, ref, size = "md", trailingIcon, variant = "outline", ...props }) {
|
|
31
|
+
const isDisabled = Boolean(disabled || ariaDisabled === true || ariaDisabled === "true");
|
|
32
|
+
const suppressDisabledActivation = React.useCallback((event) => {
|
|
33
|
+
if (!isDisabled) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
event.stopPropagation();
|
|
38
|
+
}, [isDisabled]);
|
|
39
|
+
const hasContent = React.Children.count(children) > 0;
|
|
40
|
+
return (_jsxs("a", { ...props, "aria-disabled": isDisabled ? true : ariaDisabled, className: cn("zvk-ui-button", "zvk-composite-link-action", className), "data-disabled": isDisabled ? "true" : undefined, "data-size": size, "data-variant": variant, onClickCapture: isDisabled ? suppressDisabledActivation : onClickCapture, onKeyDownCapture: isDisabled ? suppressDisabledActivation : onKeyDownCapture, ref: ref, tabIndex: isDisabled ? -1 : props.tabIndex, children: [leadingIcon ? (_jsx("span", { "aria-hidden": hasRenderableNode(leadingIcon) ? undefined : true, className: "zvk-ui-button__icon zvk-composite-link-action__icon", children: leadingIcon })) : null, hasContent ? _jsx("span", { className: "zvk-ui-button__content zvk-composite-link-action__content", children: children }) : null, trailingIcon ? (_jsx("span", { "aria-hidden": hasRenderableNode(trailingIcon) ? undefined : true, className: "zvk-ui-button__icon zvk-composite-link-action__icon", children: trailingIcon })) : null] }));
|
|
41
|
+
}
|
|
@@ -25,9 +25,10 @@ export interface SectionedWorkspaceShellProps extends Omit<React.HTMLAttributes<
|
|
|
25
25
|
onItemSelect?: ((itemId: string) => void) | undefined;
|
|
26
26
|
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
27
27
|
sections: SectionedWorkspaceShellSection[];
|
|
28
|
+
sidebarFooter?: React.ReactNode | undefined;
|
|
28
29
|
title?: React.ReactNode | undefined;
|
|
29
30
|
toolbar?: React.ReactNode | undefined;
|
|
30
31
|
}
|
|
31
32
|
export type SectionedWorkspaceItem = SectionedWorkspaceShellItem;
|
|
32
33
|
export type SectionedWorkspaceSection = SectionedWorkspaceShellSection;
|
|
33
|
-
export declare function SectionedWorkspaceShell({ actions, activeItemId, children, className, description, footer, headingLevel, navLabel, onItemSelect, ref, sections, title, toolbar, ...props }: SectionedWorkspaceShellProps): React.JSX.Element;
|
|
34
|
+
export declare function SectionedWorkspaceShell({ actions, activeItemId, children, className, description, footer, headingLevel, navLabel, onItemSelect, ref, sections, sidebarFooter, title, toolbar, ...props }: SectionedWorkspaceShellProps): React.JSX.Element;
|
|
@@ -3,7 +3,7 @@ import * as React from "react";
|
|
|
3
3
|
import { SectionedSidebarNav } from "@zvk/ui/sectioned-sidebar-nav";
|
|
4
4
|
import { cn } from "../utils/cn.js";
|
|
5
5
|
import { WorkspaceHeader } from "./workspace-header.js";
|
|
6
|
-
export function SectionedWorkspaceShell({ actions, activeItemId, children, className, description, footer, headingLevel, navLabel = "Workspace navigation", onItemSelect, ref, sections, title, toolbar, ...props }) {
|
|
6
|
+
export function SectionedWorkspaceShell({ actions, activeItemId, children, className, description, footer, headingLevel, navLabel = "Workspace navigation", onItemSelect, ref, sections, sidebarFooter, title, toolbar, ...props }) {
|
|
7
7
|
const hasHeader = Boolean(title || description || actions || toolbar);
|
|
8
8
|
const navigationProps = {
|
|
9
9
|
...(activeItemId === undefined ? {} : { activeItemId }),
|
|
@@ -15,7 +15,7 @@ export function SectionedWorkspaceShell({ actions, activeItemId, children, class
|
|
|
15
15
|
...(headingLevel === undefined ? {} : { headingLevel }),
|
|
16
16
|
...(toolbar === undefined ? {} : { toolbar })
|
|
17
17
|
};
|
|
18
|
-
return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-sectioned-workspace-shell", className), children: [
|
|
18
|
+
return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-sectioned-workspace-shell", className), children: [_jsxs("aside", { className: "zvk-composite-sectioned-workspace-shell__sidebar", children: [_jsx(SectionedWorkspaceNavigation, { ...navigationProps, navLabel: navLabel, sections: sections }), sidebarFooter ? (_jsx("div", { className: "zvk-composite-sectioned-workspace-shell__sidebar-footer", children: sidebarFooter })) : null] }), _jsxs("div", { className: "zvk-composite-sectioned-workspace-shell__body", children: [hasHeader ? (_jsx(WorkspaceHeader, { ...headerProps, className: "zvk-composite-sectioned-workspace-shell__header", title: title ?? "" })) : null, _jsx("main", { className: "zvk-composite-sectioned-workspace-shell__content", children: children }), footer ? _jsx("footer", { className: "zvk-composite-sectioned-workspace-shell__footer", children: footer }) : null] })] }));
|
|
19
19
|
}
|
|
20
20
|
function SectionedWorkspaceNavigation({ activeItemId, navLabel, onItemSelect, sections }) {
|
|
21
21
|
return (_jsx(SectionedSidebarNav, { className: "zvk-composite-sectioned-workspace-shell__nav", label: navLabel, children: sections.map((section) => (_jsxs(SectionedSidebarNav.Section, { children: [_jsx(SectionedSidebarNav.SectionTitle, { children: section.label }), _jsx(SectionedSidebarNav.List, { children: section.items.map((item) => (_jsx(SectionedWorkspaceNavigationItem, { active: item.id === activeItemId, item: item, onItemSelect: onItemSelect }, item.id))) })] }, section.id))) }));
|