@tangle-network/sandbox-ui 0.62.0 → 0.63.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/dist/chat.d.ts CHANGED
@@ -124,8 +124,21 @@ interface AgentSessionHarnessControl {
124
124
  * switch harness.
125
125
  */
126
126
  locked?: boolean;
127
- /** Tooltip shown on the locked trigger. */
127
+ /** Tooltip shown on the locked trigger when no `onNewChat` is provided. */
128
128
  lockReason?: string;
129
+ /**
130
+ * Fork action for a locked harness. When provided, the locked trigger turns
131
+ * into an informative chip: hover or tap opens a small popover explaining the
132
+ * lock and offering a button that calls this to start a fresh session. When
133
+ * omitted, the locked trigger stays a plain inert button with `lockReason`.
134
+ */
135
+ onNewChat?: () => void;
136
+ /** Popover heading. Defaults to `Agent fixed to {harness} for this conversation.` */
137
+ lockTitle?: React.ReactNode;
138
+ /** Popover sub-line. Defaults to "Conversations stay on one agent." */
139
+ lockBody?: React.ReactNode;
140
+ /** Fork button label. Defaults to "New chat to switch agent". */
141
+ newChatLabel?: string;
129
142
  }
130
143
  interface AgentSessionModelControl {
131
144
  /** Canonical model id (provider-prefixed, e.g. "anthropic/claude-opus-4-8"). */
package/dist/chat.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  modelProvider,
18
18
  snapHarnessToModel,
19
19
  snapModelToHarness
20
- } from "./chunk-R72QYE2U.js";
20
+ } from "./chunk-2E3FJM56.js";
21
21
  import "./chunk-HU4B2M4K.js";
22
22
  import "./chunk-SF6LPMMN.js";
23
23
  import "./chunk-EI44GEQ5.js";
@@ -156,7 +156,24 @@ import {
156
156
  reasoningEffortsFor
157
157
  } from "@tangle-network/agent-interface";
158
158
  import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
159
- import { ChevronDown as ChevronDown3, Lock, SlidersHorizontal } from "lucide-react";
159
+ import { ChevronDown as ChevronDown3, Lock, Plus as Plus2, SlidersHorizontal } from "lucide-react";
160
+ import * as React3 from "react";
161
+
162
+ // src/lib/use-click-outside.ts
163
+ import * as React from "react";
164
+ function useClickOutside(onOutside) {
165
+ const ref = React.useRef(null);
166
+ React.useEffect(() => {
167
+ function handler(event) {
168
+ if (ref.current && !ref.current.contains(event.target)) {
169
+ onOutside();
170
+ }
171
+ }
172
+ document.addEventListener("mousedown", handler);
173
+ return () => document.removeEventListener("mousedown", handler);
174
+ }, [onOutside]);
175
+ return ref;
176
+ }
160
177
 
161
178
  // src/chat/harness-model-compat.ts
162
179
  import {
@@ -173,21 +190,8 @@ function snapModelToHarness(harness, modelId, models) {
173
190
 
174
191
  // src/chat/agent-profile-picker.tsx
175
192
  import { Bot, Check, ChevronDown as ChevronDown2, Pencil, Plus, Trash2 } from "lucide-react";
176
- import * as React from "react";
193
+ import * as React2 from "react";
177
194
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
178
- function useClickOutside(onOutside) {
179
- const ref = React.useRef(null);
180
- React.useEffect(() => {
181
- function handler(event) {
182
- if (ref.current && !ref.current.contains(event.target)) {
183
- onOutside();
184
- }
185
- }
186
- document.addEventListener("mousedown", handler);
187
- return () => document.removeEventListener("mousedown", handler);
188
- }, [onOutside]);
189
- return ref;
190
- }
191
195
  function profileSubtitle(profile) {
192
196
  if (profile.description) return profile.description;
193
197
  const count = profile.capabilities?.length ?? 0;
@@ -205,8 +209,8 @@ function AgentProfilePicker({
205
209
  className,
206
210
  side = "top"
207
211
  }) {
208
- const [open, setOpen] = React.useState(false);
209
- const [composing, setComposing] = React.useState(
212
+ const [open, setOpen] = React2.useState(false);
213
+ const [composing, setComposing] = React2.useState(
210
214
  null
211
215
  );
212
216
  const ref = useClickOutside(() => {
@@ -373,11 +377,11 @@ function ProfileForm({
373
377
  onCancel,
374
378
  onSave
375
379
  }) {
376
- const [name, setName] = React.useState(initial?.name ?? "");
377
- const [caps, setCaps] = React.useState(
380
+ const [name, setName] = React2.useState(initial?.name ?? "");
381
+ const [caps, setCaps] = React2.useState(
378
382
  initial?.capabilities ? [...initial.capabilities] : capabilities.map((c) => c.id)
379
383
  );
380
- const [instructions, setInstructions] = React.useState(initial?.instructions ?? "");
384
+ const [instructions, setInstructions] = React2.useState(initial?.instructions ?? "");
381
385
  const toggle = (id) => setCaps(
382
386
  (prev) => prev.includes(id) ? prev.filter((c) => c !== id) : [...prev, id]
383
387
  );
@@ -466,6 +470,102 @@ function selectorIgnoreNote(harness) {
466
470
  if (ignoresEffort) return "Ignores reasoning effort";
467
471
  return null;
468
472
  }
473
+ function InformativeLock({
474
+ label,
475
+ lockTitle,
476
+ lockBody,
477
+ newChatLabel,
478
+ onNewChat
479
+ }) {
480
+ const [open, setOpen] = React3.useState(false);
481
+ const closeTimer = React3.useRef(null);
482
+ const ref = useClickOutside(() => setOpen(false));
483
+ const cancelClose = React3.useCallback(() => {
484
+ if (closeTimer.current) {
485
+ clearTimeout(closeTimer.current);
486
+ closeTimer.current = null;
487
+ }
488
+ }, []);
489
+ const scheduleClose = React3.useCallback(() => {
490
+ cancelClose();
491
+ closeTimer.current = setTimeout(() => setOpen(false), 150);
492
+ }, [cancelClose]);
493
+ React3.useEffect(() => cancelClose, [cancelClose]);
494
+ return /* @__PURE__ */ jsxs3(
495
+ "div",
496
+ {
497
+ ref,
498
+ className: "relative inline-flex",
499
+ onMouseEnter: () => {
500
+ cancelClose();
501
+ setOpen(true);
502
+ },
503
+ onMouseLeave: scheduleClose,
504
+ onKeyDown: (event) => {
505
+ if (event.key === "Escape") setOpen(false);
506
+ },
507
+ children: [
508
+ /* @__PURE__ */ jsxs3(
509
+ "button",
510
+ {
511
+ type: "button",
512
+ onClick: () => setOpen(true),
513
+ "data-state": open ? "open" : "closed",
514
+ "aria-label": "Agent harness (locked)",
515
+ "aria-haspopup": "dialog",
516
+ "aria-expanded": open,
517
+ className: cn(
518
+ "inline-flex h-8 items-center gap-1.5 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-2.5",
519
+ "text-xs font-medium text-foreground shadow-sm transition-colors",
520
+ "hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
521
+ "data-[state=open]:border-[var(--md3-outline-variant)] data-[state=open]:bg-surface-container-high"
522
+ ),
523
+ children: [
524
+ /* @__PURE__ */ jsx3(Lock, { className: "h-3 w-3 text-muted-foreground" }),
525
+ /* @__PURE__ */ jsx3("span", { children: label })
526
+ ]
527
+ }
528
+ ),
529
+ open && /* @__PURE__ */ jsxs3(
530
+ "div",
531
+ {
532
+ role: "dialog",
533
+ className: cn(
534
+ "absolute bottom-full left-0 z-50 mb-2 w-72 rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-3",
535
+ "shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]"
536
+ ),
537
+ children: [
538
+ /* @__PURE__ */ jsxs3("p", { className: "flex items-start gap-2 text-sm font-medium text-foreground", children: [
539
+ /* @__PURE__ */ jsx3(Lock, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
540
+ /* @__PURE__ */ jsx3("span", { children: lockTitle ?? `Agent fixed to ${label} for this conversation.` })
541
+ ] }),
542
+ /* @__PURE__ */ jsx3("p", { className: "mt-1.5 text-xs text-muted-foreground", children: lockBody ?? "Conversations stay on one agent." }),
543
+ /* @__PURE__ */ jsxs3(
544
+ "button",
545
+ {
546
+ type: "button",
547
+ onClick: () => {
548
+ setOpen(false);
549
+ onNewChat();
550
+ },
551
+ className: cn(
552
+ "mt-3 flex w-full items-center justify-center gap-1.5 rounded-md px-2.5 py-2 text-sm font-medium text-foreground",
553
+ "bg-primary/10 ring-1 ring-inset ring-primary/25 transition-colors",
554
+ "hover:bg-primary/15 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring"
555
+ ),
556
+ children: [
557
+ /* @__PURE__ */ jsx3(Plus2, { className: "h-4 w-4" }),
558
+ newChatLabel ?? "New chat to switch agent"
559
+ ]
560
+ }
561
+ )
562
+ ]
563
+ }
564
+ )
565
+ ]
566
+ }
567
+ );
568
+ }
469
569
  function HarnessDropdown({
470
570
  value,
471
571
  onChange,
@@ -473,6 +573,10 @@ function HarnessDropdown({
473
573
  disabled,
474
574
  locked,
475
575
  lockReason,
576
+ onNewChat,
577
+ lockTitle,
578
+ lockBody,
579
+ newChatLabel,
476
580
  side = "bottom",
477
581
  align = "start",
478
582
  avoidCollisions
@@ -482,6 +586,18 @@ function HarnessDropdown({
482
586
  );
483
587
  const options = HARNESS_OPTIONS.filter((h) => allowed.has(h.type));
484
588
  const selected = options.find((option) => option.type === value);
589
+ if (locked && onNewChat) {
590
+ return /* @__PURE__ */ jsx3(
591
+ InformativeLock,
592
+ {
593
+ label: selected?.label ?? value,
594
+ lockTitle,
595
+ lockBody,
596
+ newChatLabel,
597
+ onNewChat
598
+ }
599
+ );
600
+ }
485
601
  return /* @__PURE__ */ jsxs3(DropdownMenu2.Root, { children: [
486
602
  /* @__PURE__ */ jsx3(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
487
603
  "button",
@@ -785,7 +901,7 @@ import {
785
901
  Upload,
786
902
  X
787
903
  } from "lucide-react";
788
- import * as React2 from "react";
904
+ import * as React4 from "react";
789
905
  import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
790
906
  function AgentComposer({
791
907
  value,
@@ -816,22 +932,22 @@ function AgentComposer({
816
932
  sendLabel = "Send",
817
933
  autoFocus
818
934
  }) {
819
- const textareaRef = React2.useRef(null);
820
- const fileInputRef = React2.useRef(null);
821
- const folderInputRef = React2.useRef(null);
822
- const [dragOver, setDragOver] = React2.useState(false);
823
- const dragDepth = React2.useRef(0);
824
- const resize = React2.useCallback(
935
+ const textareaRef = React4.useRef(null);
936
+ const fileInputRef = React4.useRef(null);
937
+ const folderInputRef = React4.useRef(null);
938
+ const [dragOver, setDragOver] = React4.useState(false);
939
+ const dragDepth = React4.useRef(0);
940
+ const resize = React4.useCallback(
825
941
  (el) => {
826
942
  el.style.height = "auto";
827
943
  el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
828
944
  },
829
945
  [maxHeight]
830
946
  );
831
- React2.useEffect(() => {
947
+ React4.useEffect(() => {
832
948
  if (textareaRef.current) resize(textareaRef.current);
833
949
  }, [value, resize]);
834
- React2.useEffect(() => {
950
+ React4.useEffect(() => {
835
951
  if (!focusShortcut || disabled) return;
836
952
  function onKeyDown(event) {
837
953
  if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "l") {
@@ -1070,7 +1186,7 @@ function AgentComposer({
1070
1186
  }
1071
1187
 
1072
1188
  // src/chat/artifact-agent-dock.tsx
1073
- import * as React3 from "react";
1189
+ import * as React5 from "react";
1074
1190
  import { Sparkles as Sparkles2, Send, Square as Square2, X as X2 } from "lucide-react";
1075
1191
  import { ChatMessage } from "@tangle-network/ui/chat";
1076
1192
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -1119,23 +1235,23 @@ function ArtifactAgentDock({
1119
1235
  onError,
1120
1236
  className
1121
1237
  }) {
1122
- const [threadId, setThreadId] = React3.useState(null);
1123
- const [messages, setMessages] = React3.useState([]);
1124
- const [composer, setComposer] = React3.useState(defaultPrompt ?? "");
1125
- const [streamContent, setStreamContent] = React3.useState("");
1126
- const [sending, setSending] = React3.useState(false);
1127
- const [loading, setLoading] = React3.useState(false);
1128
- const abortRef = React3.useRef(null);
1129
- const scrollRef = React3.useRef(null);
1130
- const scopeTokenRef = React3.useRef(0);
1131
- const reportError = React3.useCallback(
1238
+ const [threadId, setThreadId] = React5.useState(null);
1239
+ const [messages, setMessages] = React5.useState([]);
1240
+ const [composer, setComposer] = React5.useState(defaultPrompt ?? "");
1241
+ const [streamContent, setStreamContent] = React5.useState("");
1242
+ const [sending, setSending] = React5.useState(false);
1243
+ const [loading, setLoading] = React5.useState(false);
1244
+ const abortRef = React5.useRef(null);
1245
+ const scrollRef = React5.useRef(null);
1246
+ const scopeTokenRef = React5.useRef(0);
1247
+ const reportError = React5.useCallback(
1132
1248
  (message) => {
1133
1249
  if (onError) onError(message);
1134
1250
  else if (typeof console !== "undefined") console.error("[ArtifactAgentDock]", message);
1135
1251
  },
1136
1252
  [onError]
1137
1253
  );
1138
- React3.useEffect(() => {
1254
+ React5.useEffect(() => {
1139
1255
  if (!open) return;
1140
1256
  scopeTokenRef.current += 1;
1141
1257
  abortRef.current?.abort();
@@ -1171,11 +1287,11 @@ function ArtifactAgentDock({
1171
1287
  cancelled = true;
1172
1288
  };
1173
1289
  }, [open, scope.kind, scope.key, transport, reportError]);
1174
- React3.useEffect(() => {
1290
+ React5.useEffect(() => {
1175
1291
  if (!scrollRef.current) return;
1176
1292
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
1177
1293
  }, [messages.length, streamContent]);
1178
- const send = React3.useCallback(async () => {
1294
+ const send = React5.useCallback(async () => {
1179
1295
  const text = composer.trim();
1180
1296
  if (!text || !threadId || sending) return;
1181
1297
  const token = scopeTokenRef.current;
@@ -1225,7 +1341,7 @@ function ArtifactAgentDock({
1225
1341
  if (abortRef.current === controller) abortRef.current = null;
1226
1342
  }
1227
1343
  }, [composer, threadId, sending, transport, reportError]);
1228
- const cancel = React3.useCallback(() => {
1344
+ const cancel = React5.useCallback(() => {
1229
1345
  if (threadId && transport.cancel) {
1230
1346
  try {
1231
1347
  void Promise.resolve(transport.cancel({ threadId })).catch(() => {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-3J6FG3FJ.js";
4
4
  import {
5
5
  PortsList
6
- } from "./chunk-OQZQFSWM.js";
6
+ } from "./chunk-DZA4UBXU.js";
7
7
  import {
8
8
  TerminalView
9
9
  } from "./chunk-VIREDUBF.js";
@@ -564,13 +564,17 @@ function RailExpandable({
564
564
  loadSubItems,
565
565
  activeSubIds,
566
566
  emptyLabel = "Nothing here yet",
567
+ defaultOpen,
567
568
  onNavigate,
568
569
  LinkComponent,
569
570
  className
570
571
  }) {
571
572
  const Link = LinkComponent ?? DefaultLink;
572
- const [open, setOpen] = React3.useState(false);
573
+ const [open, setOpen] = React3.useState(defaultOpen ?? false);
573
574
  const { items, loading, ensureLoaded } = useExpandableItems(subItems, loadSubItems);
575
+ React3.useEffect(() => {
576
+ if (defaultOpen) ensureLoaded();
577
+ }, [defaultOpen, ensureLoaded]);
574
578
  const activeSet = React3.useMemo(() => new Set(activeSubIds ?? []), [activeSubIds]);
575
579
  const triggerRef = React3.useRef(null);
576
580
  const closeTimer = React3.useRef(null);
@@ -589,8 +593,8 @@ function RailExpandable({
589
593
  onClick: onNavigate,
590
594
  ...item.prefetch !== void 0 ? { prefetch: item.prefetch } : {},
591
595
  className: cn(
592
- "flex h-8 min-w-0 items-center gap-2 rounded-md px-2.5 text-[12px] transition-colors",
593
- active ? "bg-[var(--accent-surface-strong)] font-medium text-[var(--accent-text)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground"
596
+ "flex h-7 min-w-0 items-center gap-2 rounded-md px-2.5 text-[12px] transition-colors",
597
+ active ? "bg-[var(--accent-surface-strong)] font-medium text-[var(--accent-text)]" : item.emphasis ? "font-semibold text-[var(--accent-text)] hover:bg-[var(--accent-surface-soft)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground"
594
598
  ),
595
599
  children: [
596
600
  FIcon ? /* @__PURE__ */ jsx3(FIcon, { className: "h-4 w-4 shrink-0" }) : null,
@@ -719,18 +723,15 @@ function RailExpandable({
719
723
  /* @__PURE__ */ jsx3(
720
724
  Icon,
721
725
  {
722
- className: cn(
723
- "h-[17px] w-[17px] shrink-0 transition-opacity duration-150",
724
- open ? "opacity-0" : "opacity-100 group-hover/exp:opacity-0"
725
- )
726
+ className: "h-[17px] w-[17px] shrink-0 opacity-100 transition-opacity duration-150 group-hover/exp:opacity-0"
726
727
  }
727
728
  ),
728
729
  /* @__PURE__ */ jsx3(
729
730
  ChevronRightIcon,
730
731
  {
731
732
  className: cn(
732
- "absolute h-4 w-4 transition-all duration-150",
733
- open ? "rotate-90 opacity-100" : "opacity-0 group-hover/exp:opacity-100"
733
+ "absolute h-4 w-4 opacity-0 transition-all duration-150 group-hover/exp:opacity-100",
734
+ open && "rotate-90"
734
735
  )
735
736
  }
736
737
  )
@@ -2368,6 +2369,7 @@ function SidebarLayoutInner({
2368
2369
  loadSubItems: item.loadSubItems,
2369
2370
  activeSubIds: item.subActiveIds,
2370
2371
  emptyLabel: item.emptyLabel,
2372
+ defaultOpen: item.defaultOpen,
2371
2373
  onNavigate: handleNavClick,
2372
2374
  LinkComponent
2373
2375
  },
@@ -185,6 +185,9 @@ interface RailExpandableSubItem {
185
185
  prefetch?: "none" | "intent" | "render" | "viewport";
186
186
  /** Show a live working indicator on the row while the item is busy. */
187
187
  isLoading?: boolean;
188
+ /** Render the row emphasized (bold + accent) so it stands out — e.g. a
189
+ * trailing "view all" action below a capped list. */
190
+ emphasis?: boolean;
188
191
  }
189
192
  interface RailExpandableProps {
190
193
  icon: React.ComponentType<{
@@ -201,6 +204,8 @@ interface RailExpandableProps {
201
204
  subItems?: RailExpandableSubItem[];
202
205
  /** Lazy sub-items — called once on first open; the result is cached. */
203
206
  loadSubItems?: () => Promise<RailExpandableSubItem[]>;
207
+ /** Start expanded on mount (labeled rail). Defaults to collapsed. */
208
+ defaultOpen?: boolean;
204
209
  /** Ids of sub-items whose route is active (drives sub-item highlight). */
205
210
  activeSubIds?: string[];
206
211
  /** Shown when the resolved sub-item list is empty. */
@@ -218,7 +223,7 @@ interface RailExpandableProps {
218
223
  * Sub-items can be fixed (`subItems`) or lazy (`loadSubItems`, with a loading
219
224
  * skeleton). Used for e.g. a "History" entry fronting recent sessions.
220
225
  */
221
- declare function RailExpandable({ icon: Icon, label, href, isActive, showLabel, subItems, loadSubItems, activeSubIds, emptyLabel, onNavigate, LinkComponent, className, }: RailExpandableProps): react_jsx_runtime.JSX.Element;
226
+ declare function RailExpandable({ icon: Icon, label, href, isActive, showLabel, subItems, loadSubItems, activeSubIds, emptyLabel, defaultOpen, onNavigate, LinkComponent, className, }: RailExpandableProps): react_jsx_runtime.JSX.Element;
222
227
  interface RailModeButtonProps {
223
228
  mode: string;
224
229
  icon: React.ComponentType<{
@@ -913,6 +918,8 @@ interface SidebarLayoutNavItem {
913
918
  subActiveIds?: string[];
914
919
  /** Empty-state text for an `expandable` item that resolves to no sub-items. */
915
920
  emptyLabel?: string;
921
+ /** Start an `expandable` item expanded on mount (labeled rail). */
922
+ defaultOpen?: boolean;
916
923
  badge?: number;
917
924
  /**
918
925
  * React Router prefetch behavior for this link, forwarded to the underlying
package/dist/dashboard.js CHANGED
@@ -54,7 +54,7 @@ import {
54
54
  canAdminSandbox,
55
55
  parseInsufficientBalance,
56
56
  useSidebar
57
- } from "./chunk-OQZQFSWM.js";
57
+ } from "./chunk-DZA4UBXU.js";
58
58
  import {
59
59
  BillingDashboard,
60
60
  InfoPanel,
package/dist/index.js CHANGED
@@ -102,7 +102,7 @@ import {
102
102
  modelProvider,
103
103
  snapHarnessToModel,
104
104
  snapModelToHarness
105
- } from "./chunk-R72QYE2U.js";
105
+ } from "./chunk-2E3FJM56.js";
106
106
  import {
107
107
  ExpandedToolDetail,
108
108
  InlineThinkingItem,
@@ -146,7 +146,7 @@ import {
146
146
  buildUnifiedPatch,
147
147
  computeDiffStats,
148
148
  resolveLanguage
149
- } from "./chunk-J36F6LD2.js";
149
+ } from "./chunk-6OJUOEF4.js";
150
150
  import {
151
151
  FileArtifactPane,
152
152
  FilePreview,
@@ -211,7 +211,7 @@ import {
211
211
  canAdminSandbox,
212
212
  parseInsufficientBalance,
213
213
  useSidebar
214
- } from "./chunk-OQZQFSWM.js";
214
+ } from "./chunk-DZA4UBXU.js";
215
215
  import "./chunk-VIREDUBF.js";
216
216
  import {
217
217
  usePtySession
package/dist/workbench.js CHANGED
@@ -12,9 +12,9 @@ import {
12
12
  buildUnifiedPatch,
13
13
  computeDiffStats,
14
14
  resolveLanguage
15
- } from "./chunk-J36F6LD2.js";
15
+ } from "./chunk-6OJUOEF4.js";
16
16
  import "./chunk-3J6FG3FJ.js";
17
- import "./chunk-OQZQFSWM.js";
17
+ import "./chunk-DZA4UBXU.js";
18
18
  import "./chunk-VIREDUBF.js";
19
19
  import "./chunk-77WVVJA4.js";
20
20
  import "./chunk-OMUIPJQZ.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.62.0",
3
+ "version": "0.63.0",
4
4
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
5
5
  "repository": {
6
6
  "type": "git",