@zvk/composite 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +450 -0
  3. package/dist/activity/activity-feed.d.ts +27 -0
  4. package/dist/activity/activity-feed.js +30 -0
  5. package/dist/ai/conversation-directory.d.ts +31 -0
  6. package/dist/ai/conversation-directory.js +44 -0
  7. package/dist/ai/provider-model-selector.d.ts +31 -0
  8. package/dist/ai/provider-model-selector.js +41 -0
  9. package/dist/ai/sticky-composer.d.ts +14 -0
  10. package/dist/ai/sticky-composer.js +13 -0
  11. package/dist/data/data-table-control-bar.d.ts +13 -0
  12. package/dist/data/data-table-control-bar.js +11 -0
  13. package/dist/detail/detail-inspector-panel.d.ts +21 -0
  14. package/dist/detail/detail-inspector-panel.js +18 -0
  15. package/dist/domains/activity.d.ts +2 -0
  16. package/dist/domains/activity.js +1 -0
  17. package/dist/domains/ai.d.ts +6 -0
  18. package/dist/domains/ai.js +3 -0
  19. package/dist/domains/data.d.ts +10 -0
  20. package/dist/domains/data.js +5 -0
  21. package/dist/domains/detail.d.ts +2 -0
  22. package/dist/domains/detail.js +1 -0
  23. package/dist/domains/forms.d.ts +4 -0
  24. package/dist/domains/forms.js +2 -0
  25. package/dist/domains/navigation.d.ts +10 -0
  26. package/dist/domains/navigation.js +5 -0
  27. package/dist/domains/settings.d.ts +6 -0
  28. package/dist/domains/settings.js +3 -0
  29. package/dist/domains/shell.d.ts +6 -0
  30. package/dist/domains/shell.js +3 -0
  31. package/dist/domains/state.d.ts +4 -0
  32. package/dist/domains/state.js +2 -0
  33. package/dist/domains/workflow.d.ts +6 -0
  34. package/dist/domains/workflow.js +3 -0
  35. package/dist/index.d.ts +10 -24
  36. package/dist/index.js +10 -12
  37. package/dist/integrations/integration-status-card.d.ts +20 -0
  38. package/dist/integrations/integration-status-card.js +15 -0
  39. package/dist/layout/feature-shell.d.ts +13 -0
  40. package/dist/layout/feature-shell.js +7 -0
  41. package/dist/navigation/command-palette-shell.d.ts +31 -0
  42. package/dist/navigation/command-palette-shell.js +45 -0
  43. package/dist/navigation/entity-switcher-menu.d.ts +38 -0
  44. package/dist/navigation/entity-switcher-menu.js +56 -0
  45. package/dist/navigation/link-action.d.ts +11 -0
  46. package/dist/navigation/link-action.js +41 -0
  47. package/dist/navigation/sectioned-workspace-shell.d.ts +2 -1
  48. package/dist/navigation/sectioned-workspace-shell.js +2 -2
  49. package/dist/settings/parameter-editor.d.ts +27 -0
  50. package/dist/settings/parameter-editor.js +12 -0
  51. package/dist/settings/settings-section-stack.d.ts +20 -0
  52. package/dist/settings/settings-section-stack.js +10 -0
  53. package/dist/state/route-state-frame.d.ts +10 -0
  54. package/dist/state/route-state-frame.js +31 -0
  55. package/dist/styles.css +2120 -81
  56. package/dist/workflows/process-list-panel.d.ts +26 -0
  57. package/dist/workflows/process-list-panel.js +24 -0
  58. package/dist/workflows/workflow-status-card.d.ts +20 -0
  59. package/dist/workflows/workflow-status-card.js +46 -0
  60. package/package.json +112 -17
@@ -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: [_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] })] }));
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))) }));
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ export type ParameterEditorDensity = "compact" | "default";
3
+ export interface ParameterEditorGroup {
4
+ readonly id: string;
5
+ readonly title?: React.ReactNode;
6
+ readonly description?: React.ReactNode;
7
+ readonly rows: readonly ParameterEditorRow[];
8
+ }
9
+ export interface ParameterEditorRow {
10
+ readonly id: string;
11
+ readonly label: React.ReactNode;
12
+ readonly description?: React.ReactNode;
13
+ readonly value?: React.ReactNode;
14
+ readonly control: React.ReactNode;
15
+ readonly actions?: React.ReactNode;
16
+ readonly changed?: boolean;
17
+ readonly invalid?: boolean;
18
+ readonly disabled?: boolean;
19
+ }
20
+ export interface ParameterEditorProps extends React.HTMLAttributes<HTMLDivElement> {
21
+ readonly groups: readonly ParameterEditorGroup[];
22
+ readonly density?: ParameterEditorDensity;
23
+ readonly resetAllAction?: React.ReactNode;
24
+ readonly footer?: React.ReactNode;
25
+ readonly ref?: React.Ref<HTMLDivElement>;
26
+ }
27
+ export declare function ParameterEditor({ className, density, footer, groups, ref, resetAllAction, ...props }: ParameterEditorProps): 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 { cn } from "../utils/cn.js";
4
+ function hasValue(value) {
5
+ return value !== null && value !== undefined && value !== false;
6
+ }
7
+ function shouldRenderGroup(group) {
8
+ return hasValue(group.title) || hasValue(group.description) || group.rows.length > 0;
9
+ }
10
+ export function ParameterEditor({ className, density = "default", footer, groups, ref, resetAllAction, ...props }) {
11
+ return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-parameter-editor", className), "data-density": density, children: [hasValue(resetAllAction) ? (_jsx("div", { className: "zvk-composite-parameter-editor__toolbar", children: resetAllAction })) : null, _jsx("div", { className: "zvk-composite-parameter-editor__groups", children: groups.filter(shouldRenderGroup).map((group) => (_jsxs("section", { className: "zvk-composite-parameter-editor__group", children: [hasValue(group.title) || hasValue(group.description) ? (_jsxs("div", { className: "zvk-composite-parameter-editor__group-header", children: [hasValue(group.title) ? (_jsx("h3", { className: "zvk-composite-parameter-editor__group-title", children: group.title })) : null, hasValue(group.description) ? (_jsx("p", { className: "zvk-composite-parameter-editor__group-description", children: group.description })) : null] })) : null, group.rows.length > 0 ? (_jsx("div", { className: "zvk-composite-parameter-editor__rows", children: group.rows.map((row) => (_jsxs("div", { className: "zvk-composite-parameter-editor__row", "data-changed": row.changed ? "" : undefined, "data-disabled": row.disabled ? "" : undefined, "data-invalid": row.invalid ? "" : undefined, children: [_jsxs("div", { className: "zvk-composite-parameter-editor__row-copy", children: [_jsx("div", { className: "zvk-composite-parameter-editor__row-label", children: row.label }), hasValue(row.description) ? (_jsx("p", { className: "zvk-composite-parameter-editor__row-description", children: row.description })) : null] }), hasValue(row.value) ? (_jsx("div", { className: "zvk-composite-parameter-editor__row-value", children: row.value })) : null, _jsx("div", { className: "zvk-composite-parameter-editor__row-control", children: row.control }), hasValue(row.actions) ? (_jsx("div", { className: "zvk-composite-parameter-editor__row-actions", children: row.actions })) : null] }, row.id))) })) : null] }, group.id))) }), hasValue(footer) ? _jsx("div", { className: "zvk-composite-parameter-editor__footer", children: footer }) : null] }));
12
+ }
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ export interface SettingsSection {
3
+ readonly id: string;
4
+ readonly title: React.ReactNode;
5
+ readonly description?: React.ReactNode;
6
+ readonly content: React.ReactNode;
7
+ readonly alert?: React.ReactNode;
8
+ readonly actions?: React.ReactNode;
9
+ readonly disabled?: boolean;
10
+ }
11
+ export interface SettingsSectionStackProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
12
+ readonly title?: React.ReactNode;
13
+ readonly description?: React.ReactNode;
14
+ readonly sections: readonly SettingsSection[];
15
+ readonly dirty?: boolean;
16
+ readonly saveBar?: React.ReactNode;
17
+ readonly footer?: React.ReactNode;
18
+ readonly ref?: React.Ref<HTMLDivElement>;
19
+ }
20
+ export declare function SettingsSectionStack({ className, description, dirty, footer, ref, saveBar, sections, title, ...props }: SettingsSectionStackProps): 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 { cn } from "../utils/cn.js";
4
+ function hasValue(value) {
5
+ return value !== null && value !== undefined && value !== false;
6
+ }
7
+ export function SettingsSectionStack({ className, description, dirty = false, footer, ref, saveBar, sections, title, ...props }) {
8
+ const hasHeader = hasValue(title) || hasValue(description);
9
+ return (_jsxs("div", { ...props, ref: ref, className: cn("zvk-composite-settings-section-stack", className), "data-dirty": dirty ? "" : undefined, children: [hasHeader ? (_jsxs("div", { className: "zvk-composite-settings-section-stack__header", children: [hasValue(title) ? _jsx("h2", { className: "zvk-composite-settings-section-stack__title", children: title }) : null, hasValue(description) ? (_jsx("p", { className: "zvk-composite-settings-section-stack__description", children: description })) : null] })) : null, _jsx("div", { className: "zvk-composite-settings-section-stack__sections", children: sections.map((section) => (_jsxs("section", { className: "zvk-composite-settings-section-stack__section", "data-disabled": section.disabled ? "" : undefined, children: [_jsxs("div", { className: "zvk-composite-settings-section-stack__section-header", children: [_jsxs("div", { className: "zvk-composite-settings-section-stack__section-copy", children: [_jsx("h3", { className: "zvk-composite-settings-section-stack__section-title", children: section.title }), hasValue(section.description) ? (_jsx("p", { className: "zvk-composite-settings-section-stack__section-description", children: section.description })) : null] }), hasValue(section.actions) ? (_jsx("div", { className: "zvk-composite-settings-section-stack__section-actions", children: section.actions })) : null] }), hasValue(section.alert) ? (_jsx("div", { className: "zvk-composite-settings-section-stack__section-alert", children: section.alert })) : null, _jsx("div", { className: "zvk-composite-settings-section-stack__section-content", children: section.content })] }, section.id))) }), hasValue(saveBar) ? (_jsx("div", { className: "zvk-composite-settings-section-stack__save-bar", "data-dirty": dirty ? "" : undefined, children: saveBar })) : null, hasValue(footer) ? _jsx("div", { className: "zvk-composite-settings-section-stack__footer", children: footer }) : null] }));
10
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ export type RouteStateFrameStatus = "loading" | "empty" | "error" | "not-found" | "ready";
3
+ export interface RouteStateFrameProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "title"> {
4
+ readonly status: RouteStateFrameStatus;
5
+ readonly title?: React.ReactNode;
6
+ readonly description?: React.ReactNode;
7
+ readonly actions?: React.ReactNode;
8
+ readonly children?: React.ReactNode;
9
+ }
10
+ export declare function RouteStateFrame({ actions, children, className, description, status, title, ...props }: RouteStateFrameProps): React.JSX.Element;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx } 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
+ const routeStateDefaults = {
6
+ loading: {
7
+ title: "Loading",
8
+ description: "Please wait while this view prepares its data."
9
+ },
10
+ empty: {
11
+ title: "Nothing to show",
12
+ description: "There are no items to display yet."
13
+ },
14
+ error: {
15
+ title: "Something went wrong",
16
+ description: "An error prevented this route from loading."
17
+ },
18
+ "not-found": {
19
+ title: "Page not found",
20
+ description: "The requested route is unavailable."
21
+ }
22
+ };
23
+ export function RouteStateFrame({ actions, children, className, description, status, title, ...props }) {
24
+ if (status === "ready") {
25
+ return (_jsx("section", { ...props, className: cn("zvk-composite-route-state-frame", className), "data-status": status, children: children }));
26
+ }
27
+ const fallback = routeStateDefaults[status];
28
+ const resolvedTitle = title ?? fallback.title;
29
+ const resolvedDescription = description ?? fallback.description;
30
+ return (_jsx(StateSurface, { ...props, actions: actions, className: cn("zvk-composite-route-state-frame", "zvk-composite-route-state-frame__surface", className), "data-status": status, description: resolvedDescription, state: status, title: resolvedTitle }));
31
+ }