@industry-theme/xterm-terminal-panel 0.6.0 → 0.7.1
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/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +241 -800
- package/dist/src/components/TerminalSession.d.ts.map +1 -1
- package/dist/src/panel-exports.d.ts +1 -2
- package/dist/src/panel-exports.d.ts.map +1 -1
- package/dist/src/panels/TabbedTerminalPanel.d.ts.map +1 -1
- package/dist/src/renderer/XtermRenderer.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/src/panels/TerminalPanel.d.ts +0 -3
- package/dist/src/panels/TerminalPanel.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
// package.json
|
|
36
36
|
var package_default = {
|
|
37
37
|
name: "@industry-theme/xterm-terminal-panel",
|
|
38
|
-
version: "0.
|
|
38
|
+
version: "0.7.1",
|
|
39
39
|
description: "Industry-themed xterm.js terminal components with panel framework integration",
|
|
40
40
|
type: "module",
|
|
41
41
|
main: "dist/index.js",
|
|
@@ -1285,7 +1285,14 @@ ThemedTerminalWithProvider.displayName = "ThemedTerminalWithProvider";
|
|
|
1285
1285
|
import { forwardRef as forwardRef3, useImperativeHandle as useImperativeHandle2, useRef as useRef2 } from "react";
|
|
1286
1286
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1287
1287
|
var XtermRenderer = forwardRef3((props, ref) => {
|
|
1288
|
-
const {
|
|
1288
|
+
const {
|
|
1289
|
+
transparent,
|
|
1290
|
+
enableSearch = true,
|
|
1291
|
+
enableWebLinks = true,
|
|
1292
|
+
cursorBlink = true,
|
|
1293
|
+
convertEol = true,
|
|
1294
|
+
...rest
|
|
1295
|
+
} = props;
|
|
1289
1296
|
const innerRef = useRef2(null);
|
|
1290
1297
|
useImperativeHandle2(ref, () => ({
|
|
1291
1298
|
write: (data) => innerRef.current?.write(data),
|
|
@@ -1314,6 +1321,10 @@ var XtermRenderer = forwardRef3((props, ref) => {
|
|
|
1314
1321
|
return /* @__PURE__ */ jsx4(ThemedTerminalWithProvider, {
|
|
1315
1322
|
ref: innerRef,
|
|
1316
1323
|
...rest,
|
|
1324
|
+
enableSearch,
|
|
1325
|
+
enableWebLinks,
|
|
1326
|
+
cursorBlink,
|
|
1327
|
+
convertEol,
|
|
1317
1328
|
hideHeader: true,
|
|
1318
1329
|
activityDetection: false,
|
|
1319
1330
|
allowTransparency: transparent
|
|
@@ -1494,15 +1505,26 @@ var TerminalSession = forwardRef4((props, ref) => {
|
|
|
1494
1505
|
return;
|
|
1495
1506
|
hasInitializedRef.current = true;
|
|
1496
1507
|
let mounted = true;
|
|
1508
|
+
const tracer = getTracer();
|
|
1497
1509
|
const init = async () => {
|
|
1498
1510
|
try {
|
|
1499
1511
|
if (sessionIdProp) {
|
|
1512
|
+
const span2 = tracer.startSpan("terminal.session.reconnect", {
|
|
1513
|
+
attributes: {
|
|
1514
|
+
"session.id": sessionIdProp,
|
|
1515
|
+
"session.context": sessionContext ?? "",
|
|
1516
|
+
"session.isForeign": isForeign
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1500
1519
|
if (enableOwnership) {
|
|
1501
1520
|
if (isForeign && actions.checkTerminalOwnership) {
|
|
1502
1521
|
const status = await actions.checkTerminalOwnership(sessionIdProp);
|
|
1503
1522
|
if (status.ownedByWindowId && !status.ownedByThisWindow) {
|
|
1504
1523
|
setShouldRenderTerminal(false);
|
|
1505
1524
|
setOwnerWindowId(status.ownedByWindowId);
|
|
1525
|
+
span2.addEvent("terminal.session.reconnect_blocked", {
|
|
1526
|
+
"owner.windowId": status.ownedByWindowId
|
|
1527
|
+
});
|
|
1506
1528
|
}
|
|
1507
1529
|
} else {
|
|
1508
1530
|
await claimAndConnect(sessionIdProp);
|
|
@@ -1512,6 +1534,8 @@ var TerminalSession = forwardRef4((props, ref) => {
|
|
|
1512
1534
|
setLocalSessionId(sessionIdProp);
|
|
1513
1535
|
setIsInitialized(true);
|
|
1514
1536
|
}
|
|
1537
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
1538
|
+
span2.end();
|
|
1515
1539
|
return;
|
|
1516
1540
|
}
|
|
1517
1541
|
if (!actions.createTerminalSession) {
|
|
@@ -1519,22 +1543,46 @@ var TerminalSession = forwardRef4((props, ref) => {
|
|
|
1519
1543
|
setIsInitialized(true);
|
|
1520
1544
|
return;
|
|
1521
1545
|
}
|
|
1546
|
+
const span = tracer.startSpan("terminal.session.create", {
|
|
1547
|
+
attributes: {
|
|
1548
|
+
"session.cwd": cwd ?? "",
|
|
1549
|
+
"session.context": sessionContext ?? ""
|
|
1550
|
+
}
|
|
1551
|
+
});
|
|
1522
1552
|
const newId = await actions.createTerminalSession({
|
|
1523
1553
|
cwd,
|
|
1524
1554
|
command,
|
|
1525
1555
|
context: sessionContext
|
|
1526
1556
|
});
|
|
1527
1557
|
pendingSessionIdRef.current = newId;
|
|
1528
|
-
|
|
1558
|
+
span.setAttribute("session.id", newId);
|
|
1559
|
+
if (!mounted) {
|
|
1560
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1561
|
+
span.end();
|
|
1529
1562
|
return;
|
|
1563
|
+
}
|
|
1530
1564
|
if (enableOwnership) {
|
|
1531
1565
|
await claimAndConnect(newId);
|
|
1532
1566
|
}
|
|
1533
1567
|
setLocalSessionId(newId);
|
|
1534
1568
|
setIsInitialized(true);
|
|
1535
1569
|
onSessionCreated?.(newId);
|
|
1570
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1571
|
+
span.end();
|
|
1536
1572
|
} catch (err) {
|
|
1537
1573
|
console.error("[TerminalSession] init failed:", err);
|
|
1574
|
+
const errSpan = tracer.startSpan("terminal.session.error", {
|
|
1575
|
+
attributes: {
|
|
1576
|
+
"session.context": sessionContext ?? "",
|
|
1577
|
+
"session.action": sessionIdProp ? "reconnect" : "create"
|
|
1578
|
+
}
|
|
1579
|
+
});
|
|
1580
|
+
errSpan.recordException(err);
|
|
1581
|
+
errSpan.setStatus({
|
|
1582
|
+
code: SpanStatusCode.ERROR,
|
|
1583
|
+
message: err instanceof Error ? err.message : "Unknown error"
|
|
1584
|
+
});
|
|
1585
|
+
errSpan.end();
|
|
1538
1586
|
if (mounted)
|
|
1539
1587
|
setIsInitialized(true);
|
|
1540
1588
|
}
|
|
@@ -1543,7 +1591,18 @@ var TerminalSession = forwardRef4((props, ref) => {
|
|
|
1543
1591
|
return () => {
|
|
1544
1592
|
mounted = false;
|
|
1545
1593
|
if (!persistOnUnmount && pendingSessionIdRef.current && actions.destroyTerminalSession) {
|
|
1546
|
-
|
|
1594
|
+
const tracer2 = getTracer();
|
|
1595
|
+
const span = tracer2.startSpan("terminal.session.destroy", {
|
|
1596
|
+
attributes: { "session.id": pendingSessionIdRef.current }
|
|
1597
|
+
});
|
|
1598
|
+
Promise.resolve(actions.destroyTerminalSession(pendingSessionIdRef.current)).then(() => {
|
|
1599
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1600
|
+
span.end();
|
|
1601
|
+
}).catch((err) => {
|
|
1602
|
+
span.recordException(err);
|
|
1603
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1604
|
+
span.end();
|
|
1605
|
+
});
|
|
1547
1606
|
}
|
|
1548
1607
|
};
|
|
1549
1608
|
}, []);
|
|
@@ -2204,350 +2263,21 @@ var useTabKeyboardShortcuts = ({
|
|
|
2204
2263
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2205
2264
|
}, [enabled, onNewTab, onCloseTab, onSwitchToTab]);
|
|
2206
2265
|
};
|
|
2207
|
-
// src/panels/TerminalPanel.tsx
|
|
2208
|
-
import { useTheme as useTheme6 } from "@principal-ade/industry-theme";
|
|
2209
|
-
import { Lock, Unlock, ArrowDown } from "lucide-react";
|
|
2210
|
-
import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
|
|
2211
|
-
|
|
2212
|
-
// src/panel-types/index.ts
|
|
2213
|
-
function getTerminalSessions(context2) {
|
|
2214
|
-
return context2.terminal?.data ?? [];
|
|
2215
|
-
}
|
|
2216
|
-
function getTerminalSession(context2, sessionId) {
|
|
2217
|
-
const sessions = getTerminalSessions(context2);
|
|
2218
|
-
return sessions.find((s) => s.id === sessionId);
|
|
2219
|
-
}
|
|
2220
|
-
function isTerminalLoading(context2) {
|
|
2221
|
-
return context2.terminal?.loading ?? false;
|
|
2222
|
-
}
|
|
2223
|
-
function getRepositoryPath(context2) {
|
|
2224
|
-
return context2.currentScope.repository?.path ?? null;
|
|
2225
|
-
}
|
|
2226
|
-
function getWorkspacePath(context2) {
|
|
2227
|
-
return context2.currentScope.workspace?.path ?? null;
|
|
2228
|
-
}
|
|
2229
|
-
function getTerminalDirectory(context2, terminalScope = "repository") {
|
|
2230
|
-
switch (terminalScope) {
|
|
2231
|
-
case "workspace":
|
|
2232
|
-
return getWorkspacePath(context2);
|
|
2233
|
-
case "repository":
|
|
2234
|
-
return getRepositoryPath(context2) ?? getWorkspacePath(context2);
|
|
2235
|
-
default:
|
|
2236
|
-
return getRepositoryPath(context2) ?? getWorkspacePath(context2);
|
|
2237
|
-
}
|
|
2238
|
-
}
|
|
2239
|
-
function getTerminalSlice(context2) {
|
|
2240
|
-
return context2.terminal;
|
|
2241
|
-
}
|
|
2242
|
-
|
|
2243
|
-
// src/panels/TerminalPanel.tsx
|
|
2244
|
-
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2245
|
-
var TerminalPanel = ({
|
|
2246
|
-
context: context2,
|
|
2247
|
-
actions,
|
|
2248
|
-
events: _events,
|
|
2249
|
-
terminalScope = "repository",
|
|
2250
|
-
allowTransparency = false,
|
|
2251
|
-
backgroundColor
|
|
2252
|
-
}) => {
|
|
2253
|
-
const { theme } = useTheme6();
|
|
2254
|
-
const [sessionId, setSessionId] = useState4(null);
|
|
2255
|
-
const [error, setError] = useState4(null);
|
|
2256
|
-
const [isInitializing, setIsInitializing] = useState4(true);
|
|
2257
|
-
const [scrollPosition, setScrollPosition] = useState4({
|
|
2258
|
-
isAtTop: false,
|
|
2259
|
-
isAtBottom: true,
|
|
2260
|
-
isScrollLocked: false
|
|
2261
|
-
});
|
|
2262
|
-
const terminalRef = useRef4(null);
|
|
2263
|
-
const isScrollLockedRef = useRef4(scrollPosition.isScrollLocked);
|
|
2264
|
-
const terminalDirectory = getTerminalDirectory(context2, terminalScope);
|
|
2265
|
-
const pendingSessionIdRef = useRef4(null);
|
|
2266
|
-
useEffect4(() => {
|
|
2267
|
-
let mounted = true;
|
|
2268
|
-
const initTerminal = async () => {
|
|
2269
|
-
try {
|
|
2270
|
-
if (!actions.createTerminalSession) {
|
|
2271
|
-
throw new Error("Terminal actions not available. Host must provide createTerminalSession action.");
|
|
2272
|
-
}
|
|
2273
|
-
const id = await actions.createTerminalSession({
|
|
2274
|
-
cwd: terminalDirectory || undefined
|
|
2275
|
-
});
|
|
2276
|
-
pendingSessionIdRef.current = id;
|
|
2277
|
-
if (actions.claimTerminalOwnership) {
|
|
2278
|
-
await actions.claimTerminalOwnership(id);
|
|
2279
|
-
}
|
|
2280
|
-
if (mounted) {
|
|
2281
|
-
setSessionId(id);
|
|
2282
|
-
setIsInitializing(false);
|
|
2283
|
-
}
|
|
2284
|
-
} catch (err) {
|
|
2285
|
-
if (mounted) {
|
|
2286
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
2287
|
-
setIsInitializing(false);
|
|
2288
|
-
}
|
|
2289
|
-
}
|
|
2290
|
-
};
|
|
2291
|
-
initTerminal();
|
|
2292
|
-
return () => {
|
|
2293
|
-
mounted = false;
|
|
2294
|
-
if (pendingSessionIdRef.current && actions.destroyTerminalSession) {
|
|
2295
|
-
actions.destroyTerminalSession(pendingSessionIdRef.current);
|
|
2296
|
-
}
|
|
2297
|
-
};
|
|
2298
|
-
}, []);
|
|
2299
|
-
useEffect4(() => {
|
|
2300
|
-
if (!sessionId)
|
|
2301
|
-
return;
|
|
2302
|
-
if (!actions.onTerminalData) {
|
|
2303
|
-
setError("Host does not provide onTerminalData. Terminal data cannot be displayed.");
|
|
2304
|
-
return;
|
|
2305
|
-
}
|
|
2306
|
-
let cursorMovedToHome = false;
|
|
2307
|
-
let lastWriteTime = 0;
|
|
2308
|
-
let autoScrollTimeout = null;
|
|
2309
|
-
const unsubscribe = actions.onTerminalData(sessionId, (data) => {
|
|
2310
|
-
if (!terminalRef.current)
|
|
2311
|
-
return;
|
|
2312
|
-
if (data.includes("\x1B[H")) {
|
|
2313
|
-
cursorMovedToHome = true;
|
|
2314
|
-
lastWriteTime = Date.now();
|
|
2315
|
-
}
|
|
2316
|
-
terminalRef.current.write(data);
|
|
2317
|
-
if (cursorMovedToHome && isScrollLockedRef.current) {
|
|
2318
|
-
if (autoScrollTimeout)
|
|
2319
|
-
clearTimeout(autoScrollTimeout);
|
|
2320
|
-
autoScrollTimeout = setTimeout(() => {
|
|
2321
|
-
const timeSinceLastWrite = Date.now() - lastWriteTime;
|
|
2322
|
-
if (timeSinceLastWrite >= 100 && cursorMovedToHome && terminalRef.current) {
|
|
2323
|
-
terminalRef.current.write("\x1B[9999;1H");
|
|
2324
|
-
cursorMovedToHome = false;
|
|
2325
|
-
}
|
|
2326
|
-
}, 100);
|
|
2327
|
-
}
|
|
2328
|
-
lastWriteTime = Date.now();
|
|
2329
|
-
});
|
|
2330
|
-
return () => {
|
|
2331
|
-
if (autoScrollTimeout)
|
|
2332
|
-
clearTimeout(autoScrollTimeout);
|
|
2333
|
-
unsubscribe();
|
|
2334
|
-
};
|
|
2335
|
-
}, [sessionId, actions.onTerminalData]);
|
|
2336
|
-
const handleTerminalData = useCallback5((data) => {
|
|
2337
|
-
if (sessionId && actions.writeToTerminal) {
|
|
2338
|
-
actions.writeToTerminal(sessionId, data);
|
|
2339
|
-
}
|
|
2340
|
-
}, [sessionId, actions.writeToTerminal]);
|
|
2341
|
-
const hasNotifiedPtyRef = useRef4(false);
|
|
2342
|
-
const handleTerminalResize = useCallback5((cols, rows) => {
|
|
2343
|
-
if (sessionId && actions.resizeTerminal) {
|
|
2344
|
-
const isInitialNotification = !hasNotifiedPtyRef.current;
|
|
2345
|
-
actions.resizeTerminal(sessionId, cols, rows);
|
|
2346
|
-
if (isInitialNotification && actions.writeToTerminal) {
|
|
2347
|
-
setTimeout(() => {
|
|
2348
|
-
actions.writeToTerminal(sessionId, "\f");
|
|
2349
|
-
}, 50);
|
|
2350
|
-
}
|
|
2351
|
-
hasNotifiedPtyRef.current = true;
|
|
2352
|
-
}
|
|
2353
|
-
}, [sessionId, actions.resizeTerminal, actions.writeToTerminal]);
|
|
2354
|
-
useEffect4(() => {
|
|
2355
|
-
hasNotifiedPtyRef.current = false;
|
|
2356
|
-
}, [sessionId]);
|
|
2357
|
-
useEffect4(() => {
|
|
2358
|
-
if (!sessionId || !actions.resizeTerminal)
|
|
2359
|
-
return;
|
|
2360
|
-
if (hasNotifiedPtyRef.current)
|
|
2361
|
-
return;
|
|
2362
|
-
const term = terminalRef.current?.getTerminal();
|
|
2363
|
-
if (!term || !term.cols || !term.rows)
|
|
2364
|
-
return;
|
|
2365
|
-
actions.resizeTerminal(sessionId, term.cols, term.rows);
|
|
2366
|
-
hasNotifiedPtyRef.current = true;
|
|
2367
|
-
if (actions.writeToTerminal) {
|
|
2368
|
-
const writeFn = actions.writeToTerminal;
|
|
2369
|
-
setTimeout(() => writeFn(sessionId, "\f"), 50);
|
|
2370
|
-
}
|
|
2371
|
-
}, [sessionId, actions.resizeTerminal, actions.writeToTerminal]);
|
|
2372
|
-
const handleScrollPositionChange = useCallback5((position) => {
|
|
2373
|
-
setScrollPosition(position);
|
|
2374
|
-
isScrollLockedRef.current = position.isScrollLocked;
|
|
2375
|
-
}, []);
|
|
2376
|
-
const sessionInfo = sessionId ? getTerminalSession(context2, sessionId) : undefined;
|
|
2377
|
-
if (error) {
|
|
2378
|
-
return /* @__PURE__ */ jsxs7("div", {
|
|
2379
|
-
style: {
|
|
2380
|
-
padding: "20px",
|
|
2381
|
-
color: "#ef4444",
|
|
2382
|
-
backgroundColor: allowTransparency ? "transparent" : "#1a1a1a",
|
|
2383
|
-
height: "100%",
|
|
2384
|
-
display: "flex",
|
|
2385
|
-
alignItems: "center",
|
|
2386
|
-
justifyContent: "center",
|
|
2387
|
-
flexDirection: "column",
|
|
2388
|
-
gap: "10px"
|
|
2389
|
-
},
|
|
2390
|
-
children: [
|
|
2391
|
-
/* @__PURE__ */ jsx9("div", {
|
|
2392
|
-
style: { fontSize: "16px", fontWeight: "bold" },
|
|
2393
|
-
children: "Terminal Error"
|
|
2394
|
-
}),
|
|
2395
|
-
/* @__PURE__ */ jsx9("div", {
|
|
2396
|
-
style: { fontSize: "14px", opacity: 0.8 },
|
|
2397
|
-
children: error
|
|
2398
|
-
})
|
|
2399
|
-
]
|
|
2400
|
-
});
|
|
2401
|
-
}
|
|
2402
|
-
if (isInitializing || !sessionId) {
|
|
2403
|
-
return /* @__PURE__ */ jsx9("div", {
|
|
2404
|
-
style: {
|
|
2405
|
-
padding: "20px",
|
|
2406
|
-
color: "#a0a0a0",
|
|
2407
|
-
backgroundColor: allowTransparency ? "transparent" : "#1a1a1a",
|
|
2408
|
-
height: "100%",
|
|
2409
|
-
display: "flex",
|
|
2410
|
-
alignItems: "center",
|
|
2411
|
-
justifyContent: "center"
|
|
2412
|
-
},
|
|
2413
|
-
children: "Initializing terminal..."
|
|
2414
|
-
});
|
|
2415
|
-
}
|
|
2416
|
-
const handleScrollToBottom = () => {
|
|
2417
|
-
terminalRef.current?.scrollToBottom();
|
|
2418
|
-
};
|
|
2419
|
-
const handleToggleScrollLock = () => {
|
|
2420
|
-
if (scrollPosition.isScrollLocked) {
|
|
2421
|
-
const terminal = terminalRef.current?.getTerminal();
|
|
2422
|
-
if (terminal) {
|
|
2423
|
-
terminal.scrollLines(-1);
|
|
2424
|
-
}
|
|
2425
|
-
} else {
|
|
2426
|
-
terminalRef.current?.scrollToBottom();
|
|
2427
|
-
}
|
|
2428
|
-
};
|
|
2429
|
-
return /* @__PURE__ */ jsxs7("div", {
|
|
2430
|
-
style: { height: "100%", width: "100%", display: "flex", flexDirection: "column" },
|
|
2431
|
-
children: [
|
|
2432
|
-
/* @__PURE__ */ jsxs7("div", {
|
|
2433
|
-
style: {
|
|
2434
|
-
display: "flex",
|
|
2435
|
-
gap: "8px",
|
|
2436
|
-
padding: "8px 12px",
|
|
2437
|
-
backgroundColor: allowTransparency ? "transparent" : theme.colors.backgroundSecondary,
|
|
2438
|
-
borderBottom: `1px solid ${theme.colors.border}`,
|
|
2439
|
-
alignItems: "center"
|
|
2440
|
-
},
|
|
2441
|
-
children: [
|
|
2442
|
-
/* @__PURE__ */ jsxs7("span", {
|
|
2443
|
-
style: {
|
|
2444
|
-
fontSize: "12px",
|
|
2445
|
-
color: theme.colors.textSecondary,
|
|
2446
|
-
marginRight: "auto",
|
|
2447
|
-
fontFamily: theme.fonts.monospace
|
|
2448
|
-
},
|
|
2449
|
-
children: [
|
|
2450
|
-
sessionInfo?.cwd || "Terminal",
|
|
2451
|
-
" • ",
|
|
2452
|
-
sessionInfo?.shell
|
|
2453
|
-
]
|
|
2454
|
-
}),
|
|
2455
|
-
/* @__PURE__ */ jsxs7("button", {
|
|
2456
|
-
onClick: handleToggleScrollLock,
|
|
2457
|
-
style: {
|
|
2458
|
-
display: "flex",
|
|
2459
|
-
alignItems: "center",
|
|
2460
|
-
gap: "4px",
|
|
2461
|
-
fontSize: "11px",
|
|
2462
|
-
padding: "4px 8px",
|
|
2463
|
-
borderRadius: "4px",
|
|
2464
|
-
backgroundColor: scrollPosition.isScrollLocked ? `${theme.colors.success}22` : `${theme.colors.warning}22`,
|
|
2465
|
-
color: scrollPosition.isScrollLocked ? theme.colors.success : theme.colors.warning,
|
|
2466
|
-
border: `1px solid ${scrollPosition.isScrollLocked ? `${theme.colors.success}44` : `${theme.colors.warning}44`}`,
|
|
2467
|
-
cursor: "pointer",
|
|
2468
|
-
transition: "opacity 0.2s"
|
|
2469
|
-
},
|
|
2470
|
-
onMouseEnter: (e) => e.currentTarget.style.opacity = "0.8",
|
|
2471
|
-
onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
|
|
2472
|
-
title: scrollPosition.isScrollLocked ? "Click to unlock scroll" : "Click to lock scroll to bottom",
|
|
2473
|
-
children: [
|
|
2474
|
-
scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx9(Lock, {
|
|
2475
|
-
size: 12
|
|
2476
|
-
}) : /* @__PURE__ */ jsx9(Unlock, {
|
|
2477
|
-
size: 12
|
|
2478
|
-
}),
|
|
2479
|
-
/* @__PURE__ */ jsx9("span", {
|
|
2480
|
-
children: scrollPosition.isScrollLocked ? "Locked" : "Unlocked"
|
|
2481
|
-
})
|
|
2482
|
-
]
|
|
2483
|
-
}),
|
|
2484
|
-
/* @__PURE__ */ jsxs7("button", {
|
|
2485
|
-
onClick: handleScrollToBottom,
|
|
2486
|
-
disabled: scrollPosition.isAtBottom,
|
|
2487
|
-
style: {
|
|
2488
|
-
display: "flex",
|
|
2489
|
-
alignItems: "center",
|
|
2490
|
-
gap: "4px",
|
|
2491
|
-
fontSize: "11px",
|
|
2492
|
-
padding: "4px 10px",
|
|
2493
|
-
borderRadius: "4px",
|
|
2494
|
-
backgroundColor: scrollPosition.isAtBottom ? theme.colors.backgroundHover : theme.colors.accent,
|
|
2495
|
-
color: scrollPosition.isAtBottom ? theme.colors.textTertiary : theme.colors.text,
|
|
2496
|
-
border: `1px solid ${theme.colors.border}`,
|
|
2497
|
-
cursor: scrollPosition.isAtBottom ? "not-allowed" : "pointer",
|
|
2498
|
-
transition: "opacity 0.2s",
|
|
2499
|
-
opacity: scrollPosition.isAtBottom ? 0.5 : 1
|
|
2500
|
-
},
|
|
2501
|
-
onMouseEnter: (e) => !scrollPosition.isAtBottom && (e.currentTarget.style.opacity = "0.8"),
|
|
2502
|
-
onMouseLeave: (e) => !scrollPosition.isAtBottom && (e.currentTarget.style.opacity = "1"),
|
|
2503
|
-
title: "Scroll to bottom and lock",
|
|
2504
|
-
children: [
|
|
2505
|
-
/* @__PURE__ */ jsx9(ArrowDown, {
|
|
2506
|
-
size: 12
|
|
2507
|
-
}),
|
|
2508
|
-
/* @__PURE__ */ jsx9("span", {
|
|
2509
|
-
children: "Bottom"
|
|
2510
|
-
})
|
|
2511
|
-
]
|
|
2512
|
-
})
|
|
2513
|
-
]
|
|
2514
|
-
}),
|
|
2515
|
-
/* @__PURE__ */ jsx9("div", {
|
|
2516
|
-
style: { flex: 1 },
|
|
2517
|
-
children: /* @__PURE__ */ jsx9(ThemedTerminalWithProvider, {
|
|
2518
|
-
ref: terminalRef,
|
|
2519
|
-
onData: handleTerminalData,
|
|
2520
|
-
onResize: handleTerminalResize,
|
|
2521
|
-
onScrollPositionChange: handleScrollPositionChange,
|
|
2522
|
-
hideHeader: true,
|
|
2523
|
-
autoFocus: true,
|
|
2524
|
-
convertEol: true,
|
|
2525
|
-
cursorBlink: true,
|
|
2526
|
-
scrollback: 1e4,
|
|
2527
|
-
enableSearch: true,
|
|
2528
|
-
enableWebLinks: true,
|
|
2529
|
-
allowTransparency,
|
|
2530
|
-
backgroundColor
|
|
2531
|
-
})
|
|
2532
|
-
})
|
|
2533
|
-
]
|
|
2534
|
-
});
|
|
2535
|
-
};
|
|
2536
2266
|
// src/panels/TabbedTerminalPanel.tsx
|
|
2537
|
-
import { useTheme as
|
|
2267
|
+
import { useTheme as useTheme6 } from "@principal-ade/industry-theme";
|
|
2538
2268
|
import { CollapsibleSplitPane } from "@principal-ade/panels";
|
|
2539
|
-
import { Terminal as TerminalIcon2, Lock
|
|
2269
|
+
import { Terminal as TerminalIcon2, Lock, Unlock, Box, Boxes, Paperclip } from "lucide-react";
|
|
2540
2270
|
import React3, {
|
|
2541
|
-
useState as
|
|
2542
|
-
useCallback as
|
|
2543
|
-
useEffect as
|
|
2544
|
-
useRef as
|
|
2271
|
+
useState as useState4,
|
|
2272
|
+
useCallback as useCallback5,
|
|
2273
|
+
useEffect as useEffect4,
|
|
2274
|
+
useRef as useRef4
|
|
2545
2275
|
} from "react";
|
|
2546
|
-
import { jsx as
|
|
2547
|
-
var ActivityIndicator = ({ color, isAnimating }) => /* @__PURE__ */
|
|
2276
|
+
import { jsx as jsx9, jsxs as jsxs7, Fragment as Fragment2 } from "react/jsx-runtime";
|
|
2277
|
+
var ActivityIndicator = ({ color, isAnimating }) => /* @__PURE__ */ jsxs7("div", {
|
|
2548
2278
|
style: { display: "flex", gap: 1, alignItems: "center", height: 12 },
|
|
2549
2279
|
children: [
|
|
2550
|
-
[0, 1, 2, 3, 4].map((i) => /* @__PURE__ */
|
|
2280
|
+
[0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx9("div", {
|
|
2551
2281
|
style: {
|
|
2552
2282
|
width: 2,
|
|
2553
2283
|
height: 10,
|
|
@@ -2558,7 +2288,7 @@ var ActivityIndicator = ({ color, isAnimating }) => /* @__PURE__ */ jsxs8("div",
|
|
|
2558
2288
|
animation: isAnimating ? `waveSine 1.2s ease-in-out ${i * 0.1}s infinite` : "none"
|
|
2559
2289
|
}
|
|
2560
2290
|
}, i)),
|
|
2561
|
-
/* @__PURE__ */
|
|
2291
|
+
/* @__PURE__ */ jsx9("style", {
|
|
2562
2292
|
children: `
|
|
2563
2293
|
@keyframes waveSine {
|
|
2564
2294
|
0%, 100% { transform: scaleY(0.4); }
|
|
@@ -2569,376 +2299,69 @@ var ActivityIndicator = ({ color, isAnimating }) => /* @__PURE__ */ jsxs8("div",
|
|
|
2569
2299
|
]
|
|
2570
2300
|
});
|
|
2571
2301
|
function TerminalTabContentInner(props, ref) {
|
|
2572
|
-
const {
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
}
|
|
2594
|
-
setShouldRenderTerminal(true);
|
|
2595
|
-
setOwnerWindowId(null);
|
|
2596
|
-
if (force) {
|
|
2597
|
-
needsRefreshOnResizeRef.current = true;
|
|
2598
|
-
}
|
|
2599
|
-
} catch (error) {
|
|
2600
|
-
console.error("[TerminalTabContent] Failed to claim ownership:", error);
|
|
2601
|
-
throw error;
|
|
2602
|
-
}
|
|
2603
|
-
}, [actions]);
|
|
2604
|
-
useEffect5(() => {
|
|
2605
|
-
if (hasInitializedRef.current) {
|
|
2606
|
-
return;
|
|
2607
|
-
}
|
|
2608
|
-
hasInitializedRef.current = true;
|
|
2609
|
-
let mounted = true;
|
|
2610
|
-
const initSession = async () => {
|
|
2611
|
-
try {
|
|
2612
|
-
if (sessionId) {
|
|
2613
|
-
const tracer2 = getTracer();
|
|
2614
|
-
const reconnectSpan = tracer2.startSpan("terminal.session.reconnect", {
|
|
2615
|
-
attributes: {
|
|
2616
|
-
"session.id": sessionId,
|
|
2617
|
-
"session.context": `${terminalContext}:${tab.id}`,
|
|
2618
|
-
"session.isForeign": isForeign
|
|
2619
|
-
}
|
|
2620
|
-
});
|
|
2621
|
-
reconnectSpan.addEvent("terminal.session.reconnecting", {
|
|
2622
|
-
"session.id": sessionId,
|
|
2623
|
-
"reconnect.reason": "component_remount"
|
|
2624
|
-
});
|
|
2625
|
-
if (isForeign && actions.checkTerminalOwnership) {
|
|
2626
|
-
const status = await actions.checkTerminalOwnership(sessionId);
|
|
2627
|
-
if (status.ownedByWindowId && !status.ownedByThisWindow) {
|
|
2628
|
-
setShouldRenderTerminal(false);
|
|
2629
|
-
setOwnerWindowId(status.ownedByWindowId);
|
|
2630
|
-
reconnectSpan.addEvent("terminal.session.reconnect_blocked", {
|
|
2631
|
-
"session.id": sessionId,
|
|
2632
|
-
"owner.windowId": status.ownedByWindowId
|
|
2633
|
-
});
|
|
2634
|
-
}
|
|
2635
|
-
} else {
|
|
2636
|
-
await claimAndConnect(sessionId);
|
|
2637
|
-
reconnectSpan.addEvent("terminal.session.reconnected", {
|
|
2638
|
-
"session.id": sessionId
|
|
2639
|
-
});
|
|
2640
|
-
}
|
|
2641
|
-
reconnectSpan.setStatus({ code: SpanStatusCode.OK });
|
|
2642
|
-
reconnectSpan.end();
|
|
2643
|
-
setLocalSessionId(sessionId);
|
|
2644
|
-
setIsInitialized(true);
|
|
2645
|
-
return;
|
|
2646
|
-
}
|
|
2647
|
-
if (!actions.createTerminalSession) {
|
|
2648
|
-
return;
|
|
2649
|
-
}
|
|
2650
|
-
const newSessionId = await actions.createTerminalSession({
|
|
2651
|
-
cwd: tab.directory,
|
|
2652
|
-
command: tab.command,
|
|
2653
|
-
context: `${terminalContext}:${tab.id}`
|
|
2654
|
-
});
|
|
2655
|
-
if (!mounted)
|
|
2656
|
-
return;
|
|
2657
|
-
const tracer = getTracer();
|
|
2658
|
-
const span = tracer.startSpan("terminal.session", {
|
|
2659
|
-
attributes: {
|
|
2660
|
-
"session.id": newSessionId,
|
|
2661
|
-
"session.cwd": tab.directory,
|
|
2662
|
-
"session.context": `${terminalContext}:${tab.id}`
|
|
2663
|
-
}
|
|
2664
|
-
});
|
|
2665
|
-
span.addEvent("terminal.session.created", {
|
|
2666
|
-
"session.id": newSessionId,
|
|
2667
|
-
"session.cwd": tab.directory
|
|
2668
|
-
});
|
|
2669
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
2670
|
-
span.end();
|
|
2671
|
-
setLocalSessionId(newSessionId);
|
|
2672
|
-
setIsInitialized(true);
|
|
2673
|
-
onSessionCreated(tab.id, newSessionId);
|
|
2674
|
-
await claimAndConnect(newSessionId);
|
|
2675
|
-
} catch (error) {
|
|
2676
|
-
console.error("[TerminalTabContent] Failed to create session:", error);
|
|
2677
|
-
const tracer = getTracer();
|
|
2678
|
-
const span = tracer.startSpan("terminal.session", {
|
|
2679
|
-
attributes: {
|
|
2680
|
-
"session.action": "create",
|
|
2681
|
-
"error.occurred": true
|
|
2682
|
-
}
|
|
2683
|
-
});
|
|
2684
|
-
span.addEvent("terminal.session.error", {
|
|
2685
|
-
"error.message": error instanceof Error ? error.message : "Unknown error"
|
|
2686
|
-
});
|
|
2687
|
-
span.recordException(error);
|
|
2688
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message: "Session creation failed" });
|
|
2689
|
-
span.end();
|
|
2690
|
-
}
|
|
2691
|
-
};
|
|
2692
|
-
initSession();
|
|
2693
|
-
return () => {
|
|
2694
|
-
mounted = false;
|
|
2695
|
-
};
|
|
2696
|
-
}, []);
|
|
2697
|
-
useEffect5(() => {
|
|
2698
|
-
if (!localSessionId || !isInitialized || !shouldRenderTerminal) {
|
|
2699
|
-
return;
|
|
2700
|
-
}
|
|
2701
|
-
if (!actions.onTerminalData) {
|
|
2702
|
-
return;
|
|
2703
|
-
}
|
|
2704
|
-
const tracer = getTracer();
|
|
2705
|
-
const subscribeSpan = tracer.startSpan("terminal.data.subscribe", {
|
|
2706
|
-
attributes: {
|
|
2707
|
-
"session.id": localSessionId,
|
|
2708
|
-
"tab.id": tab.id
|
|
2709
|
-
}
|
|
2710
|
-
});
|
|
2711
|
-
subscribeSpan.addEvent("terminal.data.subscribed", {
|
|
2712
|
-
"session.id": localSessionId
|
|
2713
|
-
});
|
|
2714
|
-
console.log("[TerminalTabContent] SUBSCRIBING to terminal data", { tabId: tab.id, sessionId: localSessionId });
|
|
2715
|
-
let hasReceivedData = false;
|
|
2716
|
-
const unsubscribe = actions.onTerminalData(localSessionId, (data) => {
|
|
2717
|
-
if (terminalRef.current) {
|
|
2718
|
-
if (!hasReceivedData) {
|
|
2719
|
-
hasReceivedData = true;
|
|
2720
|
-
subscribeSpan.addEvent("terminal.data.first_received", {
|
|
2721
|
-
"session.id": localSessionId,
|
|
2722
|
-
"data.length": data.length
|
|
2723
|
-
});
|
|
2724
|
-
}
|
|
2725
|
-
terminalRef.current.write(data);
|
|
2726
|
-
}
|
|
2727
|
-
});
|
|
2728
|
-
subscribeSpan.setStatus({ code: SpanStatusCode.OK });
|
|
2729
|
-
subscribeSpan.end();
|
|
2730
|
-
return () => {
|
|
2731
|
-
const unsubscribeSpan = tracer.startSpan("terminal.data.unsubscribe", {
|
|
2732
|
-
attributes: {
|
|
2733
|
-
"session.id": localSessionId,
|
|
2734
|
-
"tab.id": tab.id,
|
|
2735
|
-
"data.wasReceived": hasReceivedData
|
|
2736
|
-
}
|
|
2737
|
-
});
|
|
2738
|
-
unsubscribeSpan.addEvent("terminal.data.unsubscribed", {
|
|
2739
|
-
"session.id": localSessionId
|
|
2740
|
-
});
|
|
2741
|
-
unsubscribeSpan.setStatus({ code: SpanStatusCode.OK });
|
|
2742
|
-
unsubscribeSpan.end();
|
|
2743
|
-
console.log("[TerminalTabContent] UNSUBSCRIBING from terminal data", { tabId: tab.id, sessionId: localSessionId });
|
|
2744
|
-
unsubscribe();
|
|
2745
|
-
};
|
|
2746
|
-
}, [localSessionId, isInitialized, actions, shouldRenderTerminal, tab.id]);
|
|
2747
|
-
const handleData = useCallback6((data) => {
|
|
2748
|
-
if (localSessionId && actions.writeToTerminal) {
|
|
2749
|
-
actions.writeToTerminal(localSessionId, data);
|
|
2750
|
-
}
|
|
2751
|
-
}, [localSessionId, actions]);
|
|
2752
|
-
const handleResize = useCallback6((cols, rows) => {
|
|
2753
|
-
if (localSessionId && actions.resizeTerminal) {
|
|
2754
|
-
actions.resizeTerminal(localSessionId, cols, rows);
|
|
2755
|
-
}
|
|
2756
|
-
}, [localSessionId, actions]);
|
|
2757
|
-
const handleReady = useCallback6((cols, rows) => {
|
|
2758
|
-
if (!localSessionId || !actions.resizeTerminal) {
|
|
2759
|
-
return;
|
|
2760
|
-
}
|
|
2761
|
-
const shouldForce = needsRefreshOnResizeRef.current;
|
|
2762
|
-
if (!shouldForce) {
|
|
2763
|
-
actions.resizeTerminal(localSessionId, cols, rows, false);
|
|
2764
|
-
return;
|
|
2765
|
-
}
|
|
2766
|
-
needsRefreshOnResizeRef.current = false;
|
|
2767
|
-
const restoreBufferAndResize = async () => {
|
|
2768
|
-
let bufferRestored = false;
|
|
2769
|
-
if (actions.getTerminalBuffer && terminalRef.current) {
|
|
2770
|
-
try {
|
|
2771
|
-
const buffer = await actions.getTerminalBuffer(localSessionId);
|
|
2772
|
-
if (buffer) {
|
|
2773
|
-
terminalRef.current.write(buffer);
|
|
2774
|
-
bufferRestored = true;
|
|
2775
|
-
}
|
|
2776
|
-
} catch (error) {
|
|
2777
|
-
console.warn("[TabbedTerminalPanel] Failed to restore buffer:", error);
|
|
2778
|
-
}
|
|
2779
|
-
}
|
|
2780
|
-
const forceResize = !bufferRestored;
|
|
2781
|
-
actions.resizeTerminal(localSessionId, cols, rows, forceResize);
|
|
2782
|
-
};
|
|
2783
|
-
restoreBufferAndResize();
|
|
2784
|
-
}, [localSessionId, actions]);
|
|
2785
|
-
const handleLinkClick = useCallback6((url, modifiers) => {
|
|
2786
|
-
if (localSessionId) {
|
|
2787
|
-
events.emit({
|
|
2788
|
-
type: "terminal:link-click",
|
|
2789
|
-
source: "TabbedTerminalPanel",
|
|
2790
|
-
timestamp: Date.now(),
|
|
2791
|
-
payload: {
|
|
2792
|
-
url,
|
|
2793
|
-
sessionId: localSessionId,
|
|
2794
|
-
shiftKey: modifiers.shiftKey,
|
|
2795
|
-
metaKey: modifiers.metaKey,
|
|
2796
|
-
ctrlKey: modifiers.ctrlKey,
|
|
2797
|
-
altKey: modifiers.altKey
|
|
2798
|
-
}
|
|
2799
|
-
});
|
|
2800
|
-
}
|
|
2801
|
-
}, [localSessionId, events]);
|
|
2802
|
-
useEffect5(() => {
|
|
2803
|
-
if (!localSessionId || !actions.onOwnershipLost) {
|
|
2804
|
-
return;
|
|
2805
|
-
}
|
|
2806
|
-
const unsubscribe = actions.onOwnershipLost((data) => {
|
|
2807
|
-
if (data.sessionId === localSessionId) {
|
|
2808
|
-
setShouldRenderTerminal(false);
|
|
2809
|
-
setOwnerWindowId(data.newOwnerWindowId);
|
|
2810
|
-
}
|
|
2811
|
-
});
|
|
2812
|
-
return () => {
|
|
2813
|
-
unsubscribe();
|
|
2814
|
-
};
|
|
2815
|
-
}, [localSessionId, actions]);
|
|
2816
|
-
const handleTakeControl = useCallback6(async () => {
|
|
2817
|
-
if (!localSessionId) {
|
|
2818
|
-
return;
|
|
2819
|
-
}
|
|
2820
|
-
await claimAndConnect(localSessionId, true);
|
|
2821
|
-
}, [localSessionId, claimAndConnect]);
|
|
2822
|
-
const handleScrollPositionChange = useCallback6((position) => {
|
|
2823
|
-
setScrollPosition(position);
|
|
2302
|
+
const {
|
|
2303
|
+
tab,
|
|
2304
|
+
sessionId,
|
|
2305
|
+
isActive,
|
|
2306
|
+
isVisible,
|
|
2307
|
+
actions,
|
|
2308
|
+
events,
|
|
2309
|
+
terminalContext,
|
|
2310
|
+
onSessionCreated,
|
|
2311
|
+
onScrollPositionChange,
|
|
2312
|
+
isForeign = false,
|
|
2313
|
+
defaultScrollLocked,
|
|
2314
|
+
activityDetection = true,
|
|
2315
|
+
activityTimeout = 500,
|
|
2316
|
+
autoShowBlinds = false,
|
|
2317
|
+
onActivityStateChange
|
|
2318
|
+
} = props;
|
|
2319
|
+
const [isWorkingFromActivity, setIsWorkingFromActivity] = useState4(false);
|
|
2320
|
+
const sessionRef = useRef4(null);
|
|
2321
|
+
const handleSessionCreated = useCallback5((sid) => onSessionCreated(tab.id, sid), [onSessionCreated, tab.id]);
|
|
2322
|
+
const handleScrollPositionChange = useCallback5((position) => {
|
|
2824
2323
|
onScrollPositionChange?.(tab.id, position);
|
|
2825
|
-
}, [tab.id
|
|
2826
|
-
const
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
source: "TabbedTerminalPanel",
|
|
2831
|
-
timestamp: Date.now(),
|
|
2832
|
-
payload: {
|
|
2833
|
-
shortcut: shortcutEvent.shortcut,
|
|
2834
|
-
sessionId: localSessionId
|
|
2835
|
-
}
|
|
2836
|
-
});
|
|
2324
|
+
}, [onScrollPositionChange, tab.id]);
|
|
2325
|
+
const handleActivityChange = useCallback5((state) => {
|
|
2326
|
+
const sid = sessionRef.current?.getSessionId();
|
|
2327
|
+
if (sid) {
|
|
2328
|
+
onActivityStateChange?.(sid, state.isActive);
|
|
2837
2329
|
}
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
if (localSessionId) {
|
|
2841
|
-
onActivityStateChange?.(localSessionId, state.isActive);
|
|
2842
|
-
events.emit({
|
|
2843
|
-
type: "terminal:activity-changed",
|
|
2844
|
-
source: "TabbedTerminalPanel",
|
|
2845
|
-
timestamp: Date.now(),
|
|
2846
|
-
payload: {
|
|
2847
|
-
sessionId: localSessionId,
|
|
2848
|
-
activityType: state.isActive ? "started" : "stopped",
|
|
2849
|
-
isWorking: state.isActive
|
|
2850
|
-
}
|
|
2851
|
-
});
|
|
2330
|
+
if (autoShowBlinds) {
|
|
2331
|
+
setIsWorkingFromActivity(state.isActive);
|
|
2852
2332
|
}
|
|
2853
|
-
}, [
|
|
2854
|
-
const handleScrollToBottom = useCallback6(() => {
|
|
2855
|
-
terminalRef.current?.scrollToBottom();
|
|
2856
|
-
}, []);
|
|
2857
|
-
const handleToggleScrollLock = useCallback6(() => {
|
|
2858
|
-
if (scrollPosition.isScrollLocked) {
|
|
2859
|
-
const terminal = terminalRef.current?.getTerminal();
|
|
2860
|
-
if (terminal) {
|
|
2861
|
-
terminal.scrollLines(-1);
|
|
2862
|
-
}
|
|
2863
|
-
} else {
|
|
2864
|
-
terminalRef.current?.scrollToBottom();
|
|
2865
|
-
}
|
|
2866
|
-
}, [scrollPosition.isScrollLocked]);
|
|
2333
|
+
}, [autoShowBlinds, onActivityStateChange]);
|
|
2867
2334
|
React3.useImperativeHandle(ref, () => ({
|
|
2868
|
-
scrollToBottom:
|
|
2869
|
-
toggleScrollLock:
|
|
2870
|
-
}), [
|
|
2871
|
-
|
|
2872
|
-
return /* @__PURE__ */ jsxs8("div", {
|
|
2873
|
-
style: {
|
|
2874
|
-
display: isActive ? "flex" : "none",
|
|
2875
|
-
height: "100%",
|
|
2876
|
-
width: "100%",
|
|
2877
|
-
backgroundColor: theme.colors.background,
|
|
2878
|
-
padding: "10px 0 0 10px"
|
|
2879
|
-
},
|
|
2880
|
-
children: [
|
|
2881
|
-
/* @__PURE__ */ jsx10("div", {
|
|
2882
|
-
style: {
|
|
2883
|
-
width: "8px",
|
|
2884
|
-
height: "17px",
|
|
2885
|
-
backgroundColor: theme.colors.text,
|
|
2886
|
-
animation: "blink 1s step-end infinite"
|
|
2887
|
-
}
|
|
2888
|
-
}),
|
|
2889
|
-
/* @__PURE__ */ jsx10("style", {
|
|
2890
|
-
children: `
|
|
2891
|
-
@keyframes blink {
|
|
2892
|
-
0%, 100% { opacity: 1; }
|
|
2893
|
-
50% { opacity: 0; }
|
|
2894
|
-
}
|
|
2895
|
-
`
|
|
2896
|
-
})
|
|
2897
|
-
]
|
|
2898
|
-
});
|
|
2899
|
-
}
|
|
2900
|
-
const overlayState = !shouldRenderTerminal ? {
|
|
2901
|
-
message: "This terminal is active in another window",
|
|
2902
|
-
subtitle: ownerWindowId ? `Window ID: ${ownerWindowId}` : "Another window owns this terminal session",
|
|
2903
|
-
actions: [
|
|
2904
|
-
{
|
|
2905
|
-
label: "Take Control",
|
|
2906
|
-
onClick: handleTakeControl,
|
|
2907
|
-
primary: true
|
|
2908
|
-
}
|
|
2909
|
-
],
|
|
2910
|
-
opacity: 1
|
|
2911
|
-
} : undefined;
|
|
2912
|
-
return /* @__PURE__ */ jsx10("div", {
|
|
2335
|
+
scrollToBottom: () => sessionRef.current?.scrollToBottom(),
|
|
2336
|
+
toggleScrollLock: () => sessionRef.current?.toggleScrollLock()
|
|
2337
|
+
}), []);
|
|
2338
|
+
return /* @__PURE__ */ jsx9("div", {
|
|
2913
2339
|
style: {
|
|
2914
|
-
display:
|
|
2340
|
+
display: "flex",
|
|
2915
2341
|
flexDirection: "column",
|
|
2916
2342
|
height: "100%",
|
|
2917
2343
|
width: "100%"
|
|
2918
2344
|
},
|
|
2919
|
-
children: /* @__PURE__ */
|
|
2920
|
-
ref:
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
defaultScrollLocked,
|
|
2931
|
-
convertEol: true,
|
|
2932
|
-
cursorBlink: shouldRenderTerminal,
|
|
2933
|
-
scrollback: 1e4,
|
|
2934
|
-
enableSearch: true,
|
|
2345
|
+
children: /* @__PURE__ */ jsx9(TerminalSession, {
|
|
2346
|
+
ref: sessionRef,
|
|
2347
|
+
actions,
|
|
2348
|
+
events,
|
|
2349
|
+
sessionId,
|
|
2350
|
+
onSessionCreated: handleSessionCreated,
|
|
2351
|
+
cwd: tab.directory,
|
|
2352
|
+
command: tab.command,
|
|
2353
|
+
sessionContext: `${terminalContext}:${tab.id}`,
|
|
2354
|
+
enableOwnership: true,
|
|
2355
|
+
isForeign,
|
|
2935
2356
|
activityDetection,
|
|
2936
2357
|
activityTimeout,
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2358
|
+
onActivityChange: handleActivityChange,
|
|
2359
|
+
onScrollPositionChange: handleScrollPositionChange,
|
|
2360
|
+
defaultScrollLocked,
|
|
2361
|
+
autoFocus: isActive,
|
|
2362
|
+
isVisible: isVisible && isActive,
|
|
2363
|
+
isWorking: autoShowBlinds && isWorkingFromActivity
|
|
2364
|
+
})
|
|
2942
2365
|
});
|
|
2943
2366
|
}
|
|
2944
2367
|
var areTerminalTabContentPropsEqual = (prevProps, nextProps) => {
|
|
@@ -3005,11 +2428,11 @@ var TabbedTerminalPanelInner = ({
|
|
|
3005
2428
|
onTabAssociate: onTabAssociateProp,
|
|
3006
2429
|
onTabDissociate: _onTabDissociate
|
|
3007
2430
|
}) => {
|
|
3008
|
-
const { theme } =
|
|
2431
|
+
const { theme } = useTheme6();
|
|
3009
2432
|
const onTabAssociate = actions.onTabAssociate ?? onTabAssociateProp;
|
|
3010
|
-
const [ownedTabs, setOwnedTabs] =
|
|
3011
|
-
const [foreignTabs, setForeignTabs] =
|
|
3012
|
-
const [internalActiveTabId, setInternalActiveTabId] =
|
|
2433
|
+
const [ownedTabs, setOwnedTabs] = useState4(initialTabs);
|
|
2434
|
+
const [foreignTabs, setForeignTabs] = useState4([]);
|
|
2435
|
+
const [internalActiveTabId, setInternalActiveTabId] = useState4(null);
|
|
3013
2436
|
const isControlled = activeTabIdProp !== undefined;
|
|
3014
2437
|
const activeTabId = isControlled ? activeTabIdProp : internalActiveTabId;
|
|
3015
2438
|
const setActiveTabId = React3.useCallback((tabId) => {
|
|
@@ -3020,20 +2443,20 @@ var TabbedTerminalPanelInner = ({
|
|
|
3020
2443
|
onActiveTabChange?.(tabId);
|
|
3021
2444
|
}
|
|
3022
2445
|
}, [isControlled, onActiveTabChange]);
|
|
3023
|
-
const [activatedTabs, setActivatedTabs] =
|
|
2446
|
+
const [activatedTabs, setActivatedTabs] = useState4(() => new Set);
|
|
3024
2447
|
React3.useEffect(() => {
|
|
3025
2448
|
if (activeTabId && !activatedTabs.has(activeTabId)) {
|
|
3026
2449
|
setActivatedTabs((prev) => new Set(prev).add(activeTabId));
|
|
3027
2450
|
}
|
|
3028
2451
|
}, [activeTabId, activatedTabs]);
|
|
3029
|
-
const [sessionIds, setSessionIds] =
|
|
3030
|
-
const [scrollPositions, setScrollPositions] =
|
|
3031
|
-
const [activityStates, setActivityStates] =
|
|
2452
|
+
const [sessionIds, setSessionIds] = useState4(new Map);
|
|
2453
|
+
const [scrollPositions, setScrollPositions] = useState4(new Map);
|
|
2454
|
+
const [activityStates, setActivityStates] = useState4(new Map);
|
|
3032
2455
|
const customTabsKey = React3.useMemo(() => {
|
|
3033
2456
|
const customTabs = initialTabs.filter((tab) => tab.contentType !== "terminal");
|
|
3034
2457
|
return JSON.stringify(customTabs);
|
|
3035
2458
|
}, [initialTabs]);
|
|
3036
|
-
|
|
2459
|
+
useEffect4(() => {
|
|
3037
2460
|
const customTabsFromProp = initialTabs.filter((tab) => tab.contentType !== "terminal");
|
|
3038
2461
|
setOwnedTabs((prevTabs) => {
|
|
3039
2462
|
const existingTerminalTabs = prevTabs.filter((tab) => tab.contentType === "terminal");
|
|
@@ -3054,7 +2477,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3054
2477
|
return mergedTabs;
|
|
3055
2478
|
});
|
|
3056
2479
|
}, [customTabsKey]);
|
|
3057
|
-
|
|
2480
|
+
useEffect4(() => {
|
|
3058
2481
|
if (!requestFocusTabId) {
|
|
3059
2482
|
return;
|
|
3060
2483
|
}
|
|
@@ -3069,7 +2492,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3069
2492
|
onFocusTabHandled?.();
|
|
3070
2493
|
}
|
|
3071
2494
|
}, [requestFocusTabId, ownedTabs, foreignTabs, setActiveTabId, onFocusTabHandled, activeTabId]);
|
|
3072
|
-
const getOwnedTabLabel =
|
|
2495
|
+
const getOwnedTabLabel = useCallback5((index, _directory) => {
|
|
3073
2496
|
if (tabLabelPrefix) {
|
|
3074
2497
|
return `${tabLabelPrefix} ${index + 1}`;
|
|
3075
2498
|
}
|
|
@@ -3095,9 +2518,9 @@ var TabbedTerminalPanelInner = ({
|
|
|
3095
2518
|
}
|
|
3096
2519
|
}));
|
|
3097
2520
|
}, [tabs]);
|
|
3098
|
-
const tabRefsMap =
|
|
3099
|
-
const refCallbacksMap =
|
|
3100
|
-
const getRefCallback =
|
|
2521
|
+
const tabRefsMap = useRef4(new Map);
|
|
2522
|
+
const refCallbacksMap = useRef4(new Map);
|
|
2523
|
+
const getRefCallback = useCallback5((tabId) => {
|
|
3101
2524
|
let callback = refCallbacksMap.current.get(tabId);
|
|
3102
2525
|
if (!callback) {
|
|
3103
2526
|
callback = (ref) => {
|
|
@@ -3111,10 +2534,10 @@ var TabbedTerminalPanelInner = ({
|
|
|
3111
2534
|
}
|
|
3112
2535
|
return callback;
|
|
3113
2536
|
}, []);
|
|
3114
|
-
const hasInitializedRef =
|
|
3115
|
-
const isCreatingTabRef =
|
|
3116
|
-
const headerRef =
|
|
3117
|
-
const handleTabScrollPositionChange =
|
|
2537
|
+
const hasInitializedRef = useRef4(false);
|
|
2538
|
+
const isCreatingTabRef = useRef4(false);
|
|
2539
|
+
const headerRef = useRef4(null);
|
|
2540
|
+
const handleTabScrollPositionChange = useCallback5((tabId, position) => {
|
|
3118
2541
|
setScrollPositions((prev) => new Map(prev).set(tabId, position));
|
|
3119
2542
|
}, []);
|
|
3120
2543
|
const defaultScrollPosition = {
|
|
@@ -3122,12 +2545,12 @@ var TabbedTerminalPanelInner = ({
|
|
|
3122
2545
|
isAtBottom: true,
|
|
3123
2546
|
isScrollLocked: false
|
|
3124
2547
|
};
|
|
3125
|
-
const handleToggleScrollLock =
|
|
2548
|
+
const handleToggleScrollLock = useCallback5(() => {
|
|
3126
2549
|
if (activeTabId) {
|
|
3127
2550
|
tabRefsMap.current.get(activeTabId)?.toggleScrollLock();
|
|
3128
2551
|
}
|
|
3129
2552
|
}, [activeTabId]);
|
|
3130
|
-
const restoreOwnedSessions =
|
|
2553
|
+
const restoreOwnedSessions = useCallback5(async () => {
|
|
3131
2554
|
try {
|
|
3132
2555
|
let sessions = [];
|
|
3133
2556
|
if (actions.listTerminalSessions) {
|
|
@@ -3179,7 +2602,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3179
2602
|
console.error("[TabbedTerminalPanel] Failed to restore owned sessions:", err);
|
|
3180
2603
|
}
|
|
3181
2604
|
}, [terminalContext, sessionIds, activeTabId, onTabsChange, actions, directory, setActiveTabId]);
|
|
3182
|
-
const fetchForeignSessions =
|
|
2605
|
+
const fetchForeignSessions = useCallback5(async () => {
|
|
3183
2606
|
try {
|
|
3184
2607
|
if (!actions.listTerminalSessions) {
|
|
3185
2608
|
return;
|
|
@@ -3211,7 +2634,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3211
2634
|
console.error("[TabbedTerminalPanel] Failed to fetch foreign sessions:", err);
|
|
3212
2635
|
}
|
|
3213
2636
|
}, [terminalContext, actions]);
|
|
3214
|
-
const clearForeignTabs =
|
|
2637
|
+
const clearForeignTabs = useCallback5(() => {
|
|
3215
2638
|
setForeignTabs((prevForeign) => {
|
|
3216
2639
|
const foreignTabIds = new Set(prevForeign.map((t) => t.id));
|
|
3217
2640
|
setSessionIds((prev) => {
|
|
@@ -3222,13 +2645,13 @@ var TabbedTerminalPanelInner = ({
|
|
|
3222
2645
|
return [];
|
|
3223
2646
|
});
|
|
3224
2647
|
}, []);
|
|
3225
|
-
|
|
2648
|
+
useEffect4(() => {
|
|
3226
2649
|
if (hasInitializedRef.current)
|
|
3227
2650
|
return;
|
|
3228
2651
|
hasInitializedRef.current = true;
|
|
3229
2652
|
restoreOwnedSessions();
|
|
3230
2653
|
}, []);
|
|
3231
|
-
|
|
2654
|
+
useEffect4(() => {
|
|
3232
2655
|
const handleSessionCreated2 = (event) => {
|
|
3233
2656
|
const customEvent = event;
|
|
3234
2657
|
const { context: context2 } = customEvent.detail || {};
|
|
@@ -3242,17 +2665,17 @@ var TabbedTerminalPanelInner = ({
|
|
|
3242
2665
|
window.removeEventListener("terminal-session-created", handleSessionCreated2);
|
|
3243
2666
|
};
|
|
3244
2667
|
}, [terminalContext, restoreOwnedSessions]);
|
|
3245
|
-
|
|
2668
|
+
useEffect4(() => {
|
|
3246
2669
|
if (showAllTerminals) {
|
|
3247
2670
|
fetchForeignSessions();
|
|
3248
2671
|
} else {
|
|
3249
2672
|
clearForeignTabs();
|
|
3250
2673
|
}
|
|
3251
2674
|
}, [showAllTerminals, fetchForeignSessions, clearForeignTabs]);
|
|
3252
|
-
const switchTab =
|
|
2675
|
+
const switchTab = useCallback5((tabId) => {
|
|
3253
2676
|
setActiveTabId(tabId);
|
|
3254
2677
|
}, [setActiveTabId]);
|
|
3255
|
-
const addNewTab =
|
|
2678
|
+
const addNewTab = useCallback5((label, command, targetDirectory) => {
|
|
3256
2679
|
const targetDir = targetDirectory || directory;
|
|
3257
2680
|
const directoryName = targetDir.split("/").pop() || targetDir;
|
|
3258
2681
|
const newTab = {
|
|
@@ -3270,10 +2693,10 @@ var TabbedTerminalPanelInner = ({
|
|
|
3270
2693
|
});
|
|
3271
2694
|
setActiveTabId(newTab.id);
|
|
3272
2695
|
}, [directory, onTabsChange]);
|
|
3273
|
-
const isForeignTab =
|
|
2696
|
+
const isForeignTab = useCallback5((tabId) => {
|
|
3274
2697
|
return tabId.startsWith("tab-foreign-");
|
|
3275
2698
|
}, []);
|
|
3276
|
-
const closeTab =
|
|
2699
|
+
const closeTab = useCallback5(async (tabId) => {
|
|
3277
2700
|
const sessionId = sessionIds.get(tabId);
|
|
3278
2701
|
const isForeign = isForeignTab(tabId);
|
|
3279
2702
|
if (!isForeign && sessionId && actions.destroyTerminalSession) {
|
|
@@ -3343,10 +2766,10 @@ var TabbedTerminalPanelInner = ({
|
|
|
3343
2766
|
});
|
|
3344
2767
|
}
|
|
3345
2768
|
}, [activeTabId, sessionIds, actions, onTabsChange, isForeignTab, ownedTabs, foreignTabs]);
|
|
3346
|
-
const handleSessionCreated =
|
|
2769
|
+
const handleSessionCreated = useCallback5((tabId, sessionId) => {
|
|
3347
2770
|
setSessionIds((prev) => new Map(prev).set(tabId, sessionId));
|
|
3348
2771
|
}, []);
|
|
3349
|
-
const handleActivityStateChange =
|
|
2772
|
+
const handleActivityStateChange = useCallback5((sessionId, isActive) => {
|
|
3350
2773
|
setActivityStates((prev) => {
|
|
3351
2774
|
const next = new Map(prev);
|
|
3352
2775
|
if (isActive) {
|
|
@@ -3377,7 +2800,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3377
2800
|
}
|
|
3378
2801
|
}
|
|
3379
2802
|
});
|
|
3380
|
-
const renderTabAccessory =
|
|
2803
|
+
const renderTabAccessory = useCallback5((tab) => {
|
|
3381
2804
|
const tabSessionId = sessionIds.get(tab.id);
|
|
3382
2805
|
const hasExternalWorkingState = tabSessionId ? workingStates?.[tabSessionId]?.isWorking : false;
|
|
3383
2806
|
const hasInternalActivity = tabSessionId ? activityStates.get(tabSessionId) : false;
|
|
@@ -3386,9 +2809,9 @@ var TabbedTerminalPanelInner = ({
|
|
|
3386
2809
|
if (!isActive)
|
|
3387
2810
|
return null;
|
|
3388
2811
|
const scrollPosition = scrollPositions.get(tab.id) ?? defaultScrollPosition;
|
|
3389
|
-
return /* @__PURE__ */
|
|
2812
|
+
return /* @__PURE__ */ jsxs7(Fragment2, {
|
|
3390
2813
|
children: [
|
|
3391
|
-
/* @__PURE__ */
|
|
2814
|
+
/* @__PURE__ */ jsx9("button", {
|
|
3392
2815
|
onClick: (e) => {
|
|
3393
2816
|
e.stopPropagation();
|
|
3394
2817
|
handleToggleScrollLock();
|
|
@@ -3413,13 +2836,13 @@ var TabbedTerminalPanelInner = ({
|
|
|
3413
2836
|
e.currentTarget.style.backgroundColor = "transparent";
|
|
3414
2837
|
},
|
|
3415
2838
|
title: scrollPosition.isScrollLocked ? "Scroll locked" : "Scroll unlocked",
|
|
3416
|
-
children: scrollPosition.isScrollLocked ? /* @__PURE__ */
|
|
2839
|
+
children: scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx9(Lock, {
|
|
3417
2840
|
size: 10
|
|
3418
|
-
}) : /* @__PURE__ */
|
|
2841
|
+
}) : /* @__PURE__ */ jsx9(Unlock, {
|
|
3419
2842
|
size: 10
|
|
3420
2843
|
})
|
|
3421
2844
|
}),
|
|
3422
|
-
/* @__PURE__ */
|
|
2845
|
+
/* @__PURE__ */ jsx9("div", {
|
|
3423
2846
|
style: {
|
|
3424
2847
|
position: "absolute",
|
|
3425
2848
|
right: "8px",
|
|
@@ -3430,7 +2853,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3430
2853
|
height: "16px"
|
|
3431
2854
|
},
|
|
3432
2855
|
title: isWorking ? "Terminal active" : "Terminal idle",
|
|
3433
|
-
children: /* @__PURE__ */
|
|
2856
|
+
children: /* @__PURE__ */ jsx9(ActivityIndicator, {
|
|
3434
2857
|
color: theme.colors.primary,
|
|
3435
2858
|
isAnimating: isWorking ?? false
|
|
3436
2859
|
})
|
|
@@ -3438,8 +2861,8 @@ var TabbedTerminalPanelInner = ({
|
|
|
3438
2861
|
]
|
|
3439
2862
|
});
|
|
3440
2863
|
}, [activeTabId, scrollPositions, defaultScrollPosition, handleToggleScrollLock, theme, sessionIds, workingStates, activityStates]);
|
|
3441
|
-
const renderTerminalWithAssociation =
|
|
3442
|
-
const terminalContent = /* @__PURE__ */
|
|
2864
|
+
const renderTerminalWithAssociation = useCallback5((tab, isActive, sessionId, association) => {
|
|
2865
|
+
const terminalContent = /* @__PURE__ */ jsx9(TerminalTabContent, {
|
|
3443
2866
|
ref: getRefCallback(tab.id),
|
|
3444
2867
|
tab,
|
|
3445
2868
|
sessionId,
|
|
@@ -3458,7 +2881,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3458
2881
|
onActivityStateChange: handleActivityStateChange
|
|
3459
2882
|
}, `terminal-${tab.id}`);
|
|
3460
2883
|
const hasAssociation = !!association;
|
|
3461
|
-
const secondaryContent = hasAssociation && renderAssociatedContent ? renderAssociatedContent(association.associatedTabId, isActive) : /* @__PURE__ */
|
|
2884
|
+
const secondaryContent = hasAssociation && renderAssociatedContent ? renderAssociatedContent(association.associatedTabId, isActive) : /* @__PURE__ */ jsx9("div", {
|
|
3462
2885
|
style: {
|
|
3463
2886
|
height: "100%",
|
|
3464
2887
|
display: "flex",
|
|
@@ -3470,12 +2893,12 @@ var TabbedTerminalPanelInner = ({
|
|
|
3470
2893
|
},
|
|
3471
2894
|
children: "Drag a tab here to associate it with this terminal"
|
|
3472
2895
|
});
|
|
3473
|
-
const headerConfig = hasAssociation && getAssociatedHeader ? getAssociatedHeader(association.associatedTabId) : { title: "Drop zone", icon: /* @__PURE__ */
|
|
2896
|
+
const headerConfig = hasAssociation && getAssociatedHeader ? getAssociatedHeader(association.associatedTabId) : { title: "Drop zone", icon: /* @__PURE__ */ jsx9(Paperclip, {
|
|
3474
2897
|
size: 14
|
|
3475
2898
|
}) };
|
|
3476
2899
|
const isCollapsed = hasAssociation ? association.collapsed : true;
|
|
3477
2900
|
const handleCollapsedChange = hasAssociation ? (collapsed) => onAssociationCollapsedChange?.(tab.id, collapsed) : undefined;
|
|
3478
|
-
return /* @__PURE__ */
|
|
2901
|
+
return /* @__PURE__ */ jsx9(CollapsibleSplitPane, {
|
|
3479
2902
|
style: { height: "100%" },
|
|
3480
2903
|
primaryContent: terminalContent,
|
|
3481
2904
|
secondaryContent,
|
|
@@ -3506,7 +2929,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3506
2929
|
onAssociationRatioChange,
|
|
3507
2930
|
theme
|
|
3508
2931
|
]);
|
|
3509
|
-
const handleTabDrop =
|
|
2932
|
+
const handleTabDrop = useCallback5((draggedTabId, targetTabId) => {
|
|
3510
2933
|
const draggedTab = tabs.find((t) => t.id === draggedTabId);
|
|
3511
2934
|
const targetTab = tabs.find((t) => t.id === targetTabId);
|
|
3512
2935
|
if (targetTab?.contentType === "terminal" && draggedTab?.contentType !== "terminal") {
|
|
@@ -3514,13 +2937,13 @@ var TabbedTerminalPanelInner = ({
|
|
|
3514
2937
|
setActiveTabId(targetTabId);
|
|
3515
2938
|
}
|
|
3516
2939
|
}, [tabs, onTabAssociate, setActiveTabId]);
|
|
3517
|
-
const canDropOnTab =
|
|
2940
|
+
const canDropOnTab = useCallback5((draggedTabId, targetTabId) => {
|
|
3518
2941
|
const draggedTab = tabs.find((t) => t.id === draggedTabId);
|
|
3519
2942
|
const targetTab = tabs.find((t) => t.id === targetTabId);
|
|
3520
2943
|
return targetTab?.contentType === "terminal" && draggedTab?.contentType !== "terminal";
|
|
3521
2944
|
}, [tabs]);
|
|
3522
|
-
const [isDragOverContent, setIsDragOverContent] =
|
|
3523
|
-
const handleContentDragEnter =
|
|
2945
|
+
const [isDragOverContent, setIsDragOverContent] = useState4(false);
|
|
2946
|
+
const handleContentDragEnter = useCallback5((e) => {
|
|
3524
2947
|
e.preventDefault();
|
|
3525
2948
|
if (activeTabId) {
|
|
3526
2949
|
const activeTab = tabs.find((t) => t.id === activeTabId);
|
|
@@ -3529,13 +2952,13 @@ var TabbedTerminalPanelInner = ({
|
|
|
3529
2952
|
}
|
|
3530
2953
|
}
|
|
3531
2954
|
}, [activeTabId, tabs]);
|
|
3532
|
-
const handleContentDragLeave =
|
|
2955
|
+
const handleContentDragLeave = useCallback5((e) => {
|
|
3533
2956
|
const relatedTarget = e.relatedTarget;
|
|
3534
2957
|
if (!e.currentTarget.contains(relatedTarget)) {
|
|
3535
2958
|
setIsDragOverContent(false);
|
|
3536
2959
|
}
|
|
3537
2960
|
}, []);
|
|
3538
|
-
const handleContentDrop =
|
|
2961
|
+
const handleContentDrop = useCallback5((e) => {
|
|
3539
2962
|
e.preventDefault();
|
|
3540
2963
|
e.stopPropagation();
|
|
3541
2964
|
setIsDragOverContent(false);
|
|
@@ -3550,7 +2973,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3550
2973
|
setActiveTabId(activeTabId);
|
|
3551
2974
|
}
|
|
3552
2975
|
}, [activeTabId, tabs, onTabAssociate, setActiveTabId]);
|
|
3553
|
-
return /* @__PURE__ */
|
|
2976
|
+
return /* @__PURE__ */ jsxs7("div", {
|
|
3554
2977
|
style: {
|
|
3555
2978
|
display: "flex",
|
|
3556
2979
|
flexDirection: "column",
|
|
@@ -3558,15 +2981,15 @@ var TabbedTerminalPanelInner = ({
|
|
|
3558
2981
|
backgroundColor: theme.colors.background
|
|
3559
2982
|
},
|
|
3560
2983
|
children: [
|
|
3561
|
-
!hideHeader && /* @__PURE__ */
|
|
2984
|
+
!hideHeader && /* @__PURE__ */ jsx9("div", {
|
|
3562
2985
|
ref: headerRef,
|
|
3563
|
-
children: /* @__PURE__ */
|
|
2986
|
+
children: /* @__PURE__ */ jsx9(TabBar, {
|
|
3564
2987
|
tabs: genericTabs,
|
|
3565
2988
|
activeTabId,
|
|
3566
2989
|
onTabClick: switchTab,
|
|
3567
2990
|
onTabClose: closeTab,
|
|
3568
2991
|
onNewTab: addNewTab,
|
|
3569
|
-
leftSection: /* @__PURE__ */
|
|
2992
|
+
leftSection: /* @__PURE__ */ jsx9("button", {
|
|
3570
2993
|
onClick: () => onShowAllTerminalsChange?.(!showAllTerminals),
|
|
3571
2994
|
style: {
|
|
3572
2995
|
display: "flex",
|
|
@@ -3591,9 +3014,9 @@ var TabbedTerminalPanelInner = ({
|
|
|
3591
3014
|
}
|
|
3592
3015
|
},
|
|
3593
3016
|
title: showAllTerminals ? "Showing all terminals (click to filter by context)" : "Show all terminals",
|
|
3594
|
-
children: showAllTerminals ? /* @__PURE__ */
|
|
3017
|
+
children: showAllTerminals ? /* @__PURE__ */ jsx9(Boxes, {
|
|
3595
3018
|
size: 14
|
|
3596
|
-
}) : /* @__PURE__ */
|
|
3019
|
+
}) : /* @__PURE__ */ jsx9(Box, {
|
|
3597
3020
|
size: 14
|
|
3598
3021
|
})
|
|
3599
3022
|
}),
|
|
@@ -3606,7 +3029,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
3606
3029
|
canDropOnTab
|
|
3607
3030
|
})
|
|
3608
3031
|
}),
|
|
3609
|
-
/* @__PURE__ */
|
|
3032
|
+
/* @__PURE__ */ jsxs7("div", {
|
|
3610
3033
|
style: {
|
|
3611
3034
|
flex: 1,
|
|
3612
3035
|
display: "flex",
|
|
@@ -3660,62 +3083,71 @@ var TabbedTerminalPanelInner = ({
|
|
|
3660
3083
|
const customContent = renderTabContent(tab, isActive, sessionId, width);
|
|
3661
3084
|
if (customContent === null && tab.contentType === "terminal") {
|
|
3662
3085
|
const association = associations?.[tab.id];
|
|
3663
|
-
return /* @__PURE__ */
|
|
3086
|
+
return /* @__PURE__ */ jsx9("div", {
|
|
3664
3087
|
style: {
|
|
3665
|
-
|
|
3088
|
+
position: "absolute",
|
|
3089
|
+
inset: 0,
|
|
3090
|
+
display: "flex",
|
|
3666
3091
|
flexDirection: "column",
|
|
3667
|
-
|
|
3668
|
-
|
|
3092
|
+
visibility: isActive ? "visible" : "hidden",
|
|
3093
|
+
pointerEvents: isActive ? "auto" : "none"
|
|
3669
3094
|
},
|
|
3670
3095
|
children: renderTerminalWithAssociation(tab, isActive, sessionId, association)
|
|
3671
3096
|
}, tab.id);
|
|
3672
3097
|
}
|
|
3673
3098
|
const hasBeenActivated = activatedTabs.has(tab.id);
|
|
3674
|
-
return /* @__PURE__ */
|
|
3099
|
+
return /* @__PURE__ */ jsx9("div", {
|
|
3675
3100
|
style: {
|
|
3676
|
-
|
|
3101
|
+
position: "absolute",
|
|
3102
|
+
inset: 0,
|
|
3103
|
+
display: "flex",
|
|
3677
3104
|
flexDirection: "column",
|
|
3678
|
-
|
|
3679
|
-
|
|
3105
|
+
visibility: isActive ? "visible" : "hidden",
|
|
3106
|
+
pointerEvents: isActive ? "auto" : "none"
|
|
3680
3107
|
},
|
|
3681
3108
|
children: hasBeenActivated && customContent
|
|
3682
3109
|
}, tab.id);
|
|
3683
3110
|
}
|
|
3684
3111
|
if (tab.contentType === "terminal") {
|
|
3685
3112
|
const association = associations?.[tab.id];
|
|
3686
|
-
return /* @__PURE__ */
|
|
3113
|
+
return /* @__PURE__ */ jsx9("div", {
|
|
3687
3114
|
style: {
|
|
3688
|
-
|
|
3115
|
+
position: "absolute",
|
|
3116
|
+
inset: 0,
|
|
3117
|
+
display: "flex",
|
|
3689
3118
|
flexDirection: "column",
|
|
3690
|
-
|
|
3691
|
-
|
|
3119
|
+
visibility: isActive ? "visible" : "hidden",
|
|
3120
|
+
pointerEvents: isActive ? "auto" : "none"
|
|
3692
3121
|
},
|
|
3693
3122
|
children: renderTerminalWithAssociation(tab, isActive, sessionId, association)
|
|
3694
3123
|
}, tab.id);
|
|
3695
3124
|
}
|
|
3696
|
-
return /* @__PURE__ */
|
|
3125
|
+
return /* @__PURE__ */ jsxs7("div", {
|
|
3697
3126
|
style: {
|
|
3698
|
-
|
|
3127
|
+
position: "absolute",
|
|
3128
|
+
inset: 0,
|
|
3129
|
+
display: "flex",
|
|
3699
3130
|
alignItems: "center",
|
|
3700
3131
|
justifyContent: "center",
|
|
3701
|
-
|
|
3132
|
+
visibility: isActive ? "visible" : "hidden",
|
|
3133
|
+
pointerEvents: isActive ? "auto" : "none",
|
|
3702
3134
|
color: theme.colors.textSecondary
|
|
3703
3135
|
},
|
|
3704
3136
|
children: [
|
|
3705
|
-
/* @__PURE__ */
|
|
3137
|
+
/* @__PURE__ */ jsxs7("p", {
|
|
3706
3138
|
children: [
|
|
3707
3139
|
"Unknown content type: ",
|
|
3708
3140
|
tab.contentType
|
|
3709
3141
|
]
|
|
3710
3142
|
}),
|
|
3711
|
-
/* @__PURE__ */
|
|
3143
|
+
/* @__PURE__ */ jsx9("p", {
|
|
3712
3144
|
style: { fontSize: theme.fontSizes[0], marginTop: "8px" },
|
|
3713
3145
|
children: "Provide a renderTabContent prop to render custom tab types"
|
|
3714
3146
|
})
|
|
3715
3147
|
]
|
|
3716
3148
|
}, tab.id);
|
|
3717
3149
|
}),
|
|
3718
|
-
tabs.length === 0 && /* @__PURE__ */
|
|
3150
|
+
tabs.length === 0 && /* @__PURE__ */ jsxs7("div", {
|
|
3719
3151
|
style: {
|
|
3720
3152
|
display: "flex",
|
|
3721
3153
|
flexDirection: "column",
|
|
@@ -3725,11 +3157,11 @@ var TabbedTerminalPanelInner = ({
|
|
|
3725
3157
|
color: theme.colors.textSecondary
|
|
3726
3158
|
},
|
|
3727
3159
|
children: [
|
|
3728
|
-
/* @__PURE__ */
|
|
3160
|
+
/* @__PURE__ */ jsx9(TerminalIcon2, {
|
|
3729
3161
|
size: 32,
|
|
3730
3162
|
style: { opacity: 0.5, marginBottom: "16px" }
|
|
3731
3163
|
}),
|
|
3732
|
-
/* @__PURE__ */
|
|
3164
|
+
/* @__PURE__ */ jsx9("button", {
|
|
3733
3165
|
onClick: () => addNewTab(),
|
|
3734
3166
|
style: {
|
|
3735
3167
|
marginTop: "16px",
|
|
@@ -3958,33 +3390,43 @@ var terminalPanelToolsMetadata = {
|
|
|
3958
3390
|
};
|
|
3959
3391
|
|
|
3960
3392
|
// src/panel-exports.ts
|
|
3961
|
-
var panels = [
|
|
3962
|
-
{
|
|
3963
|
-
metadata: {
|
|
3964
|
-
id: "com.principal.terminal",
|
|
3965
|
-
name: "Terminal",
|
|
3966
|
-
icon: "terminal",
|
|
3967
|
-
version: "0.1.0",
|
|
3968
|
-
author: "Principal",
|
|
3969
|
-
description: "Integrated terminal emulator with industry theming",
|
|
3970
|
-
slices: ["terminal"],
|
|
3971
|
-
tools: terminalPanelTools
|
|
3972
|
-
},
|
|
3973
|
-
component: TerminalPanel,
|
|
3974
|
-
onMount: async (_context) => {
|
|
3975
|
-
console.log("Terminal Panel mounted for repository:", _context.currentScope.repository?.path);
|
|
3976
|
-
},
|
|
3977
|
-
onUnmount: async (_context) => {
|
|
3978
|
-
console.log("Terminal Panel unmounting");
|
|
3979
|
-
}
|
|
3980
|
-
}
|
|
3981
|
-
];
|
|
3393
|
+
var panels = [];
|
|
3982
3394
|
var onPackageLoad = async () => {
|
|
3983
3395
|
console.log("Panel package loaded - Terminal Panel Extension");
|
|
3984
3396
|
};
|
|
3985
3397
|
var onPackageUnload = async () => {
|
|
3986
3398
|
console.log("Panel package unloading - Terminal Panel Extension");
|
|
3987
3399
|
};
|
|
3400
|
+
// src/panel-types/index.ts
|
|
3401
|
+
function getTerminalSessions(context2) {
|
|
3402
|
+
return context2.terminal?.data ?? [];
|
|
3403
|
+
}
|
|
3404
|
+
function getTerminalSession(context2, sessionId) {
|
|
3405
|
+
const sessions = getTerminalSessions(context2);
|
|
3406
|
+
return sessions.find((s) => s.id === sessionId);
|
|
3407
|
+
}
|
|
3408
|
+
function isTerminalLoading(context2) {
|
|
3409
|
+
return context2.terminal?.loading ?? false;
|
|
3410
|
+
}
|
|
3411
|
+
function getRepositoryPath(context2) {
|
|
3412
|
+
return context2.currentScope.repository?.path ?? null;
|
|
3413
|
+
}
|
|
3414
|
+
function getWorkspacePath(context2) {
|
|
3415
|
+
return context2.currentScope.workspace?.path ?? null;
|
|
3416
|
+
}
|
|
3417
|
+
function getTerminalDirectory(context2, terminalScope = "repository") {
|
|
3418
|
+
switch (terminalScope) {
|
|
3419
|
+
case "workspace":
|
|
3420
|
+
return getWorkspacePath(context2);
|
|
3421
|
+
case "repository":
|
|
3422
|
+
return getRepositoryPath(context2) ?? getWorkspacePath(context2);
|
|
3423
|
+
default:
|
|
3424
|
+
return getRepositoryPath(context2) ?? getWorkspacePath(context2);
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
function getTerminalSlice(context2) {
|
|
3428
|
+
return context2.terminal;
|
|
3429
|
+
}
|
|
3988
3430
|
export {
|
|
3989
3431
|
writeToTerminalTool,
|
|
3990
3432
|
withSpanSync,
|
|
@@ -4019,7 +3461,6 @@ export {
|
|
|
4019
3461
|
ThemedTerminalWithProvider,
|
|
4020
3462
|
ThemedTerminal,
|
|
4021
3463
|
TerminalSession,
|
|
4022
|
-
TerminalPanel,
|
|
4023
3464
|
TerminalOverlay,
|
|
4024
3465
|
TabbedTerminalPanel,
|
|
4025
3466
|
TabButton,
|