@corbits/react-ui 0.1.0 → 0.2.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 +11 -11
- package/dist/test/render-hook.js +11 -12
- package/dist/theme.css +51 -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 +1 -1
- package/dist/ui/avatar.js +11 -48
- 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 +71 -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 +94 -535
package/dist/ui/file-input.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { Upload } from "lucide-react";
|
|
3
4
|
import { useRef, useState } from "react";
|
|
@@ -18,49 +19,28 @@ import { cn } from "../lib/utils.js";
|
|
|
18
19
|
* The input is cleared after each selection so choosing the same file twice
|
|
19
20
|
* still fires — the browser's change event will not repeat for an identical
|
|
20
21
|
* value.
|
|
21
|
-
*/
|
|
22
|
+
*/
|
|
23
|
+
export function FileInput({ onFiles, label = "Choose files", hint, className, disabled, ...props }) {
|
|
22
24
|
const [dragging, setDragging] = useState(false);
|
|
23
25
|
const inputRef = useRef(null);
|
|
24
|
-
return
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
return (_jsxs("label", { onDragOver: (event) => {
|
|
27
|
+
if (disabled === true)
|
|
28
|
+
return;
|
|
27
29
|
event.preventDefault();
|
|
28
30
|
setDragging(true);
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (disabled === true) return;
|
|
31
|
+
}, onDragLeave: () => setDragging(false), onDrop: (event) => {
|
|
32
|
+
if (disabled === true)
|
|
33
|
+
return;
|
|
33
34
|
event.preventDefault();
|
|
34
35
|
setDragging(false);
|
|
35
|
-
if (event.dataTransfer.files.length > 0)
|
|
36
|
-
|
|
37
|
-
className: cn("flex cursor-pointer flex-col items-center gap-1.5 rounded-lg border border-dashed border-input px-6 py-8 text-center transition-colors", dragging && "border-primary-emphasis bg-primary/10", disabled === true ? "cursor-not-allowed opacity-50" : "hover:bg-muted",
|
|
36
|
+
if (event.dataTransfer.files.length > 0)
|
|
37
|
+
onFiles(event.dataTransfer.files);
|
|
38
|
+
}, className: cn("flex cursor-pointer flex-col items-center gap-1.5 rounded-lg border border-dashed border-input px-6 py-8 text-center transition-colors", dragging && "border-primary-emphasis bg-primary/10", disabled === true ? "cursor-not-allowed opacity-50" : "hover:bg-muted",
|
|
39
|
+
// The focus ring lives on the hidden input; project it onto the zone,
|
|
38
40
|
// which is the thing the user can actually see.
|
|
39
|
-
"has-[input:focus-visible]:outline has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-2 has-[input:focus-visible]:outline-[var(--ring)]", className),
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
ref: inputRef,
|
|
43
|
-
type: "file",
|
|
44
|
-
disabled: disabled,
|
|
45
|
-
className: "sr-only",
|
|
46
|
-
onChange: (event)=>{
|
|
47
|
-
if (event.target.files !== null && event.target.files.length > 0) onFiles(event.target.files);
|
|
41
|
+
"has-[input:focus-visible]:outline has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-2 has-[input:focus-visible]:outline-[var(--ring)]", className), children: [_jsx("input", { ref: inputRef, type: "file", disabled: disabled, className: "sr-only", onChange: (event) => {
|
|
42
|
+
if (event.target.files !== null && event.target.files.length > 0)
|
|
43
|
+
onFiles(event.target.files);
|
|
48
44
|
event.target.value = "";
|
|
49
|
-
},
|
|
50
|
-
...props
|
|
51
|
-
}),
|
|
52
|
-
/*#__PURE__*/ _jsx(Upload, {
|
|
53
|
-
className: "size-5 text-muted-foreground",
|
|
54
|
-
"aria-hidden": true
|
|
55
|
-
}),
|
|
56
|
-
/*#__PURE__*/ _jsx("span", {
|
|
57
|
-
className: "text-sm font-medium",
|
|
58
|
-
children: label
|
|
59
|
-
}),
|
|
60
|
-
/*#__PURE__*/ _jsx("span", {
|
|
61
|
-
className: "text-xs text-muted-foreground",
|
|
62
|
-
children: hint ?? "or drag them here"
|
|
63
|
-
})
|
|
64
|
-
]
|
|
65
|
-
});
|
|
45
|
+
}, ...props }), _jsx(Upload, { className: "size-5 text-muted-foreground", "aria-hidden": true }), _jsx("span", { className: "text-sm font-medium", children: label }), _jsx("span", { className: "text-xs text-muted-foreground", children: hint ?? "or drag them here" })] }));
|
|
66
46
|
}
|
package/dist/ui/filter-bar.d.ts
CHANGED
|
@@ -39,4 +39,4 @@ export type FilterBarProps = {
|
|
|
39
39
|
* URL. Owning it here would mean every consumer fights the component to make
|
|
40
40
|
* their filters linkable.
|
|
41
41
|
*/
|
|
42
|
-
export declare function FilterBar({ filters, onChange, children, className }: FilterBarProps): import("react").JSX.Element;
|
|
42
|
+
export declare function FilterBar({ filters, onChange, children, className, }: FilterBarProps): import("react").JSX.Element;
|
package/dist/ui/filter-bar.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { X } from "lucide-react";
|
|
3
4
|
import { cn } from "../lib/utils.js";
|
|
@@ -21,75 +22,14 @@ import { Button } from "./button.js";
|
|
|
21
22
|
* Filter state lives with the caller because it almost always also lives in the
|
|
22
23
|
* URL. Owning it here would mean every consumer fights the component to make
|
|
23
24
|
* their filters linkable.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
children: [
|
|
35
|
-
filter.label,
|
|
36
|
-
/*#__PURE__*/ _jsxs("select", {
|
|
37
|
-
value: filter.value ?? "",
|
|
38
|
-
onChange: (event)=>onChange(filter.id, event.target.value === "" ? null : event.target.value),
|
|
39
|
-
className: "h-8 rounded-md border border-input bg-card px-2 text-xs text-foreground",
|
|
40
|
-
children: [
|
|
41
|
-
/*#__PURE__*/ _jsx("option", {
|
|
42
|
-
value: "",
|
|
43
|
-
children: filter.anyLabel
|
|
44
|
-
}),
|
|
45
|
-
filter.options.map((option)=>/*#__PURE__*/ _jsx("option", {
|
|
46
|
-
value: option.value,
|
|
47
|
-
children: option.label
|
|
48
|
-
}, option.value))
|
|
49
|
-
]
|
|
50
|
-
})
|
|
51
|
-
]
|
|
52
|
-
}, filter.id)),
|
|
53
|
-
children
|
|
54
|
-
]
|
|
55
|
-
}),
|
|
56
|
-
active.length === 0 ? null : /*#__PURE__*/ _jsxs("div", {
|
|
57
|
-
className: "flex flex-wrap items-center gap-2",
|
|
58
|
-
children: [
|
|
59
|
-
active.map((filter)=>{
|
|
60
|
-
const option = filter.options.find((candidate)=>candidate.value === filter.value);
|
|
61
|
-
return /*#__PURE__*/ _jsxs("button", {
|
|
62
|
-
type: "button",
|
|
63
|
-
onClick: ()=>onChange(filter.id, null),
|
|
64
|
-
// The whole chip is the remove control, and its accessible name
|
|
65
|
-
// says so — an "×" alone is announced as "times".
|
|
66
|
-
"aria-label": `Remove filter ${filter.label}: ${option?.label ?? filter.value}`,
|
|
67
|
-
className: "inline-flex items-center gap-1 rounded-sm bg-muted px-2 py-0.5 text-xs text-muted-foreground transition-colors hover:text-foreground",
|
|
68
|
-
children: [
|
|
69
|
-
/*#__PURE__*/ _jsx("span", {
|
|
70
|
-
className: "font-medium text-foreground",
|
|
71
|
-
children: filter.label
|
|
72
|
-
}),
|
|
73
|
-
option?.label ?? filter.value,
|
|
74
|
-
/*#__PURE__*/ _jsx(X, {
|
|
75
|
-
className: "size-3",
|
|
76
|
-
"aria-hidden": true
|
|
77
|
-
})
|
|
78
|
-
]
|
|
79
|
-
}, filter.id);
|
|
80
|
-
}),
|
|
81
|
-
/*#__PURE__*/ _jsx(Button, {
|
|
82
|
-
type: "button",
|
|
83
|
-
variant: "ghost",
|
|
84
|
-
size: "sm",
|
|
85
|
-
className: "h-6 px-2 text-xs",
|
|
86
|
-
onClick: ()=>{
|
|
87
|
-
for (const filter of active)onChange(filter.id, null);
|
|
88
|
-
},
|
|
89
|
-
children: "Clear all"
|
|
90
|
-
})
|
|
91
|
-
]
|
|
92
|
-
})
|
|
93
|
-
]
|
|
94
|
-
});
|
|
25
|
+
*/
|
|
26
|
+
export function FilterBar({ filters, onChange, children, className, }) {
|
|
27
|
+
const active = filters.filter((filter) => filter.value !== null);
|
|
28
|
+
return (_jsxs("div", { className: cn("flex flex-col gap-2", className), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [filters.map((filter) => (_jsxs("label", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [filter.label, _jsxs("select", { value: filter.value ?? "", onChange: (event) => onChange(filter.id, event.target.value === "" ? null : event.target.value), className: "h-8 rounded-md border border-input bg-card px-2 text-xs text-foreground", children: [_jsx("option", { value: "", children: filter.anyLabel }), filter.options.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value)))] })] }, filter.id))), children] }), active.length === 0 ? null : (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [active.map((filter) => {
|
|
29
|
+
const option = filter.options.find((candidate) => candidate.value === filter.value);
|
|
30
|
+
return (_jsxs("button", { type: "button", onClick: () => onChange(filter.id, null), "aria-label": `Remove filter ${filter.label}: ${option?.label ?? filter.value}`, className: "inline-flex items-center gap-1 rounded-sm bg-muted px-2 py-0.5 text-xs text-muted-foreground transition-colors hover:text-foreground", children: [_jsx("span", { className: "font-medium text-foreground", children: filter.label }), option?.label ?? filter.value, _jsx(X, { className: "size-3", "aria-hidden": true })] }, filter.id));
|
|
31
|
+
}), _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-6 px-2 text-xs", onClick: () => {
|
|
32
|
+
for (const filter of active)
|
|
33
|
+
onChange(filter.id, null);
|
|
34
|
+
}, children: "Clear all" })] }))] }));
|
|
95
35
|
}
|
package/dist/ui/filter-chip.d.ts
CHANGED
|
@@ -11,4 +11,4 @@ export type FilterChipProps = {
|
|
|
11
11
|
* `<button>` with `aria-pressed`, not a styled label, so the selection state
|
|
12
12
|
* is announced and the control is reachable with Space/Enter alone.
|
|
13
13
|
*/
|
|
14
|
-
export declare function FilterChip({ selected, onClick, children, count, className }: FilterChipProps): import("react").JSX.Element;
|
|
14
|
+
export declare function FilterChip({ selected, onClick, children, count, className, }: FilterChipProps): import("react").JSX.Element;
|
package/dist/ui/filter-chip.js
CHANGED
|
@@ -4,20 +4,12 @@ import { cn } from "../lib/utils.js";
|
|
|
4
4
|
* A toggleable filter pill — a category, a tag, a facet value. A real
|
|
5
5
|
* `<button>` with `aria-pressed`, not a styled label, so the selection state
|
|
6
6
|
* is announced and the control is reachable with Space/Enter alone.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
onClick: onClick,
|
|
12
|
-
className: cn(// active:brightness-95 mirrors Button's press state: it lands on
|
|
7
|
+
*/
|
|
8
|
+
export function FilterChip({ selected = false, onClick, children, count, className, }) {
|
|
9
|
+
return (_jsxs("button", { type: "button", "aria-pressed": selected, onClick: onClick, className: cn(
|
|
10
|
+
// active:brightness-95 mirrors Button's press state: it lands on
|
|
13
11
|
// pointer-down, so it sits outside transition-colors.
|
|
14
|
-
"inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-semibold transition-colors ease-out active:brightness-95", selected
|
|
15
|
-
|
|
16
|
-
children,
|
|
17
|
-
count === undefined ? null : /*#__PURE__*/ _jsx("span", {
|
|
18
|
-
className: cn("text-[10.5px] font-bold", selected ? "text-primary-emphasis" : "text-muted-foreground"),
|
|
19
|
-
children: count
|
|
20
|
-
})
|
|
21
|
-
]
|
|
22
|
-
});
|
|
12
|
+
"inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-semibold transition-colors ease-out active:brightness-95", selected
|
|
13
|
+
? "border-border bg-card text-foreground shadow-sm"
|
|
14
|
+
: "border-border bg-transparent text-muted-foreground hover:bg-muted hover:text-foreground", className), children: [children, count === undefined ? null : (_jsx("span", { className: cn("text-[10.5px] font-bold", selected ? "text-primary-emphasis" : "text-muted-foreground"), children: count }))] }));
|
|
23
15
|
}
|
package/dist/ui/gate-block.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import { type GateShellModel } from "../lib/workflow-registry.js";
|
|
3
|
+
export type { GateKind, GateShellModel } from "../lib/workflow-registry.js";
|
|
3
4
|
export type GateBlockProps = {
|
|
4
5
|
readonly gate: GateShellModel;
|
|
5
6
|
/** The interactive payload — a review list, choice buttons, a form. */
|
|
@@ -13,4 +14,4 @@ export type GateBlockProps = {
|
|
|
13
14
|
* component only frames it, so the resume-payload contract stays wherever
|
|
14
15
|
* the host's signal-sending logic already lives.
|
|
15
16
|
*/
|
|
16
|
-
export declare function GateBlock({ gate, children, footer, className }: GateBlockProps): import("react").JSX.Element;
|
|
17
|
+
export declare function GateBlock({ gate, children, footer, className, }: GateBlockProps): import("react").JSX.Element;
|
package/dist/ui/gate-block.js
CHANGED
|
@@ -1,37 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { GATE_KIND_LABEL } from "../lib/workflow-registry.js";
|
|
2
|
+
import { GATE_KIND_LABEL, } from "../lib/workflow-registry.js";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
4
|
/**
|
|
5
5
|
* Presentational chrome for a pending gate: a run parked on a human
|
|
6
6
|
* decision. The interactive payload is entirely the caller's — this
|
|
7
7
|
* component only frames it, so the resume-payload contract stays wherever
|
|
8
8
|
* the host's signal-sending logic already lives.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"aria-label": GATE_KIND_LABEL[gate.kind],
|
|
13
|
-
className: cn("rounded-lg border border-primary-emphasis/30 bg-primary/5 px-3.5 py-3", className),
|
|
14
|
-
children: [
|
|
15
|
-
/*#__PURE__*/ _jsx("p", {
|
|
16
|
-
className: "text-[10.5px] font-bold uppercase tracking-[0.05em] text-primary-emphasis",
|
|
17
|
-
children: GATE_KIND_LABEL[gate.kind]
|
|
18
|
-
}),
|
|
19
|
-
/*#__PURE__*/ _jsx("h3", {
|
|
20
|
-
className: "mt-1 text-sm font-semibold",
|
|
21
|
-
children: gate.title
|
|
22
|
-
}),
|
|
23
|
-
gate.prompt === undefined ? null : /*#__PURE__*/ _jsx("p", {
|
|
24
|
-
className: "mt-1 text-xs leading-snug text-muted-foreground",
|
|
25
|
-
children: gate.prompt
|
|
26
|
-
}),
|
|
27
|
-
children === undefined ? null : /*#__PURE__*/ _jsx("div", {
|
|
28
|
-
className: "mt-3",
|
|
29
|
-
children: children
|
|
30
|
-
}),
|
|
31
|
-
footer === undefined ? null : /*#__PURE__*/ _jsx("div", {
|
|
32
|
-
className: "mt-3 flex flex-wrap items-center gap-2",
|
|
33
|
-
children: footer
|
|
34
|
-
})
|
|
35
|
-
]
|
|
36
|
-
});
|
|
9
|
+
*/
|
|
10
|
+
export function GateBlock({ gate, children, footer, className, }) {
|
|
11
|
+
return (_jsxs("section", { "data-gate-kind": gate.kind, "aria-label": GATE_KIND_LABEL[gate.kind], className: cn("rounded-lg border border-primary-emphasis/30 bg-primary/5 px-3.5 py-3", className), children: [_jsx("p", { className: "text-[10.5px] font-bold uppercase tracking-[0.05em] text-primary-emphasis", children: GATE_KIND_LABEL[gate.kind] }), _jsx("h3", { className: "mt-1 text-sm font-semibold", children: gate.title }), gate.prompt === undefined ? null : (_jsx("p", { className: "mt-1 text-xs leading-snug text-muted-foreground", children: gate.prompt })), children === undefined ? null : _jsx("div", { className: "mt-3", children: children }), footer === undefined ? null : (_jsx("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: footer }))] }));
|
|
37
12
|
}
|
|
@@ -10,4 +10,4 @@ export type HorizontalStepperProps = {
|
|
|
10
10
|
* change, so a run with more steps than fit on screen never leaves the
|
|
11
11
|
* active one off to the side unannounced.
|
|
12
12
|
*/
|
|
13
|
-
export declare function HorizontalStepper({ steps, className }: HorizontalStepperProps): import("react").JSX.Element;
|
|
13
|
+
export declare function HorizontalStepper({ steps, className, }: HorizontalStepperProps): import("react").JSX.Element;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { useScrollCurrentIntoView } from "../hooks/use-scroll-current-into-view.js";
|
|
3
|
-
import { workflowStepGlyph, workflowStepLabelClass } from "../lib/workflow-run-progress.js";
|
|
4
|
+
import { workflowStepGlyph, workflowStepLabelClass, } from "../lib/workflow-run-progress.js";
|
|
4
5
|
import { cn } from "../lib/utils.js";
|
|
5
6
|
// Above this many steps, an even split can't give every label readable room,
|
|
6
7
|
// so labels compress to numbers-only pills except for the current step — the
|
|
@@ -8,9 +9,12 @@ import { cn } from "../lib/utils.js";
|
|
|
8
9
|
// renders (`sr-only`) so a screen reader still hears the full sequence.
|
|
9
10
|
const LABEL_VISIBLE_STEP_THRESHOLD = 5;
|
|
10
11
|
function pillClass(status) {
|
|
11
|
-
if (status === "completed")
|
|
12
|
-
|
|
13
|
-
if (status === "
|
|
12
|
+
if (status === "completed")
|
|
13
|
+
return "bg-success text-success-foreground";
|
|
14
|
+
if (status === "failed")
|
|
15
|
+
return "bg-destructive text-destructive-foreground";
|
|
16
|
+
if (status === "current")
|
|
17
|
+
return "bg-primary text-primary-foreground";
|
|
14
18
|
return "bg-muted text-muted-foreground";
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
@@ -19,47 +23,16 @@ function pillClass(status) {
|
|
|
19
23
|
* work. Scrolls the current step into view on mount and on every step
|
|
20
24
|
* change, so a run with more steps than fit on screen never leaves the
|
|
21
25
|
* active one off to the side unannounced.
|
|
22
|
-
*/
|
|
23
|
-
|
|
26
|
+
*/
|
|
27
|
+
export function HorizontalStepper({ steps, className, }) {
|
|
28
|
+
const currentStep = steps.find((step) => step.status === "current");
|
|
24
29
|
const currentRef = useScrollCurrentIntoView(currentStep?.number ?? -1);
|
|
25
30
|
const compress = steps.length > LABEL_VISIBLE_STEP_THRESHOLD;
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"aria-current": step.status === "current" ? "step" : undefined,
|
|
34
|
-
className: cn("flex min-w-0 items-center gap-2 last:flex-initial md:gap-3", compress ? step.status === "current" ? "flex-[8_1_0%]" : "flex-1" : "flex-1"),
|
|
35
|
-
children: [
|
|
36
|
-
/*#__PURE__*/ _jsxs("span", {
|
|
37
|
-
className: "relative flex size-8 shrink-0 items-center justify-center",
|
|
38
|
-
children: [
|
|
39
|
-
step.status === "current" ? /*#__PURE__*/ _jsx("span", {
|
|
40
|
-
"aria-hidden": true,
|
|
41
|
-
className: "absolute inset-0 rounded-full bg-primary/30 motion-safe:[animation:corbits-status-pulse_1.8s_ease-out_infinite]"
|
|
42
|
-
}) : null,
|
|
43
|
-
/*#__PURE__*/ _jsx("span", {
|
|
44
|
-
className: cn("relative flex size-8 items-center justify-center rounded-full text-sm font-medium transition-colors", pillClass(step.status)),
|
|
45
|
-
children: workflowStepGlyph(step.status, step.number)
|
|
46
|
-
})
|
|
47
|
-
]
|
|
48
|
-
}),
|
|
49
|
-
/*#__PURE__*/ _jsx("span", {
|
|
50
|
-
title: step.label,
|
|
51
|
-
className: cn("min-w-0 flex-1 truncate text-sm font-medium", compress && step.status !== "current" ? "sr-only" : workflowStepLabelClass(step.status)),
|
|
52
|
-
children: step.label
|
|
53
|
-
}),
|
|
54
|
-
index === steps.length - 1 ? null : /*#__PURE__*/ _jsx("span", {
|
|
55
|
-
className: cn("h-0.5 shrink-0 overflow-hidden rounded-full bg-border", compress ? "min-w-2 flex-1" : "w-4 md:w-6"),
|
|
56
|
-
children: /*#__PURE__*/ _jsx("span", {
|
|
57
|
-
"data-filled": step.status === "completed",
|
|
58
|
-
className: "block h-full w-full origin-left rounded-full bg-success transition-transform duration-300 ease-out data-[filled=false]:scale-x-0 data-[filled=true]:scale-x-100"
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
]
|
|
62
|
-
}, step.number))
|
|
63
|
-
})
|
|
64
|
-
});
|
|
31
|
+
return (_jsx("div", { className: cn("border-b border-border bg-card px-6 py-5", className), children: _jsx("ol", { "aria-label": "Workflow progress", className: "flex items-center gap-2 overflow-x-auto [mask-image:linear-gradient(to_right,transparent,black_12px,black_calc(100%-12px),transparent)] md:gap-3", children: steps.map((step, index) => (_jsxs("li", { ref: step.status === "current" ? currentRef : undefined, "aria-current": step.status === "current" ? "step" : undefined, className: cn("flex min-w-0 items-center gap-2 last:flex-initial md:gap-3", compress
|
|
32
|
+
? step.status === "current"
|
|
33
|
+
? "flex-[8_1_0%]"
|
|
34
|
+
: "flex-1"
|
|
35
|
+
: "flex-1"), children: [_jsxs("span", { className: "relative flex size-8 shrink-0 items-center justify-center", children: [step.status === "current" ? (_jsx("span", { "aria-hidden": true, className: "absolute inset-0 rounded-full bg-primary/30 motion-safe:[animation:corbits-status-pulse_1.8s_ease-out_infinite]" })) : null, _jsx("span", { className: cn("relative flex size-8 items-center justify-center rounded-full text-sm font-medium transition-colors", pillClass(step.status)), children: workflowStepGlyph(step.status, step.number) })] }), _jsx("span", { title: step.label, className: cn("min-w-0 flex-1 truncate text-sm font-medium", compress && step.status !== "current"
|
|
36
|
+
? "sr-only"
|
|
37
|
+
: workflowStepLabelClass(step.status)), children: step.label }), index === steps.length - 1 ? null : (_jsx("span", { className: cn("h-0.5 shrink-0 overflow-hidden rounded-full bg-border", compress ? "min-w-2 flex-1" : "w-4 md:w-6"), children: _jsx("span", { "data-filled": step.status === "completed", className: "block h-full w-full origin-left rounded-full bg-success transition-transform duration-300 ease-out data-[filled=false]:scale-x-0 data-[filled=true]:scale-x-100" }) }))] }, step.number))) }) }));
|
|
65
38
|
}
|
package/dist/ui/input.js
CHANGED
|
@@ -5,10 +5,5 @@ import { cn } from "../lib/utils.js";
|
|
|
5
5
|
// edge. `border-border` is the soft decorative one and must not be used here.
|
|
6
6
|
// The focus ring comes from the theme's base layer, not from this file.
|
|
7
7
|
export function Input({ className, type, ...props }) {
|
|
8
|
-
return
|
|
9
|
-
type: type,
|
|
10
|
-
"data-slot": "input",
|
|
11
|
-
className: cn("flex h-9 w-full min-w-0 rounded-md border border-input bg-card px-3 py-1 text-sm shadow-xs transition-colors", "placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", "aria-invalid:border-destructive disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
12
|
-
...props
|
|
13
|
-
});
|
|
8
|
+
return (_jsx("input", { type: type, "data-slot": "input", className: cn("flex h-9 w-full min-w-0 rounded-md border border-input bg-card px-3 py-1 text-sm shadow-xs transition-colors", "placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", "aria-invalid:border-destructive disabled:cursor-not-allowed disabled:opacity-50", className), ...props }));
|
|
14
9
|
}
|
|
@@ -7,7 +7,7 @@ export type InspectorEmptyProps = {
|
|
|
7
7
|
/** The "nothing selected" message inside an inspector rail. Deliberately not
|
|
8
8
|
* `EmptyState` — that component centres and pads for a full-width surface;
|
|
9
9
|
* an inspector's empty message sits left-aligned in a narrow side panel. */
|
|
10
|
-
export declare function InspectorEmpty({ title, description, className }: InspectorEmptyProps): import("react").JSX.Element;
|
|
10
|
+
export declare function InspectorEmpty({ title, description, className, }: InspectorEmptyProps): import("react").JSX.Element;
|
|
11
11
|
export type InspectorHeaderProps = {
|
|
12
12
|
readonly eyebrow?: ReactNode;
|
|
13
13
|
readonly title: ReactNode;
|
|
@@ -16,8 +16,8 @@ export type InspectorHeaderProps = {
|
|
|
16
16
|
readonly className?: string;
|
|
17
17
|
};
|
|
18
18
|
/** The chip row, title and action buttons at the top of an inspector. */
|
|
19
|
-
export declare function InspectorHeader({ eyebrow, title, description, actions, className }: InspectorHeaderProps): import("react").JSX.Element;
|
|
20
|
-
export declare function InspectorPanelTitle({ children, className }: {
|
|
19
|
+
export declare function InspectorHeader({ eyebrow, title, description, actions, className, }: InspectorHeaderProps): import("react").JSX.Element;
|
|
20
|
+
export declare function InspectorPanelTitle({ children, className, }: {
|
|
21
21
|
readonly children: ReactNode;
|
|
22
22
|
readonly className?: string;
|
|
23
23
|
}): import("react").JSX.Element;
|
|
@@ -26,7 +26,7 @@ export type InspectorKvRow = {
|
|
|
26
26
|
readonly value: ReactNode;
|
|
27
27
|
readonly mono?: boolean;
|
|
28
28
|
};
|
|
29
|
-
export declare function InspectorKv({ rows, className }: {
|
|
29
|
+
export declare function InspectorKv({ rows, className, }: {
|
|
30
30
|
readonly rows: readonly InspectorKvRow[];
|
|
31
31
|
readonly className?: string;
|
|
32
32
|
}): import("react").JSX.Element;
|
|
@@ -44,4 +44,4 @@ export type InspectorShellProps = {
|
|
|
44
44
|
* separately so a caller can compose its own layout inside this shell
|
|
45
45
|
* instead of going through a single big inspector component.
|
|
46
46
|
*/
|
|
47
|
-
export declare function InspectorShell({ header, children, empty, className }: InspectorShellProps): import("react").JSX.Element;
|
|
47
|
+
export declare function InspectorShell({ header, children, empty, className, }: InspectorShellProps): import("react").JSX.Element;
|
|
@@ -2,67 +2,19 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
3
|
/** The "nothing selected" message inside an inspector rail. Deliberately not
|
|
4
4
|
* `EmptyState` — that component centres and pads for a full-width surface;
|
|
5
|
-
* an inspector's empty message sits left-aligned in a narrow side panel. */
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
children: [
|
|
9
|
-
/*#__PURE__*/ _jsx("p", {
|
|
10
|
-
className: "text-sm font-semibold",
|
|
11
|
-
children: title
|
|
12
|
-
}),
|
|
13
|
-
description === undefined ? null : /*#__PURE__*/ _jsx("p", {
|
|
14
|
-
className: "mt-1.5 text-xs leading-snug text-muted-foreground",
|
|
15
|
-
children: description
|
|
16
|
-
})
|
|
17
|
-
]
|
|
18
|
-
});
|
|
5
|
+
* an inspector's empty message sits left-aligned in a narrow side panel. */
|
|
6
|
+
export function InspectorEmpty({ title, description, className, }) {
|
|
7
|
+
return (_jsxs("div", { className: cn("max-w-64", className), children: [_jsx("p", { className: "text-sm font-semibold", children: title }), description === undefined ? null : (_jsx("p", { className: "mt-1.5 text-xs leading-snug text-muted-foreground", children: description }))] }));
|
|
19
8
|
}
|
|
20
|
-
/** The chip row, title and action buttons at the top of an inspector. */
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
children: [
|
|
24
|
-
eyebrow === undefined ? null : /*#__PURE__*/ _jsx("div", {
|
|
25
|
-
className: "flex flex-wrap items-center gap-1.5",
|
|
26
|
-
children: eyebrow
|
|
27
|
-
}),
|
|
28
|
-
/*#__PURE__*/ _jsx("h2", {
|
|
29
|
-
className: "text-base font-bold tracking-tight",
|
|
30
|
-
children: title
|
|
31
|
-
}),
|
|
32
|
-
description === undefined ? null : /*#__PURE__*/ _jsx("p", {
|
|
33
|
-
className: "text-xs leading-snug text-muted-foreground",
|
|
34
|
-
children: description
|
|
35
|
-
}),
|
|
36
|
-
actions === undefined ? null : /*#__PURE__*/ _jsx("div", {
|
|
37
|
-
className: "mt-1 flex flex-wrap items-center gap-1.5",
|
|
38
|
-
children: actions
|
|
39
|
-
})
|
|
40
|
-
]
|
|
41
|
-
});
|
|
9
|
+
/** The chip row, title and action buttons at the top of an inspector. */
|
|
10
|
+
export function InspectorHeader({ eyebrow, title, description, actions, className, }) {
|
|
11
|
+
return (_jsxs("div", { className: cn("flex flex-col gap-2", className), children: [eyebrow === undefined ? null : (_jsx("div", { className: "flex flex-wrap items-center gap-1.5", children: eyebrow })), _jsx("h2", { className: "text-base font-bold tracking-tight", children: title }), description === undefined ? null : (_jsx("p", { className: "text-xs leading-snug text-muted-foreground", children: description })), actions === undefined ? null : (_jsx("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: actions }))] }));
|
|
42
12
|
}
|
|
43
|
-
export function InspectorPanelTitle({ children, className }) {
|
|
44
|
-
return
|
|
45
|
-
className: cn("mb-2 mt-4 text-[10.5px] font-bold uppercase tracking-[0.05em] text-muted-foreground first:mt-0", className),
|
|
46
|
-
children: children
|
|
47
|
-
});
|
|
13
|
+
export function InspectorPanelTitle({ children, className, }) {
|
|
14
|
+
return (_jsx("div", { className: cn("mb-2 mt-4 text-[10.5px] font-bold uppercase tracking-[0.05em] text-muted-foreground first:mt-0", className), children: children }));
|
|
48
15
|
}
|
|
49
|
-
export function InspectorKv({ rows, className }) {
|
|
50
|
-
return
|
|
51
|
-
className: cn("flex flex-col gap-1.5", className),
|
|
52
|
-
children: rows.map((row)=>/*#__PURE__*/ _jsxs("div", {
|
|
53
|
-
className: "flex items-baseline justify-between gap-3 text-xs",
|
|
54
|
-
children: [
|
|
55
|
-
/*#__PURE__*/ _jsx("span", {
|
|
56
|
-
className: "shrink-0 text-muted-foreground",
|
|
57
|
-
children: row.label
|
|
58
|
-
}),
|
|
59
|
-
/*#__PURE__*/ _jsx("span", {
|
|
60
|
-
className: cn("min-w-0 truncate text-right", row.mono === true && "font-mono"),
|
|
61
|
-
children: row.value
|
|
62
|
-
})
|
|
63
|
-
]
|
|
64
|
-
}, row.label))
|
|
65
|
-
});
|
|
16
|
+
export function InspectorKv({ rows, className, }) {
|
|
17
|
+
return (_jsx("div", { className: cn("flex flex-col gap-1.5", className), children: rows.map((row) => (_jsxs("div", { className: "flex items-baseline justify-between gap-3 text-xs", children: [_jsx("span", { className: "shrink-0 text-muted-foreground", children: row.label }), _jsx("span", { className: cn("min-w-0 truncate text-right", row.mono === true && "font-mono"), children: row.value })] }, row.label))) }));
|
|
66
18
|
}
|
|
67
19
|
/**
|
|
68
20
|
* The side-rail frame every inspector shares: a header region, a scrollable
|
|
@@ -70,29 +22,10 @@ export function InspectorKv({ rows, className }) {
|
|
|
70
22
|
* `InspectorHeader`/`InspectorKv`/`InspectorPanelTitle` are exported
|
|
71
23
|
* separately so a caller can compose its own layout inside this shell
|
|
72
24
|
* instead of going through a single big inspector component.
|
|
73
|
-
*/
|
|
25
|
+
*/
|
|
26
|
+
export function InspectorShell({ header, children, empty, className, }) {
|
|
74
27
|
if (empty !== undefined && header === undefined) {
|
|
75
|
-
return
|
|
76
|
-
"aria-label": "Inspector",
|
|
77
|
-
className: cn("flex min-h-0 flex-col overflow-auto border-l border-border bg-card", className),
|
|
78
|
-
children: /*#__PURE__*/ _jsx("div", {
|
|
79
|
-
className: "flex flex-1 flex-col items-start justify-center px-5 py-10",
|
|
80
|
-
children: empty
|
|
81
|
-
})
|
|
82
|
-
});
|
|
28
|
+
return (_jsx("aside", { "aria-label": "Inspector", className: cn("flex min-h-0 flex-col overflow-auto border-l border-border bg-card", className), children: _jsx("div", { className: "flex flex-1 flex-col items-start justify-center px-5 py-10", children: empty }) }));
|
|
83
29
|
}
|
|
84
|
-
return
|
|
85
|
-
"aria-label": "Inspector",
|
|
86
|
-
className: cn("flex min-h-0 flex-col overflow-hidden border-l border-border bg-card", className),
|
|
87
|
-
children: [
|
|
88
|
-
header === undefined ? null : /*#__PURE__*/ _jsx("div", {
|
|
89
|
-
className: "shrink-0 border-b border-border px-4 pb-3 pt-4",
|
|
90
|
-
children: header
|
|
91
|
-
}),
|
|
92
|
-
/*#__PURE__*/ _jsx("div", {
|
|
93
|
-
className: "min-h-0 flex-1 overflow-auto px-4 py-3",
|
|
94
|
-
children: children
|
|
95
|
-
})
|
|
96
|
-
]
|
|
97
|
-
});
|
|
30
|
+
return (_jsxs("aside", { "aria-label": "Inspector", className: cn("flex min-h-0 flex-col overflow-hidden border-l border-border bg-card", className), children: [header === undefined ? null : (_jsx("div", { className: "shrink-0 border-b border-border px-4 pb-3 pt-4", children: header })), _jsx("div", { className: "min-h-0 flex-1 overflow-auto px-4 py-3", children: children })] }));
|
|
98
31
|
}
|
package/dist/ui/intake-form.d.ts
CHANGED
|
@@ -36,4 +36,4 @@ export declare function intakeFieldsComplete(fields: readonly IntakeField[], val
|
|
|
36
36
|
* host owns the values, so the same form backs a one-off run and a saved
|
|
37
37
|
* schedule without this file knowing which.
|
|
38
38
|
*/
|
|
39
|
-
export declare function IntakeForm({ fields, values, onChange, idPrefix, disabled, className }: IntakeFormProps): import("react").JSX.Element | null;
|
|
39
|
+
export declare function IntakeForm({ fields, values, onChange, idPrefix, disabled, className, }: IntakeFormProps): import("react").JSX.Element | null;
|