@corbits/react-ui 0.1.0 → 0.3.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 +174 -499
- package/README.md +228 -85
- package/dist/blocks/login/auth-layout.d.ts +1 -1
- package/dist/blocks/login/auth-layout.js +3 -33
- package/dist/blocks/login/login-form.js +6 -119
- package/dist/hooks/use-command-palette-navigation.js +18 -17
- package/dist/hooks/use-controllable-state.d.ts +2 -2
- package/dist/hooks/use-controllable-state.js +23 -15
- package/dist/hooks/use-delayed-autofocus.js +10 -11
- package/dist/hooks/use-dismissable-popover.d.ts +2 -2
- package/dist/hooks/use-dismissable-popover.js +21 -29
- package/dist/hooks/use-list-selection.js +54 -85
- package/dist/hooks/use-prefers-reduced-motion.js +8 -4
- package/dist/hooks/use-scroll-current-into-view.js +5 -7
- package/dist/index.d.ts +0 -11
- package/dist/index.js +10 -19
- package/dist/lib/artifact.js +16 -35
- package/dist/lib/chart-geometry.js +33 -20
- package/dist/lib/chart-palette.js +17 -31
- package/dist/lib/chat-message.js +32 -13
- package/dist/lib/chat-parts.js +2 -1
- package/dist/lib/csv.js +42 -26
- package/dist/lib/metrics.js +30 -48
- package/dist/lib/now-item.js +26 -25
- package/dist/lib/relative-time.js +14 -29
- package/dist/lib/theme.js +32 -30
- package/dist/lib/url.js +9 -8
- package/dist/lib/workflow-display-flow.js +37 -33
- package/dist/lib/workflow-registry.d.ts +0 -41
- package/dist/lib/workflow-registry.js +13 -23
- package/dist/lib/workflow-run-error.js +16 -20
- package/dist/lib/workflow-run-progress.js +94 -52
- package/dist/lib/workflow-run.js +17 -13
- package/dist/styles.css +257 -19
- package/dist/test/render-hook.js +11 -12
- package/dist/theme.css +92 -14
- package/dist/ui/agent-turn.d.ts +1 -1
- package/dist/ui/agent-turn.js +4 -37
- package/dist/ui/animated-number.js +15 -28
- package/dist/ui/approval-card.js +5 -90
- package/dist/ui/artifact-body.js +47 -125
- package/dist/ui/artifact-notice.d.ts +1 -1
- package/dist/ui/artifact-notice.js +9 -16
- package/dist/ui/avatar.d.ts +21 -4
- package/dist/ui/avatar.js +40 -49
- package/dist/ui/badge.js +4 -12
- package/dist/ui/bar-chart.d.ts +1 -1
- package/dist/ui/bar-chart.js +22 -74
- package/dist/ui/block-card.js +7 -45
- package/dist/ui/boot-screen.d.ts +1 -1
- package/dist/ui/boot-screen.js +4 -33
- package/dist/ui/bulk-action-bar.d.ts +1 -1
- package/dist/ui/bulk-action-bar.js +14 -33
- package/dist/ui/button.js +10 -24
- package/dist/ui/card.js +5 -25
- package/dist/ui/category-bars.js +14 -59
- package/dist/ui/chart-frame.d.ts +2 -2
- package/dist/ui/chart-frame.js +6 -85
- package/dist/ui/chat-composer.js +4 -16
- package/dist/ui/chat-dock-timing.js +7 -3
- package/dist/ui/chat-input.js +20 -100
- package/dist/ui/chat-panel.d.ts +1 -1
- package/dist/ui/chat-panel.js +7 -41
- package/dist/ui/chat-thread.js +13 -31
- package/dist/ui/checkbox.js +10 -52
- package/dist/ui/command-palette.js +85 -246
- package/dist/ui/compare-body.d.ts +1 -1
- package/dist/ui/compare-body.js +28 -98
- package/dist/ui/confirm-button.js +8 -15
- package/dist/ui/corbits-mark.js +7 -16
- package/dist/ui/csv-table.d.ts +1 -1
- package/dist/ui/csv-table.js +8 -50
- package/dist/ui/dialog.d.ts +1 -1
- package/dist/ui/dialog.js +32 -62
- package/dist/ui/dictation-status-line.js +7 -25
- package/dist/ui/dither-canvas.d.ts +1 -1
- package/dist/ui/dither-canvas.js +31 -56
- package/dist/ui/embed-body.d.ts +1 -1
- package/dist/ui/embed-body.js +7 -56
- package/dist/ui/empty-state.d.ts +1 -1
- package/dist/ui/empty-state.js +3 -26
- package/dist/ui/file-input.js +17 -37
- package/dist/ui/filter-bar.d.ts +1 -1
- package/dist/ui/filter-bar.js +11 -71
- package/dist/ui/filter-chip.d.ts +1 -1
- package/dist/ui/filter-chip.js +7 -15
- package/dist/ui/gate-block.d.ts +2 -1
- package/dist/ui/gate-block.js +4 -29
- package/dist/ui/horizontal-stepper.d.ts +1 -1
- package/dist/ui/horizontal-stepper.js +18 -45
- package/dist/ui/input.js +1 -6
- package/dist/ui/inspector-shell.d.ts +5 -5
- package/dist/ui/inspector-shell.js +14 -81
- package/dist/ui/intake-form.d.ts +1 -1
- package/dist/ui/intake-form.js +21 -97
- package/dist/ui/kind-card-grid.js +9 -31
- package/dist/ui/library-page-header.js +4 -32
- package/dist/ui/list-detail.js +5 -35
- package/dist/ui/live-run-banner.d.ts +1 -1
- package/dist/ui/live-run-banner.js +5 -15
- package/dist/ui/live-status-line.js +6 -24
- package/dist/ui/menu.js +7 -24
- package/dist/ui/message-bubble.d.ts +3 -3
- package/dist/ui/message-bubble.js +5 -44
- package/dist/ui/mic-button.d.ts +1 -1
- package/dist/ui/mic-button.js +15 -21
- package/dist/ui/mic-permission-dialog.js +5 -41
- package/dist/ui/notifications-bell.js +9 -43
- package/dist/ui/now-cards.d.ts +2 -2
- package/dist/ui/now-cards.js +16 -94
- package/dist/ui/page-panel.js +11 -11
- package/dist/ui/page-shell.js +4 -11
- package/dist/ui/parts-renderer.js +51 -149
- package/dist/ui/profile-card.js +7 -111
- package/dist/ui/progress-checklist.js +11 -49
- package/dist/ui/provider-mark.d.ts +2 -2
- package/dist/ui/provider-mark.js +9 -16
- package/dist/ui/quick-reply-chips.js +6 -14
- package/dist/ui/quote-card.js +12 -32
- package/dist/ui/reasoning-block.d.ts +1 -1
- package/dist/ui/reasoning-block.js +14 -33
- package/dist/ui/research-body.js +32 -213
- package/dist/ui/rich-empty-state.js +6 -48
- package/dist/ui/run-now-button.js +14 -15
- package/dist/ui/section.d.ts +1 -1
- package/dist/ui/section.js +4 -40
- package/dist/ui/select.js +1 -15
- package/dist/ui/selection-checkbox.d.ts +1 -1
- package/dist/ui/selection-checkbox.js +11 -29
- package/dist/ui/settings-panel.js +7 -50
- package/dist/ui/shimmer-text.js +3 -6
- package/dist/ui/sidebar-item-row.d.ts +1 -1
- package/dist/ui/sidebar-item-row.js +9 -39
- package/dist/ui/sidebar-panel.js +15 -40
- package/dist/ui/sidebar.js +15 -76
- package/dist/ui/skeleton.js +3 -7
- package/dist/ui/sortable-table.js +29 -72
- package/dist/ui/sparkline.js +14 -38
- package/dist/ui/stat-grid.js +17 -52
- package/dist/ui/status-dot.d.ts +1 -1
- package/dist/ui/status-dot.js +8 -20
- package/dist/ui/step-list.d.ts +1 -0
- package/dist/ui/step-list.js +11 -50
- package/dist/ui/switch.js +4 -16
- package/dist/ui/table.js +7 -32
- package/dist/ui/tabs.js +39 -54
- package/dist/ui/textarea.js +10 -19
- package/dist/ui/theme-provider.js +54 -78
- package/dist/ui/theme-toggle.js +13 -16
- package/dist/ui/thinking-indicator.js +3 -15
- package/dist/ui/thinking-label.js +16 -35
- package/dist/ui/thinking-mark.d.ts +1 -1
- package/dist/ui/thinking-mark.js +4 -145
- package/dist/ui/time-series-chart.js +43 -174
- package/dist/ui/toast.js +12 -20
- package/dist/ui/token-mosaic.js +5 -43
- package/dist/ui/tool-block.js +18 -70
- package/dist/ui/tool-narrative.d.ts +1 -1
- package/dist/ui/tool-narrative.js +10 -57
- package/dist/ui/tool-picker.js +57 -145
- package/dist/ui/tooltip.d.ts +1 -1
- package/dist/ui/tooltip.js +4 -33
- package/dist/ui/top-bar.js +14 -72
- package/dist/ui/trace-waterfall.d.ts +1 -1
- package/dist/ui/trace-waterfall.js +21 -93
- package/dist/ui/typing-indicator.d.ts +1 -1
- package/dist/ui/typing-indicator.js +4 -18
- package/dist/ui/view-toggle.js +10 -29
- package/dist/ui/voice-waveform.js +3 -11
- package/package.json +96 -535
package/dist/ui/top-bar.js
CHANGED
|
@@ -9,45 +9,15 @@ import { cn } from "../lib/utils.js";
|
|
|
9
9
|
* pair: pages need a search box, a filter row or a context strip in that space,
|
|
10
10
|
* and a fixed prop list would push every one of them through a `ReactNode` prop
|
|
11
11
|
* that does the same job as a child.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
});
|
|
12
|
+
*/
|
|
13
|
+
export function TopBar({ className, ...props }) {
|
|
14
|
+
return (_jsx("header", { "data-slot": "top-bar", className: cn("flex min-h-14 shrink-0 flex-wrap items-center gap-3 border-b border-border px-4 py-2", className), ...props }));
|
|
18
15
|
}
|
|
19
16
|
export function TopBarTitle({ count, subtitle, className, children, ...props }) {
|
|
20
|
-
return
|
|
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
|
-
});
|
|
17
|
+
return (_jsxs("div", { "data-slot": "top-bar-title", className: cn("flex min-w-0 shrink items-center gap-2", className), ...props, children: [_jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("h1", { className: "truncate text-base font-semibold tracking-tight", children: children }), subtitle === undefined ? null : (_jsx("p", { className: "truncate text-xs text-muted-foreground", children: subtitle }))] }), count === undefined ? null : (_jsx("span", { className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-mono text-xs text-muted-foreground", children: count }))] }));
|
|
44
18
|
}
|
|
45
|
-
function DefaultBreadcrumbLink({ href, className, children }) {
|
|
46
|
-
return
|
|
47
|
-
href: href,
|
|
48
|
-
className: className,
|
|
49
|
-
children: children
|
|
50
|
-
});
|
|
19
|
+
function DefaultBreadcrumbLink({ href, className, children, }) {
|
|
20
|
+
return (_jsx("a", { href: href, className: className, children: children }));
|
|
51
21
|
}
|
|
52
22
|
/**
|
|
53
23
|
* Breadcrumb trail. The last crumb is the current page: it is rendered as text
|
|
@@ -57,42 +27,14 @@ function DefaultBreadcrumbLink({ href, className, children }) {
|
|
|
57
27
|
* Every other crumb renders through `linkComponent`, defaulting to a plain
|
|
58
28
|
* `<a>`. A consumer routing through a SPA router passes its own `Link` so a
|
|
59
29
|
* breadcrumb click does not force a full page reload.
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
|
|
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)=>{
|
|
30
|
+
*/
|
|
31
|
+
export function TopBarBreadcrumbs({ crumbs, linkComponent: LinkComponent = DefaultBreadcrumbLink, className, ...props }) {
|
|
32
|
+
return (_jsx("nav", { "data-slot": "top-bar-breadcrumbs", "aria-label": "Breadcrumb", className: cn("min-w-0", className), ...props, children: _jsx("ol", { className: "flex min-w-0 items-center gap-1 text-sm", children: crumbs.map((crumb, index) => {
|
|
69
33
|
const isLast = index === crumbs.length - 1;
|
|
70
|
-
return
|
|
71
|
-
|
|
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
|
-
});
|
|
34
|
+
return (_jsxs("li", { className: "flex min-w-0 items-center gap-1", children: [index === 0 ? null : (_jsx(ChevronRight, { className: "size-3.5 shrink-0 text-muted-foreground", "aria-hidden": true })), isLast || crumb.href === undefined ? (_jsx("span", { "aria-current": isLast ? "page" : undefined, className: cn("truncate", isLast ? "font-medium" : "text-muted-foreground"), children: crumb.label })) : (_jsx(LinkComponent, { href: crumb.href, className: "truncate text-muted-foreground hover:text-foreground", children: crumb.label }))] }, index));
|
|
35
|
+
}) }) }));
|
|
91
36
|
}
|
|
92
|
-
/** Trailing controls. Pushes itself to the right; put it last. */
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
className: cn("ml-auto flex shrink-0 items-center gap-1", className),
|
|
96
|
-
...props
|
|
97
|
-
});
|
|
37
|
+
/** Trailing controls. Pushes itself to the right; put it last. */
|
|
38
|
+
export function TopBarActions({ className, ...props }) {
|
|
39
|
+
return (_jsx("div", { "data-slot": "top-bar-actions", className: cn("ml-auto flex shrink-0 items-center gap-1", className), ...props }));
|
|
98
40
|
}
|
|
@@ -35,4 +35,4 @@ export type TraceWaterfallProps = {
|
|
|
35
35
|
* doesn't have. Failed spans surface their error under the row. The
|
|
36
36
|
* accessible table carries the same numbers for non-visual readers.
|
|
37
37
|
*/
|
|
38
|
-
export declare function TraceWaterfall({ title, description, spans, className }: TraceWaterfallProps): import("react").JSX.Element;
|
|
38
|
+
export declare function TraceWaterfall({ title, description, spans, className, }: TraceWaterfallProps): import("react").JSX.Element;
|
|
@@ -4,12 +4,12 @@ import { ChartFrame } from "./chart-frame.js";
|
|
|
4
4
|
const PHASE_FILL = {
|
|
5
5
|
ok: "bg-success-foreground",
|
|
6
6
|
awaiting: "bg-warning-foreground",
|
|
7
|
-
failed: "bg-destructive"
|
|
7
|
+
failed: "bg-destructive",
|
|
8
8
|
};
|
|
9
9
|
const PHASE_LABEL = {
|
|
10
10
|
ok: "ok",
|
|
11
11
|
awaiting: "awaiting",
|
|
12
|
-
failed: "failed"
|
|
12
|
+
failed: "failed",
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
15
|
* Run-trace timeline: one row per span with a duration, and optional token
|
|
@@ -18,104 +18,32 @@ const PHASE_LABEL = {
|
|
|
18
18
|
* point marker instead, so the chart never implies a duration the data
|
|
19
19
|
* doesn't have. Failed spans surface their error under the row. The
|
|
20
20
|
* accessible table carries the same numbers for non-visual readers.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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)=>{
|
|
21
|
+
*/
|
|
22
|
+
export function TraceWaterfall({ title, description, spans, className, }) {
|
|
23
|
+
return (_jsx(ChartFrame, { title: title, ...(description === undefined ? {} : { description }), table: {
|
|
24
|
+
columns: ["Step", "Kind", "Duration", "Tokens", "Status"],
|
|
25
|
+
rows: spans.map((span) => [
|
|
26
|
+
span.label,
|
|
27
|
+
span.kind,
|
|
28
|
+
durationText(span.durationLabel),
|
|
29
|
+
span.tokensLabel ?? "—",
|
|
30
|
+
PHASE_LABEL[span.phase],
|
|
31
|
+
]),
|
|
32
|
+
}, className: className, children: _jsx("div", { className: "flex flex-col gap-1.5", role: "presentation", children: spans.map((span) => {
|
|
48
33
|
const isOrdinal = span.timingSource === "ordinal";
|
|
49
34
|
const left = clamp01(span.start) * 100;
|
|
50
35
|
const width = Math.max(0.5, (clamp01(span.end) - clamp01(span.start)) * 100);
|
|
51
|
-
return
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
});
|
|
36
|
+
return (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsxs("div", { className: "grid grid-cols-[minmax(7rem,11rem)_1fr_minmax(4.5rem,6rem)] items-center gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-xs font-semibold", children: span.label }), _jsx("p", { className: "truncate text-[10px] text-muted-foreground", children: span.kind })] }), _jsx("div", { className: "relative h-4 w-full bg-muted", children: isOrdinal ? (_jsx("span", { className: cn("absolute top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2 rotate-45", PHASE_FILL[span.phase]), style: { left: `${left}%` }, children: _jsx("span", { className: "sr-only", children: "Approximate position by event order, not a measured duration" }) })) : (_jsx("div", { className: cn("absolute inset-y-0", PHASE_FILL[span.phase], span.phase === "awaiting" &&
|
|
37
|
+
"[background-image:repeating-linear-gradient(135deg,transparent,transparent_3px,rgba(0,0,0,0.15)_3px,rgba(0,0,0,0.15)_6px)]"), style: { left: `${left}%`, width: `${width}%` } })) }), _jsxs("div", { className: "text-right font-mono text-[11px] leading-tight", children: [_jsx("p", { className: "font-semibold", children: durationText(span.durationLabel) }), span.tokensLabel === undefined ? null : (_jsx("p", { className: "text-muted-foreground", children: span.tokensLabel }))] })] }), span.error === undefined ? null : (_jsx("p", { className: "ml-[11.5rem] border border-destructive/40 bg-destructive/10 px-2 py-1 text-[11px] text-destructive-foreground", children: span.error }))] }, span.id));
|
|
38
|
+
}) }) }));
|
|
113
39
|
}
|
|
114
40
|
function durationText(durationLabel) {
|
|
115
41
|
return durationLabel ?? "—";
|
|
116
42
|
}
|
|
117
43
|
function clamp01(value) {
|
|
118
|
-
if (value < 0)
|
|
119
|
-
|
|
44
|
+
if (value < 0)
|
|
45
|
+
return 0;
|
|
46
|
+
if (value > 1)
|
|
47
|
+
return 1;
|
|
120
48
|
return value;
|
|
121
49
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* yet. `role="status"` with a text label, because the dots carry no words a
|
|
4
4
|
* screen reader can read — the label is the only accessible content here.
|
|
5
5
|
*/
|
|
6
|
-
export declare function TypingIndicator({ label, className }: {
|
|
6
|
+
export declare function TypingIndicator({ label, className, }: {
|
|
7
7
|
label?: string;
|
|
8
8
|
className?: string;
|
|
9
9
|
}): import("react").JSX.Element;
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
|
-
const DOT_DELAY_MS = [
|
|
4
|
-
0,
|
|
5
|
-
160,
|
|
6
|
-
320
|
|
7
|
-
];
|
|
3
|
+
const DOT_DELAY_MS = [0, 160, 320];
|
|
8
4
|
/**
|
|
9
5
|
* Three pulsing dots: the agent is composing a reply, with nothing to report
|
|
10
6
|
* yet. `role="status"` with a text label, because the dots carry no words a
|
|
11
7
|
* screen reader can read — the label is the only accessible content here.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
});
|
|
8
|
+
*/
|
|
9
|
+
export function TypingIndicator({ label = "Thinking", className, }) {
|
|
10
|
+
return (_jsx("div", { role: "status", "aria-label": label, className: cn("flex items-center gap-1 px-1 py-2", className), children: DOT_DELAY_MS.map((delay) => (_jsx("span", { "aria-hidden": true, style: { animationDelay: `${delay}ms` }, className: "size-1.5 rounded-full bg-muted-foreground [animation:corbits-typing-bounce_1.2s_ease-in-out_infinite]" }, delay))) }));
|
|
25
11
|
}
|
package/dist/ui/view-toggle.js
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
3
|
import { LayoutGrid, Rows3 } from "lucide-react";
|
|
3
4
|
import { cn } from "../lib/utils.js";
|
|
4
5
|
const OPTIONS = [
|
|
5
|
-
{
|
|
6
|
-
|
|
7
|
-
label: "Grid view",
|
|
8
|
-
Icon: LayoutGrid
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
mode: "rows",
|
|
12
|
-
label: "Rows view",
|
|
13
|
-
Icon: Rows3
|
|
14
|
-
}
|
|
6
|
+
{ mode: "grid", label: "Grid view", Icon: LayoutGrid },
|
|
7
|
+
{ mode: "rows", label: "Rows view", Icon: Rows3 },
|
|
15
8
|
];
|
|
16
9
|
/**
|
|
17
10
|
* Grid or rows, as a segmented control.
|
|
@@ -23,24 +16,12 @@ const OPTIONS = [
|
|
|
23
16
|
* Each button carries a text label for assistive tech; the icon alone is not a
|
|
24
17
|
* name. Stateless — the page owns `mode`, because the choice usually outlives
|
|
25
18
|
* the component and gets persisted.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
|
|
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 })=>{
|
|
19
|
+
*/
|
|
20
|
+
export function ViewToggle({ mode, onChange, className, }) {
|
|
21
|
+
return (_jsx("div", { role: "group", "aria-label": "View", className: cn("flex items-center gap-0.5 rounded-md border border-border p-0.5", className), children: OPTIONS.map(({ mode: option, label, Icon }) => {
|
|
32
22
|
const active = mode === option;
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
});
|
|
23
|
+
return (_jsx("button", { type: "button", "aria-label": label, "aria-pressed": active, onClick: () => onChange(option), className: cn("grid size-7 place-items-center rounded-sm transition-colors", active
|
|
24
|
+
? "bg-muted text-foreground"
|
|
25
|
+
: "text-muted-foreground hover:text-foreground"), children: _jsx(Icon, { className: "size-4", "aria-hidden": true }) }, option));
|
|
26
|
+
}) }));
|
|
46
27
|
}
|
|
@@ -9,15 +9,7 @@ import { cn } from "../lib/utils.js";
|
|
|
9
9
|
* Bar height is an inline `scaleY` transform per frame; the `duration-75`
|
|
10
10
|
* transition is plain CSS, so the theme's global reduced-motion rule already
|
|
11
11
|
* collapses it — no JS-side handling needed here.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
});
|
|
12
|
+
*/
|
|
13
|
+
export function VoiceWaveform({ levels, className }) {
|
|
14
|
+
return (_jsx("span", { "aria-hidden": true, className: cn("inline-flex h-4 items-center gap-px", className), children: levels.map((level, index) => (_jsx("i", { className: "inline-block h-full w-0.5 origin-center rounded-full bg-current transition-transform duration-75", style: { transform: `scaleY(${Math.max(0.08, Math.min(1, level))})` } }, index))) }));
|
|
23
15
|
}
|