@tangle-network/sandbox-ui 0.12.0 → 0.14.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/{chunk-ESVYBDGA.js → chunk-AG7QDC2Q.js} +182 -2
- package/dist/globals.css +407 -403
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/styles.css +407 -403
- package/dist/terminal.js +39 -2
- package/dist/{use-sandbox-metrics-B64diPqN.d.ts → use-sandbox-metrics-DWc0k9Xm.d.ts} +18 -6
- package/package.json +8 -1
package/dist/terminal.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
usePtySession
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AG7QDC2Q.js";
|
|
4
4
|
|
|
5
5
|
// src/terminal/terminal-view.tsx
|
|
6
6
|
import "@xterm/xterm/css/xterm.css";
|
|
@@ -48,8 +48,19 @@ function TerminalView({
|
|
|
48
48
|
const containerRef = useRef(null);
|
|
49
49
|
const termRef = useRef(null);
|
|
50
50
|
const fitAddonRef = useRef(null);
|
|
51
|
+
const pendingWritesRef = useRef([]);
|
|
52
|
+
const writeRafRef = useRef(null);
|
|
51
53
|
const onData = useCallback((data) => {
|
|
52
|
-
|
|
54
|
+
if (!data) return;
|
|
55
|
+
pendingWritesRef.current.push(data);
|
|
56
|
+
if (writeRafRef.current !== null) return;
|
|
57
|
+
writeRafRef.current = requestAnimationFrame(() => {
|
|
58
|
+
writeRafRef.current = null;
|
|
59
|
+
const chunks = pendingWritesRef.current;
|
|
60
|
+
if (chunks.length === 0) return;
|
|
61
|
+
pendingWritesRef.current = [];
|
|
62
|
+
termRef.current?.write(chunks.length === 1 ? chunks[0] : chunks.join(""));
|
|
63
|
+
});
|
|
53
64
|
}, []);
|
|
54
65
|
const { isConnected, error, sendCommand, resizeTerminal, reconnect } = usePtySession({
|
|
55
66
|
apiUrl,
|
|
@@ -74,6 +85,25 @@ function TerminalView({
|
|
|
74
85
|
term.loadAddon(fitAddon);
|
|
75
86
|
term.loadAddon(webLinksAddon);
|
|
76
87
|
term.open(containerRef.current);
|
|
88
|
+
let webglAddon = null;
|
|
89
|
+
let webglCancelled = false;
|
|
90
|
+
void (async () => {
|
|
91
|
+
try {
|
|
92
|
+
const mod = await import("@xterm/addon-webgl");
|
|
93
|
+
if (webglCancelled) return;
|
|
94
|
+
try {
|
|
95
|
+
const addon = new mod.WebglAddon();
|
|
96
|
+
addon.onContextLoss(() => {
|
|
97
|
+
webglAddon?.dispose();
|
|
98
|
+
webglAddon = null;
|
|
99
|
+
});
|
|
100
|
+
webglAddon = addon;
|
|
101
|
+
term.loadAddon(addon);
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
}
|
|
106
|
+
})();
|
|
77
107
|
requestAnimationFrame(() => {
|
|
78
108
|
fitAddon.fit();
|
|
79
109
|
});
|
|
@@ -102,7 +132,14 @@ function TerminalView({
|
|
|
102
132
|
});
|
|
103
133
|
ro.observe(containerRef.current);
|
|
104
134
|
return () => {
|
|
135
|
+
webglCancelled = true;
|
|
105
136
|
ro.disconnect();
|
|
137
|
+
if (writeRafRef.current !== null) {
|
|
138
|
+
cancelAnimationFrame(writeRafRef.current);
|
|
139
|
+
writeRafRef.current = null;
|
|
140
|
+
}
|
|
141
|
+
pendingWritesRef.current = [];
|
|
142
|
+
webglAddon?.dispose();
|
|
106
143
|
term.dispose();
|
|
107
144
|
termRef.current = null;
|
|
108
145
|
fitAddonRef.current = null;
|
|
@@ -46,7 +46,7 @@ interface UsePtySessionOptions {
|
|
|
46
46
|
onData: (data: string) => void;
|
|
47
47
|
}
|
|
48
48
|
interface UsePtySessionReturn {
|
|
49
|
-
/** Whether the
|
|
49
|
+
/** Whether the underlying transport is connected and receiving data. */
|
|
50
50
|
isConnected: boolean;
|
|
51
51
|
/** Connection or API error, if any. */
|
|
52
52
|
error: string | null;
|
|
@@ -60,11 +60,23 @@ interface UsePtySessionReturn {
|
|
|
60
60
|
/**
|
|
61
61
|
* Manages a PTY session against the sidecar terminal API.
|
|
62
62
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
63
|
+
* Transport:
|
|
64
|
+
* 1. POST /terminals creates the session.
|
|
65
|
+
* 2. The hook tries WebSocket: GET /terminals/:id/ws (Upgrade).
|
|
66
|
+
* - Server → client: TEXT frames carrying raw PTY output.
|
|
67
|
+
* - Client → server: BINARY frames carrying stdin (UTF-8); TEXT
|
|
68
|
+
* frames carrying JSON control messages (`{"type":"resize",...}`).
|
|
69
|
+
* 3. If the WS does not reach OPEN within WS_OPEN_TIMEOUT_MS, or it
|
|
70
|
+
* errors before opening, the hook falls back to SSE+POST:
|
|
71
|
+
* - GET /terminals/:id/stream (SSE for output)
|
|
72
|
+
* - POST /terminals/:id/input (one batched POST at a time)
|
|
73
|
+
* - PATCH /terminals/:id (resize)
|
|
74
|
+
* 4. DELETE /terminals/:id closes the session (both transports).
|
|
75
|
+
*
|
|
76
|
+
* The WS path eliminates the per-keystroke HTTP round-trip that
|
|
77
|
+
* dominates typing latency through edge proxies; the HTTP+SSE path is
|
|
78
|
+
* preserved as a fallback so the hook keeps working against
|
|
79
|
+
* deployments that have not yet shipped the WS endpoint.
|
|
68
80
|
*/
|
|
69
81
|
declare function usePtySession({ apiUrl, token, onData }: UsePtySessionOptions): UsePtySessionReturn;
|
|
70
82
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/sandbox-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.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",
|
|
@@ -105,6 +105,7 @@
|
|
|
105
105
|
"test:watch": "vitest"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
|
+
"@tangle-network/brand": "^0.2.0",
|
|
108
109
|
"react": "^18 || ^19",
|
|
109
110
|
"react-dom": "^18 || ^19"
|
|
110
111
|
},
|
|
@@ -118,6 +119,9 @@
|
|
|
118
119
|
"@xterm/addon-web-links": {
|
|
119
120
|
"optional": true
|
|
120
121
|
},
|
|
122
|
+
"@xterm/addon-webgl": {
|
|
123
|
+
"optional": true
|
|
124
|
+
},
|
|
121
125
|
"@tanstack/react-query": {
|
|
122
126
|
"optional": true
|
|
123
127
|
},
|
|
@@ -189,6 +193,7 @@
|
|
|
189
193
|
"@storybook/react-vite": "^8.6.18",
|
|
190
194
|
"@tailwindcss/postcss": "^4.2.2",
|
|
191
195
|
"@tailwindcss/vite": "^4.2.2",
|
|
196
|
+
"@tangle-network/brand": "^0.2.0",
|
|
192
197
|
"@tanstack/react-query": "^5.91.0",
|
|
193
198
|
"@testing-library/dom": "^10.4.1",
|
|
194
199
|
"@testing-library/jest-dom": "^6.9.1",
|
|
@@ -204,9 +209,11 @@
|
|
|
204
209
|
"@types/turndown": "^5.0.6",
|
|
205
210
|
"@xterm/addon-fit": "^0.11.0",
|
|
206
211
|
"@xterm/addon-web-links": "^0.12.0",
|
|
212
|
+
"@xterm/addon-webgl": "^0.19.0",
|
|
207
213
|
"@xterm/xterm": "^6.0.0",
|
|
208
214
|
"jsdom": "^29.0.2",
|
|
209
215
|
"postcss": "^8.5.8",
|
|
216
|
+
"postcss-import": "^16.1.1",
|
|
210
217
|
"react": "^19.1.0",
|
|
211
218
|
"react-dom": "^19.1.0",
|
|
212
219
|
"storybook": "^8.6.18",
|