@tangle-network/sandbox-ui 0.113.4 → 0.113.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/chat.js +1 -1
- package/dist/{chunk-JZCRK2BJ.js → chunk-3KBNPQQF.js} +117 -44
- package/dist/chunk-ANSC5AFC.js +314 -0
- package/dist/{chunk-XFEJ66AG.js → chunk-NNARED4T.js} +165 -68
- package/dist/{chunk-LDAKIKTV.js → chunk-SX344CDB.js} +100 -54
- package/dist/{chunk-EKYA6AFY.js → chunk-TADGS4Q7.js} +15 -7
- package/dist/{chunk-PZVUIUUW.js → chunk-ULPLRBMF.js} +8 -2
- package/dist/{chunk-TK46XFLM.js → chunk-X3YXP7FG.js} +10 -0
- package/dist/connectors.js +2 -1
- package/dist/dashboard.d.ts +8 -8
- package/dist/dashboard.js +2 -2
- package/dist/files.d.ts +1 -1
- package/dist/files.js +9 -3
- package/dist/globals.css +369 -129
- package/dist/index.d.ts +5 -4
- package/dist/index.js +26 -8
- package/dist/integrations.js +10 -7
- package/dist/logo-DiAjq759.d.ts +15 -0
- package/dist/pages.js +69 -46
- package/dist/primitives.d.ts +3 -2
- package/dist/primitives.js +3 -1
- package/dist/styles.css +369 -129
- package/dist/tokens.css +37 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +11 -1
- package/dist/workbench.d.ts +6 -3
- package/dist/workbench.js +4 -4
- package/dist/workspace.js +1 -1
- package/package.json +5 -5
- package/dist/chunk-2XPJ2XF7.js +0 -345
- package/dist/logo-CaIvk3J1.d.ts +0 -18
package/README.md
CHANGED
|
@@ -10,13 +10,15 @@
|
|
|
10
10
|
|
|
11
11
|
React component library for [Tangle Sandbox](https://sandbox.tangle.tools) — a shadcn-style primitive layer plus higher-order sandbox surfaces for agent chat, files, runtime state, artifacts, and dashboard views.
|
|
12
12
|
|
|
13
|
+
[Browse the live Storybook](https://sandbox-ui-storybook.pages.dev/) to inspect component states in dark and light themes at desktop and mobile widths.
|
|
14
|
+
|
|
13
15
|
## Install
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
18
|
npm install @tangle-network/sandbox-ui
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
**Required peers:** `react` and `react-dom` 18 or 19, `@tangle-network/agent-interface ^1.0.0 || ^2.0.0`, `@tangle-network/brand ^1.
|
|
21
|
+
**Required peers:** `react` and `react-dom` 18 or 19, `@tangle-network/agent-interface ^1.0.0 || ^2.0.0`, `@tangle-network/brand ^1.6.0`, and `@tangle-network/ui ^11.10.0`.
|
|
20
22
|
Optional peers are required only by the subpaths that use them; see [package.json](./package.json). `/editor` needs its tiptap, `yjs` and `@hocuspocus/provider` peers only when it renders an editor, and the `@tangle-network/ui` README holds the table of which surface needs which.
|
|
21
23
|
|
|
22
24
|
## Usage
|
package/dist/chat.js
CHANGED
|
@@ -36,6 +36,7 @@ function WorkspacePaneHeader({
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// src/workspace/workspace-layout.tsx
|
|
39
|
+
import { focusRing } from "@tangle-network/ui/utils";
|
|
39
40
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
40
41
|
var DESKTOP_BREAKPOINT = "(min-width: 1024px)";
|
|
41
42
|
function clamp(value, min, max) {
|
|
@@ -104,7 +105,7 @@ function ResizeHandle({ label, onDragStart, onStep, className }) {
|
|
|
104
105
|
className: cn(
|
|
105
106
|
"relative hidden w-3 shrink-0 cursor-col-resize lg:flex",
|
|
106
107
|
"items-stretch justify-center bg-transparent touch-none",
|
|
107
|
-
|
|
108
|
+
focusRing,
|
|
108
109
|
className
|
|
109
110
|
),
|
|
110
111
|
children: [
|
|
@@ -141,7 +142,7 @@ function HorizontalResizeHandle({ label, onDragStart, onStep, className }) {
|
|
|
141
142
|
className: cn(
|
|
142
143
|
"relative hidden h-3 shrink-0 cursor-row-resize lg:flex",
|
|
143
144
|
"items-center justify-center bg-transparent touch-none w-full",
|
|
144
|
-
|
|
145
|
+
focusRing,
|
|
145
146
|
className
|
|
146
147
|
),
|
|
147
148
|
children: [
|
|
@@ -178,7 +179,7 @@ function MobileDrawer({ side, title, header, onClose, children }) {
|
|
|
178
179
|
type: "button",
|
|
179
180
|
"aria-label": `Close ${title}`,
|
|
180
181
|
onClick: onClose,
|
|
181
|
-
className:
|
|
182
|
+
className: `rounded-[2px] p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
182
183
|
children: /* @__PURE__ */ jsx2(X, { className: "h-4 w-4" })
|
|
183
184
|
}
|
|
184
185
|
)
|
|
@@ -410,7 +411,7 @@ function WorkspaceLayout({
|
|
|
410
411
|
type: "button",
|
|
411
412
|
"aria-label": "Collapse left panel",
|
|
412
413
|
onClick: () => setLeftOpen(false),
|
|
413
|
-
className:
|
|
414
|
+
className: `rounded-[2px] p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
414
415
|
children: /* @__PURE__ */ jsx2(PanelLeftClose, { className: "h-4 w-4" })
|
|
415
416
|
}
|
|
416
417
|
)
|
|
@@ -436,7 +437,7 @@ function WorkspaceLayout({
|
|
|
436
437
|
type: "button",
|
|
437
438
|
"aria-label": "Open left panel",
|
|
438
439
|
onClick: () => setLeftOpen(true),
|
|
439
|
-
className:
|
|
440
|
+
className: `rounded-[2px] p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
440
441
|
children: /* @__PURE__ */ jsx2(PanelLeftOpen, { className: "h-4 w-4" })
|
|
441
442
|
}
|
|
442
443
|
)),
|
|
@@ -447,7 +448,7 @@ function WorkspaceLayout({
|
|
|
447
448
|
type: "button",
|
|
448
449
|
"aria-label": "Open bottom panel",
|
|
449
450
|
onClick: () => setBottomOpen(true),
|
|
450
|
-
className:
|
|
451
|
+
className: `rounded-[2px] p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
451
452
|
children: /* @__PURE__ */ jsx2(PanelBottomOpen, { className: "h-4 w-4" })
|
|
452
453
|
}
|
|
453
454
|
),
|
|
@@ -457,7 +458,7 @@ function WorkspaceLayout({
|
|
|
457
458
|
type: "button",
|
|
458
459
|
"aria-label": "Open right panel",
|
|
459
460
|
onClick: () => setRightOpen(true),
|
|
460
|
-
className:
|
|
461
|
+
className: `rounded-[2px] p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
461
462
|
children: /* @__PURE__ */ jsx2(PanelRightOpen, { className: "h-4 w-4" })
|
|
462
463
|
}
|
|
463
464
|
)
|
|
@@ -487,7 +488,7 @@ function WorkspaceLayout({
|
|
|
487
488
|
type: "button",
|
|
488
489
|
"aria-label": "Collapse bottom panel",
|
|
489
490
|
onClick: () => setBottomOpen(false),
|
|
490
|
-
className:
|
|
491
|
+
className: `rounded-[2px] p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
491
492
|
children: /* @__PURE__ */ jsx2(PanelBottomClose, { className: "h-4 w-4" })
|
|
492
493
|
}
|
|
493
494
|
)
|
|
@@ -523,7 +524,7 @@ function WorkspaceLayout({
|
|
|
523
524
|
type: "button",
|
|
524
525
|
"aria-label": "Collapse right panel",
|
|
525
526
|
onClick: () => setRightOpen(false),
|
|
526
|
-
className:
|
|
527
|
+
className: `rounded-[2px] p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
527
528
|
children: /* @__PURE__ */ jsx2(PanelRightClose, { className: "h-4 w-4" })
|
|
528
529
|
}
|
|
529
530
|
)
|
|
@@ -572,6 +573,7 @@ import {
|
|
|
572
573
|
} from "@tangle-network/ui/files";
|
|
573
574
|
import { EmptyState } from "@tangle-network/ui/primitives";
|
|
574
575
|
import { Input } from "@tangle-network/ui/primitives";
|
|
576
|
+
import { focusRing as focusRing2 } from "@tangle-network/ui/utils";
|
|
575
577
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
576
578
|
function countNodes(node) {
|
|
577
579
|
if (node.type === "file") {
|
|
@@ -647,7 +649,7 @@ function DirectoryPane({
|
|
|
647
649
|
type: "button",
|
|
648
650
|
"aria-label": "Refresh directory",
|
|
649
651
|
onClick: onRefresh,
|
|
650
|
-
className:
|
|
652
|
+
className: `rounded-[2px] p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing2}`,
|
|
651
653
|
children: /* @__PURE__ */ jsx3(RefreshCw, { className: "h-4 w-4" })
|
|
652
654
|
}
|
|
653
655
|
),
|
|
@@ -657,7 +659,7 @@ function DirectoryPane({
|
|
|
657
659
|
type: "button",
|
|
658
660
|
"aria-label": "Upload files",
|
|
659
661
|
onClick: onUpload,
|
|
660
|
-
className:
|
|
662
|
+
className: `rounded-[2px] p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing2}`,
|
|
661
663
|
children: /* @__PURE__ */ jsx3(Upload, { className: "h-4 w-4" })
|
|
662
664
|
}
|
|
663
665
|
)
|
|
@@ -819,8 +821,9 @@ function StatusBar({
|
|
|
819
821
|
}
|
|
820
822
|
|
|
821
823
|
// src/workspace/terminal-panel.tsx
|
|
822
|
-
import { useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
824
|
+
import { useRef as useRef2, useEffect as useEffect2, useId } from "react";
|
|
823
825
|
import { Terminal as TerminalIcon, ChevronDown, ChevronUp, X as X3 } from "lucide-react";
|
|
826
|
+
import { focusRing as focusRing3 } from "@tangle-network/ui/utils";
|
|
824
827
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
825
828
|
var LINE_COLORS = {
|
|
826
829
|
command: "text-[var(--code-function)]",
|
|
@@ -844,33 +847,48 @@ function TerminalPanel({
|
|
|
844
847
|
className
|
|
845
848
|
}) {
|
|
846
849
|
const scrollRef = useRef2(null);
|
|
850
|
+
const contentId = useId();
|
|
847
851
|
useEffect2(() => {
|
|
848
852
|
if (!isCollapsed && scrollRef.current) {
|
|
849
853
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
850
854
|
}
|
|
851
855
|
}, [lines, isCollapsed]);
|
|
852
856
|
return /* @__PURE__ */ jsxs5("div", { className: cn("border-t border-[var(--md3-outline-variant)] bg-surface-container", className), children: [
|
|
857
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center px-1", children: [
|
|
858
|
+
/* @__PURE__ */ jsxs5(
|
|
859
|
+
"button",
|
|
860
|
+
{
|
|
861
|
+
type: "button",
|
|
862
|
+
onClick: onToggle,
|
|
863
|
+
disabled: !onToggle,
|
|
864
|
+
"aria-expanded": !isCollapsed,
|
|
865
|
+
"aria-controls": contentId,
|
|
866
|
+
className: `flex min-w-0 flex-1 items-center gap-2 rounded px-2 py-1.5 text-left text-xs text-muted-foreground transition-colors hover:text-foreground disabled:cursor-default ${focusRing3}`,
|
|
867
|
+
children: [
|
|
868
|
+
/* @__PURE__ */ jsx6(TerminalIcon, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
869
|
+
/* @__PURE__ */ jsx6("span", { className: "font-medium", children: title }),
|
|
870
|
+
lines.length > 0 && /* @__PURE__ */ jsx6("span", { className: "rounded-full bg-surface-container-high px-1.5 py-0.5 text-[10px] tabular-nums", children: lines.length }),
|
|
871
|
+
/* @__PURE__ */ jsx6("span", { className: "flex-1" }),
|
|
872
|
+
isCollapsed ? /* @__PURE__ */ jsx6(ChevronUp, { className: "h-3 w-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx6(ChevronDown, { className: "h-3 w-3", "aria-hidden": "true" })
|
|
873
|
+
]
|
|
874
|
+
}
|
|
875
|
+
),
|
|
876
|
+
onClose && /* @__PURE__ */ jsx6(
|
|
877
|
+
"button",
|
|
878
|
+
{
|
|
879
|
+
type: "button",
|
|
880
|
+
"aria-label": `Close ${title}`,
|
|
881
|
+
onClick: onClose,
|
|
882
|
+
className: `rounded p-1.5 text-muted-foreground transition-colors hover:text-foreground ${focusRing3}`,
|
|
883
|
+
children: /* @__PURE__ */ jsx6(X3, { className: "h-3 w-3", "aria-hidden": "true" })
|
|
884
|
+
}
|
|
885
|
+
)
|
|
886
|
+
] }),
|
|
853
887
|
/* @__PURE__ */ jsxs5(
|
|
854
|
-
"button",
|
|
855
|
-
{
|
|
856
|
-
onClick: onToggle,
|
|
857
|
-
className: "flex items-center gap-2 w-full px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
858
|
-
children: [
|
|
859
|
-
/* @__PURE__ */ jsx6(TerminalIcon, { className: "h-3.5 w-3.5" }),
|
|
860
|
-
/* @__PURE__ */ jsx6("span", { className: "font-medium", children: title }),
|
|
861
|
-
lines.length > 0 && /* @__PURE__ */ jsx6("span", { className: "px-1.5 py-0.5 rounded-full bg-surface-container-high text-[10px] tabular-nums", children: lines.length }),
|
|
862
|
-
/* @__PURE__ */ jsx6("div", { className: "flex-1" }),
|
|
863
|
-
onClose && /* @__PURE__ */ jsx6(X3, { className: "h-3 w-3 hover:text-foreground", onClick: (e) => {
|
|
864
|
-
e.stopPropagation();
|
|
865
|
-
onClose();
|
|
866
|
-
} }),
|
|
867
|
-
isCollapsed ? /* @__PURE__ */ jsx6(ChevronUp, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx6(ChevronDown, { className: "h-3 w-3" })
|
|
868
|
-
]
|
|
869
|
-
}
|
|
870
|
-
),
|
|
871
|
-
!isCollapsed && /* @__PURE__ */ jsxs5(
|
|
872
888
|
"div",
|
|
873
889
|
{
|
|
890
|
+
id: contentId,
|
|
891
|
+
hidden: isCollapsed,
|
|
874
892
|
ref: scrollRef,
|
|
875
893
|
className: "overflow-auto px-3 pb-2 font-mono text-xs leading-[1.6] bg-surface-container-lowest",
|
|
876
894
|
style: { maxHeight },
|
|
@@ -1019,6 +1037,7 @@ function useOptimisticSessionItems(items, options = {}) {
|
|
|
1019
1037
|
}
|
|
1020
1038
|
|
|
1021
1039
|
// src/workspace/session-sidebar.tsx
|
|
1040
|
+
import { focusField, focusRing as focusRing4 } from "@tangle-network/ui/utils";
|
|
1022
1041
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1023
1042
|
var NO_CONTROLLER = {
|
|
1024
1043
|
add: () => {
|
|
@@ -1405,7 +1424,7 @@ function SessionSidebar({
|
|
|
1405
1424
|
placeholder: searchPlaceholder,
|
|
1406
1425
|
"aria-label": searchPlaceholder,
|
|
1407
1426
|
className: cn(
|
|
1408
|
-
quiet ?
|
|
1427
|
+
quiet ? `h-8 w-full rounded-md border-0 bg-transparent pl-7 pr-2 text-sm text-foreground placeholder:text-muted-foreground transition-colors focus-visible:bg-surface-container ${focusRing4}` : `h-8 w-full rounded-[var(--radius-sm)] border bg-surface-container-lowest pl-7 pr-2 text-sm text-foreground placeholder:text-muted-foreground ${focusField}`,
|
|
1409
1428
|
MOTION_CONTROL
|
|
1410
1429
|
)
|
|
1411
1430
|
}
|
|
@@ -1604,7 +1623,7 @@ function SessionActivityMonitor({
|
|
|
1604
1623
|
}
|
|
1605
1624
|
|
|
1606
1625
|
// src/workspace/sandbox-workbench.tsx
|
|
1607
|
-
import { useEffect as useEffect4, useMemo as useMemo4, useState as useState5 } from "react";
|
|
1626
|
+
import { useEffect as useEffect4, useId as useId2, useMemo as useMemo4, useRef as useRef5, useState as useState5 } from "react";
|
|
1608
1627
|
import {
|
|
1609
1628
|
Bot,
|
|
1610
1629
|
Boxes,
|
|
@@ -1621,6 +1640,7 @@ import { ChatContainer } from "@tangle-network/ui/chat";
|
|
|
1621
1640
|
import { FileArtifactPane } from "@tangle-network/ui/files";
|
|
1622
1641
|
import { OpenUIArtifactRenderer } from "@tangle-network/ui/openui";
|
|
1623
1642
|
import { ArtifactPane as ArtifactPane2 } from "@tangle-network/ui/primitives";
|
|
1643
|
+
import { focusRing as focusRing5, focusRingInset } from "@tangle-network/ui/utils";
|
|
1624
1644
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1625
1645
|
function getArtifactTabIcon(kind) {
|
|
1626
1646
|
switch (kind) {
|
|
@@ -1650,10 +1670,13 @@ function ArtifactTabs({
|
|
|
1650
1670
|
artifacts,
|
|
1651
1671
|
activeArtifactId,
|
|
1652
1672
|
onSelect,
|
|
1653
|
-
onClose
|
|
1673
|
+
onClose,
|
|
1674
|
+
tabIdPrefix,
|
|
1675
|
+
panelId
|
|
1654
1676
|
}) {
|
|
1677
|
+
const tabRefs = useRef5(/* @__PURE__ */ new Map());
|
|
1655
1678
|
if (artifacts.length === 0) return null;
|
|
1656
|
-
return /* @__PURE__ */ jsx10("div", { className: "flex items-center overflow-x-auto border-b border-[var(--md3-outline-variant)] bg-surface-container-high", children: artifacts.map((artifact) => {
|
|
1679
|
+
return /* @__PURE__ */ jsx10("div", { role: "tablist", "aria-label": "Artifacts", className: "flex items-center overflow-x-auto border-b border-[var(--md3-outline-variant)] bg-surface-container-high", children: artifacts.map((artifact) => {
|
|
1657
1680
|
const Icon = artifact.icon ?? getArtifactTabIcon(artifact.kind);
|
|
1658
1681
|
const isActive = artifact.id === activeArtifactId;
|
|
1659
1682
|
return /* @__PURE__ */ jsxs9(
|
|
@@ -1668,8 +1691,41 @@ function ArtifactTabs({
|
|
|
1668
1691
|
"button",
|
|
1669
1692
|
{
|
|
1670
1693
|
type: "button",
|
|
1694
|
+
ref: (element) => {
|
|
1695
|
+
if (element) tabRefs.current.set(artifact.id, element);
|
|
1696
|
+
else tabRefs.current.delete(artifact.id);
|
|
1697
|
+
},
|
|
1698
|
+
id: `${tabIdPrefix}-${artifact.id}`,
|
|
1699
|
+
role: "tab",
|
|
1700
|
+
"aria-controls": panelId,
|
|
1701
|
+
"aria-selected": isActive,
|
|
1702
|
+
tabIndex: isActive ? 0 : -1,
|
|
1671
1703
|
onClick: () => onSelect(artifact.id),
|
|
1672
|
-
|
|
1704
|
+
onKeyDown: (event) => {
|
|
1705
|
+
const index = artifacts.findIndex((entry) => entry.id === artifact.id);
|
|
1706
|
+
let nextIndex;
|
|
1707
|
+
switch (event.key) {
|
|
1708
|
+
case "ArrowRight":
|
|
1709
|
+
nextIndex = (index + 1) % artifacts.length;
|
|
1710
|
+
break;
|
|
1711
|
+
case "ArrowLeft":
|
|
1712
|
+
nextIndex = (index - 1 + artifacts.length) % artifacts.length;
|
|
1713
|
+
break;
|
|
1714
|
+
case "Home":
|
|
1715
|
+
nextIndex = 0;
|
|
1716
|
+
break;
|
|
1717
|
+
case "End":
|
|
1718
|
+
nextIndex = artifacts.length - 1;
|
|
1719
|
+
break;
|
|
1720
|
+
default:
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
event.preventDefault();
|
|
1724
|
+
const next = artifacts[nextIndex];
|
|
1725
|
+
onSelect(next.id);
|
|
1726
|
+
tabRefs.current.get(next.id)?.focus();
|
|
1727
|
+
},
|
|
1728
|
+
className: `flex min-w-0 items-center gap-2 px-3 py-2 text-[12px] uppercase tracking-wider font-medium transition-colors hover:text-foreground ${focusRingInset}`,
|
|
1673
1729
|
children: [
|
|
1674
1730
|
/* @__PURE__ */ jsx10(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
1675
1731
|
/* @__PURE__ */ jsx10("span", { className: "max-w-[14rem] truncate", children: artifactTabLabel(artifact) })
|
|
@@ -1681,8 +1737,9 @@ function ArtifactTabs({
|
|
|
1681
1737
|
{
|
|
1682
1738
|
type: "button",
|
|
1683
1739
|
"aria-label": `Close ${artifactTabLabel(artifact)}`,
|
|
1740
|
+
tabIndex: isActive ? 0 : -1,
|
|
1684
1741
|
onClick: () => onClose(artifact.id),
|
|
1685
|
-
className:
|
|
1742
|
+
className: `mr-1 rounded-[2px] p-1 opacity-0 transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100 ${focusRing5}`,
|
|
1686
1743
|
children: /* @__PURE__ */ jsx10(X4, { className: "h-3 w-3" })
|
|
1687
1744
|
}
|
|
1688
1745
|
)
|
|
@@ -1818,6 +1875,8 @@ function SandboxWorkbench({
|
|
|
1818
1875
|
className
|
|
1819
1876
|
}) {
|
|
1820
1877
|
const artifacts = useMemo4(() => sortPinnedFirst(artifactsProp), [artifactsProp]);
|
|
1878
|
+
const artifactTabsId = useId2();
|
|
1879
|
+
const artifactPanelId = `${artifactTabsId}-panel`;
|
|
1821
1880
|
const [uncontrolledArtifactId, setUncontrolledArtifactId] = useState5(
|
|
1822
1881
|
activeArtifactId ?? artifacts[0]?.id
|
|
1823
1882
|
);
|
|
@@ -1889,17 +1948,30 @@ function SandboxWorkbench({
|
|
|
1889
1948
|
artifacts,
|
|
1890
1949
|
activeArtifactId: resolvedArtifactId,
|
|
1891
1950
|
onSelect: handleArtifactChange,
|
|
1892
|
-
onClose: onArtifactClose
|
|
1951
|
+
onClose: onArtifactClose,
|
|
1952
|
+
tabIdPrefix: artifactTabsId,
|
|
1953
|
+
panelId: artifactPanelId
|
|
1893
1954
|
}
|
|
1894
1955
|
),
|
|
1895
|
-
/* @__PURE__ */ jsx10(
|
|
1896
|
-
|
|
1956
|
+
/* @__PURE__ */ jsx10(
|
|
1957
|
+
"div",
|
|
1897
1958
|
{
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1959
|
+
id: artifactPanelId,
|
|
1960
|
+
role: "tabpanel",
|
|
1961
|
+
"aria-labelledby": activeArtifact ? `${artifactTabsId}-${activeArtifact.id}` : void 0,
|
|
1962
|
+
"aria-label": activeArtifact ? void 0 : "Artifact content",
|
|
1963
|
+
tabIndex: 0,
|
|
1964
|
+
className: `min-h-0 flex-1 overflow-auto bg-surface-container ${focusRingInset}`,
|
|
1965
|
+
children: activeArtifact ? renderArtifact(activeArtifact) : /* @__PURE__ */ jsx10("div", { className: "flex h-full items-center justify-center p-6", children: emptyArtifactState ?? /* @__PURE__ */ jsx10(
|
|
1966
|
+
EmptyState2,
|
|
1967
|
+
{
|
|
1968
|
+
icon: /* @__PURE__ */ jsx10(Boxes, { className: "h-8 w-8" }),
|
|
1969
|
+
title: "No artifact selected",
|
|
1970
|
+
description: "Select a generated artifact, file preview, or OpenUI panel to inspect it here."
|
|
1971
|
+
}
|
|
1972
|
+
) })
|
|
1901
1973
|
}
|
|
1902
|
-
)
|
|
1974
|
+
)
|
|
1903
1975
|
] }) : null;
|
|
1904
1976
|
const directoryPlacement = layout?.directoryPlacement ?? (directory ? "left" : "hidden");
|
|
1905
1977
|
const artifactPlacement = layout?.artifactPlacement ?? (artifactPanel ? "right" : "hidden");
|
|
@@ -2380,6 +2452,7 @@ function CalendarView({
|
|
|
2380
2452
|
|
|
2381
2453
|
// src/workspace/approval-queue.tsx
|
|
2382
2454
|
import { useState as useState8, useMemo as useMemo7 } from "react";
|
|
2455
|
+
import { focusField as focusField2 } from "@tangle-network/ui/utils";
|
|
2383
2456
|
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2384
2457
|
function ApprovalQueue({
|
|
2385
2458
|
items,
|
|
@@ -2498,7 +2571,7 @@ function ApprovalQueue({
|
|
|
2498
2571
|
placeholder: "Why are you rejecting this?",
|
|
2499
2572
|
value: rejectReason,
|
|
2500
2573
|
onChange: (e) => setRejectReason(e.target.value),
|
|
2501
|
-
className:
|
|
2574
|
+
className: `w-full rounded-md border bg-surface-container-low px-3 py-2 text-sm placeholder:text-muted-foreground mb-2 ${focusField2}`,
|
|
2502
2575
|
rows: 2
|
|
2503
2576
|
}
|
|
2504
2577
|
),
|