@corbits/react-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +501 -0
- package/README.md +125 -0
- package/dist/blocks/login/auth-layout.d.ts +38 -0
- package/dist/blocks/login/auth-layout.js +52 -0
- package/dist/blocks/login/login-form.d.ts +60 -0
- package/dist/blocks/login/login-form.js +151 -0
- package/dist/hooks/use-command-palette-navigation.d.ts +25 -0
- package/dist/hooks/use-command-palette-navigation.js +52 -0
- package/dist/hooks/use-controllable-state.d.ts +28 -0
- package/dist/hooks/use-controllable-state.js +44 -0
- package/dist/hooks/use-delayed-autofocus.d.ts +9 -0
- package/dist/hooks/use-delayed-autofocus.js +20 -0
- package/dist/hooks/use-dismissable-popover.d.ts +37 -0
- package/dist/hooks/use-dismissable-popover.js +64 -0
- package/dist/hooks/use-list-selection.d.ts +66 -0
- package/dist/hooks/use-list-selection.js +147 -0
- package/dist/hooks/use-prefers-reduced-motion.d.ts +13 -0
- package/dist/hooks/use-prefers-reduced-motion.js +28 -0
- package/dist/hooks/use-scroll-current-into-view.d.ts +19 -0
- package/dist/hooks/use-scroll-current-into-view.js +33 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +131 -0
- package/dist/lib/artifact.d.ts +72 -0
- package/dist/lib/artifact.js +67 -0
- package/dist/lib/chart-geometry.d.ts +62 -0
- package/dist/lib/chart-geometry.js +86 -0
- package/dist/lib/chart-palette.d.ts +76 -0
- package/dist/lib/chart-palette.js +92 -0
- package/dist/lib/chat-message.d.ts +115 -0
- package/dist/lib/chat-message.js +41 -0
- package/dist/lib/chat-parts.d.ts +64 -0
- package/dist/lib/chat-parts.js +16 -0
- package/dist/lib/csv.d.ts +60 -0
- package/dist/lib/csv.js +108 -0
- package/dist/lib/metrics.d.ts +70 -0
- package/dist/lib/metrics.js +101 -0
- package/dist/lib/now-item.d.ts +65 -0
- package/dist/lib/now-item.js +59 -0
- package/dist/lib/relative-time.d.ts +9 -0
- package/dist/lib/relative-time.js +47 -0
- package/dist/lib/theme.d.ts +30 -0
- package/dist/lib/theme.js +77 -0
- package/dist/lib/url.d.ts +26 -0
- package/dist/lib/url.js +37 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/lib/workflow-display-flow.d.ts +83 -0
- package/dist/lib/workflow-display-flow.js +104 -0
- package/dist/lib/workflow-registry.d.ts +90 -0
- package/dist/lib/workflow-registry.js +56 -0
- package/dist/lib/workflow-run-error.d.ts +31 -0
- package/dist/lib/workflow-run-error.js +105 -0
- package/dist/lib/workflow-run-progress.d.ts +97 -0
- package/dist/lib/workflow-run-progress.js +135 -0
- package/dist/lib/workflow-run.d.ts +43 -0
- package/dist/lib/workflow-run.js +56 -0
- package/dist/styles.css +3080 -0
- package/dist/test/render-hook.d.ts +14 -0
- package/dist/test/render-hook.js +38 -0
- package/dist/theme.css +628 -0
- package/dist/ui/agent-turn.d.ts +26 -0
- package/dist/ui/agent-turn.js +60 -0
- package/dist/ui/animated-number.d.ts +25 -0
- package/dist/ui/animated-number.js +63 -0
- package/dist/ui/approval-card.d.ts +46 -0
- package/dist/ui/approval-card.js +116 -0
- package/dist/ui/artifact-body.d.ts +26 -0
- package/dist/ui/artifact-body.js +170 -0
- package/dist/ui/artifact-notice.d.ts +21 -0
- package/dist/ui/artifact-notice.js +36 -0
- package/dist/ui/avatar.d.ts +37 -0
- package/dist/ui/avatar.js +73 -0
- package/dist/ui/badge.d.ts +10 -0
- package/dist/ui/badge.js +35 -0
- package/dist/ui/bar-chart.d.ts +38 -0
- package/dist/ui/bar-chart.js +118 -0
- package/dist/ui/block-card.d.ts +29 -0
- package/dist/ui/block-card.js +66 -0
- package/dist/ui/boot-screen.d.ts +23 -0
- package/dist/ui/boot-screen.js +49 -0
- package/dist/ui/bulk-action-bar.d.ts +37 -0
- package/dist/ui/bulk-action-bar.js +64 -0
- package/dist/ui/button.d.ts +12 -0
- package/dist/ui/button.js +73 -0
- package/dist/ui/card.d.ts +6 -0
- package/dist/ui/card.js +37 -0
- package/dist/ui/category-bars.d.ts +20 -0
- package/dist/ui/category-bars.js +69 -0
- package/dist/ui/chart-frame.d.ts +54 -0
- package/dist/ui/chart-frame.js +108 -0
- package/dist/ui/chat-composer.d.ts +24 -0
- package/dist/ui/chat-composer.js +32 -0
- package/dist/ui/chat-dock-timing.d.ts +15 -0
- package/dist/ui/chat-dock-timing.js +11 -0
- package/dist/ui/chat-input.d.ts +38 -0
- package/dist/ui/chat-input.js +138 -0
- package/dist/ui/chat-panel.d.ts +20 -0
- package/dist/ui/chat-panel.js +56 -0
- package/dist/ui/chat-thread.d.ts +28 -0
- package/dist/ui/chat-thread.js +61 -0
- package/dist/ui/checkbox.d.ts +25 -0
- package/dist/ui/checkbox.js +63 -0
- package/dist/ui/command-palette.d.ts +100 -0
- package/dist/ui/command-palette.js +341 -0
- package/dist/ui/compare-body.d.ts +52 -0
- package/dist/ui/compare-body.js +140 -0
- package/dist/ui/confirm-button.d.ts +29 -0
- package/dist/ui/confirm-button.js +41 -0
- package/dist/ui/corbits-mark.d.ts +29 -0
- package/dist/ui/corbits-mark.js +33 -0
- package/dist/ui/csv-table.d.ts +22 -0
- package/dist/ui/csv-table.js +85 -0
- package/dist/ui/dialog.d.ts +37 -0
- package/dist/ui/dialog.js +105 -0
- package/dist/ui/dictation-status-line.d.ts +20 -0
- package/dist/ui/dictation-status-line.js +38 -0
- package/dist/ui/dither-canvas.d.ts +31 -0
- package/dist/ui/dither-canvas.js +169 -0
- package/dist/ui/embed-body.d.ts +30 -0
- package/dist/ui/embed-body.js +92 -0
- package/dist/ui/empty-state.d.ts +26 -0
- package/dist/ui/empty-state.js +42 -0
- package/dist/ui/file-input.d.ts +25 -0
- package/dist/ui/file-input.js +66 -0
- package/dist/ui/filter-bar.d.ts +42 -0
- package/dist/ui/filter-bar.js +95 -0
- package/dist/ui/filter-chip.d.ts +14 -0
- package/dist/ui/filter-chip.js +23 -0
- package/dist/ui/gate-block.d.ts +16 -0
- package/dist/ui/gate-block.js +37 -0
- package/dist/ui/horizontal-stepper.d.ts +13 -0
- package/dist/ui/horizontal-stepper.js +65 -0
- package/dist/ui/input.d.ts +2 -0
- package/dist/ui/input.js +14 -0
- package/dist/ui/inspector-shell.d.ts +47 -0
- package/dist/ui/inspector-shell.js +98 -0
- package/dist/ui/intake-form.d.ts +39 -0
- package/dist/ui/intake-form.js +119 -0
- package/dist/ui/kind-card-grid.d.ts +23 -0
- package/dist/ui/kind-card-grid.js +43 -0
- package/dist/ui/library-page-header.d.ts +20 -0
- package/dist/ui/library-page-header.js +43 -0
- package/dist/ui/list-detail.d.ts +28 -0
- package/dist/ui/list-detail.js +55 -0
- package/dist/ui/live-run-banner.d.ts +13 -0
- package/dist/ui/live-run-banner.js +23 -0
- package/dist/ui/live-status-line.d.ts +22 -0
- package/dist/ui/live-status-line.js +37 -0
- package/dist/ui/menu.d.ts +18 -0
- package/dist/ui/menu.js +45 -0
- package/dist/ui/message-bubble.d.ts +24 -0
- package/dist/ui/message-bubble.js +64 -0
- package/dist/ui/mic-button.d.ts +35 -0
- package/dist/ui/mic-button.js +61 -0
- package/dist/ui/mic-permission-dialog.d.ts +20 -0
- package/dist/ui/mic-permission-dialog.js +50 -0
- package/dist/ui/notifications-bell.d.ts +28 -0
- package/dist/ui/notifications-bell.js +69 -0
- package/dist/ui/now-cards.d.ts +37 -0
- package/dist/ui/now-cards.js +116 -0
- package/dist/ui/page-panel.d.ts +37 -0
- package/dist/ui/page-panel.js +23 -0
- package/dist/ui/page-shell.d.ts +21 -0
- package/dist/ui/page-shell.js +26 -0
- package/dist/ui/parts-renderer.d.ts +22 -0
- package/dist/ui/parts-renderer.js +234 -0
- package/dist/ui/profile-card.d.ts +39 -0
- package/dist/ui/profile-card.js +124 -0
- package/dist/ui/progress-checklist.d.ts +25 -0
- package/dist/ui/progress-checklist.js +70 -0
- package/dist/ui/provider-mark.d.ts +32 -0
- package/dist/ui/provider-mark.js +31 -0
- package/dist/ui/quick-reply-chips.d.ts +14 -0
- package/dist/ui/quick-reply-chips.js +24 -0
- package/dist/ui/quote-card.d.ts +39 -0
- package/dist/ui/quote-card.js +66 -0
- package/dist/ui/reasoning-block.d.ts +35 -0
- package/dist/ui/reasoning-block.js +60 -0
- package/dist/ui/research-body.d.ts +70 -0
- package/dist/ui/research-body.js +270 -0
- package/dist/ui/rich-empty-state.d.ts +35 -0
- package/dist/ui/rich-empty-state.js +65 -0
- package/dist/ui/run-now-button.d.ts +23 -0
- package/dist/ui/run-now-button.js +42 -0
- package/dist/ui/section.d.ts +20 -0
- package/dist/ui/section.js +48 -0
- package/dist/ui/select.d.ts +2 -0
- package/dist/ui/select.js +22 -0
- package/dist/ui/selection-checkbox.d.ts +42 -0
- package/dist/ui/selection-checkbox.js +54 -0
- package/dist/ui/settings-panel.d.ts +35 -0
- package/dist/ui/settings-panel.js +68 -0
- package/dist/ui/shimmer-text.d.ts +19 -0
- package/dist/ui/shimmer-text.js +20 -0
- package/dist/ui/sidebar-item-row.d.ts +40 -0
- package/dist/ui/sidebar-item-row.js +64 -0
- package/dist/ui/sidebar-panel.d.ts +25 -0
- package/dist/ui/sidebar-panel.js +56 -0
- package/dist/ui/sidebar.d.ts +46 -0
- package/dist/ui/sidebar.js +111 -0
- package/dist/ui/skeleton.d.ts +13 -0
- package/dist/ui/skeleton.js +20 -0
- package/dist/ui/sortable-table.d.ts +43 -0
- package/dist/ui/sortable-table.js +103 -0
- package/dist/ui/sparkline.d.ts +27 -0
- package/dist/ui/sparkline.js +68 -0
- package/dist/ui/stat-grid.d.ts +55 -0
- package/dist/ui/stat-grid.js +87 -0
- package/dist/ui/status-dot.d.ts +13 -0
- package/dist/ui/status-dot.js +51 -0
- package/dist/ui/step-list.d.ts +21 -0
- package/dist/ui/step-list.js +77 -0
- package/dist/ui/switch.d.ts +23 -0
- package/dist/ui/switch.js +29 -0
- package/dist/ui/table.d.ts +8 -0
- package/dist/ui/table.js +48 -0
- package/dist/ui/tabs.d.ts +44 -0
- package/dist/ui/tabs.js +101 -0
- package/dist/ui/textarea.d.ts +8 -0
- package/dist/ui/textarea.js +32 -0
- package/dist/ui/theme-provider.d.ts +36 -0
- package/dist/ui/theme-provider.js +126 -0
- package/dist/ui/theme-toggle.d.ts +11 -0
- package/dist/ui/theme-toggle.js +32 -0
- package/dist/ui/thinking-indicator.d.ts +7 -0
- package/dist/ui/thinking-indicator.js +19 -0
- package/dist/ui/thinking-label.d.ts +19 -0
- package/dist/ui/thinking-label.js +54 -0
- package/dist/ui/thinking-mark.d.ts +10 -0
- package/dist/ui/thinking-mark.js +153 -0
- package/dist/ui/time-series-chart.d.ts +55 -0
- package/dist/ui/time-series-chart.js +249 -0
- package/dist/ui/toast.d.ts +16 -0
- package/dist/ui/toast.js +41 -0
- package/dist/ui/token-mosaic.d.ts +22 -0
- package/dist/ui/token-mosaic.js +65 -0
- package/dist/ui/tool-block.d.ts +54 -0
- package/dist/ui/tool-block.js +170 -0
- package/dist/ui/tool-narrative.d.ts +22 -0
- package/dist/ui/tool-narrative.js +77 -0
- package/dist/ui/tool-picker.d.ts +44 -0
- package/dist/ui/tool-picker.js +200 -0
- package/dist/ui/tooltip.d.ts +21 -0
- package/dist/ui/tooltip.js +48 -0
- package/dist/ui/top-bar.d.ts +53 -0
- package/dist/ui/top-bar.js +98 -0
- package/dist/ui/trace-waterfall.d.ts +38 -0
- package/dist/ui/trace-waterfall.js +121 -0
- package/dist/ui/typing-indicator.d.ts +9 -0
- package/dist/ui/typing-indicator.js +25 -0
- package/dist/ui/view-toggle.d.ts +17 -0
- package/dist/ui/view-toggle.js +46 -0
- package/dist/ui/voice-waveform.d.ts +16 -0
- package/dist/ui/voice-waveform.js +23 -0
- package/package.json +583 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronRight } from "lucide-react";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* The row above the page. It owns no content of its own — a title or a
|
|
6
|
+
* breadcrumb trail on the left, whatever the page contributes on the right.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately a `<header>` with parts rather than a `title`/`actions` prop
|
|
9
|
+
* pair: pages need a search box, a filter row or a context strip in that space,
|
|
10
|
+
* and a fixed prop list would push every one of them through a `ReactNode` prop
|
|
11
|
+
* that does the same job as a child.
|
|
12
|
+
*/ export function TopBar({ className, ...props }) {
|
|
13
|
+
return /*#__PURE__*/ _jsx("header", {
|
|
14
|
+
"data-slot": "top-bar",
|
|
15
|
+
className: cn("flex min-h-14 shrink-0 flex-wrap items-center gap-3 border-b border-border px-4 py-2", className),
|
|
16
|
+
...props
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export function TopBarTitle({ count, subtitle, className, children, ...props }) {
|
|
20
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
21
|
+
"data-slot": "top-bar-title",
|
|
22
|
+
className: cn("flex min-w-0 shrink items-center gap-2", className),
|
|
23
|
+
...props,
|
|
24
|
+
children: [
|
|
25
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
26
|
+
className: "flex min-w-0 flex-col",
|
|
27
|
+
children: [
|
|
28
|
+
/*#__PURE__*/ _jsx("h1", {
|
|
29
|
+
className: "truncate text-base font-semibold tracking-tight",
|
|
30
|
+
children: children
|
|
31
|
+
}),
|
|
32
|
+
subtitle === undefined ? null : /*#__PURE__*/ _jsx("p", {
|
|
33
|
+
className: "truncate text-xs text-muted-foreground",
|
|
34
|
+
children: subtitle
|
|
35
|
+
})
|
|
36
|
+
]
|
|
37
|
+
}),
|
|
38
|
+
count === undefined ? null : /*#__PURE__*/ _jsx("span", {
|
|
39
|
+
className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-mono text-xs text-muted-foreground",
|
|
40
|
+
children: count
|
|
41
|
+
})
|
|
42
|
+
]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function DefaultBreadcrumbLink({ href, className, children }) {
|
|
46
|
+
return /*#__PURE__*/ _jsx("a", {
|
|
47
|
+
href: href,
|
|
48
|
+
className: className,
|
|
49
|
+
children: children
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Breadcrumb trail. The last crumb is the current page: it is rendered as text
|
|
54
|
+
* with `aria-current="page"` even if a caller passes an href, because linking
|
|
55
|
+
* to where you already are is a known screen-reader annoyance.
|
|
56
|
+
*
|
|
57
|
+
* Every other crumb renders through `linkComponent`, defaulting to a plain
|
|
58
|
+
* `<a>`. A consumer routing through a SPA router passes its own `Link` so a
|
|
59
|
+
* breadcrumb click does not force a full page reload.
|
|
60
|
+
*/ export function TopBarBreadcrumbs({ crumbs, linkComponent: LinkComponent = DefaultBreadcrumbLink, className, ...props }) {
|
|
61
|
+
return /*#__PURE__*/ _jsx("nav", {
|
|
62
|
+
"data-slot": "top-bar-breadcrumbs",
|
|
63
|
+
"aria-label": "Breadcrumb",
|
|
64
|
+
className: cn("min-w-0", className),
|
|
65
|
+
...props,
|
|
66
|
+
children: /*#__PURE__*/ _jsx("ol", {
|
|
67
|
+
className: "flex min-w-0 items-center gap-1 text-sm",
|
|
68
|
+
children: crumbs.map((crumb, index)=>{
|
|
69
|
+
const isLast = index === crumbs.length - 1;
|
|
70
|
+
return /*#__PURE__*/ _jsxs("li", {
|
|
71
|
+
className: "flex min-w-0 items-center gap-1",
|
|
72
|
+
children: [
|
|
73
|
+
index === 0 ? null : /*#__PURE__*/ _jsx(ChevronRight, {
|
|
74
|
+
className: "size-3.5 shrink-0 text-muted-foreground",
|
|
75
|
+
"aria-hidden": true
|
|
76
|
+
}),
|
|
77
|
+
isLast || crumb.href === undefined ? /*#__PURE__*/ _jsx("span", {
|
|
78
|
+
"aria-current": isLast ? "page" : undefined,
|
|
79
|
+
className: cn("truncate", isLast ? "font-medium" : "text-muted-foreground"),
|
|
80
|
+
children: crumb.label
|
|
81
|
+
}) : /*#__PURE__*/ _jsx(LinkComponent, {
|
|
82
|
+
href: crumb.href,
|
|
83
|
+
className: "truncate text-muted-foreground hover:text-foreground",
|
|
84
|
+
children: crumb.label
|
|
85
|
+
})
|
|
86
|
+
]
|
|
87
|
+
}, index);
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/** Trailing controls. Pushes itself to the right; put it last. */ export function TopBarActions({ className, ...props }) {
|
|
93
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
94
|
+
"data-slot": "top-bar-actions",
|
|
95
|
+
className: cn("ml-auto flex shrink-0 items-center gap-1", className),
|
|
96
|
+
...props
|
|
97
|
+
});
|
|
98
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type TracePhase = "ok" | "awaiting" | "failed";
|
|
2
|
+
export type TraceSpan = {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly label: string;
|
|
5
|
+
readonly kind: string;
|
|
6
|
+
/** Inclusive start as a fraction of the total timeline (0–1). */
|
|
7
|
+
readonly start: number;
|
|
8
|
+
/** Inclusive end as a fraction of the total timeline (0–1). */
|
|
9
|
+
readonly end: number;
|
|
10
|
+
readonly durationLabel: string | null;
|
|
11
|
+
readonly tokensLabel?: string;
|
|
12
|
+
readonly phase: TracePhase;
|
|
13
|
+
readonly error?: string;
|
|
14
|
+
/**
|
|
15
|
+
* How `start`/`end` were derived. "measured" (the default when omitted)
|
|
16
|
+
* means real wall-clock timing, rendered as a proportional duration bar.
|
|
17
|
+
* "ordinal" means the span was positioned only by event order within its
|
|
18
|
+
* parent, with no real duration — it renders as a point marker at `start`
|
|
19
|
+
* instead of a bar spanning start→end, so the chart never implies a
|
|
20
|
+
* duration the data doesn't have.
|
|
21
|
+
*/
|
|
22
|
+
readonly timingSource?: "measured" | "ordinal";
|
|
23
|
+
};
|
|
24
|
+
export type TraceWaterfallProps = {
|
|
25
|
+
readonly title: string;
|
|
26
|
+
readonly description?: string;
|
|
27
|
+
readonly spans: readonly TraceSpan[];
|
|
28
|
+
readonly className?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Run-trace timeline: one row per span with a duration, and optional token
|
|
32
|
+
* count. A span with real wall-clock timing renders a proportional bar; a
|
|
33
|
+
* span positioned only by event order (`timingSource: "ordinal"`) renders a
|
|
34
|
+
* point marker instead, so the chart never implies a duration the data
|
|
35
|
+
* doesn't have. Failed spans surface their error under the row. The
|
|
36
|
+
* accessible table carries the same numbers for non-visual readers.
|
|
37
|
+
*/
|
|
38
|
+
export declare function TraceWaterfall({ title, description, spans, className }: TraceWaterfallProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { ChartFrame } from "./chart-frame.js";
|
|
4
|
+
const PHASE_FILL = {
|
|
5
|
+
ok: "bg-success-foreground",
|
|
6
|
+
awaiting: "bg-warning-foreground",
|
|
7
|
+
failed: "bg-destructive"
|
|
8
|
+
};
|
|
9
|
+
const PHASE_LABEL = {
|
|
10
|
+
ok: "ok",
|
|
11
|
+
awaiting: "awaiting",
|
|
12
|
+
failed: "failed"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Run-trace timeline: one row per span with a duration, and optional token
|
|
16
|
+
* count. A span with real wall-clock timing renders a proportional bar; a
|
|
17
|
+
* span positioned only by event order (`timingSource: "ordinal"`) renders a
|
|
18
|
+
* point marker instead, so the chart never implies a duration the data
|
|
19
|
+
* doesn't have. Failed spans surface their error under the row. The
|
|
20
|
+
* accessible table carries the same numbers for non-visual readers.
|
|
21
|
+
*/ export function TraceWaterfall({ title, description, spans, className }) {
|
|
22
|
+
return /*#__PURE__*/ _jsx(ChartFrame, {
|
|
23
|
+
title: title,
|
|
24
|
+
...description === undefined ? {} : {
|
|
25
|
+
description
|
|
26
|
+
},
|
|
27
|
+
table: {
|
|
28
|
+
columns: [
|
|
29
|
+
"Step",
|
|
30
|
+
"Kind",
|
|
31
|
+
"Duration",
|
|
32
|
+
"Tokens",
|
|
33
|
+
"Status"
|
|
34
|
+
],
|
|
35
|
+
rows: spans.map((span)=>[
|
|
36
|
+
span.label,
|
|
37
|
+
span.kind,
|
|
38
|
+
durationText(span.durationLabel),
|
|
39
|
+
span.tokensLabel ?? "—",
|
|
40
|
+
PHASE_LABEL[span.phase]
|
|
41
|
+
])
|
|
42
|
+
},
|
|
43
|
+
className: className,
|
|
44
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
45
|
+
className: "flex flex-col gap-1.5",
|
|
46
|
+
role: "presentation",
|
|
47
|
+
children: spans.map((span)=>{
|
|
48
|
+
const isOrdinal = span.timingSource === "ordinal";
|
|
49
|
+
const left = clamp01(span.start) * 100;
|
|
50
|
+
const width = Math.max(0.5, (clamp01(span.end) - clamp01(span.start)) * 100);
|
|
51
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
52
|
+
className: "flex flex-col gap-0.5",
|
|
53
|
+
children: [
|
|
54
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
55
|
+
className: "grid grid-cols-[minmax(7rem,11rem)_1fr_minmax(4.5rem,6rem)] items-center gap-2",
|
|
56
|
+
children: [
|
|
57
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
58
|
+
className: "min-w-0",
|
|
59
|
+
children: [
|
|
60
|
+
/*#__PURE__*/ _jsx("p", {
|
|
61
|
+
className: "truncate text-xs font-semibold",
|
|
62
|
+
children: span.label
|
|
63
|
+
}),
|
|
64
|
+
/*#__PURE__*/ _jsx("p", {
|
|
65
|
+
className: "truncate text-[10px] text-muted-foreground",
|
|
66
|
+
children: span.kind
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
}),
|
|
70
|
+
/*#__PURE__*/ _jsx("div", {
|
|
71
|
+
className: "relative h-4 w-full bg-muted",
|
|
72
|
+
children: isOrdinal ? /*#__PURE__*/ _jsx("span", {
|
|
73
|
+
className: cn("absolute top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2 rotate-45", PHASE_FILL[span.phase]),
|
|
74
|
+
style: {
|
|
75
|
+
left: `${left}%`
|
|
76
|
+
},
|
|
77
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
78
|
+
className: "sr-only",
|
|
79
|
+
children: "Approximate position by event order, not a measured duration"
|
|
80
|
+
})
|
|
81
|
+
}) : /*#__PURE__*/ _jsx("div", {
|
|
82
|
+
className: cn("absolute inset-y-0", PHASE_FILL[span.phase], span.phase === "awaiting" && "[background-image:repeating-linear-gradient(135deg,transparent,transparent_3px,rgba(0,0,0,0.15)_3px,rgba(0,0,0,0.15)_6px)]"),
|
|
83
|
+
style: {
|
|
84
|
+
left: `${left}%`,
|
|
85
|
+
width: `${width}%`
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
}),
|
|
89
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
90
|
+
className: "text-right font-mono text-[11px] leading-tight",
|
|
91
|
+
children: [
|
|
92
|
+
/*#__PURE__*/ _jsx("p", {
|
|
93
|
+
className: "font-semibold",
|
|
94
|
+
children: durationText(span.durationLabel)
|
|
95
|
+
}),
|
|
96
|
+
span.tokensLabel === undefined ? null : /*#__PURE__*/ _jsx("p", {
|
|
97
|
+
className: "text-muted-foreground",
|
|
98
|
+
children: span.tokensLabel
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
})
|
|
102
|
+
]
|
|
103
|
+
}),
|
|
104
|
+
span.error === undefined ? null : /*#__PURE__*/ _jsx("p", {
|
|
105
|
+
className: "ml-[11.5rem] border border-destructive/40 bg-destructive/10 px-2 py-1 text-[11px] text-destructive-foreground",
|
|
106
|
+
children: span.error
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
}, span.id);
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function durationText(durationLabel) {
|
|
115
|
+
return durationLabel ?? "—";
|
|
116
|
+
}
|
|
117
|
+
function clamp01(value) {
|
|
118
|
+
if (value < 0) return 0;
|
|
119
|
+
if (value > 1) return 1;
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three pulsing dots: the agent is composing a reply, with nothing to report
|
|
3
|
+
* yet. `role="status"` with a text label, because the dots carry no words a
|
|
4
|
+
* screen reader can read — the label is the only accessible content here.
|
|
5
|
+
*/
|
|
6
|
+
export declare function TypingIndicator({ label, className }: {
|
|
7
|
+
label?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
const DOT_DELAY_MS = [
|
|
4
|
+
0,
|
|
5
|
+
160,
|
|
6
|
+
320
|
|
7
|
+
];
|
|
8
|
+
/**
|
|
9
|
+
* Three pulsing dots: the agent is composing a reply, with nothing to report
|
|
10
|
+
* yet. `role="status"` with a text label, because the dots carry no words a
|
|
11
|
+
* screen reader can read — the label is the only accessible content here.
|
|
12
|
+
*/ export function TypingIndicator({ label = "Thinking", className }) {
|
|
13
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
14
|
+
role: "status",
|
|
15
|
+
"aria-label": label,
|
|
16
|
+
className: cn("flex items-center gap-1 px-1 py-2", className),
|
|
17
|
+
children: DOT_DELAY_MS.map((delay)=>/*#__PURE__*/ _jsx("span", {
|
|
18
|
+
"aria-hidden": true,
|
|
19
|
+
style: {
|
|
20
|
+
animationDelay: `${delay}ms`
|
|
21
|
+
},
|
|
22
|
+
className: "size-1.5 rounded-full bg-muted-foreground [animation:corbits-typing-bounce_1.2s_ease-in-out_infinite]"
|
|
23
|
+
}, delay))
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type ViewMode = "grid" | "rows";
|
|
2
|
+
/**
|
|
3
|
+
* Grid or rows, as a segmented control.
|
|
4
|
+
*
|
|
5
|
+
* `role="group"` with `aria-pressed` toggles rather than a radiogroup: these
|
|
6
|
+
* are two buttons that change a view, and radios promise arrow-key navigation
|
|
7
|
+
* between options plus form-submission semantics that do not apply.
|
|
8
|
+
*
|
|
9
|
+
* Each button carries a text label for assistive tech; the icon alone is not a
|
|
10
|
+
* name. Stateless — the page owns `mode`, because the choice usually outlives
|
|
11
|
+
* the component and gets persisted.
|
|
12
|
+
*/
|
|
13
|
+
export declare function ViewToggle({ mode, onChange, className, }: {
|
|
14
|
+
mode: ViewMode;
|
|
15
|
+
onChange: (mode: ViewMode) => void;
|
|
16
|
+
className?: string;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { LayoutGrid, Rows3 } from "lucide-react";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
const OPTIONS = [
|
|
5
|
+
{
|
|
6
|
+
mode: "grid",
|
|
7
|
+
label: "Grid view",
|
|
8
|
+
Icon: LayoutGrid
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
mode: "rows",
|
|
12
|
+
label: "Rows view",
|
|
13
|
+
Icon: Rows3
|
|
14
|
+
}
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Grid or rows, as a segmented control.
|
|
18
|
+
*
|
|
19
|
+
* `role="group"` with `aria-pressed` toggles rather than a radiogroup: these
|
|
20
|
+
* are two buttons that change a view, and radios promise arrow-key navigation
|
|
21
|
+
* between options plus form-submission semantics that do not apply.
|
|
22
|
+
*
|
|
23
|
+
* Each button carries a text label for assistive tech; the icon alone is not a
|
|
24
|
+
* name. Stateless — the page owns `mode`, because the choice usually outlives
|
|
25
|
+
* the component and gets persisted.
|
|
26
|
+
*/ export function ViewToggle({ mode, onChange, className }) {
|
|
27
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
28
|
+
role: "group",
|
|
29
|
+
"aria-label": "View",
|
|
30
|
+
className: cn("flex items-center gap-0.5 rounded-md border border-border p-0.5", className),
|
|
31
|
+
children: OPTIONS.map(({ mode: option, label, Icon })=>{
|
|
32
|
+
const active = mode === option;
|
|
33
|
+
return /*#__PURE__*/ _jsx("button", {
|
|
34
|
+
type: "button",
|
|
35
|
+
"aria-label": label,
|
|
36
|
+
"aria-pressed": active,
|
|
37
|
+
onClick: ()=>onChange(option),
|
|
38
|
+
className: cn("grid size-7 place-items-center rounded-sm transition-colors", active ? "bg-muted text-foreground" : "text-muted-foreground hover:text-foreground"),
|
|
39
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
40
|
+
className: "size-4",
|
|
41
|
+
"aria-hidden": true
|
|
42
|
+
})
|
|
43
|
+
}, option);
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type VoiceWaveformProps = {
|
|
2
|
+
/** Recent input levels, 0..1, oldest first. One bar per entry. */
|
|
3
|
+
readonly levels: readonly number[];
|
|
4
|
+
readonly className?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* A bar waveform driven entirely by `levels` — no microphone or audio API
|
|
8
|
+
* here, the consumer's dictation hook owns sampling and passes the numbers
|
|
9
|
+
* in. `aria-hidden`: the state it shows is spoken separately by
|
|
10
|
+
* `DictationStatusLine`.
|
|
11
|
+
*
|
|
12
|
+
* Bar height is an inline `scaleY` transform per frame; the `duration-75`
|
|
13
|
+
* transition is plain CSS, so the theme's global reduced-motion rule already
|
|
14
|
+
* collapses it — no JS-side handling needed here.
|
|
15
|
+
*/
|
|
16
|
+
export declare function VoiceWaveform({ levels, className }: VoiceWaveformProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* A bar waveform driven entirely by `levels` — no microphone or audio API
|
|
5
|
+
* here, the consumer's dictation hook owns sampling and passes the numbers
|
|
6
|
+
* in. `aria-hidden`: the state it shows is spoken separately by
|
|
7
|
+
* `DictationStatusLine`.
|
|
8
|
+
*
|
|
9
|
+
* Bar height is an inline `scaleY` transform per frame; the `duration-75`
|
|
10
|
+
* transition is plain CSS, so the theme's global reduced-motion rule already
|
|
11
|
+
* collapses it — no JS-side handling needed here.
|
|
12
|
+
*/ export function VoiceWaveform({ levels, className }) {
|
|
13
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
14
|
+
"aria-hidden": true,
|
|
15
|
+
className: cn("inline-flex h-4 items-center gap-px", className),
|
|
16
|
+
children: levels.map((level, index)=>/*#__PURE__*/ _jsx("i", {
|
|
17
|
+
className: "inline-block h-full w-0.5 origin-center rounded-full bg-current transition-transform duration-75",
|
|
18
|
+
style: {
|
|
19
|
+
transform: `scaleY(${Math.max(0.08, Math.min(1, level))})`
|
|
20
|
+
}
|
|
21
|
+
}, index))
|
|
22
|
+
});
|
|
23
|
+
}
|