@ctrl-ui/react 0.9.4 → 0.9.6

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.
Files changed (80) hide show
  1. package/README.md +27 -0
  2. package/dist/action-bar.js +16 -8
  3. package/dist/activity.d.ts +1 -1
  4. package/dist/activity.js +3 -1
  5. package/dist/audio-visualizer.js +1 -1
  6. package/dist/blocks/agent-run-clock.d.ts +5 -0
  7. package/dist/blocks/agent-run-clock.js +52 -0
  8. package/dist/blocks/agent-run-sidebar.d.ts +13 -0
  9. package/dist/blocks/agent-run-sidebar.js +100 -0
  10. package/dist/blocks/agent-run-status.d.ts +32 -0
  11. package/dist/blocks/agent-run-status.js +27 -0
  12. package/dist/blocks/agent-run.d.ts +80 -0
  13. package/dist/blocks/agent-run.js +254 -0
  14. package/dist/blocks/coding-agent.d.ts +1 -1
  15. package/dist/blocks/coding-agent.js +1 -4
  16. package/dist/blocks/design-canvas-data.d.ts +1 -1
  17. package/dist/blocks/design-canvas.d.ts +2 -1
  18. package/dist/blocks/design-canvas.js +15 -8
  19. package/dist/blocks/file-explorer.js +14 -16
  20. package/dist/chat-message.js +33 -39
  21. package/dist/knob-contracts/infinite-canvas-knobs.d.ts +1 -1
  22. package/dist/knob-contracts/infinite-canvas-knobs.js +1 -7
  23. package/dist/knob-contracts/swap-knobs.d.ts +4 -0
  24. package/dist/knob-contracts/swap-knobs.js +9 -0
  25. package/dist/knob-contracts/timeline-knobs.d.ts +1 -1
  26. package/dist/knob-contracts/timeline-knobs.js +1 -0
  27. package/dist/knob-contracts/tool-approval-knobs.d.ts +4 -0
  28. package/dist/knob-contracts/tool-approval-knobs.js +32 -0
  29. package/dist/lib/cn.d.ts +2 -0
  30. package/dist/lib/cn.js +29 -24
  31. package/dist/lib/infinite-canvas-camera-store.d.ts +65 -0
  32. package/dist/lib/infinite-canvas-camera-store.js +233 -0
  33. package/dist/lib/infinite-canvas-camera.d.ts +33 -0
  34. package/dist/lib/infinite-canvas-camera.js +98 -0
  35. package/dist/lib/infinite-canvas-navigation.d.ts +19 -0
  36. package/dist/lib/infinite-canvas-navigation.js +395 -0
  37. package/dist/markdown-editor/bubble-menu.d.ts +6 -0
  38. package/dist/markdown-editor/bubble-menu.js +45 -0
  39. package/dist/markdown-editor/toolbar.d.ts +17 -1
  40. package/dist/markdown-editor/toolbar.js +103 -81
  41. package/dist/styles/index.css +10 -8
  42. package/dist/styles/recipes/activity.css +8 -0
  43. package/dist/styles/recipes/button-group.css +12 -6
  44. package/dist/styles/recipes/button-states.css +12 -0
  45. package/dist/styles/recipes/button.css +13 -3
  46. package/dist/styles/recipes/chat-composer-attachment.css +7 -0
  47. package/dist/styles/recipes/chat-message-edit.css +6 -21
  48. package/dist/styles/recipes/color-picker-details.css +7 -0
  49. package/dist/styles/recipes/field.css +7 -0
  50. package/dist/styles/recipes/infinite-canvas.css +17 -57
  51. package/dist/styles/recipes/inline-attachment.css +7 -0
  52. package/dist/styles/recipes/kbd.css +7 -0
  53. package/dist/styles/recipes/markdown-editor.css +12 -0
  54. package/dist/styles/recipes/pagination.css +8 -1
  55. package/dist/styles/recipes/scroll-area.css +1 -3
  56. package/dist/styles/recipes/swap.css +143 -0
  57. package/dist/styles/recipes/tabs.css +12 -0
  58. package/dist/styles/recipes/timeline.css +11 -0
  59. package/dist/styles/recipes/tool-approval.css +267 -0
  60. package/dist/styles/recipes/track-highlight.css +19 -6
  61. package/dist/styles/theme.css +6 -5
  62. package/dist/styles/type-scale.css +2 -1
  63. package/dist/tool-approval.d.ts +49 -0
  64. package/dist/tool-approval.js +260 -0
  65. package/dist/ui/code.js +13 -3
  66. package/dist/ui/command.js +1 -0
  67. package/dist/ui/infinite-canvas.d.ts +19 -22
  68. package/dist/ui/infinite-canvas.js +264 -325
  69. package/dist/ui/rich-tooltip.d.ts +2 -1
  70. package/dist/ui/rich-tooltip.js +32 -29
  71. package/dist/ui/sidebar.js +1 -1
  72. package/dist/ui/swap.d.ts +14 -0
  73. package/dist/ui/swap.js +69 -0
  74. package/dist/ui/timeline.d.ts +1 -1
  75. package/dist/ui/timeline.js +1 -1
  76. package/dist/ui/typography.d.ts +2 -0
  77. package/dist/ui/typography.js +2 -0
  78. package/dist/user-ask.js +1 -1
  79. package/lint/no-raw-type-classes.grit +7 -0
  80. package/package.json +4 -3
@@ -0,0 +1,254 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { LiveStatus } from "../ui/live-status.js";
4
+ import { Activity, ActivityContent, ActivityDetail, ActivityDetailContent, ActivityDetailLabel, ActivityIcon, ActivityRow, ActivityStatus, ActivityTitle, ActivityTrigger } from "../activity.js";
5
+ import { Heading, Text } from "../ui/typography.js";
6
+ import { Badge } from "../ui/badge.js";
7
+ import { elapsedIsoDuration, formatElapsed, useRunClock } from "./agent-run-clock.js";
8
+ import { SidebarProvider } from "../ui/sidebar-provider.js";
9
+ import { SidebarInset, SidebarTrigger } from "../ui/sidebar.js";
10
+ import { agentRunStatusColors, agentRunStatusLabels, agentRunStepLabels } from "./agent-run-status.js";
11
+ import { AgentRunSidebar } from "./agent-run-sidebar.js";
12
+ import { Card, CardAction, CardContent, CardHeader } from "../ui/card.js";
13
+ import { Timeline, TimelineContent, TimelineDescription, TimelineIndicator, TimelineItem, TimelineMeta, TimelineSeparator, TimelineTitle } from "../ui/timeline.js";
14
+ import { createContext, useContext, useId } from "react";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ import { Check, Circle, CircleAlert, CircleDashed, CirclePause, LoaderCircle } from "lucide-react";
17
+ //#region src/blocks/agent-run.tsx
18
+ const AgentRunLayoutContext = createContext("viewport");
19
+ function useHeadingLevels() {
20
+ return useContext(AgentRunLayoutContext) === "contained" ? {
21
+ title: 2,
22
+ section: 3
23
+ } : {
24
+ title: 1,
25
+ section: 2
26
+ };
27
+ }
28
+ function AgentRunBlock({ appName = "Agents", brand, runs, activeRunId, onRunSelect, onNewRun, sidebarFooter, children, layout = "viewport", className, style, ...props }) {
29
+ const providerStyle = {
30
+ "--sidebar-width": "16rem",
31
+ ...style
32
+ };
33
+ return /* @__PURE__ */ jsxs(SidebarProvider, {
34
+ layout,
35
+ className: cn("bg-background text-foreground", layout === "viewport" && "h-svh overflow-hidden", className),
36
+ style: providerStyle,
37
+ ...props,
38
+ children: [/* @__PURE__ */ jsx(AgentRunSidebar, {
39
+ appName,
40
+ brand,
41
+ runs,
42
+ activeRunId,
43
+ sidebarFooter,
44
+ onRunSelect,
45
+ onNewRun
46
+ }), /* @__PURE__ */ jsx(SidebarInset, {
47
+ className: "@container/agent-run flex h-full min-h-0 min-w-0 flex-col overflow-hidden",
48
+ children: /* @__PURE__ */ jsx(AgentRunLayoutContext.Provider, {
49
+ value: layout,
50
+ children
51
+ })
52
+ })]
53
+ });
54
+ }
55
+ function AgentRunElapsed({ startedAt, endedAt, className, ...props }) {
56
+ const now = useRunClock(endedAt === void 0);
57
+ const end = endedAt ?? now;
58
+ const ms = end === null ? null : Math.max(0, end - startedAt);
59
+ return /* @__PURE__ */ jsx("time", {
60
+ dateTime: ms === null ? void 0 : elapsedIsoDuration(ms),
61
+ className: cn("text-label tabular-nums text-muted-foreground", className),
62
+ ...props,
63
+ children: ms === null ? "" : formatElapsed(ms)
64
+ });
65
+ }
66
+ function AgentRunHeader({ title, status, startedAt, endedAt, actions, className, ...props }) {
67
+ const levels = useHeadingLevels();
68
+ return /* @__PURE__ */ jsxs("header", {
69
+ className: cn("flex h-12 shrink-0 items-center gap-2 border-b border-border/70 px-3", className),
70
+ ...props,
71
+ children: [
72
+ /* @__PURE__ */ jsx(SidebarTrigger, {
73
+ size: "xs",
74
+ className: "lg:hidden"
75
+ }),
76
+ /* @__PURE__ */ jsx(Heading, {
77
+ level: levels.title,
78
+ size: "label",
79
+ weight: "medium",
80
+ className: "min-w-0 truncate",
81
+ title,
82
+ children: title
83
+ }),
84
+ /* @__PURE__ */ jsx(Badge, {
85
+ size: "sm",
86
+ color: agentRunStatusColors[status],
87
+ children: agentRunStatusLabels[status]
88
+ }),
89
+ startedAt === void 0 ? null : /* @__PURE__ */ jsx(AgentRunElapsed, {
90
+ startedAt,
91
+ endedAt,
92
+ className: "text-body"
93
+ }),
94
+ /* @__PURE__ */ jsx("div", {
95
+ className: "ms-auto flex shrink-0 items-center gap-1",
96
+ children: actions
97
+ }),
98
+ /* @__PURE__ */ jsx(LiveStatus, { message: `${title}: ${agentRunStatusLabels[status]}` })
99
+ ]
100
+ });
101
+ }
102
+ function AgentRunBody({ aside, className, children, ...props }) {
103
+ return /* @__PURE__ */ jsxs("div", {
104
+ className: cn("grid min-h-0 flex-1 content-start overflow-y-auto @3xl/agent-run:grid-cols-[minmax(0,1fr)_minmax(18rem,22rem)] @3xl/agent-run:content-stretch @3xl/agent-run:overflow-hidden", className),
105
+ ...props,
106
+ children: [/* @__PURE__ */ jsx("div", {
107
+ className: "min-w-0 px-4 py-5 @lg/agent-run:px-6 @3xl/agent-run:overflow-y-auto",
108
+ children
109
+ }), aside]
110
+ });
111
+ }
112
+ function AgentRunPlan({ title = "Plan", description, className, children, ...props }) {
113
+ const levels = useHeadingLevels();
114
+ const headingId = useId();
115
+ return /* @__PURE__ */ jsxs("section", {
116
+ "aria-labelledby": headingId,
117
+ className: cn("min-w-0", className),
118
+ ...props,
119
+ children: [
120
+ /* @__PURE__ */ jsx(Heading, {
121
+ id: headingId,
122
+ level: levels.section,
123
+ size: "label",
124
+ weight: "medium",
125
+ children: title
126
+ }),
127
+ description ? /* @__PURE__ */ jsx(Text, {
128
+ size: "caption",
129
+ tone: "muted",
130
+ children: description
131
+ }) : null,
132
+ /* @__PURE__ */ jsx(Timeline, {
133
+ className: "mt-3",
134
+ children
135
+ })
136
+ ]
137
+ });
138
+ }
139
+ const stepIcons = {
140
+ neutral: /* @__PURE__ */ jsx(Circle, { "aria-hidden": "true" }),
141
+ pending: /* @__PURE__ */ jsx(CircleDashed, { "aria-hidden": "true" }),
142
+ running: /* @__PURE__ */ jsx(LoaderCircle, {
143
+ className: "motion-safe:animate-spin",
144
+ "aria-hidden": "true"
145
+ }),
146
+ waiting: /* @__PURE__ */ jsx(CirclePause, { "aria-hidden": "true" }),
147
+ success: /* @__PURE__ */ jsx(Check, { "aria-hidden": "true" }),
148
+ error: /* @__PURE__ */ jsx(CircleAlert, { "aria-hidden": "true" })
149
+ };
150
+ function AgentRunStep({ title, detail, startedAt, endedAt, actions, state = "pending", children, ...props }) {
151
+ const hasMeta = startedAt !== void 0 || actions !== void 0;
152
+ return /* @__PURE__ */ jsxs(TimelineItem, {
153
+ state,
154
+ ...props,
155
+ children: [
156
+ /* @__PURE__ */ jsx(TimelineIndicator, {
157
+ "aria-label": agentRunStepLabels[state],
158
+ children: stepIcons[state]
159
+ }),
160
+ /* @__PURE__ */ jsx(TimelineSeparator, {}),
161
+ /* @__PURE__ */ jsxs(TimelineContent, { children: [
162
+ /* @__PURE__ */ jsx(TimelineTitle, { children: title }),
163
+ detail ? /* @__PURE__ */ jsx(TimelineDescription, { children: detail }) : null,
164
+ hasMeta ? /* @__PURE__ */ jsxs(TimelineMeta, { children: [startedAt === void 0 ? null : /* @__PURE__ */ jsx(AgentRunElapsed, {
165
+ startedAt,
166
+ endedAt
167
+ }), actions] }) : null,
168
+ children ? /* @__PURE__ */ jsx("div", {
169
+ className: "mt-2 grid gap-2",
170
+ children
171
+ }) : null
172
+ ] })
173
+ ]
174
+ });
175
+ }
176
+ function formatToolValue(value) {
177
+ return typeof value === "string" ? value : JSON.stringify(value, null, 2);
178
+ }
179
+ function AgentRunToolCall({ name, summary, icon, input, output, errorText, startedAt, endedAt, ...props }) {
180
+ const hasDetails = input !== void 0 || output !== void 0 || errorText !== void 0;
181
+ const Row = hasDetails ? ActivityTrigger : ActivityRow;
182
+ return /* @__PURE__ */ jsxs(Activity, {
183
+ kind: "tool",
184
+ name,
185
+ ...props,
186
+ children: [/* @__PURE__ */ jsxs(Row, { children: [
187
+ icon ? /* @__PURE__ */ jsx(ActivityIcon, { children: icon }) : /* @__PURE__ */ jsx(ActivityIcon, {}),
188
+ /* @__PURE__ */ jsxs(ActivityTitle, { children: [name, summary ? /* @__PURE__ */ jsxs("span", {
189
+ className: "text-muted-foreground",
190
+ children: [" · ", summary]
191
+ }) : null] }),
192
+ startedAt === void 0 ? null : /* @__PURE__ */ jsx(AgentRunElapsed, {
193
+ startedAt,
194
+ endedAt,
195
+ className: "ms-2"
196
+ }),
197
+ /* @__PURE__ */ jsx(ActivityStatus, { className: "sr-only" })
198
+ ] }), hasDetails ? /* @__PURE__ */ jsxs(ActivityContent, { children: [
199
+ input === void 0 ? null : /* @__PURE__ */ jsxs(ActivityDetail, { children: [/* @__PURE__ */ jsx(ActivityDetailLabel, { children: "Input" }), /* @__PURE__ */ jsx(ActivityDetailContent, {
200
+ format: "code",
201
+ children: formatToolValue(input)
202
+ })] }),
203
+ output === void 0 ? null : /* @__PURE__ */ jsxs(ActivityDetail, { children: [/* @__PURE__ */ jsx(ActivityDetailLabel, { children: "Output" }), /* @__PURE__ */ jsx(ActivityDetailContent, {
204
+ format: "code",
205
+ children: formatToolValue(output)
206
+ })] }),
207
+ errorText === void 0 ? null : /* @__PURE__ */ jsxs(ActivityDetail, { children: [/* @__PURE__ */ jsx(ActivityDetailLabel, { children: "Error" }), /* @__PURE__ */ jsx(ActivityDetailContent, {
208
+ className: "text-destructive-text",
209
+ children: errorText
210
+ })] })
211
+ ] }) : null]
212
+ });
213
+ }
214
+ function AgentRunAside({ className, ...props }) {
215
+ return /* @__PURE__ */ jsx("aside", {
216
+ "aria-label": "Run output",
217
+ className: cn("grid content-start gap-4 border-t border-border/70 px-4 py-5 @lg/agent-run:px-6 @3xl/agent-run:overflow-y-auto @3xl/agent-run:border-t-0 @3xl/agent-run:border-s", className),
218
+ ...props
219
+ });
220
+ }
221
+ function AgentRunSection({ title, actions, children, ...props }) {
222
+ const levels = useHeadingLevels();
223
+ return /* @__PURE__ */ jsxs(Card, {
224
+ ...props,
225
+ children: [/* @__PURE__ */ jsxs(CardHeader, { children: [/* @__PURE__ */ jsx(Heading, {
226
+ level: levels.section,
227
+ size: "label",
228
+ weight: "medium",
229
+ children: title
230
+ }), actions ? /* @__PURE__ */ jsx(CardAction, { children: actions }) : null] }), /* @__PURE__ */ jsx(CardContent, { children })]
231
+ });
232
+ }
233
+ function AgentRunDetails({ title = "Details", items, ...props }) {
234
+ if (items.length === 0) return null;
235
+ return /* @__PURE__ */ jsx(AgentRunSection, {
236
+ title,
237
+ ...props,
238
+ children: /* @__PURE__ */ jsx("dl", {
239
+ className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-4 gap-y-2 text-body",
240
+ children: items.map((item) => /* @__PURE__ */ jsxs("div", {
241
+ className: "contents",
242
+ children: [/* @__PURE__ */ jsx("dt", {
243
+ className: "text-muted-foreground",
244
+ children: item.label
245
+ }), /* @__PURE__ */ jsx("dd", {
246
+ className: "min-w-0 break-words",
247
+ children: item.value
248
+ })]
249
+ }, item.label))
250
+ })
251
+ });
252
+ }
253
+ //#endregion
254
+ export { AgentRunAside, AgentRunBlock, AgentRunBody, AgentRunDetails, AgentRunElapsed, AgentRunHeader, AgentRunPlan, AgentRunSection, AgentRunStep, AgentRunToolCall };
@@ -1,6 +1,6 @@
1
- import { ChatLayout } from "../chat-layout.js";
2
1
  import { SidebarProviderProps } from "../ui/sidebar-provider.js";
3
2
  import "../ui/sidebar.js";
3
+ import { ChatLayout } from "../chat-layout.js";
4
4
  import { ComponentProps, ReactNode } from "react";
5
5
  //#region src/blocks/coding-agent.d.ts
6
6
  export type CodingAgentNavigationItem = {
@@ -182,10 +182,7 @@ function CodingAgentSidebar({ appName, brand, sidebarTop, navigation, projects,
182
182
  }, project.id))
183
183
  })]
184
184
  })] }),
185
- sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, {
186
- className: "border-t border-sidebar-border",
187
- children: sidebarFooter
188
- }) : null,
185
+ sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, { children: sidebarFooter }) : null,
189
186
  /* @__PURE__ */ jsx(SidebarRail, {})
190
187
  ]
191
188
  });
@@ -1,6 +1,6 @@
1
1
  //#region src/blocks/design-canvas-data.d.ts
2
2
  export type DesignCanvasLayerKind = "frame" | "rectangle" | "ellipse" | "text";
3
- export type DesignCanvasTool = "move" | DesignCanvasLayerKind;
3
+ export type DesignCanvasTool = "move" | "hand" | DesignCanvasLayerKind;
4
4
  export type DesignCanvasFill = {
5
5
  color: string;
6
6
  opacity: number;
@@ -1,5 +1,6 @@
1
1
  import { DesignCanvasFill, DesignCanvasLayer, DesignCanvasLayerKind, DesignCanvasTool } from "./design-canvas-data.js";
2
- import { InfiniteCanvasTransform } from "../ui/infinite-canvas.js";
2
+ import { InfiniteCanvasTransform } from "../lib/infinite-canvas-camera.js";
3
+ import "../ui/infinite-canvas.js";
3
4
  import { ComponentProps } from "react";
4
5
  //#region src/blocks/design-canvas.d.ts
5
6
  export type DesignCanvasBlockProps = Omit<ComponentProps<"div">, "children" | "defaultValue" | "onChange"> & {
@@ -7,12 +7,12 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/
7
7
  import { Drawer, DrawerContent, DrawerTitle } from "../ui/drawer.js";
8
8
  import { createDesignCanvasLayer, designCanvasFillColor, drawnDesignCanvasBounds } from "./design-canvas-data.js";
9
9
  import { DesignCanvasInspector } from "./design-canvas-inspector.js";
10
+ import { Toolbar, ToolbarButton, ToolbarGroup, ToolbarSeparator } from "../ui/toolbar.js";
10
11
  import { InfiniteCanvas, InfiniteCanvasContent, InfiniteCanvasControls, InfiniteCanvasItem } from "../ui/infinite-canvas.js";
11
12
  import { ResizableFloatingPanel } from "../ui/resizable.js";
12
- import { Toolbar, ToolbarButton, ToolbarGroup, ToolbarSeparator } from "../ui/toolbar.js";
13
13
  import { useRef, useState } from "react";
14
14
  import { jsx, jsxs } from "react/jsx-runtime";
15
- import { CircleIcon, FrameIcon, LayersIcon, MousePointer2Icon, SlidersHorizontalIcon, SquareIcon, TypeIcon } from "lucide-react";
15
+ import { CircleIcon, FrameIcon, HandIcon, LayersIcon, MousePointer2Icon, SlidersHorizontalIcon, SquareIcon, TypeIcon } from "lucide-react";
16
16
  //#region src/blocks/design-canvas.tsx
17
17
  const TOOLS = [
18
18
  {
@@ -21,6 +21,12 @@ const TOOLS = [
21
21
  shortcut: "V",
22
22
  icon: /* @__PURE__ */ jsx(MousePointer2Icon, {})
23
23
  },
24
+ {
25
+ tool: "hand",
26
+ label: "Hand",
27
+ shortcut: "H",
28
+ icon: /* @__PURE__ */ jsx(HandIcon, {})
29
+ },
24
30
  {
25
31
  tool: "frame",
26
32
  label: "Frame",
@@ -99,6 +105,7 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
99
105
  const currentLayers = layers ?? internalLayers;
100
106
  const currentSelectedLayerId = selectedLayerId === void 0 ? internalSelectedLayerId : selectedLayerId;
101
107
  const selectedLayer = currentLayers.find((layer) => layer.id === currentSelectedLayerId);
108
+ const drawingKind = tool === "move" || tool === "hand" ? null : tool;
102
109
  function changeLayers(next) {
103
110
  if (layers === void 0) setInternalLayers(next);
104
111
  onLayersChange?.(next);
@@ -139,7 +146,7 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
139
146
  }
140
147
  function beginDrawOrDeselect(event) {
141
148
  if (event.defaultPrevented || event.target !== event.currentTarget) return;
142
- if (tool === "move") {
149
+ if (!drawingKind) {
143
150
  selectLayer(null);
144
151
  return;
145
152
  }
@@ -148,7 +155,7 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
148
155
  event.currentTarget.setPointerCapture(event.pointerId);
149
156
  const point = worldPointAt(event);
150
157
  setDraft({
151
- kind: tool,
158
+ kind: drawingKind,
152
159
  pointerId: event.pointerId,
153
160
  start: point,
154
161
  end: point,
@@ -200,7 +207,7 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
200
207
  setDraft(null);
201
208
  setTool("move");
202
209
  selectLayer(null);
203
- } else if (event.key === "Enter" && tool !== "move" && event.target === event.currentTarget) addLayerAtViewportCenter(tool, event.currentTarget);
210
+ } else if (event.key === "Enter" && drawingKind && event.target === event.currentTarget) addLayerAtViewportCenter(drawingKind, event.currentTarget);
204
211
  else if (!selectedLayer || !editLayerWithKey(selectedLayer, event)) return;
205
212
  event.preventDefault();
206
213
  }
@@ -226,7 +233,8 @@ function DesignCanvasBlock({ layers, defaultLayers = [], onLayersChange, selecte
226
233
  transformRef.current = next;
227
234
  },
228
235
  "data-tool": tool,
229
- className: cn("size-full", tool !== "move" && "cursor-crosshair"),
236
+ panOnDrag: tool === "hand" ? "anywhere" : "background",
237
+ className: cn("size-full", drawingKind && "cursor-crosshair"),
230
238
  style: {
231
239
  "--cui-infinite-canvas-radius": "0px",
232
240
  "--cui-infinite-canvas-border-color": "transparent",
@@ -452,8 +460,7 @@ function DesignCanvasToolbarButton({ label, hint, pressed, children, ...props })
452
460
  ...props,
453
461
  "aria-label": label,
454
462
  iconOnly: true,
455
- "aria-pressed": pressed,
456
- "data-pressed": pressed ? "" : void 0
463
+ "aria-pressed": pressed
457
464
  }),
458
465
  children
459
466
  }), /* @__PURE__ */ jsx(TooltipContent, { children: hint })] });
@@ -147,7 +147,7 @@ function FileExplorerSidebar({ locations, activeLocationId, sidebarTop, sidebarF
147
147
  collapsible: "offcanvas",
148
148
  children: [
149
149
  sidebarTop ? /* @__PURE__ */ jsx(SidebarHeader, {
150
- className: "min-h-11 justify-center border-b border-sidebar-border px-3",
150
+ className: "min-h-11 justify-center px-3",
151
151
  children: sidebarTop
152
152
  }) : null,
153
153
  /* @__PURE__ */ jsx(SidebarContent, { children: groups.map((group) => /* @__PURE__ */ jsxs(SidebarGroup, { children: [group.label ? /* @__PURE__ */ jsx(SidebarGroupLabel, { children: group.label }) : null, /* @__PURE__ */ jsx(SidebarMenu, { children: group.items.map((location) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, {
@@ -159,24 +159,22 @@ function FileExplorerSidebar({ locations, activeLocationId, sidebarTop, sidebarF
159
159
  },
160
160
  children: [location.icon ?? /* @__PURE__ */ jsx(FolderIcon, {}), /* @__PURE__ */ jsx("span", { children: location.label })]
161
161
  }) }, location.id)) })] }, group.label || "locations")) }),
162
- sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, {
163
- className: "border-t border-sidebar-border",
164
- children: sidebarFooter
165
- }) : null,
162
+ sidebarFooter ? /* @__PURE__ */ jsx(SidebarFooter, { children: sidebarFooter }) : null,
166
163
  /* @__PURE__ */ jsx(SidebarRail, {})
167
164
  ]
168
165
  });
169
166
  }
170
167
  function FileExplorerHeader({ location, headingLevel, breadcrumbs, query, searchPlaceholder, searchLabel, clearSearchLabel, backLabel, moreActionsLabel, canGoBack, headerActions, headerMenuItems, onBack, onBreadcrumbSelect, onQueryChange }) {
171
168
  return /* @__PURE__ */ jsxs("header", {
172
- className: "shrink-0 border-b border-border/70 bg-card/35",
169
+ className: "shrink-0 border-b border-border/70",
173
170
  children: [/* @__PURE__ */ jsxs("div", {
174
171
  className: "flex h-12 items-center gap-2 px-3",
175
172
  children: [
176
- /* @__PURE__ */ jsx(SidebarTrigger, { size: "xs" }),
173
+ /* @__PURE__ */ jsx(SidebarTrigger, { size: "sm" }),
177
174
  /* @__PURE__ */ jsx(Button, {
178
175
  variant: "ghost",
179
- size: "xs",
176
+ size: "sm",
177
+ iconOnly: true,
180
178
  className: "hidden @xl/explorer:inline-flex",
181
179
  disabled: !canGoBack,
182
180
  "aria-label": backLabel,
@@ -200,7 +198,7 @@ function FileExplorerHeader({ location, headingLevel, breadcrumbs, query, search
200
198
  }) : null,
201
199
  headerMenuItems ? /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
202
200
  variant: "ghost",
203
- size: "xs",
201
+ size: "sm",
204
202
  iconOnly: true,
205
203
  "aria-label": moreActionsLabel,
206
204
  className: headerActions ? "@2xl/explorer:hidden" : void 0,
@@ -214,7 +212,7 @@ function FileExplorerHeader({ location, headingLevel, breadcrumbs, query, search
214
212
  })] }) : null,
215
213
  searchPlaceholder ? /* @__PURE__ */ jsxs(InputGroup, {
216
214
  size: "sm",
217
- className: "flex-[0_1_9rem] bg-background/60 @xl/explorer:flex-[0_0_12rem]",
215
+ className: "flex-[0_1_9rem] @xl/explorer:flex-[0_0_12rem]",
218
216
  children: [
219
217
  /* @__PURE__ */ jsx(InputGroupAddon, {
220
218
  className: "ps-2",
@@ -408,7 +406,7 @@ function FileExplorerColumns({ columns, selectedEntry, selectedPath, headingLeve
408
406
  })
409
407
  }) }) : null })] })]
410
408
  }), /* @__PURE__ */ jsx("div", {
411
- className: "min-h-0 flex-1 bg-card",
409
+ className: "min-h-0 flex-1",
412
410
  children: activeColumn ? renderColumn(activeColumn, activeIndex, "narrow") : null
413
411
  })] }) : null
414
412
  }), /* @__PURE__ */ jsx("div", {
@@ -416,7 +414,7 @@ function FileExplorerColumns({ columns, selectedEntry, selectedPath, headingLeve
416
414
  className: "hidden h-full min-h-0 @xl/explorer:block",
417
415
  children: wideDisplayed ? /* @__PURE__ */ jsxs(ResizablePanelGroup, {
418
416
  orientation: "horizontal",
419
- className: "rounded-none border-0 bg-card shadow-none",
417
+ variant: "nested",
420
418
  children: [columns.map((column, columnIndex) => /* @__PURE__ */ jsx(FileExplorerPanel, {
421
419
  defaultSize: columnSize,
422
420
  minSize: "16%",
@@ -531,7 +529,7 @@ function FileExplorerColumnView({ column, optionRef, onSelect, onOpen, onOptionK
531
529
  }
532
530
  function FileExplorerPreview({ entry, headingLevel }) {
533
531
  if (!entry) return /* @__PURE__ */ jsx(Empty, {
534
- className: "h-full rounded-none bg-background/45",
532
+ className: "h-full rounded-none",
535
533
  children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [
536
534
  /* @__PURE__ */ jsx(EmptyMedia, { children: /* @__PURE__ */ jsx(FileIcon, {}) }),
537
535
  /* @__PURE__ */ jsx(EmptyTitle, { children: "Select an item" }),
@@ -539,7 +537,7 @@ function FileExplorerPreview({ entry, headingLevel }) {
539
537
  ] })
540
538
  });
541
539
  return /* @__PURE__ */ jsx(ScrollArea, {
542
- className: "h-full bg-background/45",
540
+ className: "h-full",
543
541
  lockAxis: "x",
544
542
  children: /* @__PURE__ */ jsx(FileExplorerPreviewContent, {
545
543
  entry,
@@ -681,7 +679,7 @@ function FileExplorerStatusBar({ breadcrumbs, selectedEntry }) {
681
679
  const itemCount = selectedEntry?.children?.length ?? 0;
682
680
  const itemLabel = itemCount === 1 ? "1 item" : `${itemCount} items`;
683
681
  return /* @__PURE__ */ jsxs("footer", {
684
- className: "flex h-8 shrink-0 items-center gap-3 border-t border-border/70 bg-card/45 px-3 text-micro text-muted-foreground",
682
+ className: "flex h-8 shrink-0 items-center gap-3 border-t border-border/70 px-3 text-micro text-muted-foreground",
685
683
  children: [/* @__PURE__ */ jsx("span", {
686
684
  className: "min-w-0 flex-1 truncate",
687
685
  title: path,
@@ -695,7 +693,7 @@ function FileExplorerStatusBar({ breadcrumbs, selectedEntry }) {
695
693
  function FileExplorerAddressBar({ breadcrumbs, onSelect }) {
696
694
  return /* @__PURE__ */ jsx(Breadcrumb, {
697
695
  "aria-label": "Current folder",
698
- className: "min-w-0 overflow-hidden rounded-[var(--radius-control)] border bg-background/55 px-2 py-1 shadow-inner",
696
+ className: "min-w-0 overflow-hidden px-1",
699
697
  children: /* @__PURE__ */ jsx(BreadcrumbList, {
700
698
  className: "min-w-0 flex-nowrap overflow-hidden",
701
699
  children: breadcrumbs.map((breadcrumb, index) => {
@@ -224,6 +224,7 @@ function ChatMessageEditable({ value, onSave, onSaveError, editorLabel = "Edit m
224
224
  children: [
225
225
  /* @__PURE__ */ jsxs(ChatMessageContent, {
226
226
  "data-editable": "",
227
+ "data-focus-ring": "within",
227
228
  children: [
228
229
  /* @__PURE__ */ jsx("span", {
229
230
  "data-control-ui": "chat-message",
@@ -268,47 +269,40 @@ function ChatMessageEditable({ value, onSave, onSaveError, editorLabel = "Edit m
268
269
  })
269
270
  ]
270
271
  }),
271
- /* @__PURE__ */ jsxs("div", {
272
+ /* @__PURE__ */ jsx("div", {
272
273
  "data-control-ui": "chat-message",
273
274
  "data-control-family": "chat-message",
274
- "data-slot": "edit-toolbars",
275
- children: [/* @__PURE__ */ jsx("div", {
276
- "data-control-ui": "chat-message",
277
- "data-control-family": "chat-message",
278
- "data-slot": "edit-toolbar",
279
- "data-active": !editing ? "" : void 0,
280
- inert: editing,
281
- "aria-hidden": editing,
282
- children: /* @__PURE__ */ jsx(ActionBar, {
283
- align: message.isEndAligned ? "end" : "start",
284
- copyValue: value,
285
- onEdit: startEditing,
286
- children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ActionBarCopy, {}), /* @__PURE__ */ jsx(ActionBarEdit, {})] })
287
- })
288
- }), /* @__PURE__ */ jsx("div", {
289
- "data-control-ui": "chat-message",
290
- "data-control-family": "chat-message",
291
- "data-slot": "edit-toolbar",
292
- "data-active": editing ? "" : void 0,
293
- inert: !editing,
294
- "aria-hidden": !editing,
295
- children: /* @__PURE__ */ jsxs(ActionBar, {
296
- align: message.isEndAligned ? "end" : "start",
297
- label: "Edit actions",
298
- "aria-busy": saving,
299
- children: [/* @__PURE__ */ jsx(ActionBarItem, {
300
- type: "button",
301
- disabled: saving || !draft.trim(),
302
- onClick: () => void save(),
303
- children: saveLabel
304
- }), /* @__PURE__ */ jsx(ActionBarItem, {
305
- type: "button",
306
- disabled: saving,
307
- onClick: cancelEditing,
308
- children: cancelLabel
309
- })]
310
- })
311
- })]
275
+ "data-slot": "read-actions",
276
+ children: /* @__PURE__ */ jsx(ActionBar, {
277
+ align: message.isEndAligned ? "end" : "start",
278
+ copyValue: value,
279
+ onEdit: startEditing,
280
+ children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ActionBarCopy, {}), /* @__PURE__ */ jsx(ActionBarEdit, {})] })
281
+ })
282
+ }),
283
+ /* @__PURE__ */ jsx("div", {
284
+ "data-control-ui": "chat-message",
285
+ "data-control-family": "chat-message",
286
+ "data-slot": "edit-actions",
287
+ children: /* @__PURE__ */ jsxs(ActionBar, {
288
+ align: message.isEndAligned ? "end" : "start",
289
+ label: "Edit actions",
290
+ "aria-busy": saving,
291
+ style: { "--cui-action-bar-hidden-opacity": "1" },
292
+ children: [/* @__PURE__ */ jsx(ActionBarItem, {
293
+ type: "button",
294
+ variant: "surface",
295
+ disabled: saving,
296
+ onClick: cancelEditing,
297
+ children: cancelLabel
298
+ }), /* @__PURE__ */ jsx(ActionBarItem, {
299
+ type: "button",
300
+ variant: "solid",
301
+ disabled: saving || !draft.trim(),
302
+ onClick: () => void save(),
303
+ children: saveLabel
304
+ })]
305
+ })
312
306
  }),
313
307
  /* @__PURE__ */ jsx(LiveStatus, { message: saving ? savingLabel : "" }),
314
308
  /* @__PURE__ */ jsx("span", {
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/infinite-canvas-knobs.d.ts
2
- export declare const infiniteCanvasKnobs: readonly ["--cui-infinite-canvas-radius", "--cui-infinite-canvas-background", "--cui-infinite-canvas-grid-dot-color", "--cui-infinite-canvas-border-color", "--cui-infinite-canvas-padding", "--cui-infinite-canvas-controls-item-radius", "--cui-infinite-canvas-controls-padding", "--cui-infinite-canvas-controls-radius", "--cui-infinite-canvas-controls-background", "--cui-infinite-canvas-controls-border-color", "--cui-infinite-canvas-controls-shadow"];
2
+ export declare const infiniteCanvasKnobs: readonly ["--cui-infinite-canvas-radius", "--cui-infinite-canvas-background", "--cui-infinite-canvas-grid-dot-color", "--cui-infinite-canvas-border-color", "--cui-infinite-canvas-padding"];
3
3
  export type InfiniteCanvasKnobStyle = Partial<Record<(typeof infiniteCanvasKnobs)[number], string>>;
4
4
  //#endregion
@@ -4,13 +4,7 @@ const infiniteCanvasKnobs = [
4
4
  "--cui-infinite-canvas-background",
5
5
  "--cui-infinite-canvas-grid-dot-color",
6
6
  "--cui-infinite-canvas-border-color",
7
- "--cui-infinite-canvas-padding",
8
- "--cui-infinite-canvas-controls-item-radius",
9
- "--cui-infinite-canvas-controls-padding",
10
- "--cui-infinite-canvas-controls-radius",
11
- "--cui-infinite-canvas-controls-background",
12
- "--cui-infinite-canvas-controls-border-color",
13
- "--cui-infinite-canvas-controls-shadow"
7
+ "--cui-infinite-canvas-padding"
14
8
  ];
15
9
  //#endregion
16
10
  export { infiniteCanvasKnobs };
@@ -0,0 +1,4 @@
1
+ //#region src/knob-contracts/swap-knobs.d.ts
2
+ export declare const swapKnobs: readonly ["--cui-swap-animation-duration", "--cui-swap-easing", "--cui-swap-label-inset", "--cui-swap-icon-scale"];
3
+ export type SwapKnobStyle = Partial<Record<(typeof swapKnobs)[number], string>>;
4
+ //#endregion
@@ -0,0 +1,9 @@
1
+ //#region src/knob-contracts/swap-knobs.ts
2
+ const swapKnobs = [
3
+ "--cui-swap-animation-duration",
4
+ "--cui-swap-easing",
5
+ "--cui-swap-label-inset",
6
+ "--cui-swap-icon-scale"
7
+ ];
8
+ //#endregion
9
+ export { swapKnobs };
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/timeline-knobs.d.ts
2
- export declare const timelineKnobs: readonly ["--cui-timeline-indicator-background", "--cui-timeline-indicator-foreground", "--cui-timeline-running-foreground", "--cui-timeline-success-foreground", "--cui-timeline-error-foreground", "--cui-timeline-separator-background", "--cui-timeline-title-foreground"];
2
+ export declare const timelineKnobs: readonly ["--cui-timeline-indicator-background", "--cui-timeline-indicator-foreground", "--cui-timeline-running-foreground", "--cui-timeline-waiting-foreground", "--cui-timeline-success-foreground", "--cui-timeline-error-foreground", "--cui-timeline-separator-background", "--cui-timeline-title-foreground"];
3
3
  export type TimelineKnobStyle = Partial<Record<(typeof timelineKnobs)[number], string>>;
4
4
  //#endregion
@@ -3,6 +3,7 @@ const timelineKnobs = [
3
3
  "--cui-timeline-indicator-background",
4
4
  "--cui-timeline-indicator-foreground",
5
5
  "--cui-timeline-running-foreground",
6
+ "--cui-timeline-waiting-foreground",
6
7
  "--cui-timeline-success-foreground",
7
8
  "--cui-timeline-error-foreground",
8
9
  "--cui-timeline-separator-background",
@@ -0,0 +1,4 @@
1
+ //#region src/knob-contracts/tool-approval-knobs.d.ts
2
+ export declare const toolApprovalKnobs: readonly ["--cui-tool-approval-background", "--cui-tool-approval-foreground", "--cui-tool-approval-border-color", "--cui-tool-approval-border-width", "--cui-tool-approval-radius", "--cui-tool-approval-shadow", "--cui-tool-approval-padding", "--cui-tool-approval-body-background", "--cui-tool-approval-body-border-color", "--cui-tool-approval-body-border-width", "--cui-tool-approval-body-radius", "--cui-tool-approval-body-shadow", "--cui-tool-approval-body-padding", "--cui-tool-approval-body-gap", "--cui-tool-approval-footer-border-color", "--cui-tool-approval-footer-border-width", "--cui-tool-approval-footer-padding", "--cui-tool-approval-footer-gap", "--cui-tool-approval-preview-background", "--cui-tool-approval-preview-border-color", "--cui-tool-approval-preview-border-width", "--cui-tool-approval-preview-radius", "--cui-tool-approval-preview-padding", "--cui-tool-approval-preview-gap", "--cui-tool-approval-label-foreground", "--cui-tool-approval-description-foreground", "--cui-tool-approval-status-foreground"];
3
+ export type ToolApprovalKnobStyle = Partial<Record<(typeof toolApprovalKnobs)[number], string>>;
4
+ //#endregion