@cueplusplus/ui 0.20.1 → 0.21.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/CHANGELOG.md +115 -0
- package/dist/chat/agent-pile.js +2 -2
- package/dist/chrome/_status-bar.js +1 -1
- package/dist/chrome/app-shell.js +1 -1
- package/dist/chrome/navigation-menu.js +3 -3
- package/dist/chrome/row.js +1 -1
- package/dist/chrome/scroll-area.js +1 -1
- package/dist/chrome/section-header.js +1 -1
- package/dist/chrome/segmented-control.js +1 -1
- package/dist/chrome/tabs.js +1 -1
- package/dist/chrome/toolbar.js +1 -1
- package/dist/chrome/tree.js +3 -3
- package/dist/date/calendar.js +3 -3
- package/dist/dmx/channel-matrix.js +1 -1
- package/dist/dmx/universe-grid.js +1 -1
- package/dist/elements/agent-handoff.js +3 -3
- package/dist/elements/agent-plan.js +1 -1
- package/dist/elements/agent-status.js +1 -1
- package/dist/elements/agent-surface.d.ts +9 -6
- package/dist/elements/agent-surface.js +3 -2
- package/dist/elements/approval-card.d.ts +29 -3
- package/dist/elements/approval-card.js +18 -8
- package/dist/elements/artifact-card.js +2 -2
- package/dist/elements/canvas-split.js +3 -3
- package/dist/elements/chart.js +1 -1
- package/dist/elements/chat-panel.js +2 -2
- package/dist/elements/checkpoint-history.js +1 -1
- package/dist/elements/code-diff.js +1 -1
- package/dist/elements/code-runner.js +1 -1
- package/dist/elements/composer.d.ts +8 -2
- package/dist/elements/composer.js +20 -12
- package/dist/elements/computer-use.js +2 -2
- package/dist/elements/confidence-marker.js +1 -1
- package/dist/elements/connection-state.js +2 -2
- package/dist/elements/context-breakdown.js +1 -1
- package/dist/elements/context-usage.js +1 -1
- package/dist/elements/conversation-search.js +2 -2
- package/dist/elements/cost-meter.js +1 -1
- package/dist/elements/data-table.js +1 -1
- package/dist/elements/diagram.js +1 -1
- package/dist/elements/draft-restore.js +2 -2
- package/dist/elements/edit-message.js +1 -1
- package/dist/elements/elements.css +134 -0
- package/dist/elements/elicitation-form.d.ts +8 -1
- package/dist/elements/elicitation-form.js +24 -16
- package/dist/elements/empty-state.js +3 -3
- package/dist/elements/error-state.js +2 -2
- package/dist/elements/event-feed.d.ts +88 -0
- package/dist/elements/event-feed.js +190 -0
- package/dist/elements/feedback-dialog.js +2 -2
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/flow-graph.js +2 -2
- package/dist/elements/generative.css +13 -0
- package/dist/elements/generative.d.ts +8 -6
- package/dist/elements/generative.js +4 -3
- package/dist/elements/image-generation.js +2 -2
- package/dist/elements/index.d.ts +7 -3
- package/dist/elements/index.js +5 -2
- package/dist/elements/inline-citation.js +1 -1
- package/dist/elements/job-progress.js +1 -1
- package/dist/elements/launcher-bubble.js +3 -3
- package/dist/elements/loading-state.js +1 -1
- package/dist/elements/map-answer.js +1 -1
- package/dist/elements/math-block.js +1 -1
- package/dist/elements/mcp-server-panel.js +3 -3
- package/dist/elements/memory-chips.js +1 -1
- package/dist/elements/message-attachment.js +3 -3
- package/dist/elements/message-branches.js +1 -1
- package/dist/elements/message-pair.js +2 -2
- package/dist/elements/message-queue.js +1 -1
- package/dist/elements/message-timing.js +1 -1
- package/dist/elements/mobile-composer.js +1 -1
- package/dist/elements/model-picker.js +1 -1
- package/dist/elements/number-ticker.js +1 -1
- package/dist/elements/onboarding.js +3 -3
- package/dist/elements/permission-grant.js +3 -3
- package/dist/elements/prompt-library.js +1 -1
- package/dist/elements/question-card.d.ts +50 -0
- package/dist/elements/question-card.js +117 -0
- package/dist/elements/queue-dock.js +1 -1
- package/dist/elements/quota-banner.js +1 -1
- package/dist/elements/quote-reply.js +3 -3
- package/dist/elements/read-aloud.js +2 -2
- package/dist/elements/reasoning-effort.js +2 -2
- package/dist/elements/reasoning-panel.js +3 -3
- package/dist/elements/recommendation-card.js +2 -2
- package/dist/elements/regenerate-menu.js +1 -1
- package/dist/elements/request-delivery.js +31 -0
- package/dist/elements/research-report.js +1 -1
- package/dist/elements/retrieval-chunks.js +3 -3
- package/dist/elements/revert-dock.js +1 -1
- package/dist/elements/reviewable-diff.js +4 -4
- package/dist/elements/schedule-card.js +2 -2
- package/dist/elements/score-breakdown.js +2 -2
- package/dist/elements/scroll-anchor.js +2 -2
- package/dist/elements/settings-panel.js +3 -3
- package/dist/elements/sources.js +1 -1
- package/dist/elements/spec-sheet.js +1 -1
- package/dist/elements/stopped-run.js +2 -2
- package/dist/elements/streaming-text.js +2 -2
- package/dist/elements/subagent-list.js +4 -4
- package/dist/elements/suggestions.js +1 -1
- package/dist/elements/surfaces.d.ts +6 -6
- package/dist/elements/surfaces.js +7 -7
- package/dist/elements/tail-status.js +1 -1
- package/dist/elements/terminal-block.js +1 -1
- package/dist/elements/thinking-indicator.js +1 -1
- package/dist/elements/timeline.js +1 -1
- package/dist/elements/todo-list.js +1 -1
- package/dist/elements/tool-call.d.ts +18 -2
- package/dist/elements/tool-call.js +20 -11
- package/dist/elements/tool-error.js +2 -2
- package/dist/elements/tool-group.d.ts +11 -3
- package/dist/elements/tool-group.js +62 -38
- package/dist/elements/tool-state.d.ts +13 -0
- package/dist/elements/tool-state.js +44 -0
- package/dist/elements/tool-timeline.js +2 -2
- package/dist/elements/trace-waterfall.js +2 -2
- package/dist/elements/unsupported-request-card.d.ts +31 -0
- package/dist/elements/unsupported-request-card.js +80 -0
- package/dist/elements/vocabulary.d.ts +50 -1
- package/dist/elements/vocabulary.js +50 -1
- package/dist/elements/voice-conversation.js +5 -5
- package/dist/elements/web-preview.js +1 -1
- package/dist/elements/web-search.js +2 -2
- package/dist/elements/work-collapse.js +1 -1
- package/dist/forms/file-upload.js +1 -1
- package/dist/forms/rating.js +1 -1
- package/dist/forms/select.js +1 -1
- package/dist/forms/switch.js +2 -2
- package/dist/forms/toggle.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/instruments/_ledger-disclosure.js +1 -1
- package/dist/instruments/data-tree.js +1 -1
- package/dist/instruments/meter.js +1 -1
- package/dist/instruments/seam-grid.js +1 -1
- package/dist/layout/_collapse.js +3 -3
- package/dist/layout/bento.js +1 -1
- package/dist/layout/breadcrumb.js +1 -1
- package/dist/layout/carousel.js +1 -1
- package/dist/layout/collapsible.js +1 -1
- package/dist/layout/index.d.ts +3 -1
- package/dist/layout/index.js +3 -1
- package/dist/layout/item.js +1 -1
- package/dist/layout/link.js +1 -1
- package/dist/layout/pagination.js +1 -1
- package/dist/layout/pane-seam.d.ts +75 -0
- package/dist/layout/pane-seam.js +127 -0
- package/dist/layout/resizable.d.ts +2 -1
- package/dist/layout/resizable.js +3 -2
- package/dist/layout/sidebar.js +3 -3
- package/dist/layout/split-pane.d.ts +74 -0
- package/dist/layout/split-pane.js +135 -0
- package/dist/layout/stepper.js +1 -1
- package/dist/lib/auto-grow.js +42 -0
- package/dist/overlays/_surface.d.ts +4 -4
- package/dist/overlays/_surface.js +4 -4
- package/dist/overlays/drawer.js +1 -1
- package/dist/overlays/menubar.js +1 -1
- package/dist/overlays/sheet.js +1 -1
- package/dist/overlays/toast.js +1 -1
- package/dist/primitives/button.js +1 -1
- package/dist/primitives/chip.d.ts +1 -1
- package/dist/system/agent-skin.d.ts +11 -5
- package/manifest/components/agent-surface.json +5 -4
- package/manifest/components/approval-card.json +45 -7
- package/manifest/components/composer-input.json +16 -2
- package/manifest/components/elicitation-form.json +16 -1
- package/manifest/components/event-feed.json +171 -0
- package/manifest/components/event-row.json +116 -0
- package/manifest/components/generative-ui.json +4 -3
- package/manifest/components/pane-seam.json +171 -0
- package/manifest/components/question-card.json +157 -0
- package/manifest/components/resizable.json +1 -1
- package/manifest/components/split-pane.json +224 -0
- package/manifest/components/tool-call.json +46 -2
- package/manifest/components/tool-group.json +15 -3
- package/manifest/components/unsupported-request-card.json +117 -0
- package/manifest/fixtures.json +16 -0
- package/manifest/manifest.json +88 -10
- package/manifest/tokens.json +9 -2
- package/package.json +2 -2
|
@@ -48,8 +48,8 @@ function ScheduleCard({ name, cadence, nextRun, enabled, history, onToggle, clas
|
|
|
48
48
|
"aria-checked": enabled,
|
|
49
49
|
"aria-label": `${enabled ? "Pause" : "Resume"} ${name}`,
|
|
50
50
|
onClick: onToggle,
|
|
51
|
-
className: cn("flex h-5 w-9 shrink-0 items-center rounded-full p-0.5 transition-colors duration-
|
|
52
|
-
children: /* @__PURE__ */ jsx("span", { className: cn("bg-bg size-4 rounded-full transition-transform duration-
|
|
51
|
+
className: cn("flex h-5 w-9 shrink-0 items-center rounded-full p-0.5 transition-colors duration-brisk", enabled ? "bg-accent" : "bg-surface-3"),
|
|
52
|
+
children: /* @__PURE__ */ jsx("span", { className: cn("bg-bg size-4 rounded-full transition-transform duration-brisk motion-reduce:transition-none", enabled && "translate-x-4") })
|
|
53
53
|
})
|
|
54
54
|
]
|
|
55
55
|
}),
|
|
@@ -43,7 +43,7 @@ function ScoreBreakdown({ verdict, total, outOf, criteria, visibleCount, classNa
|
|
|
43
43
|
}), /* @__PURE__ */ jsx("div", {
|
|
44
44
|
className: "flex flex-col gap-2",
|
|
45
45
|
children: take(criteria, visibleCount).map((criterion) => /* @__PURE__ */ jsxs("div", {
|
|
46
|
-
className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both flex flex-col gap-1 duration-
|
|
46
|
+
className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both flex flex-col gap-1 duration-base",
|
|
47
47
|
children: [
|
|
48
48
|
/* @__PURE__ */ jsxs("div", {
|
|
49
49
|
className: "flex items-baseline gap-2",
|
|
@@ -65,7 +65,7 @@ function ScoreBreakdown({ verdict, total, outOf, criteria, visibleCount, classNa
|
|
|
65
65
|
/* @__PURE__ */ jsx("span", {
|
|
66
66
|
className: "bg-surface-2 h-[3px] w-full overflow-hidden rounded-full",
|
|
67
67
|
children: /* @__PURE__ */ jsx("span", {
|
|
68
|
-
className: "block h-full rounded-full bg-stream transition-[width] duration-
|
|
68
|
+
className: "block h-full rounded-full bg-stream transition-[width] duration-slow motion-reduce:transition-none",
|
|
69
69
|
style: { width: `${pct(criterion.score, outOf)}%` }
|
|
70
70
|
})
|
|
71
71
|
}),
|
|
@@ -100,7 +100,7 @@ function ScrollAnchor({ messages, paused = false, onSettled, className, ...props
|
|
|
100
100
|
ref: viewportRef,
|
|
101
101
|
className: "flex h-full flex-col gap-2.5 overflow-y-hidden scroll-smooth motion-reduce:scroll-auto p-4",
|
|
102
102
|
children: messages.slice(0, count).map((message, i) => /* @__PURE__ */ jsx("div", {
|
|
103
|
-
className: cn("cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in max-w-[85%] text-(length:--cue-text-ui) leading-(--cue-leading-ui) duration-
|
|
103
|
+
className: cn("cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in max-w-[85%] text-(length:--cue-text-ui) leading-(--cue-leading-ui) duration-base motion-reduce:animate-none", message.role === "user" ? cn(field, "self-end rounded-overlay px-3 py-1.5") : "text-fg-muted self-start"),
|
|
104
104
|
children: message.text
|
|
105
105
|
}, i))
|
|
106
106
|
}),
|
|
@@ -111,7 +111,7 @@ function ScrollAnchor({ messages, paused = false, onSettled, className, ...props
|
|
|
111
111
|
!pinned && newCount > 0 && /* @__PURE__ */ jsxs("button", {
|
|
112
112
|
type: "button",
|
|
113
113
|
onClick: jump,
|
|
114
|
-
className: cn("bg-surface-2 border border-border-overlay", "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in absolute inset-x-0 bottom-3 mx-auto flex w-fit items-center gap-1.5 rounded-full px-3.5 py-1.5 text-(length:--cue-text-ui) transition-transform duration-
|
|
114
|
+
className: cn("bg-surface-2 border border-border-overlay", "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in absolute inset-x-0 bottom-3 mx-auto flex w-fit items-center gap-1.5 rounded-full px-3.5 py-1.5 text-(length:--cue-text-ui) transition-transform duration-brisk hover:-translate-y-px"),
|
|
115
115
|
children: [
|
|
116
116
|
/* @__PURE__ */ jsx(ArrowDownIcon, { className: "size-3 opacity-60" }),
|
|
117
117
|
newCount,
|
|
@@ -37,7 +37,7 @@ function SettingsPanel({ model, models, systemPrompt, temperature, toggles, onMo
|
|
|
37
37
|
type: "button",
|
|
38
38
|
"aria-pressed": option === model,
|
|
39
39
|
onClick: () => onModelChange?.(option),
|
|
40
|
-
className: cn("flex-1 rounded-full py-1 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-
|
|
40
|
+
className: cn("flex-1 rounded-full py-1 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.97]", option === model ? "bg-bg text-fg" : "text-fg-muted hover:text-fg-muted"),
|
|
41
41
|
children: option
|
|
42
42
|
}, option))
|
|
43
43
|
})]
|
|
@@ -96,8 +96,8 @@ function SettingsPanel({ model, models, systemPrompt, temperature, toggles, onMo
|
|
|
96
96
|
"aria-checked": toggle.on,
|
|
97
97
|
"aria-label": toggle.label,
|
|
98
98
|
onClick: () => onToggle?.(toggle.key),
|
|
99
|
-
className: cn("flex h-5 w-9 shrink-0 items-center rounded-full p-0.5 transition-colors duration-
|
|
100
|
-
children: /* @__PURE__ */ jsx("span", { className: cn("bg-bg size-4 rounded-full transition-transform duration-
|
|
99
|
+
className: cn("flex h-5 w-9 shrink-0 items-center rounded-full p-0.5 transition-colors duration-brisk", toggle.on ? "bg-accent" : "bg-surface-3"),
|
|
100
|
+
children: /* @__PURE__ */ jsx("span", { className: cn("bg-bg size-4 rounded-full transition-transform duration-brisk motion-reduce:transition-none", toggle.on && "translate-x-4") })
|
|
101
101
|
})]
|
|
102
102
|
}, toggle.key))
|
|
103
103
|
})
|
package/dist/elements/sources.js
CHANGED
|
@@ -32,7 +32,7 @@ function Sources({ sources, open, onOpenChange, className }) {
|
|
|
32
32
|
className: cn(mono, "text-fg-subtle tabular-nums"),
|
|
33
33
|
children: sources.length
|
|
34
34
|
}),
|
|
35
|
-
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3 opacity-60 transition-transform duration-
|
|
35
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3 opacity-60 transition-transform duration-brisk ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[panel-open]/trigger:rotate-180 motion-reduce:transition-none" })
|
|
36
36
|
]
|
|
37
37
|
}), /* @__PURE__ */ jsx(Collapsible.Panel, {
|
|
38
38
|
className: cn(collapsePanel, "outline-none"),
|
|
@@ -29,7 +29,7 @@ function SpecSheet({ title, subtitle, rows, visibleCount, className, ...props })
|
|
|
29
29
|
}), /* @__PURE__ */ jsx("div", {
|
|
30
30
|
className: "flex flex-col",
|
|
31
31
|
children: take(rows, visibleCount).map((row) => /* @__PURE__ */ jsxs("div", {
|
|
32
|
-
className: "border-border cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both flex items-baseline gap-3 border-t py-1.5 duration-
|
|
32
|
+
className: "border-border cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both flex items-baseline gap-3 border-t py-1.5 duration-base first:border-t-0 first:pt-0",
|
|
33
33
|
children: [/* @__PURE__ */ jsx("span", {
|
|
34
34
|
className: cn(mono, "text-fg-subtle w-24 shrink-0"),
|
|
35
35
|
children: row.label
|
|
@@ -33,13 +33,13 @@ function StoppedRun({ words, reason, onContinue, onDiscard, className, ...props
|
|
|
33
33
|
/* @__PURE__ */ jsxs("button", {
|
|
34
34
|
type: "button",
|
|
35
35
|
onClick: onContinue,
|
|
36
|
-
className: "text-fg-muted hover:bg-surface-2 hover:text-fg ms-auto flex h-7 items-center gap-1 rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-
|
|
36
|
+
className: "text-fg-muted hover:bg-surface-2 hover:text-fg ms-auto flex h-7 items-center gap-1 rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96]",
|
|
37
37
|
children: ["Continue", /* @__PURE__ */ jsx(ArrowRightIcon, { className: "size-3" })]
|
|
38
38
|
}),
|
|
39
39
|
/* @__PURE__ */ jsx("button", {
|
|
40
40
|
type: "button",
|
|
41
41
|
onClick: onDiscard,
|
|
42
|
-
className: "text-fg-muted hover:bg-surface-2 hover:text-fg flex h-7 items-center rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-
|
|
42
|
+
className: "text-fg-muted hover:bg-surface-2 hover:text-fg flex h-7 items-center rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96]",
|
|
43
43
|
children: "Discard"
|
|
44
44
|
})
|
|
45
45
|
]
|
|
@@ -29,9 +29,9 @@ function StreamingText({ segments, count, streaming, className, ...props }) {
|
|
|
29
29
|
children: [shown.map(({ word, mono: isMono }, i) => {
|
|
30
30
|
const fresh = streaming && shown.length - 1 - i < 2;
|
|
31
31
|
return /* @__PURE__ */ jsxs("span", {
|
|
32
|
-
className: "cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both duration-
|
|
32
|
+
className: "cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both duration-slow motion-reduce:animate-none",
|
|
33
33
|
children: [/* @__PURE__ */ jsx("span", {
|
|
34
|
-
className: cn("transition-colors duration-
|
|
34
|
+
className: cn("transition-colors duration-slower motion-reduce:transition-none", fresh && "text-stream", isMono && "bg-surface-2 rounded-control px-1.5 py-0.5 font-mono text-[0.85em]"),
|
|
35
35
|
children: word
|
|
36
36
|
}), " "]
|
|
37
37
|
}, i);
|
|
@@ -32,7 +32,7 @@ function SubagentList({ agents, completedCount, progress, showSummary, summaryAg
|
|
|
32
32
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
33
33
|
className: "flex items-center gap-2",
|
|
34
34
|
children: [
|
|
35
|
-
done ? /* @__PURE__ */ jsx(CheckIcon, { className: "cue-elements-fade-in cue-elements-zoom-in-90 cue-elements-animate-in size-3.5 shrink-0 text-ok duration-
|
|
35
|
+
done ? /* @__PURE__ */ jsx(CheckIcon, { className: "cue-elements-fade-in cue-elements-zoom-in-90 cue-elements-animate-in size-3.5 shrink-0 text-ok duration-brisk" }) : /* @__PURE__ */ jsx(Loader2Icon, { className: "text-fg-subtle size-3.5 shrink-0 animate-spin motion-reduce:animate-none" }),
|
|
36
36
|
/* @__PURE__ */ jsx("span", {
|
|
37
37
|
className: "flex-1 truncate text-(length:--cue-text-body)",
|
|
38
38
|
children: agent.name
|
|
@@ -45,13 +45,13 @@ function SubagentList({ agents, completedCount, progress, showSummary, summaryAg
|
|
|
45
45
|
}), /* @__PURE__ */ jsx("span", {
|
|
46
46
|
className: "bg-surface-2 h-[3px] w-full overflow-hidden rounded-full",
|
|
47
47
|
children: /* @__PURE__ */ jsx("span", {
|
|
48
|
-
className: cn("block h-full rounded-full transition-[width] duration-
|
|
48
|
+
className: cn("block h-full rounded-full transition-[width] duration-slower", done ? "bg-ok/70" : "bg-accent"),
|
|
49
49
|
style: { width: `${pct(width, 100)}%` }
|
|
50
50
|
})
|
|
51
51
|
})]
|
|
52
52
|
}, agent.name);
|
|
53
53
|
}), showSummary && /* @__PURE__ */ jsxs("div", {
|
|
54
|
-
className: cn("bg-surface-1 border border-border", "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in flex flex-col gap-2 rounded-overlay px-3.5 py-2.5 duration-
|
|
54
|
+
className: cn("bg-surface-1 border border-border", "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in flex flex-col gap-2 rounded-overlay px-3.5 py-2.5 duration-base"),
|
|
55
55
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
56
56
|
className: "flex items-center gap-2",
|
|
57
57
|
children: [
|
|
@@ -68,7 +68,7 @@ function SubagentList({ agents, completedCount, progress, showSummary, summaryAg
|
|
|
68
68
|
}), /* @__PURE__ */ jsx("span", {
|
|
69
69
|
className: "bg-surface-2 h-[3px] w-full overflow-hidden rounded-full",
|
|
70
70
|
children: /* @__PURE__ */ jsx("span", {
|
|
71
|
-
className: "bg-accent block h-full rounded-full transition-[width] duration-
|
|
71
|
+
className: "bg-accent block h-full rounded-full transition-[width] duration-slower",
|
|
72
72
|
style: { width: "42%" }
|
|
73
73
|
})
|
|
74
74
|
})]
|
|
@@ -26,7 +26,7 @@ function Suggestions({ suggestions, selectedSuggestion, cycle, onSuggestion, var
|
|
|
26
26
|
type: "button",
|
|
27
27
|
"aria-pressed": selectedSuggestion === suggestion,
|
|
28
28
|
onClick: () => onSuggestion(suggestion),
|
|
29
|
-
className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in cue-elements-fill-mode-both flex cursor-pointer items-center text-(length:--cue-text-body) transition-transform duration-
|
|
29
|
+
className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in cue-elements-fill-mode-both flex cursor-pointer items-center text-(length:--cue-text-body) transition-transform duration-base hover:-translate-y-px active:scale-[0.96] motion-reduce:animate-none", list ? "w-full rounded-overlay px-4 py-2.5 text-start" : "rounded-full px-4 py-2", selectedSuggestion === suggestion && "bg-accent text-accent-fg"),
|
|
30
30
|
style: { animationDelay: `${index * 70}ms` },
|
|
31
31
|
children: suggestion
|
|
32
32
|
}, suggestion))
|
|
@@ -9,19 +9,19 @@ declare const field = "bg-fg/[0.06]";
|
|
|
9
9
|
/** {@link field} for something clickable. */
|
|
10
10
|
declare const fieldInteractive = "bg-fg/[0.06] transition-colors hover:bg-fg/[0.09]";
|
|
11
11
|
/** The press affordance: a 4% squash on pointer-down, stilled under reduced motion. */
|
|
12
|
-
declare const pressable = "transition-transform duration-
|
|
12
|
+
declare const pressable = "transition-transform duration-fast ease-[cubic-bezier(0.23,1,0.32,1)] active:scale-[0.96] motion-reduce:transition-none";
|
|
13
13
|
/** A round chromeless icon button, with the ring cue puts on everything focusable. */
|
|
14
|
-
declare const ghostButton = "flex items-center justify-center rounded-full text-fg-muted outline-none transition-[background-color,color,scale] duration-
|
|
14
|
+
declare const ghostButton = "flex items-center justify-center rounded-full text-fg-muted outline-none transition-[background-color,color,scale] duration-fast hover:bg-surface-2 hover:text-fg active:scale-[0.96] focus-visible:outline-solid focus-visible:outline-[length:var(--cue-style-focus-width,var(--cue-focus-ring))] focus-visible:outline-(--cue-focus) focus-visible:outline-offset-1 motion-reduce:transition-none";
|
|
15
15
|
/** The inverse fill: accent ground, accent ink — the one loud button in a panel. */
|
|
16
|
-
declare const inkButton = "bg-accent text-accent-fg transition-[background-color,scale] duration-
|
|
16
|
+
declare const inkButton = "bg-accent text-accent-fg transition-[background-color,scale] duration-fast ease-[cubic-bezier(0.23,1,0.32,1)] hover:bg-accent-hover active:scale-[0.96] motion-reduce:transition-none";
|
|
17
17
|
/** The stacked layer of an icon crossfade. Both layers share one grid cell. */
|
|
18
|
-
declare const iconSwap = "[grid-area:1/1] transition-[opacity,scale,filter] duration-
|
|
18
|
+
declare const iconSwap = "[grid-area:1/1] transition-[opacity,scale,filter] duration-brisk ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none";
|
|
19
19
|
/** The icon that is showing. */
|
|
20
20
|
declare const iconSwapIn = "scale-100 opacity-100 blur-none";
|
|
21
21
|
/** The icon that is leaving: shrunk, blurred and gone. */
|
|
22
22
|
declare const iconSwapOut = "scale-[0.25] opacity-0 blur-[4px]";
|
|
23
23
|
/** The stacked layer of a label crossfade, measured by {@link SwapLabel}. */
|
|
24
|
-
declare const labelSwap = "col-start-1 row-start-1 flex w-max items-center gap-1.5 leading-none transition-[opacity,filter] duration-
|
|
24
|
+
declare const labelSwap = "col-start-1 row-start-1 flex w-max items-center gap-1.5 leading-none transition-[opacity,filter] duration-base ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none";
|
|
25
25
|
/** The label that is showing. */
|
|
26
26
|
declare const labelSwapIn = "opacity-100 blur-none";
|
|
27
27
|
/** The label that is leaving, and which must not be selectable while it goes. */
|
|
@@ -34,7 +34,7 @@ declare const labelSwapOut = "pointer-events-none select-none opacity-0 blur-[2p
|
|
|
34
34
|
* wired to the peer this package already requires rather than to the one
|
|
35
35
|
* upstream's registry asks for.
|
|
36
36
|
*/
|
|
37
|
-
declare const collapsePanel = "h-(--collapsible-panel-height) overflow-hidden transition-[height] duration-
|
|
37
|
+
declare const collapsePanel = "h-(--collapsible-panel-height) overflow-hidden transition-[height] duration-brisk ease-[cubic-bezier(0.32,0.72,0,1)] data-[ending-style]:h-0 data-[starting-style]:h-0 motion-reduce:transition-none";
|
|
38
38
|
/** The streaming hue: what is happening right now, rather than what has happened. */
|
|
39
39
|
declare const live = "text-stream";
|
|
40
40
|
/** The metadata typeface: mono, one rung down, tight. Used about a hundred times. */
|
|
@@ -13,19 +13,19 @@ const field = "bg-fg/[0.06]";
|
|
|
13
13
|
/** {@link field} for something clickable. */
|
|
14
14
|
const fieldInteractive = "bg-fg/[0.06] transition-colors hover:bg-fg/[0.09]";
|
|
15
15
|
/** The press affordance: a 4% squash on pointer-down, stilled under reduced motion. */
|
|
16
|
-
const pressable = "transition-transform duration-
|
|
16
|
+
const pressable = "transition-transform duration-fast ease-[cubic-bezier(0.23,1,0.32,1)] active:scale-[0.96] motion-reduce:transition-none";
|
|
17
17
|
/** A round chromeless icon button, with the ring cue puts on everything focusable. */
|
|
18
|
-
const ghostButton = `flex items-center justify-center rounded-full text-fg-muted outline-none transition-[background-color,color,scale] duration-
|
|
18
|
+
const ghostButton = `flex items-center justify-center rounded-full text-fg-muted outline-none transition-[background-color,color,scale] duration-fast hover:bg-surface-2 hover:text-fg active:scale-[0.96] ${FOCUS_RING} motion-reduce:transition-none`;
|
|
19
19
|
/** The inverse fill: accent ground, accent ink — the one loud button in a panel. */
|
|
20
|
-
const inkButton = "bg-accent text-accent-fg transition-[background-color,scale] duration-
|
|
20
|
+
const inkButton = "bg-accent text-accent-fg transition-[background-color,scale] duration-fast ease-[cubic-bezier(0.23,1,0.32,1)] hover:bg-accent-hover active:scale-[0.96] motion-reduce:transition-none";
|
|
21
21
|
/** The stacked layer of an icon crossfade. Both layers share one grid cell. */
|
|
22
|
-
const iconSwap = "[grid-area:1/1] transition-[opacity,scale,filter] duration-
|
|
22
|
+
const iconSwap = "[grid-area:1/1] transition-[opacity,scale,filter] duration-brisk ease-[cubic-bezier(0.2,0,0,1)] motion-reduce:transition-none";
|
|
23
23
|
/** The icon that is showing. */
|
|
24
24
|
const iconSwapIn = "scale-100 opacity-100 blur-none";
|
|
25
25
|
/** The icon that is leaving: shrunk, blurred and gone. */
|
|
26
26
|
const iconSwapOut = "scale-[0.25] opacity-0 blur-[4px]";
|
|
27
27
|
/** The stacked layer of a label crossfade, measured by {@link SwapLabel}. */
|
|
28
|
-
const labelSwap = "col-start-1 row-start-1 flex w-max items-center gap-1.5 leading-none transition-[opacity,filter] duration-
|
|
28
|
+
const labelSwap = "col-start-1 row-start-1 flex w-max items-center gap-1.5 leading-none transition-[opacity,filter] duration-base ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none";
|
|
29
29
|
/** The label that is showing. */
|
|
30
30
|
const labelSwapIn = "opacity-100 blur-none";
|
|
31
31
|
/** The label that is leaving, and which must not be selectable while it goes. */
|
|
@@ -38,7 +38,7 @@ const labelSwapOut = "pointer-events-none select-none opacity-0 blur-[2px]";
|
|
|
38
38
|
* wired to the peer this package already requires rather than to the one
|
|
39
39
|
* upstream's registry asks for.
|
|
40
40
|
*/
|
|
41
|
-
const collapsePanel = "h-(--collapsible-panel-height) overflow-hidden transition-[height] duration-
|
|
41
|
+
const collapsePanel = "h-(--collapsible-panel-height) overflow-hidden transition-[height] duration-brisk ease-[cubic-bezier(0.32,0.72,0,1)] data-[ending-style]:h-0 data-[starting-style]:h-0 motion-reduce:transition-none";
|
|
42
42
|
/** The streaming hue: what is happening right now, rather than what has happened. */
|
|
43
43
|
const live = "text-stream";
|
|
44
44
|
/** The metadata typeface: mono, one rung down, tight. Used about a hundred times. */
|
|
@@ -96,7 +96,7 @@ function SwapLabel({ active, children, className }) {
|
|
|
96
96
|
return /* @__PURE__ */ jsx("span", {
|
|
97
97
|
"data-slot": "swap-label",
|
|
98
98
|
style: width === null ? void 0 : { width },
|
|
99
|
-
className: cn("grid overflow-x-clip transition-[width] duration-
|
|
99
|
+
className: cn("grid overflow-x-clip transition-[width] duration-base ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none", className),
|
|
100
100
|
children: children.map((layer, index) => /* @__PURE__ */ jsx("span", {
|
|
101
101
|
ref: index === 0 ? restingRef : activeRef,
|
|
102
102
|
"aria-hidden": active !== index,
|
|
@@ -71,7 +71,7 @@ const TailStatus = React.forwardRef(function TailStatus({ action, detail, active
|
|
|
71
71
|
children: active ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-3.5 animate-spin text-stream motion-reduce:animate-none" }) : null
|
|
72
72
|
}),
|
|
73
73
|
/* @__PURE__ */ jsxs("span", {
|
|
74
|
-
className: cn("flex min-w-0 flex-1 items-baseline gap-1.5 text-(length:--cue-text-ui)", updatesInPlace && "cue-elements-fade-in cue-elements-animate-in duration-
|
|
74
|
+
className: cn("flex min-w-0 flex-1 items-baseline gap-1.5 text-(length:--cue-text-ui)", updatesInPlace && "cue-elements-fade-in cue-elements-animate-in duration-brisk motion-reduce:animate-none"),
|
|
75
75
|
children: [/* @__PURE__ */ jsx(ShimmerLabel, {
|
|
76
76
|
active,
|
|
77
77
|
className: cn("shrink-0", priority === "attention" ? "text-fg" : "text-fg-muted"),
|
|
@@ -40,7 +40,7 @@ function TerminalBlock({ command, lines, visibleCount, done, variant = "paper",
|
|
|
40
40
|
children: [take(lines, visibleCount).map((line, i) => {
|
|
41
41
|
const isLast = i === lines.length - 1;
|
|
42
42
|
return /* @__PURE__ */ jsx("div", {
|
|
43
|
-
className: cn("cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both duration-
|
|
43
|
+
className: cn("cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both duration-base", isLast && "text-fg"),
|
|
44
44
|
children: line
|
|
45
45
|
}, `${i}-${line}`);
|
|
46
46
|
}), !done && /* @__PURE__ */ jsx("span", {
|
|
@@ -22,7 +22,7 @@ function ThinkingIndicator({ label, elapsed, className, ...props }) {
|
|
|
22
22
|
className: "size-1.5 shrink-0 animate-pulse rounded-full bg-stream motion-reduce:animate-none"
|
|
23
23
|
}),
|
|
24
24
|
/* @__PURE__ */ jsx(ShimmerLabel, {
|
|
25
|
-
className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in relative inline-block leading-none duration-
|
|
25
|
+
className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in relative inline-block leading-none duration-base",
|
|
26
26
|
children: label
|
|
27
27
|
}, label),
|
|
28
28
|
elapsed !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
@@ -18,7 +18,7 @@ function ElementsTimeline({ events, visibleCount, className, ...props }) {
|
|
|
18
18
|
className: cn(paper, "flex w-full max-w-sm flex-col rounded-overlay p-4", className),
|
|
19
19
|
...props,
|
|
20
20
|
children: take(events, visibleCount).map((event, i, shown) => /* @__PURE__ */ jsxs("div", {
|
|
21
|
-
className: "cue-elements-fade-in cue-elements-slide-in-from-left-1 cue-elements-animate-in cue-elements-fill-mode-both grid grid-cols-[3.5rem_1rem_minmax(0,1fr)] gap-x-2 duration-
|
|
21
|
+
className: "cue-elements-fade-in cue-elements-slide-in-from-left-1 cue-elements-animate-in cue-elements-fill-mode-both grid grid-cols-[3.5rem_1rem_minmax(0,1fr)] gap-x-2 duration-base",
|
|
22
22
|
children: [
|
|
23
23
|
/* @__PURE__ */ jsx("span", {
|
|
24
24
|
className: cn(mono, "pt-[3px] text-end tabular-nums", event.when === "future" ? "text-fg-subtle" : "text-fg-subtle"),
|
|
@@ -37,7 +37,7 @@ function TodoList({ items, revision, className, ...props }) {
|
|
|
37
37
|
}), /* @__PURE__ */ jsx("ul", {
|
|
38
38
|
className: "flex flex-col gap-1",
|
|
39
39
|
children: items.map((item) => /* @__PURE__ */ jsxs("li", {
|
|
40
|
-
className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both flex items-start gap-2.5 py-0.5 text-(length:--cue-text-body) duration-
|
|
40
|
+
className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both flex items-start gap-2.5 py-0.5 text-(length:--cue-text-body) duration-base",
|
|
41
41
|
children: [/* @__PURE__ */ jsx("span", {
|
|
42
42
|
className: "flex size-4 h-5 shrink-0 items-center justify-center",
|
|
43
43
|
children: item.status === "done" ? /* @__PURE__ */ jsx("span", {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ToolAbsence, ToolState } from "./tool-state.js";
|
|
1
2
|
//#region src/elements/tool-call.d.ts
|
|
2
3
|
interface ToolCallProps {
|
|
3
4
|
/** Tool name shown on the collapsed trigger row. */
|
|
@@ -11,7 +12,22 @@ interface ToolCallProps {
|
|
|
11
12
|
/** Result payload shown once the call is no longer running. */
|
|
12
13
|
result: string;
|
|
13
14
|
/** When true a spinner replaces the success check on the trigger. */
|
|
14
|
-
running
|
|
15
|
+
running?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Where the call got to: `running`, `done`, `failed` or `refused`. Each settled
|
|
18
|
+
* state ends the row with its own mark. Supersedes `running`.
|
|
19
|
+
*/
|
|
20
|
+
state?: ToolState;
|
|
21
|
+
/**
|
|
22
|
+
* `card` (the default) or `inline`, a denser row that spans its column, for a
|
|
23
|
+
* transcript of many calls.
|
|
24
|
+
*/
|
|
25
|
+
variant?: "card" | "inline";
|
|
26
|
+
/**
|
|
27
|
+
* What an empty `result` means: `none` (it returned nothing), `refused` or
|
|
28
|
+
* `unanswered`. Read only when `result` is empty.
|
|
29
|
+
*/
|
|
30
|
+
absence?: ToolAbsence;
|
|
15
31
|
/** Whether the request and result panel is expanded. */
|
|
16
32
|
open: boolean;
|
|
17
33
|
/** Called when the user expands or collapses the call. */
|
|
@@ -36,6 +52,6 @@ interface ToolCallProps {
|
|
|
36
52
|
* onOpenChange={setOpen}
|
|
37
53
|
* />
|
|
38
54
|
*/
|
|
39
|
-
declare function ToolCall({ label, activeLabel, query, request, result, running, open, onOpenChange, className }: ToolCallProps): import("react").JSX.Element;
|
|
55
|
+
declare function ToolCall({ label, activeLabel, query, request, result, running, state, variant, absence, open, onOpenChange, className }: ToolCallProps): import("react").JSX.Element;
|
|
40
56
|
//#endregion
|
|
41
57
|
export { ToolCall, ToolCallProps };
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
3
|
import { FOCUS_RING } from "../system/_focus-ring.js";
|
|
4
4
|
import { ShimmerLabel, SwapLabel, collapsePanel, field, mono } from "./surfaces.js";
|
|
5
|
+
import { ABSENCE_TEXT, ToolStateMark, resolveToolState } from "./tool-state.js";
|
|
5
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
7
|
-
import {
|
|
8
|
+
import { ChevronRightIcon } from "lucide-react";
|
|
8
9
|
//#region src/elements/tool-call.tsx
|
|
9
10
|
/**
|
|
10
11
|
* One tool invocation with its request and result tucked behind a disclosure.
|
|
@@ -23,32 +24,40 @@ import { CheckIcon, ChevronRightIcon } from "lucide-react";
|
|
|
23
24
|
* onOpenChange={setOpen}
|
|
24
25
|
* />
|
|
25
26
|
*/
|
|
26
|
-
function ToolCall({ label, activeLabel, query, request, result, running, open, onOpenChange, className }) {
|
|
27
|
+
function ToolCall({ label, activeLabel, query, request, result, running, state, variant = "card", absence, open, onOpenChange, className }) {
|
|
28
|
+
const resolved = resolveToolState(state, running);
|
|
29
|
+
const busy = resolved === "running";
|
|
27
30
|
return /* @__PURE__ */ jsxs(Collapsible.Root, {
|
|
28
31
|
"data-slot": "tool-call",
|
|
32
|
+
"data-state": resolved,
|
|
33
|
+
"data-variant": variant,
|
|
34
|
+
"data-inline": variant === "inline" || void 0,
|
|
29
35
|
open,
|
|
30
36
|
onOpenChange,
|
|
31
|
-
className: cn("w-full max-w-sm", className),
|
|
37
|
+
className: cn("group/tool-call w-full", variant === "card" && "max-w-sm", className),
|
|
32
38
|
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
|
|
33
|
-
className: `group/trigger text-fg-muted hover:text-fg flex items-center gap-2 rounded-control py-1 text-(length:--cue-text-body) transition-colors outline-none ${FOCUS_RING}`,
|
|
39
|
+
className: `group/trigger text-fg-muted hover:text-fg flex items-center gap-2 group-data-inline/tool-call:gap-1.5 group-data-inline/tool-call:py-0.5 group-data-inline/tool-call:text-(length:--cue-text-ui) rounded-control py-1 text-(length:--cue-text-body) transition-colors outline-none ${FOCUS_RING}`,
|
|
34
40
|
children: [
|
|
35
|
-
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "size-3.5 shrink-0 opacity-60 transition-transform duration-
|
|
41
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "size-3.5 shrink-0 opacity-60 transition-transform duration-brisk ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[panel-open]/trigger:rotate-90 motion-reduce:transition-none" }),
|
|
36
42
|
/* @__PURE__ */ jsxs(SwapLabel, {
|
|
37
|
-
active:
|
|
43
|
+
active: busy ? 0 : 1,
|
|
38
44
|
className: "text-start",
|
|
39
45
|
children: [/* @__PURE__ */ jsx(ShimmerLabel, {
|
|
40
|
-
active:
|
|
46
|
+
active: busy,
|
|
41
47
|
className: "relative inline-block leading-none",
|
|
42
48
|
children: activeLabel
|
|
43
49
|
}), /* @__PURE__ */ jsx(Fragment, { children: label })]
|
|
44
50
|
}),
|
|
45
51
|
/* @__PURE__ */ jsx("span", {
|
|
46
|
-
className: cn(mono, "bg-surface-2 text-fg-muted rounded-control px-1.5 py-0.5"),
|
|
52
|
+
className: cn(mono, "bg-surface-2 text-fg-muted rounded-control px-1.5 py-0.5 group-data-inline/tool-call:bg-transparent group-data-inline/tool-call:px-0"),
|
|
47
53
|
children: query
|
|
48
54
|
}),
|
|
49
55
|
/* @__PURE__ */ jsx("span", {
|
|
50
56
|
className: "ms-auto flex w-4 items-center justify-end",
|
|
51
|
-
children:
|
|
57
|
+
children: /* @__PURE__ */ jsx(ToolStateMark, {
|
|
58
|
+
state: resolved,
|
|
59
|
+
className: "size-3.5"
|
|
60
|
+
})
|
|
52
61
|
})
|
|
53
62
|
]
|
|
54
63
|
}), /* @__PURE__ */ jsx(Collapsible.Panel, {
|
|
@@ -73,8 +82,8 @@ function ToolCall({ label, activeLabel, query, request, result, running, open, o
|
|
|
73
82
|
className: cn(mono, "text-fg-subtle mb-1"),
|
|
74
83
|
children: "Result"
|
|
75
84
|
}), /* @__PURE__ */ jsx("p", {
|
|
76
|
-
className: "text-fg",
|
|
77
|
-
children: result
|
|
85
|
+
className: result === "" && absence !== void 0 ? "text-fg-muted italic" : "text-fg",
|
|
86
|
+
children: result === "" && absence !== void 0 ? ABSENCE_TEXT[absence] : result
|
|
78
87
|
})]
|
|
79
88
|
})
|
|
80
89
|
]
|
|
@@ -59,13 +59,13 @@ function ToolError({ name, target, message, attempt, maxAttempts, retrying, onRe
|
|
|
59
59
|
type: "button",
|
|
60
60
|
onClick: onSkip,
|
|
61
61
|
disabled: !onSkip,
|
|
62
|
-
className: "text-fg-muted hover:bg-surface-2 hover:text-fg h-7 rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-
|
|
62
|
+
className: "text-fg-muted hover:bg-surface-2 hover:text-fg h-7 rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96] disabled:pointer-events-none disabled:opacity-30",
|
|
63
63
|
children: "Skip"
|
|
64
64
|
}), /* @__PURE__ */ jsxs("button", {
|
|
65
65
|
type: "button",
|
|
66
66
|
onClick: onRetry,
|
|
67
67
|
disabled: retrying,
|
|
68
|
-
className: "text-fg-muted hover:bg-surface-2 hover:text-fg flex h-7 items-center gap-1.5 rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-
|
|
68
|
+
className: "text-fg-muted hover:bg-surface-2 hover:text-fg flex h-7 items-center gap-1.5 rounded-full px-2.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96] disabled:pointer-events-none",
|
|
69
69
|
children: [retrying ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-3 animate-spin motion-reduce:animate-none" }) : /* @__PURE__ */ jsx(RotateCwIcon, { className: "size-3" }), retrying ? "Retrying" : "Retry"]
|
|
70
70
|
})]
|
|
71
71
|
})
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { ComponentProps } from "react";
|
|
2
2
|
//#region src/elements/tool-group.d.ts
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Where one tool in a group got to: still running, finished, failed, or refused before
|
|
5
|
+
* it ran.
|
|
6
|
+
*/
|
|
7
|
+
type GroupedToolState = "running" | "done" | "failed" | "refused";
|
|
5
8
|
/** One row of a tool group: what ran, against what, and how it ended. */
|
|
6
9
|
interface GroupedTool {
|
|
7
10
|
/** Stable identity for the row key. */
|
|
@@ -28,7 +31,7 @@ interface GroupedTool {
|
|
|
28
31
|
* onOpenChange={setOpen}
|
|
29
32
|
* />
|
|
30
33
|
*/
|
|
31
|
-
declare function ToolGroup({ label, tools, open, onOpenChange, className, ...props }: Omit<ComponentProps<"div">, "children" | "label" | "tools" | "open" | "onOpenChange"> & {
|
|
34
|
+
declare function ToolGroup({ label, tools, open, onOpenChange, variant, className, ...props }: Omit<ComponentProps<"div">, "children" | "label" | "tools" | "open" | "onOpenChange"> & {
|
|
32
35
|
/** What the group did, as one line. */
|
|
33
36
|
label: string;
|
|
34
37
|
/**
|
|
@@ -40,6 +43,11 @@ declare function ToolGroup({ label, tools, open, onOpenChange, className, ...pro
|
|
|
40
43
|
open: boolean;
|
|
41
44
|
/** Called when the group is expanded or collapsed. */
|
|
42
45
|
onOpenChange?: (open: boolean) => void;
|
|
46
|
+
/**
|
|
47
|
+
* `card` (the default) or `inline`, a row in its column without the paper, for a
|
|
48
|
+
* transcript of many groups.
|
|
49
|
+
*/
|
|
50
|
+
variant?: "card" | "inline";
|
|
43
51
|
}): import("react").JSX.Element;
|
|
44
52
|
//#endregion
|
|
45
53
|
export { GroupedTool, GroupedToolState, ToolGroup };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
-
import { mono
|
|
3
|
+
import { mono } from "./surfaces.js";
|
|
4
|
+
import { ToolStateMark } from "./tool-state.js";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
6
|
+
import { ChevronRightIcon, Loader2Icon } from "lucide-react";
|
|
6
7
|
//#region src/elements/tool-group.tsx
|
|
7
8
|
/**
|
|
8
9
|
* Calls that went out together, collapsed to one row until you want the detail.
|
|
@@ -17,54 +18,77 @@ import { CheckIcon, ChevronRightIcon, Loader2Icon, XIcon } from "lucide-react";
|
|
|
17
18
|
* onOpenChange={setOpen}
|
|
18
19
|
* />
|
|
19
20
|
*/
|
|
20
|
-
function ToolGroup({ label, tools, open, onOpenChange, className, ...props }) {
|
|
21
|
+
function ToolGroup({ label, tools, open, onOpenChange, variant = "card", className, ...props }) {
|
|
21
22
|
const running = tools.filter((tool) => tool.state === "running").length;
|
|
22
23
|
const failed = tools.filter((tool) => tool.state === "failed").length;
|
|
24
|
+
const refused = tools.filter((tool) => tool.state === "refused").length;
|
|
25
|
+
const live = open ? void 0 : tools.find((tool) => tool.state === "running");
|
|
23
26
|
return /* @__PURE__ */ jsxs("div", {
|
|
24
27
|
"data-slot": "tool-group",
|
|
25
|
-
|
|
28
|
+
"data-variant": variant,
|
|
29
|
+
className: cn(variant === "card" && "bg-surface-1 border border-border", "flex w-full flex-col overflow-hidden", variant === "card" && "max-w-sm rounded-overlay", className),
|
|
26
30
|
...props,
|
|
27
|
-
children: [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/* @__PURE__ */ jsx(ChevronRightIcon, { className: cn("text-fg-subtle size-3 shrink-0 transition-transform duration-200 motion-reduce:transition-none", open && "rotate-90") }),
|
|
34
|
-
/* @__PURE__ */ jsx("span", {
|
|
35
|
-
className: "min-w-0 flex-1 truncate text-(length:--cue-text-body)",
|
|
36
|
-
children: label
|
|
37
|
-
}),
|
|
38
|
-
/* @__PURE__ */ jsx("span", {
|
|
39
|
-
className: cn(mono, "text-fg-subtle shrink-0 tabular-nums"),
|
|
40
|
-
children: running > 0 ? `${tools.length - running}/${tools.length}` : failed > 0 ? `${failed} failed` : `${tools.length} done`
|
|
41
|
-
}),
|
|
42
|
-
running > 0 ? /* @__PURE__ */ jsx(Loader2Icon, { className: "text-fg-subtle size-3.5 shrink-0 animate-spin motion-reduce:animate-none" }) : failed > 0 ? /* @__PURE__ */ jsx(XIcon, { className: "size-3.5 shrink-0 text-danger" }) : /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5 shrink-0 text-ok" })
|
|
43
|
-
]
|
|
44
|
-
}), open && /* @__PURE__ */ jsx("div", {
|
|
45
|
-
className: "border-border cue-elements-fade-in cue-elements-slide-in-from-top-1 cue-elements-animate-in flex flex-col border-t duration-200",
|
|
46
|
-
children: tools.map((tool) => /* @__PURE__ */ jsxs("div", {
|
|
47
|
-
className: "flex items-center gap-2.5 px-3.5 py-2",
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ jsxs("button", {
|
|
33
|
+
type: "button",
|
|
34
|
+
"aria-expanded": open,
|
|
35
|
+
onClick: () => onOpenChange?.(!open),
|
|
36
|
+
className: "hover:bg-surface-1 flex items-center gap-2.5 px-3.5 py-2.5 text-start transition-colors",
|
|
48
37
|
children: [
|
|
38
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: cn("text-fg-subtle size-3 shrink-0 transition-transform duration-brisk motion-reduce:transition-none", open && "rotate-90") }),
|
|
49
39
|
/* @__PURE__ */ jsx("span", {
|
|
50
|
-
className: "
|
|
51
|
-
children:
|
|
40
|
+
className: "min-w-0 flex-1 truncate text-(length:--cue-text-body)",
|
|
41
|
+
children: label
|
|
52
42
|
}),
|
|
53
43
|
/* @__PURE__ */ jsx("span", {
|
|
54
|
-
className: cn(
|
|
55
|
-
children:
|
|
44
|
+
className: cn(mono, "text-fg-subtle shrink-0 tabular-nums"),
|
|
45
|
+
children: running > 0 ? `${tools.length - running}/${tools.length}` : failed > 0 ? `${failed} failed` : refused > 0 ? `${refused} refused` : `${tools.length} done`
|
|
56
46
|
}),
|
|
57
|
-
/* @__PURE__ */ jsx("
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
tool.durationMs !== void 0 && /* @__PURE__ */ jsxs("span", {
|
|
62
|
-
className: cn("font-mono text-(length:--cue-text-label) tracking-tight", "text-fg-subtle shrink-0 tabular-nums"),
|
|
63
|
-
children: [tool.durationMs, "ms"]
|
|
47
|
+
running > 0 ? /* @__PURE__ */ jsx(Loader2Icon, { className: "text-fg-subtle size-3.5 shrink-0 animate-spin motion-reduce:animate-none" }) : /* @__PURE__ */ jsx(ToolStateMark, {
|
|
48
|
+
state: failed > 0 ? "failed" : refused > 0 ? "refused" : "done",
|
|
49
|
+
animated: false,
|
|
50
|
+
className: "size-3.5 shrink-0"
|
|
64
51
|
})
|
|
65
52
|
]
|
|
66
|
-
},
|
|
67
|
-
|
|
53
|
+
}),
|
|
54
|
+
live !== void 0 && /* @__PURE__ */ jsxs("p", {
|
|
55
|
+
"data-slot": "tool-group-live",
|
|
56
|
+
className: cn("font-mono text-(length:--cue-text-label) tracking-tight", "text-fg-subtle -mt-1.5 truncate px-3.5 pb-2 ps-9"),
|
|
57
|
+
children: [
|
|
58
|
+
live.name,
|
|
59
|
+
" ",
|
|
60
|
+
live.target
|
|
61
|
+
]
|
|
62
|
+
}),
|
|
63
|
+
open && /* @__PURE__ */ jsx("div", {
|
|
64
|
+
className: "border-border cue-elements-fade-in cue-elements-slide-in-from-top-1 cue-elements-animate-in flex flex-col border-t duration-brisk",
|
|
65
|
+
children: tools.map((tool) => /* @__PURE__ */ jsxs("div", {
|
|
66
|
+
className: "flex items-center gap-2.5 px-3.5 py-2",
|
|
67
|
+
children: [
|
|
68
|
+
/* @__PURE__ */ jsx("span", {
|
|
69
|
+
className: "flex size-3.5 shrink-0 items-center justify-center",
|
|
70
|
+
children: tool.state === "running" ? /* @__PURE__ */ jsx(Loader2Icon, { className: "text-fg-subtle size-3 animate-spin motion-reduce:animate-none" }) : /* @__PURE__ */ jsx(ToolStateMark, {
|
|
71
|
+
state: tool.state,
|
|
72
|
+
animated: false,
|
|
73
|
+
className: "size-3"
|
|
74
|
+
})
|
|
75
|
+
}),
|
|
76
|
+
/* @__PURE__ */ jsx("span", {
|
|
77
|
+
className: cn("font-mono text-(length:--cue-text-label) tracking-tight", "text-fg-muted shrink-0"),
|
|
78
|
+
children: tool.name
|
|
79
|
+
}),
|
|
80
|
+
/* @__PURE__ */ jsx("span", {
|
|
81
|
+
className: "text-fg-muted min-w-0 flex-1 truncate text-(length:--cue-text-body)",
|
|
82
|
+
children: tool.target
|
|
83
|
+
}),
|
|
84
|
+
tool.durationMs !== void 0 && /* @__PURE__ */ jsxs("span", {
|
|
85
|
+
className: cn("font-mono text-(length:--cue-text-label) tracking-tight", "text-fg-subtle shrink-0 tabular-nums"),
|
|
86
|
+
children: [tool.durationMs, "ms"]
|
|
87
|
+
})
|
|
88
|
+
]
|
|
89
|
+
}, tool.id))
|
|
90
|
+
})
|
|
91
|
+
]
|
|
68
92
|
});
|
|
69
93
|
}
|
|
70
94
|
//#endregion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/elements/tool-state.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Where a tool call got to: still running, finished, failed, or refused before
|
|
4
|
+
* it ran (cue-ui-51). The four a transcript has to tell apart at a glance.
|
|
5
|
+
*/
|
|
6
|
+
type ToolState = "running" | "done" | "failed" | "refused";
|
|
7
|
+
/**
|
|
8
|
+
* What kind of nothing an empty result is (cue-ui-52): the call ran and
|
|
9
|
+
* returned nothing, it was refused, or it was never answered.
|
|
10
|
+
*/
|
|
11
|
+
type ToolAbsence = "none" | "refused" | "unanswered";
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ToolAbsence, ToolState };
|