@ctrl-ui/react 0.9.5 → 0.9.8
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/README.md +38 -2
- package/dist/action-bar.js +16 -8
- package/dist/activity.d.ts +4 -2
- package/dist/activity.js +5 -2
- package/dist/audio-visualizer.js +1 -1
- package/dist/blocks/agent-run-clock.d.ts +5 -0
- package/dist/blocks/agent-run-clock.js +52 -0
- package/dist/blocks/agent-run-sidebar.d.ts +13 -0
- package/dist/blocks/agent-run-sidebar.js +101 -0
- package/dist/blocks/agent-run-status.d.ts +32 -0
- package/dist/blocks/agent-run-status.js +27 -0
- package/dist/blocks/agent-run.d.ts +82 -0
- package/dist/blocks/agent-run.js +262 -0
- package/dist/blocks/coding-agent.d.ts +1 -1
- package/dist/blocks/coding-agent.js +50 -69
- package/dist/blocks/design-canvas-data.d.ts +1 -1
- package/dist/blocks/design-canvas-inspector.js +1 -1
- package/dist/blocks/design-canvas.d.ts +2 -1
- package/dist/blocks/design-canvas.js +56 -42
- package/dist/blocks/discussion.js +1 -1
- package/dist/blocks/file-explorer.js +66 -47
- package/dist/blocks/settings.js +37 -41
- package/dist/blocks/team-chat.js +2 -1
- package/dist/blocks/theme-toggle.d.ts +2 -1
- package/dist/blocks/theme-toggle.js +13 -4
- package/dist/chat-message.js +33 -39
- package/dist/hooks/use-mobile.d.ts +1 -1
- package/dist/hooks/use-mobile.js +1 -1
- package/dist/knob-contracts/badge-knobs.d.ts +1 -1
- package/dist/knob-contracts/badge-knobs.js +3 -1
- package/dist/knob-contracts/button-knobs.d.ts +1 -1
- package/dist/knob-contracts/button-knobs.js +1 -0
- package/dist/knob-contracts/calendar-knobs.d.ts +1 -1
- package/dist/knob-contracts/calendar-knobs.js +9 -1
- package/dist/knob-contracts/card-knobs.d.ts +1 -1
- package/dist/knob-contracts/card-knobs.js +5 -1
- package/dist/knob-contracts/choice-knobs.d.ts +1 -1
- package/dist/knob-contracts/choice-knobs.js +1 -0
- package/dist/knob-contracts/collapsible-knobs.d.ts +1 -1
- package/dist/knob-contracts/collapsible-knobs.js +5 -1
- package/dist/knob-contracts/emoji-picker-knobs.d.ts +1 -1
- package/dist/knob-contracts/emoji-picker-knobs.js +3 -1
- package/dist/knob-contracts/field-knobs.d.ts +1 -1
- package/dist/knob-contracts/field-knobs.js +17 -1
- package/dist/knob-contracts/infinite-canvas-knobs.d.ts +1 -1
- package/dist/knob-contracts/infinite-canvas-knobs.js +1 -7
- package/dist/knob-contracts/item-knobs.d.ts +1 -1
- package/dist/knob-contracts/item-knobs.js +5 -1
- package/dist/knob-contracts/kbd-knobs.d.ts +1 -1
- package/dist/knob-contracts/kbd-knobs.js +4 -1
- package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
- package/dist/knob-contracts/page-layout-knobs.js +1 -0
- package/dist/knob-contracts/pagination-knobs.d.ts +1 -1
- package/dist/knob-contracts/pagination-knobs.js +2 -1
- package/dist/knob-contracts/popup-knobs.d.ts +1 -1
- package/dist/knob-contracts/popup-knobs.js +9 -0
- package/dist/knob-contracts/range-knobs.d.ts +1 -1
- package/dist/knob-contracts/range-knobs.js +2 -0
- package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
- package/dist/knob-contracts/sidebar-knobs.js +2 -0
- package/dist/knob-contracts/swap-knobs.d.ts +4 -0
- package/dist/knob-contracts/swap-knobs.js +9 -0
- package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
- package/dist/knob-contracts/tabs-knobs.js +3 -0
- package/dist/knob-contracts/timeline-knobs.d.ts +1 -1
- package/dist/knob-contracts/timeline-knobs.js +5 -1
- package/dist/knob-contracts/tool-approval-knobs.d.ts +4 -0
- package/dist/knob-contracts/tool-approval-knobs.js +32 -0
- package/dist/knob-contracts/tree-knobs.d.ts +1 -1
- package/dist/knob-contracts/tree-knobs.js +3 -1
- package/dist/lib/infinite-canvas-camera-store.d.ts +65 -0
- package/dist/lib/infinite-canvas-camera-store.js +233 -0
- package/dist/lib/infinite-canvas-camera.d.ts +33 -0
- package/dist/lib/infinite-canvas-camera.js +98 -0
- package/dist/lib/infinite-canvas-navigation.d.ts +19 -0
- package/dist/lib/infinite-canvas-navigation.js +395 -0
- package/dist/markdown-editor/bubble-menu.d.ts +6 -0
- package/dist/markdown-editor/bubble-menu.js +45 -0
- package/dist/markdown-editor/toolbar.d.ts +17 -1
- package/dist/markdown-editor/toolbar.js +103 -81
- package/dist/skin.d.ts +2 -0
- package/dist/styles/index.css +11 -10
- package/dist/styles/recipes/activity.css +12 -0
- package/dist/styles/recipes/avatar.css +1 -1
- package/dist/styles/recipes/badge.css +17 -0
- package/dist/styles/recipes/button-group.css +12 -6
- package/dist/styles/recipes/button.css +20 -3
- package/dist/styles/recipes/calendar.css +82 -6
- package/dist/styles/recipes/card.css +40 -5
- package/dist/styles/recipes/chat-message-edit.css +6 -21
- package/dist/styles/recipes/choice.css +9 -2
- package/dist/styles/recipes/collapsible.css +8 -1
- package/dist/styles/recipes/color-picker-values.css +4 -0
- package/dist/styles/recipes/emoji-picker.css +29 -8
- package/dist/styles/recipes/field-parts.css +80 -5
- package/dist/styles/recipes/field.css +113 -40
- package/dist/styles/recipes/infinite-canvas.css +17 -57
- package/dist/styles/recipes/item.css +33 -5
- package/dist/styles/recipes/kbd.css +26 -6
- package/dist/styles/recipes/markdown-editor.css +12 -0
- package/dist/styles/recipes/morphing-panel.css +1 -1
- package/dist/styles/recipes/page-layout.css +18 -2
- package/dist/styles/recipes/pagination.css +8 -0
- package/dist/styles/recipes/popup-controls.css +9 -0
- package/dist/styles/recipes/popup-drawer.css +1 -0
- package/dist/styles/recipes/popup-lists.css +55 -6
- package/dist/styles/recipes/popup-motion.css +7 -1
- package/dist/styles/recipes/popup.css +10 -0
- package/dist/styles/recipes/range.css +16 -2
- package/dist/styles/recipes/sidebar-mobile.css +1 -1
- package/dist/styles/recipes/sidebar-parts.css +17 -1
- package/dist/styles/recipes/sidebar.css +11 -0
- package/dist/styles/recipes/swap.css +143 -0
- package/dist/styles/recipes/tabs.css +41 -8
- package/dist/styles/recipes/timeline.css +36 -2
- package/dist/styles/recipes/tool-approval.css +267 -0
- package/dist/styles/recipes/track-highlight.css +19 -6
- package/dist/styles/recipes/tree.css +33 -0
- package/dist/styles/theme.css +17 -6
- package/dist/tool-approval.d.ts +49 -0
- package/dist/tool-approval.js +260 -0
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/badge.js +1 -1
- package/dist/ui/calendar.js +9 -4
- package/dist/ui/card.d.ts +3 -1
- package/dist/ui/card.js +2 -1
- package/dist/ui/code.js +13 -3
- package/dist/ui/command.js +1 -0
- package/dist/ui/dialog.js +1 -1
- package/dist/ui/dropdown-menu.d.ts +1 -1
- package/dist/ui/dropdown-menu.js +23 -6
- package/dist/ui/dropzone.js +10 -11
- package/dist/ui/field.d.ts +6 -2
- package/dist/ui/field.js +4 -2
- package/dist/ui/infinite-canvas.d.ts +19 -22
- package/dist/ui/infinite-canvas.js +264 -325
- package/dist/ui/morphing-panel.d.ts +5 -1
- package/dist/ui/morphing-panel.js +4 -2
- package/dist/ui/rich-tooltip.d.ts +2 -1
- package/dist/ui/rich-tooltip.js +32 -29
- package/dist/ui/select.js +2 -2
- package/dist/ui/sidebar-mobile.js +1 -1
- package/dist/ui/sidebar-provider.d.ts +3 -1
- package/dist/ui/sidebar-provider.js +3 -2
- package/dist/ui/sidebar-resize-rail.js +1 -1
- package/dist/ui/sidebar.d.ts +6 -5
- package/dist/ui/sidebar.js +10 -9
- package/dist/ui/swap.d.ts +14 -0
- package/dist/ui/swap.js +69 -0
- package/dist/ui/tabs.d.ts +1 -1
- package/dist/ui/tabs.js +2 -13
- package/dist/ui/timeline.d.ts +1 -1
- package/dist/ui/timeline.js +2 -2
- package/dist/ui/typography.d.ts +11 -5
- package/dist/ui/typography.js +18 -6
- package/dist/user-ask.js +1 -1
- package/lint/biome-preset.json +3 -0
- package/lint/class-policy.mjs +17 -0
- package/lint/eslint-plugin.mjs +87 -0
- package/lint/grit-rules.mjs +40 -0
- package/lint/no-component-style-classes.grit +16 -0
- package/lint/no-raw-type-classes.grit +3 -4
- package/lint/write-grit-rules.mjs +19 -0
- package/package.json +12 -3
- package/dist/styles/type-scale.css +0 -72
package/README.md
CHANGED
|
@@ -47,10 +47,46 @@ const twMerge = extendTailwindMerge({ extend: { classGroups: { "font-size": [{ t
|
|
|
47
47
|
|
|
48
48
|
Controls size their own text: pick the control's `size`, or set its `--cui-*-font-size` knob in your theme, rather than wrapping the label in a `text-*` span.
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
## Lint rules
|
|
51
|
+
|
|
52
|
+
Two rules keep call sites honest, shipped for Biome, ESLint, and oxlint from one policy (`lint/class-policy.mjs`):
|
|
53
|
+
|
|
54
|
+
- `no-component-style-classes` errors when `className` on a component imported from `@ctrl-ui/react` (or a `components/control-ui` directory) sets what the component owns: colors, type, padding, borders, radius, shadows, state styles such as `hover:` and `data-[…]:`, or `!important`. Layout classes (`flex`, `gap-*`, widths, heights, margins, placement) stay allowed. Restyle through the component's props or its `--cui-*` knobs instead.
|
|
55
|
+
- `no-raw-type-classes` errors on text sizes in any `className`: the type rungs, Tailwind's `text-xs`…`text-9xl`, and arbitrary `text-[13px]`. It reaches beyond Control UI, so adopt it folder by folder while you migrate.
|
|
56
|
+
|
|
57
|
+
Biome, extending the shipped preset so rules added later arrive with the package update:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"extends": ["@ctrl-ui/react/biome"],
|
|
62
|
+
"overrides": [{ "includes": ["src/features/**"], "plugins": ["./node_modules/@ctrl-ui/react/lint/no-raw-type-classes.grit"] }]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
ESLint flat config:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import controlUi from "@ctrl-ui/react/eslint-plugin";
|
|
70
|
+
|
|
71
|
+
export default [{ plugins: { "control-ui": controlUi }, rules: { "control-ui/no-component-style-classes": "error" } }];
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
oxlint, through its JS plugin support:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{ "jsPlugins": ["@ctrl-ui/react/eslint-plugin"], "rules": { "control-ui/no-component-style-classes": "error" } }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
When your app imports components through its own wrapper package or folder, declare that path so the rule follows those imports too:
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
rules: { "control-ui/no-component-style-classes": ["error", { importSources: ["@acme/ui/components/"] }] }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Biome's Grit plugins take no options, so the package ships `control-ui-grit` to write the rules with your paths. Run it on install so a package update regenerates them, gitignore `.control-ui`, and list `./.control-ui/no-component-style-classes.grit` under `plugins` in place of the preset:
|
|
51
87
|
|
|
52
88
|
```json
|
|
53
|
-
{ "
|
|
89
|
+
{ "scripts": { "postinstall": "control-ui-grit --import-source=@acme/ui/components/ --out=.control-ui" } }
|
|
54
90
|
```
|
|
55
91
|
|
|
56
92
|
## Customize
|
package/dist/action-bar.js
CHANGED
|
@@ -3,6 +3,7 @@ import { useCopyToClipboard } from "./hooks/use-copy-to-clipboard.js";
|
|
|
3
3
|
import { cn } from "./lib/cn.js";
|
|
4
4
|
import { Button } from "./ui/button.js";
|
|
5
5
|
import { LiveStatus } from "./ui/live-status.js";
|
|
6
|
+
import { Swap, SwapItem } from "./ui/swap.js";
|
|
6
7
|
import { Toolbar } from "@base-ui/react/toolbar";
|
|
7
8
|
import { createContext, useContext } from "react";
|
|
8
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -66,21 +67,28 @@ function ActionBarCopy({ value, children = "Copy", copiedChildren = "Copied", co
|
|
|
66
67
|
onCopyError?.(error);
|
|
67
68
|
}
|
|
68
69
|
}
|
|
70
|
+
const copied = status === "copied";
|
|
69
71
|
let copyStatus = "";
|
|
70
|
-
if (
|
|
72
|
+
if (copied) copyStatus = copiedAriaLabel;
|
|
71
73
|
else if (status === "failed") copyStatus = copyFailedLabel;
|
|
72
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */
|
|
74
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(ActionBarItem, {
|
|
73
75
|
disabled: disabled ?? !copyValue,
|
|
74
76
|
onClick: handleClick,
|
|
75
77
|
...props,
|
|
76
|
-
children:
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
children: [/* @__PURE__ */ jsxs(Swap, {
|
|
79
|
+
value: copied ? "copied" : "idle",
|
|
80
|
+
children: [/* @__PURE__ */ jsx(SwapItem, {
|
|
81
|
+
value: "idle",
|
|
82
|
+
children
|
|
83
|
+
}), /* @__PURE__ */ jsx(SwapItem, {
|
|
84
|
+
value: "copied",
|
|
85
|
+
"aria-hidden": "true",
|
|
86
|
+
children: copiedChildren
|
|
87
|
+
})]
|
|
88
|
+
}), copied ? /* @__PURE__ */ jsx("span", {
|
|
81
89
|
className: "sr-only",
|
|
82
90
|
children
|
|
83
|
-
})
|
|
91
|
+
}) : null]
|
|
84
92
|
}), /* @__PURE__ */ jsx(LiveStatus, { message: copyStatus })] });
|
|
85
93
|
}
|
|
86
94
|
function ActionBarEdit({ value, children = "Edit", disabled, onClick, ...props }) {
|
package/dist/activity.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ScrollAreaProps } from "./ui/scroll-area.js";
|
|
|
4
4
|
import { CSSProperties, ComponentProps, ReactNode } from "react";
|
|
5
5
|
import { ChevronRight } from "lucide-react";
|
|
6
6
|
//#region src/activity.d.ts
|
|
7
|
-
export type ActivityState = "pending" | "running" | "success" | "error";
|
|
7
|
+
export type ActivityState = "pending" | "running" | "waiting" | "success" | "error";
|
|
8
8
|
export type ActivityKind = "default" | "tool" | "reasoning" | "signal";
|
|
9
9
|
export type ActivityDetailFormat = "text" | "code";
|
|
10
10
|
export type ActivityProps = Omit<CollapsibleProps, "children" | "style"> & {
|
|
@@ -45,8 +45,10 @@ export type ActivityDetailProps = ComponentProps<"div"> & {
|
|
|
45
45
|
export declare function ActivityDetail({ className, ...props }: ActivityDetailProps): import("react").JSX.Element;
|
|
46
46
|
export type ActivityDetailLabelProps = ActivityStyleProps<ComponentProps<"div">, ActivityKnobStyle>;
|
|
47
47
|
export declare function ActivityDetailLabel({ className, ...props }: ActivityDetailLabelProps): import("react").JSX.Element;
|
|
48
|
+
export type ActivityDetailTone = "default" | "destructive";
|
|
48
49
|
export type ActivityDetailContentProps = ActivityStyleProps<ComponentProps<"div">, ActivityKnobStyle> & {
|
|
49
50
|
format?: ActivityDetailFormat;
|
|
51
|
+
tone?: ActivityDetailTone;
|
|
50
52
|
};
|
|
51
|
-
export declare function ActivityDetailContent({ format, className, ...props }: ActivityDetailContentProps): import("react").JSX.Element;
|
|
53
|
+
export declare function ActivityDetailContent({ format, tone, className, ...props }: ActivityDetailContentProps): import("react").JSX.Element;
|
|
52
54
|
//#endregion
|
package/dist/activity.js
CHANGED
|
@@ -5,17 +5,19 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collap
|
|
|
5
5
|
import { ScrollArea } from "./ui/scroll-area.js";
|
|
6
6
|
import { createContext, useContext } from "react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { Check, ChevronRight, CircleAlert, CircleDashed, LoaderCircle } from "lucide-react";
|
|
8
|
+
import { Check, ChevronRight, CircleAlert, CircleDashed, CirclePause, LoaderCircle } from "lucide-react";
|
|
9
9
|
//#region src/activity.tsx
|
|
10
10
|
const activityStatusLabels = {
|
|
11
11
|
pending: "Pending",
|
|
12
12
|
running: "Running",
|
|
13
|
+
waiting: "Waiting",
|
|
13
14
|
success: "Complete",
|
|
14
15
|
error: "Failed"
|
|
15
16
|
};
|
|
16
17
|
const activityStatusIcons = {
|
|
17
18
|
pending: CircleDashed,
|
|
18
19
|
running: LoaderCircle,
|
|
20
|
+
waiting: CirclePause,
|
|
19
21
|
success: Check,
|
|
20
22
|
error: CircleAlert
|
|
21
23
|
};
|
|
@@ -166,12 +168,13 @@ function ActivityDetailLabel({ className, ...props }) {
|
|
|
166
168
|
className: cn("uppercase", className)
|
|
167
169
|
});
|
|
168
170
|
}
|
|
169
|
-
function ActivityDetailContent({ format = "text", className, ...props }) {
|
|
171
|
+
function ActivityDetailContent({ format = "text", tone = "default", className, ...props }) {
|
|
170
172
|
return /* @__PURE__ */ jsx("div", {
|
|
171
173
|
"data-control-ui": "activity",
|
|
172
174
|
"data-control-family": "activity",
|
|
173
175
|
"data-slot": "detail-content",
|
|
174
176
|
"data-format": format,
|
|
177
|
+
"data-tone": tone,
|
|
175
178
|
...props,
|
|
176
179
|
className: cn("min-w-0 whitespace-pre-wrap wrap-anywhere", format === "code" && "w-fit max-w-full", className)
|
|
177
180
|
});
|
package/dist/audio-visualizer.js
CHANGED
|
@@ -61,7 +61,7 @@ function AudioVisualizer({ levels, points, active = true, className, style, ...p
|
|
|
61
61
|
const visibleLevel = MIN_VISIBLE_LEVEL + perceptualLevel * .96;
|
|
62
62
|
const levelStyle = {
|
|
63
63
|
"--_audio-visualizer-level-opacity": `${.48 + perceptualLevel * .52}`,
|
|
64
|
-
clipPath: `inset(${(1 - visibleLevel) * 50}% 0 round var(--cui-audio-visualizer-bar-radius))`
|
|
64
|
+
clipPath: `inset(${((1 - visibleLevel) * 50).toFixed(3)}% 0 round var(--cui-audio-visualizer-bar-radius))`
|
|
65
65
|
};
|
|
66
66
|
return /* @__PURE__ */ jsx("span", {
|
|
67
67
|
ref: key === "bar-0" ? firstBarRef : void 0,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
//#region src/blocks/agent-run-clock.ts
|
|
3
|
+
const TICK_MS = 1e3;
|
|
4
|
+
let now = null;
|
|
5
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
6
|
+
let interval;
|
|
7
|
+
function tick() {
|
|
8
|
+
if (document.hidden) return;
|
|
9
|
+
now = Date.now();
|
|
10
|
+
for (const listener of listeners) listener();
|
|
11
|
+
}
|
|
12
|
+
function onVisibilityChange() {
|
|
13
|
+
if (!document.hidden) tick();
|
|
14
|
+
}
|
|
15
|
+
function subscribeToRunClock(listener) {
|
|
16
|
+
listeners.add(listener);
|
|
17
|
+
if (listeners.size === 1) {
|
|
18
|
+
now = Date.now();
|
|
19
|
+
interval = setInterval(tick, TICK_MS);
|
|
20
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
21
|
+
}
|
|
22
|
+
return () => {
|
|
23
|
+
listeners.delete(listener);
|
|
24
|
+
if (listeners.size > 0) return;
|
|
25
|
+
clearInterval(interval);
|
|
26
|
+
interval = void 0;
|
|
27
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const subscribeToNothing = () => () => {};
|
|
31
|
+
function useRunClock(active) {
|
|
32
|
+
return useSyncExternalStore(active ? subscribeToRunClock : subscribeToNothing, () => now, () => null);
|
|
33
|
+
}
|
|
34
|
+
function splitElapsed(ms) {
|
|
35
|
+
const totalSeconds = Math.floor(Math.max(0, ms) / 1e3);
|
|
36
|
+
return {
|
|
37
|
+
hours: Math.floor(totalSeconds / 3600),
|
|
38
|
+
minutes: Math.floor(totalSeconds % 3600 / 60),
|
|
39
|
+
seconds: totalSeconds % 60
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const pad2 = (value) => String(value).padStart(2, "0");
|
|
43
|
+
function formatElapsed(ms) {
|
|
44
|
+
const { hours, minutes, seconds } = splitElapsed(ms);
|
|
45
|
+
return hours > 0 ? `${hours}:${pad2(minutes)}:${pad2(seconds)}` : `${minutes}:${pad2(seconds)}`;
|
|
46
|
+
}
|
|
47
|
+
function elapsedIsoDuration(ms) {
|
|
48
|
+
const { hours, minutes, seconds } = splitElapsed(ms);
|
|
49
|
+
return `PT${hours ? `${hours}H` : ""}${minutes ? `${minutes}M` : ""}${seconds}S`;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { elapsedIsoDuration, formatElapsed, useRunClock };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AgentRunSummary } from "./agent-run-status.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/blocks/agent-run-sidebar.d.ts
|
|
4
|
+
export declare function AgentRunSidebar({ appName, brand, runs, activeRunId, sidebarFooter, onRunSelect, onNewRun }: {
|
|
5
|
+
appName: string;
|
|
6
|
+
brand?: ReactNode;
|
|
7
|
+
runs: readonly AgentRunSummary[];
|
|
8
|
+
activeRunId?: string;
|
|
9
|
+
sidebarFooter?: ReactNode;
|
|
10
|
+
onRunSelect?: (run: AgentRunSummary) => void;
|
|
11
|
+
onNewRun?: () => void;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Text } from "../ui/typography.js";
|
|
3
|
+
import { useSidebar } from "../ui/sidebar-provider.js";
|
|
4
|
+
import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar-menu.js";
|
|
5
|
+
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail } from "../ui/sidebar.js";
|
|
6
|
+
import { agentRunStatusLabels } from "./agent-run-status.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { BotIcon, CheckIcon, CircleAlertIcon, CircleDashedIcon, CirclePauseIcon, CircleSlashIcon, LoaderCircleIcon, PlusIcon } from "lucide-react";
|
|
9
|
+
//#region src/blocks/agent-run-sidebar.tsx
|
|
10
|
+
const runStatusIcons = {
|
|
11
|
+
running: /* @__PURE__ */ jsx(LoaderCircleIcon, {
|
|
12
|
+
className: "size-3.5 shrink-0 motion-safe:animate-spin",
|
|
13
|
+
"aria-hidden": "true"
|
|
14
|
+
}),
|
|
15
|
+
waiting: /* @__PURE__ */ jsx(CirclePauseIcon, {
|
|
16
|
+
className: "size-3.5 shrink-0 text-warning-text",
|
|
17
|
+
"aria-hidden": "true"
|
|
18
|
+
}),
|
|
19
|
+
success: /* @__PURE__ */ jsx(CheckIcon, {
|
|
20
|
+
className: "size-3.5 shrink-0 text-success-text",
|
|
21
|
+
"aria-hidden": "true"
|
|
22
|
+
}),
|
|
23
|
+
error: /* @__PURE__ */ jsx(CircleAlertIcon, {
|
|
24
|
+
className: "size-3.5 shrink-0 text-destructive-text",
|
|
25
|
+
"aria-hidden": "true"
|
|
26
|
+
}),
|
|
27
|
+
cancelled: /* @__PURE__ */ jsx(CircleSlashIcon, {
|
|
28
|
+
className: "size-3.5 shrink-0 text-muted-foreground",
|
|
29
|
+
"aria-hidden": "true"
|
|
30
|
+
}),
|
|
31
|
+
pending: /* @__PURE__ */ jsx(CircleDashedIcon, {
|
|
32
|
+
className: "size-3.5 shrink-0 text-muted-foreground",
|
|
33
|
+
"aria-hidden": "true"
|
|
34
|
+
})
|
|
35
|
+
};
|
|
36
|
+
function AgentRunSidebar({ appName, brand, runs, activeRunId, sidebarFooter, onRunSelect, onNewRun }) {
|
|
37
|
+
const { setOpenMobile } = useSidebar();
|
|
38
|
+
return /* @__PURE__ */ jsxs(Sidebar, {
|
|
39
|
+
collapsible: "offcanvas",
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ jsxs(SidebarHeader, {
|
|
42
|
+
divider: true,
|
|
43
|
+
className: "gap-1.5",
|
|
44
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
45
|
+
className: "flex min-w-0 items-center gap-2 px-1 py-1",
|
|
46
|
+
children: [brand ?? /* @__PURE__ */ jsx("span", {
|
|
47
|
+
className: "flex size-6 shrink-0 items-center justify-center rounded-md bg-foreground text-background",
|
|
48
|
+
children: /* @__PURE__ */ jsx(BotIcon, {
|
|
49
|
+
className: "size-3.5",
|
|
50
|
+
"aria-hidden": "true"
|
|
51
|
+
})
|
|
52
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
53
|
+
size: "label",
|
|
54
|
+
weight: "semibold",
|
|
55
|
+
className: "truncate",
|
|
56
|
+
title: appName,
|
|
57
|
+
children: appName
|
|
58
|
+
})]
|
|
59
|
+
}), onNewRun ? /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, {
|
|
60
|
+
size: "sm",
|
|
61
|
+
onClick: () => {
|
|
62
|
+
onNewRun();
|
|
63
|
+
setOpenMobile(false);
|
|
64
|
+
},
|
|
65
|
+
children: [/* @__PURE__ */ jsx(PlusIcon, {}), /* @__PURE__ */ jsx("span", { children: "New run" })]
|
|
66
|
+
}) }) }) : null]
|
|
67
|
+
}),
|
|
68
|
+
/* @__PURE__ */ jsx(SidebarContent, { children: /* @__PURE__ */ jsxs(SidebarGroup, {
|
|
69
|
+
className: "gap-1",
|
|
70
|
+
children: [/* @__PURE__ */ jsx(SidebarGroupLabel, { children: "Runs" }), runs.length === 0 ? /* @__PURE__ */ jsx(Text, {
|
|
71
|
+
size: "caption",
|
|
72
|
+
tone: "muted",
|
|
73
|
+
className: "mx-2",
|
|
74
|
+
children: "No runs yet"
|
|
75
|
+
}) : /* @__PURE__ */ jsx(SidebarMenu, { children: runs.map((run) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, {
|
|
76
|
+
size: "sm",
|
|
77
|
+
isActive: run.id === activeRunId,
|
|
78
|
+
onClick: () => {
|
|
79
|
+
onRunSelect?.(run);
|
|
80
|
+
setOpenMobile(false);
|
|
81
|
+
},
|
|
82
|
+
children: [
|
|
83
|
+
runStatusIcons[run.status],
|
|
84
|
+
/* @__PURE__ */ jsx("span", {
|
|
85
|
+
className: "truncate",
|
|
86
|
+
children: run.title
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ jsxs("span", {
|
|
89
|
+
className: "sr-only",
|
|
90
|
+
children: [", ", agentRunStatusLabels[run.status]]
|
|
91
|
+
})
|
|
92
|
+
]
|
|
93
|
+
}) }, run.id)) })]
|
|
94
|
+
}) }),
|
|
95
|
+
sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, { children: sidebarFooter }) : null,
|
|
96
|
+
/* @__PURE__ */ jsx(SidebarRail, {})
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { AgentRunSidebar };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/blocks/agent-run-status.d.ts
|
|
2
|
+
export type AgentRunStatus = "pending" | "running" | "waiting" | "success" | "error" | "cancelled";
|
|
3
|
+
export type AgentRunSummary = {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
status: AgentRunStatus;
|
|
7
|
+
};
|
|
8
|
+
export declare const agentRunStatusLabels: {
|
|
9
|
+
pending: string;
|
|
10
|
+
running: string;
|
|
11
|
+
waiting: string;
|
|
12
|
+
success: string;
|
|
13
|
+
error: string;
|
|
14
|
+
cancelled: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const agentRunStatusColors: {
|
|
17
|
+
pending: "neutral";
|
|
18
|
+
running: "blue";
|
|
19
|
+
waiting: "yellow";
|
|
20
|
+
success: "green";
|
|
21
|
+
error: "red";
|
|
22
|
+
cancelled: "neutral";
|
|
23
|
+
};
|
|
24
|
+
export declare const agentRunStepLabels: {
|
|
25
|
+
neutral: string;
|
|
26
|
+
pending: string;
|
|
27
|
+
running: string;
|
|
28
|
+
waiting: string;
|
|
29
|
+
success: string;
|
|
30
|
+
error: string;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/blocks/agent-run-status.ts
|
|
2
|
+
const agentRunStatusLabels = {
|
|
3
|
+
pending: "Queued",
|
|
4
|
+
running: "Running",
|
|
5
|
+
waiting: "Needs approval",
|
|
6
|
+
success: "Done",
|
|
7
|
+
error: "Failed",
|
|
8
|
+
cancelled: "Cancelled"
|
|
9
|
+
};
|
|
10
|
+
const agentRunStatusColors = {
|
|
11
|
+
pending: "neutral",
|
|
12
|
+
running: "blue",
|
|
13
|
+
waiting: "yellow",
|
|
14
|
+
success: "green",
|
|
15
|
+
error: "red",
|
|
16
|
+
cancelled: "neutral"
|
|
17
|
+
};
|
|
18
|
+
const agentRunStepLabels = {
|
|
19
|
+
neutral: "Step",
|
|
20
|
+
pending: "Pending",
|
|
21
|
+
running: "Running",
|
|
22
|
+
waiting: "Waiting for approval",
|
|
23
|
+
success: "Done",
|
|
24
|
+
error: "Failed"
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { agentRunStatusColors, agentRunStatusLabels, agentRunStepLabels };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ActivityProps } from "../activity.js";
|
|
2
|
+
import { AgentRunStatus, AgentRunSummary } from "./agent-run-status.js";
|
|
3
|
+
import { Card } from "../ui/card.js";
|
|
4
|
+
import { SidebarProviderProps } from "../ui/sidebar-provider.js";
|
|
5
|
+
import "../ui/sidebar.js";
|
|
6
|
+
import { TimelineItemProps } from "../ui/timeline.js";
|
|
7
|
+
import { TypeSize } from "../ui/typography.js";
|
|
8
|
+
import { ComponentProps, ReactNode } from "react";
|
|
9
|
+
//#region src/blocks/agent-run.d.ts
|
|
10
|
+
type AgentRunLayout = "viewport" | "contained";
|
|
11
|
+
export type AgentRunBlockProps = Omit<ComponentProps<"div">, "children"> & Pick<SidebarProviderProps, "persistOpen" | "keyboardShortcut"> & {
|
|
12
|
+
appName?: string;
|
|
13
|
+
brand?: ReactNode;
|
|
14
|
+
runs: readonly AgentRunSummary[];
|
|
15
|
+
activeRunId?: string;
|
|
16
|
+
onRunSelect?: (run: AgentRunSummary) => void;
|
|
17
|
+
onNewRun?: () => void;
|
|
18
|
+
sidebarFooter?: ReactNode;
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
layout?: AgentRunLayout;
|
|
21
|
+
};
|
|
22
|
+
export declare function AgentRunBlock({ appName, brand, runs, activeRunId, onRunSelect, onNewRun, sidebarFooter, children, layout, className, style, ...props }: AgentRunBlockProps): import("react").JSX.Element;
|
|
23
|
+
export type AgentRunElapsedProps = Omit<ComponentProps<"time">, "dateTime" | "children"> & {
|
|
24
|
+
startedAt: number;
|
|
25
|
+
endedAt?: number;
|
|
26
|
+
size?: TypeSize;
|
|
27
|
+
};
|
|
28
|
+
export declare function AgentRunElapsed({ startedAt, endedAt, size, className, ...props }: AgentRunElapsedProps): import("react").JSX.Element;
|
|
29
|
+
export type AgentRunHeaderProps = Omit<ComponentProps<"header">, "title"> & {
|
|
30
|
+
title: string;
|
|
31
|
+
status: AgentRunStatus;
|
|
32
|
+
startedAt?: number;
|
|
33
|
+
endedAt?: number;
|
|
34
|
+
actions?: ReactNode;
|
|
35
|
+
};
|
|
36
|
+
export declare function AgentRunHeader({ title, status, startedAt, endedAt, actions, className, ...props }: AgentRunHeaderProps): import("react").JSX.Element;
|
|
37
|
+
export type AgentRunBodyProps = ComponentProps<"div"> & {
|
|
38
|
+
aside?: ReactNode;
|
|
39
|
+
};
|
|
40
|
+
export declare function AgentRunBody({ aside, className, children, ...props }: AgentRunBodyProps): import("react").JSX.Element;
|
|
41
|
+
export type AgentRunPlanProps = Omit<ComponentProps<"section">, "title"> & {
|
|
42
|
+
title?: ReactNode;
|
|
43
|
+
description?: ReactNode;
|
|
44
|
+
};
|
|
45
|
+
export declare function AgentRunPlan({ title, description, className, children, ...props }: AgentRunPlanProps): import("react").JSX.Element;
|
|
46
|
+
export type AgentRunStepProps = Omit<TimelineItemProps, "title"> & {
|
|
47
|
+
title: ReactNode;
|
|
48
|
+
detail?: ReactNode;
|
|
49
|
+
startedAt?: number;
|
|
50
|
+
endedAt?: number;
|
|
51
|
+
actions?: ReactNode;
|
|
52
|
+
};
|
|
53
|
+
export declare function AgentRunStep({ title, detail, startedAt, endedAt, actions, state, children, ...props }: AgentRunStepProps): import("react").JSX.Element;
|
|
54
|
+
export type AgentRunToolCallProps = Omit<ActivityProps, "kind" | "name" | "children"> & {
|
|
55
|
+
name: string;
|
|
56
|
+
summary?: ReactNode;
|
|
57
|
+
icon?: ReactNode;
|
|
58
|
+
input?: unknown;
|
|
59
|
+
output?: unknown;
|
|
60
|
+
errorText?: string;
|
|
61
|
+
startedAt?: number;
|
|
62
|
+
endedAt?: number;
|
|
63
|
+
};
|
|
64
|
+
export declare function AgentRunToolCall({ name, summary, icon, input, output, errorText, startedAt, endedAt, ...props }: AgentRunToolCallProps): import("react").JSX.Element;
|
|
65
|
+
export type AgentRunAsideProps = ComponentProps<"aside">;
|
|
66
|
+
export declare function AgentRunAside({ className, ...props }: AgentRunAsideProps): import("react").JSX.Element;
|
|
67
|
+
export type AgentRunSectionProps = Omit<ComponentProps<typeof Card>, "title"> & {
|
|
68
|
+
title: ReactNode;
|
|
69
|
+
actions?: ReactNode;
|
|
70
|
+
};
|
|
71
|
+
export declare function AgentRunSection({ title, actions, children, ...props }: AgentRunSectionProps): import("react").JSX.Element;
|
|
72
|
+
export type AgentRunDetail = {
|
|
73
|
+
label: string;
|
|
74
|
+
value: ReactNode;
|
|
75
|
+
};
|
|
76
|
+
export type AgentRunDetailsProps = Omit<AgentRunSectionProps, "title" | "children"> & {
|
|
77
|
+
title?: ReactNode;
|
|
78
|
+
items: readonly AgentRunDetail[];
|
|
79
|
+
};
|
|
80
|
+
export declare function AgentRunDetails({ title, items, ...props }: AgentRunDetailsProps): import("react").JSX.Element | null;
|
|
81
|
+
//#endregion
|
|
82
|
+
export type { AgentRunStatus, AgentRunSummary };
|