@zvk/composite 0.1.1
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 +17 -0
- package/LICENSE.md +3 -0
- package/README.md +12 -0
- package/dist/data/data-table-page-frame.d.ts +16 -0
- package/dist/data/data-table-page-frame.js +10 -0
- package/dist/forms/confirm-action-dialog.d.ts +17 -0
- package/dist/forms/confirm-action-dialog.js +21 -0
- package/dist/forms/form-surface.d.ts +11 -0
- package/dist/forms/form-surface.js +7 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +12 -0
- package/dist/layout/page-scaffold.d.ts +20 -0
- package/dist/layout/page-scaffold.js +19 -0
- package/dist/lists/entity-card.d.ts +17 -0
- package/dist/lists/entity-card.js +39 -0
- package/dist/lists/entity-list-section.d.ts +28 -0
- package/dist/lists/entity-list-section.js +8 -0
- package/dist/lists/settings-hub-list.d.ts +22 -0
- package/dist/lists/settings-hub-list.js +19 -0
- package/dist/lists/summary-metric-grid.d.ts +34 -0
- package/dist/lists/summary-metric-grid.js +9 -0
- package/dist/navigation/app-workspace-shell.d.ts +14 -0
- package/dist/navigation/app-workspace-shell.js +12 -0
- package/dist/navigation/sectioned-workspace-shell.d.ts +33 -0
- package/dist/navigation/sectioned-workspace-shell.js +36 -0
- package/dist/navigation/workspace-header.d.ts +25 -0
- package/dist/navigation/workspace-header.js +36 -0
- package/dist/state/state-surface.d.ts +21 -0
- package/dist/state/state-surface.js +25 -0
- package/dist/styles.css +1220 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +4 -0
- package/package.json +118 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# @zvk/composite Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.1](https://github.com/brandon-schabel/zvk/compare/composite-v0.1.0...composite-v0.1.1) (2026-06-16)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add composite component package ([dc0920f](https://github.com/brandon-schabel/zvk/commit/dc0920fe77dd2bd63015a40b3d7675fe8f1d0067))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* harden popup positioning ([efb8c8a](https://github.com/brandon-schabel/zvk/commit/efb8c8a98c2b759f4e84a60f5ae292b1e8900907))
|
|
14
|
+
|
|
15
|
+
## 0.1.0
|
|
16
|
+
|
|
17
|
+
- Initial package scaffold for composite workspace components.
|
package/LICENSE.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @zvk/composite
|
|
2
|
+
|
|
3
|
+
Drop-in composite React components built from public `@zvk/ui` primitives.
|
|
4
|
+
|
|
5
|
+
Import `@zvk/ui/styles.css` once in the app root, then import `@zvk/composite/styles.css` after it:
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import "@zvk/ui/styles.css";
|
|
9
|
+
import "@zvk/composite/styles.css";
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Components are UI-only and accept typed props, slots, and callbacks. They do not own routing, persistence, data fetching, authentication, billing, or business rules.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface DataTablePageFrameProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
3
|
+
bulkActions?: React.ReactNode;
|
|
4
|
+
description?: React.ReactNode;
|
|
5
|
+
empty?: React.ReactNode;
|
|
6
|
+
filters?: React.ReactNode;
|
|
7
|
+
footer?: React.ReactNode;
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
loadingLabel?: React.ReactNode;
|
|
10
|
+
pagination?: React.ReactNode;
|
|
11
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
12
|
+
search?: React.ReactNode;
|
|
13
|
+
table?: React.ReactNode;
|
|
14
|
+
title: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export declare function DataTablePageFrame({ bulkActions, className, description, empty, filters, footer, loading, loadingLabel, pagination, ref, search, table, title, ...props }: DataTablePageFrameProps): React.JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Card } from "@zvk/ui/card";
|
|
4
|
+
import { Table } from "@zvk/ui/table";
|
|
5
|
+
import { cn } from "../utils/cn.js";
|
|
6
|
+
export function DataTablePageFrame({ bulkActions, className, description, empty, filters, footer, loading = false, loadingLabel = "Loading data", pagination, ref, search, table, title, ...props }) {
|
|
7
|
+
const hasToolbar = Boolean(search || filters || bulkActions);
|
|
8
|
+
const hasFooter = Boolean(pagination || footer);
|
|
9
|
+
return (_jsxs("section", { ...props, ref: ref, className: cn("zvk-composite-data-table-page-frame", className), children: [_jsx("div", { className: "zvk-composite-data-table-page-frame__header", children: _jsxs("div", { className: "zvk-composite-data-table-page-frame__heading", children: [_jsx("h2", { className: "zvk-composite-data-table-page-frame__title", children: title }), description ? _jsx("p", { className: "zvk-composite-data-table-page-frame__description", children: description }) : null] }) }), _jsxs(Card, { className: "zvk-composite-data-table-page-frame__card", padding: "none", variant: "outline", children: [hasToolbar ? (_jsxs("div", { className: "zvk-composite-data-table-page-frame__toolbar", children: [search ? _jsx("div", { className: "zvk-composite-data-table-page-frame__search", children: search }) : null, filters ? _jsx("div", { className: "zvk-composite-data-table-page-frame__filters", children: filters }) : null, bulkActions ? (_jsx("div", { className: "zvk-composite-data-table-page-frame__bulk-actions", children: bulkActions })) : null] })) : null, _jsx(Card.Content, { className: "zvk-composite-data-table-page-frame__content", children: loading ? (_jsx("div", { className: "zvk-composite-data-table-page-frame__state", role: "status", children: loadingLabel })) : table ? (_jsx(Table.Container, { className: "zvk-composite-data-table-page-frame__table", children: table })) : empty ? (_jsx("div", { className: "zvk-composite-data-table-page-frame__state", children: empty })) : null }), hasFooter ? (_jsxs(Card.Footer, { className: "zvk-composite-data-table-page-frame__footer", children: [footer ? _jsx("div", { className: "zvk-composite-data-table-page-frame__footer-content", children: footer }) : null, pagination ? (_jsx("div", { className: "zvk-composite-data-table-page-frame__pagination", children: pagination })) : null] })) : null] })] }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type ConfirmActionDialogTone = "destructive" | "warning" | "primary";
|
|
3
|
+
export interface ConfirmActionDialogProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
4
|
+
cancelLabel?: React.ReactNode;
|
|
5
|
+
confirmLabel: React.ReactNode;
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
description: React.ReactNode;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
onConfirm: () => void;
|
|
10
|
+
onOpenChange?: (open: boolean) => void;
|
|
11
|
+
open?: boolean;
|
|
12
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
13
|
+
title: React.ReactNode;
|
|
14
|
+
tone?: ConfirmActionDialogTone;
|
|
15
|
+
trigger: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare function ConfirmActionDialog({ cancelLabel, className, confirmLabel, defaultOpen, description, disabled, onConfirm, onOpenChange, open, ref, title, tone, trigger, ...props }: ConfirmActionDialogProps): React.JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { AlertDialog } from "@zvk/ui/alert-dialog";
|
|
5
|
+
import { Button } from "@zvk/ui/button";
|
|
6
|
+
import { cn } from "../utils/cn.js";
|
|
7
|
+
function getConfirmVariant(tone) {
|
|
8
|
+
if (tone === "destructive") {
|
|
9
|
+
return "destructive";
|
|
10
|
+
}
|
|
11
|
+
return "primary";
|
|
12
|
+
}
|
|
13
|
+
export function ConfirmActionDialog({ cancelLabel = "Cancel", className, confirmLabel, defaultOpen, description, disabled = false, onConfirm, onOpenChange, open, ref, title, tone = "destructive", trigger, ...props }) {
|
|
14
|
+
const rootProps = {
|
|
15
|
+
...(defaultOpen !== undefined ? { defaultOpen } : {}),
|
|
16
|
+
...(onOpenChange ? { onOpenChange } : {}),
|
|
17
|
+
...(open !== undefined ? { open } : {})
|
|
18
|
+
};
|
|
19
|
+
const triggerContent = React.isValidElement(trigger) ? (trigger) : (_jsx(Button, { className: "zvk-composite-confirm-action-dialog__trigger", disabled: disabled, type: "button", variant: tone === "destructive" ? "destructive" : "primary", children: trigger }));
|
|
20
|
+
return (_jsxs(AlertDialog, { ...props, ...rootProps, ...(ref !== undefined ? { ref } : {}), className: cn("zvk-composite-confirm-action-dialog", className), "data-tone": tone, children: [_jsx(AlertDialog.Trigger, { asChild: true, disabled: disabled, children: triggerContent }), _jsxs(AlertDialog.Content, { className: "zvk-composite-confirm-action-dialog__content", children: [_jsx(AlertDialog.Title, { className: "zvk-composite-confirm-action-dialog__title", children: title }), _jsx(AlertDialog.Description, { className: "zvk-composite-confirm-action-dialog__description", children: description }), _jsxs(AlertDialog.Footer, { className: "zvk-composite-confirm-action-dialog__footer", children: [_jsx(AlertDialog.Cancel, { asChild: true, children: _jsx(Button, { type: "button", variant: "secondary", children: cancelLabel }) }), _jsx(AlertDialog.Action, { asChild: true, disabled: disabled, onClick: onConfirm, children: _jsx(Button, { className: "zvk-composite-confirm-action-dialog__confirm", disabled: disabled, type: "button", variant: getConfirmVariant(tone), children: confirmLabel }) })] })] })] }));
|
|
21
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface FormSurfaceProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>, "children" | "title"> {
|
|
3
|
+
actions?: React.ReactNode;
|
|
4
|
+
alert?: React.ReactNode;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
description?: React.ReactNode;
|
|
7
|
+
footer?: React.ReactNode;
|
|
8
|
+
ref?: React.Ref<HTMLFormElement>;
|
|
9
|
+
title: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export declare function FormSurface({ actions, alert, children, className, description, footer, ref, title, ...props }: FormSurfaceProps): React.JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Card } from "@zvk/ui/card";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
export function FormSurface({ actions, alert, children, className, description, footer, ref, title, ...props }) {
|
|
6
|
+
return (_jsx("form", { ...props, ref: ref, className: cn("zvk-composite-form-surface", className), children: _jsxs(Card, { className: "zvk-composite-form-surface__card", padding: "none", variant: "outline", children: [_jsxs(Card.Header, { className: "zvk-composite-form-surface__header", children: [_jsxs("div", { className: "zvk-composite-form-surface__heading", children: [_jsx(Card.Title, { className: "zvk-composite-form-surface__title", children: title }), description ? (_jsx(Card.Description, { className: "zvk-composite-form-surface__description", children: description })) : null] }), actions ? _jsx(Card.Action, { className: "zvk-composite-form-surface__actions", children: actions }) : null] }), alert ? _jsx("div", { className: "zvk-composite-form-surface__alert", children: alert }) : null, _jsx(Card.Content, { className: "zvk-composite-form-surface__content", children: children }), footer ? _jsx(Card.Footer, { className: "zvk-composite-form-surface__footer", children: footer }) : null] }) }));
|
|
7
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export { PageScaffold } from "./layout/page-scaffold.js";
|
|
2
|
+
export type { PageScaffoldMaxWidth, PageScaffoldProps } from "./layout/page-scaffold.js";
|
|
3
|
+
export { AppWorkspaceShell } from "./navigation/app-workspace-shell.js";
|
|
4
|
+
export type { AppWorkspaceShellProps } from "./navigation/app-workspace-shell.js";
|
|
5
|
+
export { BreadcrumbPageHeader, WorkspaceHeader } from "./navigation/workspace-header.js";
|
|
6
|
+
export type { BreadcrumbPageHeaderProps, BreadcrumbPageHeaderItem, WorkspaceHeaderAlign, WorkspaceHeaderHeadingLevel, WorkspaceHeaderProps } from "./navigation/workspace-header.js";
|
|
7
|
+
export { SectionedWorkspaceShell } from "./navigation/sectioned-workspace-shell.js";
|
|
8
|
+
export type { SectionedWorkspaceItem, SectionedWorkspaceSection, SectionedWorkspaceShellProps } from "./navigation/sectioned-workspace-shell.js";
|
|
9
|
+
export { StateSurface } from "./state/state-surface.js";
|
|
10
|
+
export type { StateSurfaceAlign, StateSurfaceProps, StateSurfaceSize, StateSurfaceState } from "./state/state-surface.js";
|
|
11
|
+
export { EntityCard } from "./lists/entity-card.js";
|
|
12
|
+
export type { EntityCardProps } from "./lists/entity-card.js";
|
|
13
|
+
export { EntityListSection } from "./lists/entity-list-section.js";
|
|
14
|
+
export type { EntityListSectionProps } from "./lists/entity-list-section.js";
|
|
15
|
+
export { SummaryMetricGrid } from "./lists/summary-metric-grid.js";
|
|
16
|
+
export type { SummaryMetric, SummaryMetricGridActionPosition, SummaryMetricGridColumns, SummaryMetricGridProps } from "./lists/summary-metric-grid.js";
|
|
17
|
+
export { SettingsHubList } from "./lists/settings-hub-list.js";
|
|
18
|
+
export type { SettingsHubItem, SettingsHubListProps } from "./lists/settings-hub-list.js";
|
|
19
|
+
export { ConfirmActionDialog } from "./forms/confirm-action-dialog.js";
|
|
20
|
+
export type { ConfirmActionDialogProps, ConfirmActionDialogTone } from "./forms/confirm-action-dialog.js";
|
|
21
|
+
export { FormSurface } from "./forms/form-surface.js";
|
|
22
|
+
export type { FormSurfaceProps } from "./forms/form-surface.js";
|
|
23
|
+
export { DataTablePageFrame } from "./data/data-table-page-frame.js";
|
|
24
|
+
export type { DataTablePageFrameProps } from "./data/data-table-page-frame.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { PageScaffold } from "./layout/page-scaffold.js";
|
|
2
|
+
export { AppWorkspaceShell } from "./navigation/app-workspace-shell.js";
|
|
3
|
+
export { BreadcrumbPageHeader, WorkspaceHeader } from "./navigation/workspace-header.js";
|
|
4
|
+
export { SectionedWorkspaceShell } from "./navigation/sectioned-workspace-shell.js";
|
|
5
|
+
export { StateSurface } from "./state/state-surface.js";
|
|
6
|
+
export { EntityCard } from "./lists/entity-card.js";
|
|
7
|
+
export { EntityListSection } from "./lists/entity-list-section.js";
|
|
8
|
+
export { SummaryMetricGrid } from "./lists/summary-metric-grid.js";
|
|
9
|
+
export { SettingsHubList } from "./lists/settings-hub-list.js";
|
|
10
|
+
export { ConfirmActionDialog } from "./forms/confirm-action-dialog.js";
|
|
11
|
+
export { FormSurface } from "./forms/form-surface.js";
|
|
12
|
+
export { DataTablePageFrame } from "./data/data-table-page-frame.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { WorkspaceHeaderAlign, WorkspaceHeaderHeadingLevel } from "../navigation/workspace-header.js";
|
|
3
|
+
export type PageScaffoldMaxWidth = "sm" | "md" | "lg" | "xl" | "full";
|
|
4
|
+
export interface PageScaffoldProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
5
|
+
actions?: React.ReactNode | undefined;
|
|
6
|
+
aside?: React.ReactNode | undefined;
|
|
7
|
+
children?: React.ReactNode | undefined;
|
|
8
|
+
description?: React.ReactNode | undefined;
|
|
9
|
+
eyebrow?: React.ReactNode | undefined;
|
|
10
|
+
footer?: React.ReactNode | undefined;
|
|
11
|
+
headerAlign?: WorkspaceHeaderAlign | undefined;
|
|
12
|
+
headingLevel?: WorkspaceHeaderHeadingLevel | undefined;
|
|
13
|
+
maxWidth?: PageScaffoldMaxWidth | undefined;
|
|
14
|
+
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
15
|
+
state?: React.ReactNode | undefined;
|
|
16
|
+
status?: React.ReactNode | undefined;
|
|
17
|
+
title?: React.ReactNode | undefined;
|
|
18
|
+
toolbar?: React.ReactNode | undefined;
|
|
19
|
+
}
|
|
20
|
+
export declare function PageScaffold({ actions, aside, children, className, description, eyebrow, footer, headerAlign, headingLevel, maxWidth, ref, state, status, title, toolbar, ...props }: PageScaffoldProps): React.JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
import { WorkspaceHeader } from "../navigation/workspace-header.js";
|
|
5
|
+
export function PageScaffold({ actions, aside, children, className, description, eyebrow, footer, headerAlign, headingLevel, maxWidth = "xl", ref, state, status, title, toolbar, ...props }) {
|
|
6
|
+
const hasTitle = title !== undefined && title !== null && title !== false;
|
|
7
|
+
const hasHeader = Boolean(hasTitle || actions || toolbar);
|
|
8
|
+
const hasAside = Boolean(aside);
|
|
9
|
+
const headerProps = {
|
|
10
|
+
...(actions === undefined ? {} : { actions }),
|
|
11
|
+
...(description === undefined ? {} : { description }),
|
|
12
|
+
...(eyebrow === undefined ? {} : { eyebrow }),
|
|
13
|
+
...(headerAlign === undefined ? {} : { align: headerAlign }),
|
|
14
|
+
...(headingLevel === undefined ? {} : { headingLevel }),
|
|
15
|
+
...(status === undefined ? {} : { status }),
|
|
16
|
+
...(toolbar === undefined ? {} : { toolbar })
|
|
17
|
+
};
|
|
18
|
+
return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-page-scaffold", className), "data-max-width": maxWidth, "data-with-aside": hasAside ? "true" : "false", children: [hasTitle ? (_jsx(WorkspaceHeader, { ...headerProps, className: "zvk-composite-page-scaffold__header", title: title })) : hasHeader ? (_jsxs("div", { className: "zvk-composite-page-scaffold__header zvk-composite-page-scaffold__header--controls-only", children: [toolbar ? _jsx("div", { className: "zvk-composite-page-scaffold__toolbar", children: toolbar }) : null, actions ? _jsx("div", { className: "zvk-composite-page-scaffold__actions", children: actions }) : null] })) : null, state ? _jsx("div", { className: "zvk-composite-page-scaffold__state", children: state }) : null, _jsxs("div", { className: "zvk-composite-page-scaffold__grid", children: [_jsx("main", { className: "zvk-composite-page-scaffold__main", children: children }), hasAside ? _jsx("aside", { className: "zvk-composite-page-scaffold__aside", children: aside }) : null] }), footer ? _jsx("footer", { className: "zvk-composite-page-scaffold__footer", children: footer }) : null] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface EntityCardProps extends Omit<React.HTMLAttributes<HTMLElement>, "title" | "onSelect"> {
|
|
3
|
+
title: React.ReactNode;
|
|
4
|
+
description?: React.ReactNode;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
badges?: React.ReactNode;
|
|
7
|
+
meta?: React.ReactNode;
|
|
8
|
+
actions?: React.ReactNode;
|
|
9
|
+
href?: string;
|
|
10
|
+
onSelect?: () => void;
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
loading?: boolean;
|
|
14
|
+
error?: React.ReactNode;
|
|
15
|
+
ref?: React.Ref<HTMLElement>;
|
|
16
|
+
}
|
|
17
|
+
export declare function EntityCard({ actions, badges, className, description, disabled, error, href, icon, loading, meta, onSelect, ref, selected, title, ...props }: EntityCardProps): React.JSX.Element;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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 EntityCard({ actions, badges, className, description, disabled = false, error, href, icon, loading = false, meta, onSelect, ref, selected = false, title, ...props }) {
|
|
9
|
+
const interactive = Boolean(href || onSelect);
|
|
10
|
+
const classNames = cn("zvk-composite-entity-card", className);
|
|
11
|
+
const { onClick, ...restProps } = props;
|
|
12
|
+
const content = (_jsxs(_Fragment, { children: [hasValue(icon) ? _jsx("div", { className: "zvk-composite-entity-card__icon", children: icon }) : null, _jsxs("div", { className: "zvk-composite-entity-card__body", children: [_jsxs("div", { className: "zvk-composite-entity-card__heading", children: [_jsx("h3", { className: "zvk-composite-entity-card__title", children: title }), hasValue(badges) ? _jsx("div", { className: "zvk-composite-entity-card__badges", children: badges }) : null] }), hasValue(description) ? _jsx("p", { className: "zvk-composite-entity-card__description", children: description }) : null, hasValue(meta) ? _jsx("div", { className: "zvk-composite-entity-card__meta", children: meta }) : null, hasValue(error) ? _jsx("div", { className: "zvk-composite-entity-card__error", children: error }) : null] }), loading ? (_jsx("div", { className: "zvk-composite-entity-card__status", children: _jsx(Spinner, { label: "Loading", size: "sm", tone: "muted" }) })) : null, hasValue(actions) ? _jsx("div", { className: "zvk-composite-entity-card__actions", children: actions }) : null] }));
|
|
13
|
+
const sharedProps = {
|
|
14
|
+
...restProps,
|
|
15
|
+
"aria-busy": loading ? true : props["aria-busy"],
|
|
16
|
+
"aria-current": selected ? "true" : props["aria-current"],
|
|
17
|
+
"aria-disabled": disabled ? true : props["aria-disabled"],
|
|
18
|
+
className: classNames
|
|
19
|
+
};
|
|
20
|
+
if (href) {
|
|
21
|
+
const handleAnchorClick = (event) => {
|
|
22
|
+
onClick?.(event);
|
|
23
|
+
if (disabled) {
|
|
24
|
+
event.preventDefault();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
return (_jsx("a", { ...sharedProps, "data-disabled": disabled ? "" : undefined, "data-interactive": interactive ? "" : undefined, "data-loading": loading ? "" : undefined, "data-selected": selected ? "" : undefined, href: href, onClick: handleAnchorClick, ref: ref, children: content }));
|
|
28
|
+
}
|
|
29
|
+
if (onSelect) {
|
|
30
|
+
const handleButtonClick = (event) => {
|
|
31
|
+
onClick?.(event);
|
|
32
|
+
if (!disabled) {
|
|
33
|
+
onSelect();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
return (_jsx("button", { ...sharedProps, "data-disabled": disabled ? "" : undefined, "data-interactive": interactive ? "" : undefined, "data-loading": loading ? "" : undefined, "data-selected": selected ? "" : undefined, disabled: disabled, onClick: handleButtonClick, ref: ref, type: "button", children: content }));
|
|
37
|
+
}
|
|
38
|
+
return (_jsx("article", { ...sharedProps, "data-disabled": disabled ? "" : undefined, "data-interactive": interactive ? "" : undefined, "data-loading": loading ? "" : undefined, "data-selected": selected ? "" : undefined, ref: ref, children: content }));
|
|
39
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface EntityListSectionProps<T> extends Omit<React.ComponentPropsWithoutRef<"section">, "title" | "children"> {
|
|
3
|
+
title: React.ReactNode;
|
|
4
|
+
description?: React.ReactNode;
|
|
5
|
+
toolbar?: React.ReactNode;
|
|
6
|
+
actions?: React.ReactNode;
|
|
7
|
+
empty?: React.ReactNode;
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
loadingLabel?: React.ReactNode;
|
|
10
|
+
footer?: React.ReactNode;
|
|
11
|
+
classNames?: {
|
|
12
|
+
header?: string;
|
|
13
|
+
copy?: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
actions?: string;
|
|
17
|
+
toolbar?: string;
|
|
18
|
+
list?: string;
|
|
19
|
+
item?: string;
|
|
20
|
+
state?: string;
|
|
21
|
+
footer?: string;
|
|
22
|
+
};
|
|
23
|
+
items: readonly T[];
|
|
24
|
+
getItemKey: (item: T, index: number) => React.Key;
|
|
25
|
+
renderItem: (item: T, index: number) => React.ReactNode;
|
|
26
|
+
ref?: React.Ref<HTMLElement>;
|
|
27
|
+
}
|
|
28
|
+
export declare function EntityListSection<T>({ actions, className, classNames, description, empty, footer, getItemKey, items, loading, loadingLabel, ref, renderItem, title, toolbar, ...props }: EntityListSectionProps<T>): React.JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { StateSurface } from "../state/state-surface.js";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
export function EntityListSection({ actions, className, classNames, description, empty, footer, getItemKey, items, loading = false, loadingLabel = "Loading", ref, renderItem, title, toolbar, ...props }) {
|
|
6
|
+
const hasItems = items.length > 0;
|
|
7
|
+
return (_jsxs("section", { ...props, ref: ref, className: cn("zvk-composite-entity-list-section", className), children: [_jsxs("div", { className: cn("zvk-composite-entity-list-section__header", classNames?.header), children: [_jsxs("div", { className: cn("zvk-composite-entity-list-section__copy", classNames?.copy), children: [_jsx("h2", { className: cn("zvk-composite-entity-list-section__title", classNames?.title), children: title }), description ? _jsx("p", { className: cn("zvk-composite-entity-list-section__description", classNames?.description), children: description }) : null] }), actions ? _jsx("div", { className: cn("zvk-composite-entity-list-section__actions", classNames?.actions), children: actions }) : null] }), toolbar ? _jsx("div", { className: cn("zvk-composite-entity-list-section__toolbar", classNames?.toolbar), children: toolbar }) : null, loading ? (_jsx(StateSurface, { align: "center", className: cn("zvk-composite-entity-list-section__state", classNames?.state), size: "sm", state: "loading", title: loadingLabel })) : hasItems ? (_jsx("ul", { className: cn("zvk-composite-entity-list-section__list", classNames?.list), children: items.map((item, index) => (_jsx("li", { className: cn("zvk-composite-entity-list-section__item", classNames?.item), children: renderItem(item, index) }, getItemKey(item, index)))) })) : (empty ?? (_jsx(StateSurface, { align: "center", className: cn("zvk-composite-entity-list-section__state", classNames?.state), size: "sm", state: "empty", title: "No items" }))), footer ? _jsx("div", { className: cn("zvk-composite-entity-list-section__footer", classNames?.footer), children: footer }) : null] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface SettingsHubListItem {
|
|
3
|
+
id: React.Key;
|
|
4
|
+
title: React.ReactNode;
|
|
5
|
+
description?: React.ReactNode;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
badge?: React.ReactNode;
|
|
8
|
+
meta?: React.ReactNode;
|
|
9
|
+
href?: string;
|
|
10
|
+
onSelect?: () => void;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type SettingsHubItem = SettingsHubListItem;
|
|
14
|
+
export interface SettingsHubListProps extends Omit<React.ComponentPropsWithoutRef<"section">, "title" | "children"> {
|
|
15
|
+
items: readonly SettingsHubListItem[];
|
|
16
|
+
title?: React.ReactNode;
|
|
17
|
+
description?: React.ReactNode;
|
|
18
|
+
actions?: React.ReactNode;
|
|
19
|
+
empty?: React.ReactNode;
|
|
20
|
+
ref?: React.Ref<HTMLElement>;
|
|
21
|
+
}
|
|
22
|
+
export declare function SettingsHubList({ actions, className, description, empty, items, ref, title, ...props }: SettingsHubListProps): React.JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
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 { EntityCard } from "./entity-card.js";
|
|
5
|
+
import { StateSurface } from "../state/state-surface.js";
|
|
6
|
+
import { cn } from "../utils/cn.js";
|
|
7
|
+
function renderBadge(badge) {
|
|
8
|
+
if (badge === null || badge === undefined || badge === false) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
if (React.isValidElement(badge)) {
|
|
12
|
+
return badge;
|
|
13
|
+
}
|
|
14
|
+
return _jsx(Badge, { children: badge });
|
|
15
|
+
}
|
|
16
|
+
export function SettingsHubList({ actions, className, description, empty, items, ref, title, ...props }) {
|
|
17
|
+
const showHeader = title !== undefined || description !== undefined || actions !== undefined;
|
|
18
|
+
return (_jsxs("section", { ...props, ref: ref, className: cn("zvk-composite-settings-hub-list", className), children: [showHeader ? (_jsxs("div", { className: "zvk-composite-settings-hub-list__header", children: [_jsxs("div", { className: "zvk-composite-settings-hub-list__copy", children: [title ? _jsx("h2", { className: "zvk-composite-settings-hub-list__title", children: title }) : null, description ? _jsx("p", { className: "zvk-composite-settings-hub-list__description", children: description }) : null] }), actions ? _jsx("div", { className: "zvk-composite-settings-hub-list__actions", children: actions }) : null] })) : null, items.length > 0 ? (_jsx("ul", { className: "zvk-composite-settings-hub-list__list", children: items.map((item) => (_jsx("li", { className: "zvk-composite-settings-hub-list__item", children: _jsx(EntityCard, { badges: renderBadge(item.badge), description: item.description, icon: item.icon, meta: item.meta, title: item.title, ...(item.disabled === undefined ? {} : { disabled: item.disabled }), ...(item.href === undefined ? {} : { href: item.href }), ...(item.onSelect === undefined ? {} : { onSelect: item.onSelect }) }) }, item.id))) })) : (empty ?? (_jsx(StateSurface, { align: "center", className: "zvk-composite-settings-hub-list__empty", size: "sm", state: "empty", title: "No settings" })))] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type StatTone } from "@zvk/ui/stat";
|
|
3
|
+
export type SummaryMetricGridColumns = 1 | 2 | 3 | 4;
|
|
4
|
+
export type SummaryMetricGridActionPosition = "footer" | "top";
|
|
5
|
+
export interface SummaryMetric {
|
|
6
|
+
id: React.Key;
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
value: React.ReactNode;
|
|
9
|
+
description?: React.ReactNode;
|
|
10
|
+
trend?: React.ReactNode;
|
|
11
|
+
tone?: StatTone;
|
|
12
|
+
action?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export interface SummaryMetricGridProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
15
|
+
metrics: readonly SummaryMetric[];
|
|
16
|
+
title?: React.ReactNode;
|
|
17
|
+
description?: React.ReactNode;
|
|
18
|
+
actions?: React.ReactNode;
|
|
19
|
+
columns?: SummaryMetricGridColumns;
|
|
20
|
+
actionPosition?: SummaryMetricGridActionPosition;
|
|
21
|
+
classNames?: {
|
|
22
|
+
header?: string;
|
|
23
|
+
copy?: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
actions?: string;
|
|
27
|
+
metrics?: string;
|
|
28
|
+
card?: string;
|
|
29
|
+
stat?: string;
|
|
30
|
+
action?: string;
|
|
31
|
+
};
|
|
32
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
33
|
+
}
|
|
34
|
+
export declare function SummaryMetricGrid({ actionPosition, actions, className, classNames, columns, description, metrics, ref, title, ...props }: SummaryMetricGridProps): React.JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Card } from "@zvk/ui/card";
|
|
4
|
+
import { Stat } from "@zvk/ui/stat";
|
|
5
|
+
import { cn } from "../utils/cn.js";
|
|
6
|
+
export function SummaryMetricGrid({ actionPosition = "footer", actions, className, classNames, columns = 4, description, metrics, ref, title, ...props }) {
|
|
7
|
+
const showHeader = title !== undefined || description !== undefined || actions !== undefined;
|
|
8
|
+
return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-summary-metric-grid", className), "data-columns": columns, children: [showHeader ? (_jsxs("div", { className: cn("zvk-composite-summary-metric-grid__header", classNames?.header), children: [_jsxs("div", { className: cn("zvk-composite-summary-metric-grid__copy", classNames?.copy), children: [title ? _jsx("h2", { className: cn("zvk-composite-summary-metric-grid__title", classNames?.title), children: title }) : null, description ? _jsx("p", { className: cn("zvk-composite-summary-metric-grid__description", classNames?.description), children: description }) : null] }), actions ? _jsx("div", { className: cn("zvk-composite-summary-metric-grid__actions", classNames?.actions), children: actions }) : null] })) : null, _jsx("div", { className: cn("zvk-composite-summary-metric-grid__metrics", classNames?.metrics), children: metrics.map((metric) => (_jsxs(Card, { className: cn("zvk-composite-summary-metric-grid__card", classNames?.card), "data-action-position": actionPosition, padding: "none", variant: "outline", children: [metric.action && actionPosition === "top" ? (_jsx("div", { className: cn("zvk-composite-summary-metric-grid__action", classNames?.action), "data-position": "top", children: metric.action })) : null, _jsx(Stat, { className: cn("zvk-composite-summary-metric-grid__stat", classNames?.stat), description: metric.description, label: metric.label, trend: metric.trend, value: metric.value, ...(metric.tone === undefined ? {} : { tone: metric.tone }) }), metric.action && actionPosition === "footer" ? (_jsx("div", { className: cn("zvk-composite-summary-metric-grid__action", classNames?.action), "data-position": "footer", children: metric.action })) : null] }, metric.id))) })] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface AppWorkspaceShellProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
accountMenu?: React.ReactNode | undefined;
|
|
4
|
+
brand: React.ReactNode;
|
|
5
|
+
children?: React.ReactNode | undefined;
|
|
6
|
+
commandPalette?: React.ReactNode | undefined;
|
|
7
|
+
footer?: React.ReactNode | undefined;
|
|
8
|
+
header?: React.ReactNode | undefined;
|
|
9
|
+
mobileNavigationLabel?: string | undefined;
|
|
10
|
+
navigation: React.ReactNode;
|
|
11
|
+
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
12
|
+
workspaceSwitcher?: React.ReactNode | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function AppWorkspaceShell({ accountMenu, brand, children, className, commandPalette, footer, header, mobileNavigationLabel, navigation, ref, workspaceSwitcher, ...props }: AppWorkspaceShellProps): React.JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { SidebarShell } from "@zvk/ui/sidebar-shell";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
export function AppWorkspaceShell({ accountMenu, brand, children, className, commandPalette, footer, header, mobileNavigationLabel = "Navigation", navigation, ref, workspaceSwitcher, ...props }) {
|
|
6
|
+
const hasTopbar = Boolean(header || commandPalette || workspaceSwitcher || accountMenu);
|
|
7
|
+
const shellProps = {
|
|
8
|
+
...props,
|
|
9
|
+
...(ref === undefined ? {} : { ref })
|
|
10
|
+
};
|
|
11
|
+
return (_jsxs(SidebarShell, { ...shellProps, className: cn("zvk-composite-app-workspace-shell", className), width: "md", children: [_jsxs(SidebarShell.Sidebar, { className: "zvk-composite-app-workspace-shell__sidebar", "aria-label": "Workspace", children: [_jsx("div", { className: "zvk-composite-app-workspace-shell__brand", children: brand }), workspaceSwitcher ? (_jsx("div", { className: "zvk-composite-app-workspace-shell__workspace-switcher", children: workspaceSwitcher })) : null, _jsx("div", { className: "zvk-composite-app-workspace-shell__navigation", children: navigation })] }), _jsxs(SidebarShell.Main, { className: "zvk-composite-app-workspace-shell__main", children: [_jsxs("details", { className: "zvk-composite-app-workspace-shell__mobile-nav", children: [_jsx("summary", { className: "zvk-composite-app-workspace-shell__mobile-nav-summary", children: mobileNavigationLabel }), _jsxs("div", { className: "zvk-composite-app-workspace-shell__mobile-nav-content", children: [_jsxs("div", { className: "zvk-composite-app-workspace-shell__mobile-nav-context", children: [_jsx("div", { className: "zvk-composite-app-workspace-shell__brand", children: brand }), workspaceSwitcher ? (_jsx("div", { className: "zvk-composite-app-workspace-shell__workspace-switcher", children: workspaceSwitcher })) : null] }), navigation] })] }), hasTopbar ? (_jsxs(SidebarShell.Header, { className: "zvk-composite-app-workspace-shell__header", children: [header ? _jsx("div", { className: "zvk-composite-app-workspace-shell__header-content", children: header }) : null, commandPalette ? (_jsx("div", { className: "zvk-composite-app-workspace-shell__command-palette", children: commandPalette })) : null, accountMenu ? _jsx("div", { className: "zvk-composite-app-workspace-shell__account-menu", children: accountMenu }) : null] })) : null, _jsx(SidebarShell.Content, { className: "zvk-composite-app-workspace-shell__content", children: children }), footer ? (_jsx(SidebarShell.Footer, { className: "zvk-composite-app-workspace-shell__footer", children: footer })) : null] })] }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { WorkspaceHeaderHeadingLevel } from "./workspace-header.js";
|
|
3
|
+
export interface SectionedWorkspaceShellItem {
|
|
4
|
+
badge?: React.ReactNode | undefined;
|
|
5
|
+
description?: React.ReactNode | undefined;
|
|
6
|
+
disabled?: boolean | undefined;
|
|
7
|
+
href?: string | undefined;
|
|
8
|
+
icon?: React.ReactNode | undefined;
|
|
9
|
+
id: string;
|
|
10
|
+
label: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export interface SectionedWorkspaceShellSection {
|
|
13
|
+
id: string;
|
|
14
|
+
items: SectionedWorkspaceShellItem[];
|
|
15
|
+
label: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export interface SectionedWorkspaceShellProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
18
|
+
actions?: React.ReactNode | undefined;
|
|
19
|
+
activeItemId?: string | undefined;
|
|
20
|
+
children?: React.ReactNode | undefined;
|
|
21
|
+
description?: React.ReactNode | undefined;
|
|
22
|
+
footer?: React.ReactNode | undefined;
|
|
23
|
+
headingLevel?: WorkspaceHeaderHeadingLevel | undefined;
|
|
24
|
+
navLabel?: string | undefined;
|
|
25
|
+
onItemSelect?: ((itemId: string) => void) | undefined;
|
|
26
|
+
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
27
|
+
sections: SectionedWorkspaceShellSection[];
|
|
28
|
+
title?: React.ReactNode | undefined;
|
|
29
|
+
toolbar?: React.ReactNode | undefined;
|
|
30
|
+
}
|
|
31
|
+
export type SectionedWorkspaceItem = SectionedWorkspaceShellItem;
|
|
32
|
+
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;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { SectionedSidebarNav } from "@zvk/ui/sectioned-sidebar-nav";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
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 }) {
|
|
7
|
+
const hasHeader = Boolean(title || description || actions || toolbar);
|
|
8
|
+
const navigationProps = {
|
|
9
|
+
...(activeItemId === undefined ? {} : { activeItemId }),
|
|
10
|
+
...(onItemSelect === undefined ? {} : { onItemSelect })
|
|
11
|
+
};
|
|
12
|
+
const headerProps = {
|
|
13
|
+
...(actions === undefined ? {} : { actions }),
|
|
14
|
+
...(description === undefined ? {} : { description }),
|
|
15
|
+
...(headingLevel === undefined ? {} : { headingLevel }),
|
|
16
|
+
...(toolbar === undefined ? {} : { toolbar })
|
|
17
|
+
};
|
|
18
|
+
return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-sectioned-workspace-shell", className), children: [_jsx("aside", { className: "zvk-composite-sectioned-workspace-shell__sidebar", children: _jsx(SectionedWorkspaceNavigation, { ...navigationProps, navLabel: navLabel, sections: sections }) }), _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
|
+
}
|
|
20
|
+
function SectionedWorkspaceNavigation({ activeItemId, navLabel, onItemSelect, sections }) {
|
|
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))) }));
|
|
22
|
+
}
|
|
23
|
+
function SectionedWorkspaceNavigationItem({ active, item, onItemSelect }) {
|
|
24
|
+
const content = (_jsxs("span", { className: "zvk-composite-sectioned-workspace-shell__nav-item-content", children: [_jsx("span", { className: "zvk-composite-sectioned-workspace-shell__nav-item-label", children: item.label }), item.description ? (_jsx("span", { className: "zvk-composite-sectioned-workspace-shell__nav-item-description", children: item.description })) : null] }));
|
|
25
|
+
const handleSelect = () => onItemSelect?.(item.id);
|
|
26
|
+
const itemProps = {
|
|
27
|
+
...(item.badge === undefined ? {} : { badge: item.badge }),
|
|
28
|
+
...(item.disabled === undefined ? {} : { disabled: item.disabled }),
|
|
29
|
+
...(item.icon === undefined ? {} : { icon: item.icon }),
|
|
30
|
+
onClick: handleSelect
|
|
31
|
+
};
|
|
32
|
+
if (item.href) {
|
|
33
|
+
return (_jsx(SectionedSidebarNav.Item, { ...itemProps, active: active, href: item.href, children: content }));
|
|
34
|
+
}
|
|
35
|
+
return (_jsx(SectionedSidebarNav.Item, { ...itemProps, active: active, children: content }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type WorkspaceHeaderAlign = "start" | "center";
|
|
3
|
+
export type WorkspaceHeaderHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
4
|
+
export interface WorkspaceHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
|
|
5
|
+
actions?: React.ReactNode | undefined;
|
|
6
|
+
align?: WorkspaceHeaderAlign | undefined;
|
|
7
|
+
description?: React.ReactNode | undefined;
|
|
8
|
+
eyebrow?: React.ReactNode | undefined;
|
|
9
|
+
headingLevel?: WorkspaceHeaderHeadingLevel | undefined;
|
|
10
|
+
meta?: React.ReactNode | undefined;
|
|
11
|
+
ref?: React.Ref<HTMLElement> | undefined;
|
|
12
|
+
status?: React.ReactNode | undefined;
|
|
13
|
+
title: React.ReactNode;
|
|
14
|
+
toolbar?: React.ReactNode | undefined;
|
|
15
|
+
}
|
|
16
|
+
export interface BreadcrumbPageHeaderItem {
|
|
17
|
+
current?: boolean | undefined;
|
|
18
|
+
href?: string | undefined;
|
|
19
|
+
label: React.ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export interface BreadcrumbPageHeaderProps extends Omit<WorkspaceHeaderProps, "eyebrow"> {
|
|
22
|
+
breadcrumbs: BreadcrumbPageHeaderItem[];
|
|
23
|
+
}
|
|
24
|
+
export declare function WorkspaceHeader({ actions, align, className, description, eyebrow, headingLevel, meta, ref, status, title, toolbar, ...props }: WorkspaceHeaderProps): React.JSX.Element;
|
|
25
|
+
export declare function BreadcrumbPageHeader({ breadcrumbs, className, ...headerProps }: BreadcrumbPageHeaderProps): React.JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Breadcrumbs } from "@zvk/ui/breadcrumbs";
|
|
4
|
+
import { cn } from "../utils/cn.js";
|
|
5
|
+
function getHeadingTag(headingLevel) {
|
|
6
|
+
switch (headingLevel) {
|
|
7
|
+
case 1:
|
|
8
|
+
return "h1";
|
|
9
|
+
case 2:
|
|
10
|
+
return "h2";
|
|
11
|
+
case 3:
|
|
12
|
+
return "h3";
|
|
13
|
+
case 4:
|
|
14
|
+
return "h4";
|
|
15
|
+
case 5:
|
|
16
|
+
return "h5";
|
|
17
|
+
case 6:
|
|
18
|
+
return "h6";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function WorkspaceHeader({ actions, align = "start", className, description, eyebrow, headingLevel = 1, meta, ref, status, title, toolbar, ...props }) {
|
|
22
|
+
const hasKicker = Boolean(eyebrow || status);
|
|
23
|
+
const hasBody = Boolean(description || meta);
|
|
24
|
+
const hasControls = Boolean(actions || toolbar);
|
|
25
|
+
const Heading = getHeadingTag(headingLevel);
|
|
26
|
+
return (_jsxs("header", { ...props, ref: ref, className: cn("zvk-composite-workspace-header", className), "data-align": align, children: [_jsxs("div", { className: "zvk-composite-workspace-header__content", children: [hasKicker ? (_jsxs("div", { className: "zvk-composite-workspace-header__kicker", children: [eyebrow ? _jsx("span", { className: "zvk-composite-workspace-header__eyebrow", children: eyebrow }) : null, status ? _jsx("span", { className: "zvk-composite-workspace-header__status", children: status }) : null] })) : null, _jsx(Heading, { className: "zvk-composite-workspace-header__title", children: title }), hasBody ? (_jsxs("div", { className: "zvk-composite-workspace-header__body", children: [description ? _jsx("p", { className: "zvk-composite-workspace-header__description", children: description }) : null, meta ? _jsx("div", { className: "zvk-composite-workspace-header__meta", children: meta }) : null] })) : null] }), hasControls ? (_jsxs("div", { className: "zvk-composite-workspace-header__controls", children: [toolbar ? _jsx("div", { className: "zvk-composite-workspace-header__toolbar", children: toolbar }) : null, actions ? _jsx("div", { className: "zvk-composite-workspace-header__actions", children: actions }) : null] })) : null] }));
|
|
27
|
+
}
|
|
28
|
+
export function BreadcrumbPageHeader({ breadcrumbs, className, ...headerProps }) {
|
|
29
|
+
return (_jsxs("div", { className: cn("zvk-composite-breadcrumb-page-header", className), children: [_jsx(Breadcrumbs, { children: breadcrumbs.map((breadcrumb, index) => {
|
|
30
|
+
const breadcrumbProps = {
|
|
31
|
+
...(breadcrumb.current === undefined ? {} : { current: breadcrumb.current }),
|
|
32
|
+
...(breadcrumb.href === undefined ? {} : { href: breadcrumb.href })
|
|
33
|
+
};
|
|
34
|
+
return (_jsx(Breadcrumbs.Item, { ...breadcrumbProps, children: breadcrumb.label }, `${String(breadcrumb.label)}-${index}`));
|
|
35
|
+
}) }), _jsx(WorkspaceHeader, { ...headerProps, className: "zvk-composite-breadcrumb-page-header__header" })] }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type StateSurfaceState = "loading" | "empty" | "error" | "not-found" | "permission" | "search-empty" | "success";
|
|
3
|
+
export type StateSurfaceSize = "sm" | "md" | "lg";
|
|
4
|
+
export type StateSurfaceAlign = "start" | "center";
|
|
5
|
+
export interface StateSurfaceClassNames {
|
|
6
|
+
emptyState?: string;
|
|
7
|
+
footer?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface StateSurfaceProps extends Omit<React.ComponentPropsWithoutRef<"section">, "title"> {
|
|
10
|
+
state: StateSurfaceState;
|
|
11
|
+
title: React.ReactNode;
|
|
12
|
+
description?: React.ReactNode;
|
|
13
|
+
icon?: React.ReactNode;
|
|
14
|
+
actions?: React.ReactNode;
|
|
15
|
+
footer?: React.ReactNode;
|
|
16
|
+
classNames?: StateSurfaceClassNames;
|
|
17
|
+
size?: StateSurfaceSize;
|
|
18
|
+
align?: StateSurfaceAlign;
|
|
19
|
+
ref?: React.Ref<HTMLElement>;
|
|
20
|
+
}
|
|
21
|
+
export declare function StateSurface({ actions, align, className, classNames, description, footer, icon, ref, size, state, title, ...props }: StateSurfaceProps): React.JSX.Element;
|