@industry-theme/xterm-terminal-panel 0.2.3 → 0.2.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/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +534 -338
- package/dist/src/components/TabBar/TabBar.d.ts +4 -0
- package/dist/src/components/TabBar/TabBar.d.ts.map +1 -0
- package/dist/src/components/TabBar/TabButton.d.ts +4 -0
- package/dist/src/components/TabBar/TabButton.d.ts.map +1 -0
- package/dist/src/components/TabBar/index.d.ts +4 -0
- package/dist/src/components/TabBar/index.d.ts.map +1 -0
- package/dist/src/components/ThemedTerminal.d.ts.map +1 -1
- package/dist/src/hooks/useTabKeyboardShortcuts.d.ts +8 -0
- package/dist/src/hooks/useTabKeyboardShortcuts.d.ts.map +1 -0
- package/dist/src/panel-types/index.d.ts +7 -7
- package/dist/src/panel-types/index.d.ts.map +1 -1
- package/dist/src/panels/TabbedTerminalPanel.d.ts +2 -2
- package/dist/src/panels/TabbedTerminalPanel.d.ts.map +1 -1
- package/dist/src/types/mixed-tab.d.ts +20 -0
- package/dist/src/types/mixed-tab.d.ts.map +1 -0
- package/dist/src/types/tab.d.ts +42 -0
- package/dist/src/types/tab.d.ts.map +1 -0
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -800,10 +800,268 @@ function useThemedTerminal() {
|
|
|
800
800
|
getCSSVariables
|
|
801
801
|
};
|
|
802
802
|
}
|
|
803
|
-
// src/
|
|
803
|
+
// src/components/TabBar/TabBar.tsx
|
|
804
|
+
import { useTheme as useTheme4 } from "@principal-ade/industry-theme";
|
|
805
|
+
import { Plus } from "lucide-react";
|
|
806
|
+
import { useState as useState2 } from "react";
|
|
807
|
+
|
|
808
|
+
// src/components/TabBar/TabButton.tsx
|
|
804
809
|
import { useTheme as useTheme3 } from "@principal-ade/industry-theme";
|
|
810
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
811
|
+
var TabButton = ({
|
|
812
|
+
tab,
|
|
813
|
+
isActive,
|
|
814
|
+
isHovered,
|
|
815
|
+
onMouseEnter,
|
|
816
|
+
onMouseLeave,
|
|
817
|
+
onClick,
|
|
818
|
+
onClose,
|
|
819
|
+
keyboardHint,
|
|
820
|
+
renderAccessory
|
|
821
|
+
}) => {
|
|
822
|
+
const { theme } = useTheme3();
|
|
823
|
+
const showCloseButton = isHovered || isActive;
|
|
824
|
+
const closable = tab.closable !== false;
|
|
825
|
+
return /* @__PURE__ */ jsxs2("div", {
|
|
826
|
+
onMouseEnter,
|
|
827
|
+
onMouseLeave,
|
|
828
|
+
onClick,
|
|
829
|
+
style: {
|
|
830
|
+
display: "flex",
|
|
831
|
+
alignItems: "center",
|
|
832
|
+
justifyContent: "center",
|
|
833
|
+
gap: "6px",
|
|
834
|
+
padding: "6px 8px",
|
|
835
|
+
backgroundColor: isActive ? theme.colors.background : theme.colors.backgroundSecondary,
|
|
836
|
+
cursor: "pointer",
|
|
837
|
+
fontSize: theme.fontSizes[1],
|
|
838
|
+
fontWeight: isActive ? theme.fontWeights.semibold : theme.fontWeights.body,
|
|
839
|
+
fontFamily: theme.fonts.body,
|
|
840
|
+
color: isActive ? theme.colors.text : theme.colors.textSecondary,
|
|
841
|
+
whiteSpace: "nowrap",
|
|
842
|
+
transition: "all 0.2s",
|
|
843
|
+
flex: 1,
|
|
844
|
+
minWidth: 0,
|
|
845
|
+
height: "100%",
|
|
846
|
+
position: "relative",
|
|
847
|
+
boxSizing: "border-box"
|
|
848
|
+
},
|
|
849
|
+
children: [
|
|
850
|
+
closable && showCloseButton && /* @__PURE__ */ jsx3("button", {
|
|
851
|
+
onClick: (e) => {
|
|
852
|
+
e.stopPropagation();
|
|
853
|
+
onClose();
|
|
854
|
+
},
|
|
855
|
+
style: {
|
|
856
|
+
display: "flex",
|
|
857
|
+
alignItems: "center",
|
|
858
|
+
justifyContent: "center",
|
|
859
|
+
width: "16px",
|
|
860
|
+
height: "16px",
|
|
861
|
+
borderRadius: "3px",
|
|
862
|
+
border: "none",
|
|
863
|
+
backgroundColor: "transparent",
|
|
864
|
+
cursor: "pointer",
|
|
865
|
+
color: theme.colors.textSecondary,
|
|
866
|
+
padding: 0,
|
|
867
|
+
position: "absolute",
|
|
868
|
+
left: "8px"
|
|
869
|
+
},
|
|
870
|
+
onMouseEnter: (e) => {
|
|
871
|
+
e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
|
|
872
|
+
},
|
|
873
|
+
onMouseLeave: (e) => {
|
|
874
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
875
|
+
},
|
|
876
|
+
title: "Close (⌘W)",
|
|
877
|
+
children: "×"
|
|
878
|
+
}),
|
|
879
|
+
tab.icon && /* @__PURE__ */ jsx3("div", {
|
|
880
|
+
style: { flexShrink: 0, display: "flex", alignItems: "center" },
|
|
881
|
+
children: tab.icon
|
|
882
|
+
}),
|
|
883
|
+
/* @__PURE__ */ jsx3("span", {
|
|
884
|
+
style: {
|
|
885
|
+
overflow: "hidden",
|
|
886
|
+
textOverflow: "ellipsis",
|
|
887
|
+
whiteSpace: "nowrap"
|
|
888
|
+
},
|
|
889
|
+
title: tab.label,
|
|
890
|
+
children: tab.label
|
|
891
|
+
}),
|
|
892
|
+
renderAccessory ? renderAccessory(tab) : keyboardHint && /* @__PURE__ */ jsx3("span", {
|
|
893
|
+
style: {
|
|
894
|
+
fontSize: theme.fontSizes[0],
|
|
895
|
+
color: theme.colors.textSecondary,
|
|
896
|
+
opacity: 0.6,
|
|
897
|
+
flexShrink: 0
|
|
898
|
+
},
|
|
899
|
+
children: keyboardHint
|
|
900
|
+
})
|
|
901
|
+
]
|
|
902
|
+
});
|
|
903
|
+
};
|
|
904
|
+
TabButton.displayName = "TabButton";
|
|
905
|
+
|
|
906
|
+
// src/components/TabBar/TabBar.tsx
|
|
907
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
908
|
+
var TabBar = ({
|
|
909
|
+
tabs,
|
|
910
|
+
activeTabId,
|
|
911
|
+
onTabClick,
|
|
912
|
+
onTabClose,
|
|
913
|
+
onNewTab,
|
|
914
|
+
leftSection,
|
|
915
|
+
rightSection,
|
|
916
|
+
renderTabAccessory,
|
|
917
|
+
className,
|
|
918
|
+
showKeyboardHints = true
|
|
919
|
+
}) => {
|
|
920
|
+
const { theme } = useTheme4();
|
|
921
|
+
const [hoveredTabId, setHoveredTabId] = useState2(null);
|
|
922
|
+
return /* @__PURE__ */ jsxs3("div", {
|
|
923
|
+
className,
|
|
924
|
+
style: {
|
|
925
|
+
display: "flex",
|
|
926
|
+
alignItems: "stretch",
|
|
927
|
+
height: "40px",
|
|
928
|
+
flexShrink: 0,
|
|
929
|
+
boxSizing: "border-box"
|
|
930
|
+
},
|
|
931
|
+
children: [
|
|
932
|
+
leftSection && /* @__PURE__ */ jsx4("div", {
|
|
933
|
+
style: {
|
|
934
|
+
display: "flex",
|
|
935
|
+
alignItems: "center",
|
|
936
|
+
gap: "4px",
|
|
937
|
+
padding: "0 8px",
|
|
938
|
+
backgroundColor: theme.colors.backgroundSecondary,
|
|
939
|
+
borderRight: `1px solid ${theme.colors.border}`,
|
|
940
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
941
|
+
boxSizing: "border-box"
|
|
942
|
+
},
|
|
943
|
+
children: leftSection
|
|
944
|
+
}),
|
|
945
|
+
/* @__PURE__ */ jsx4("div", {
|
|
946
|
+
style: {
|
|
947
|
+
display: "flex",
|
|
948
|
+
alignItems: "center",
|
|
949
|
+
flex: 1,
|
|
950
|
+
overflow: "hidden",
|
|
951
|
+
backgroundColor: theme.colors.backgroundSecondary,
|
|
952
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
953
|
+
boxSizing: "border-box"
|
|
954
|
+
},
|
|
955
|
+
children: tabs.map((tab, index) => /* @__PURE__ */ jsx4(TabButton, {
|
|
956
|
+
tab,
|
|
957
|
+
isActive: tab.id === activeTabId,
|
|
958
|
+
isHovered: tab.id === hoveredTabId,
|
|
959
|
+
onMouseEnter: () => setHoveredTabId(tab.id),
|
|
960
|
+
onMouseLeave: () => setHoveredTabId(null),
|
|
961
|
+
onClick: () => onTabClick(tab.id),
|
|
962
|
+
onClose: () => onTabClose(tab.id),
|
|
963
|
+
keyboardHint: showKeyboardHints && index < 9 ? `⌘ ${index + 1}` : undefined,
|
|
964
|
+
renderAccessory: renderTabAccessory
|
|
965
|
+
}, tab.id))
|
|
966
|
+
}),
|
|
967
|
+
rightSection !== undefined ? rightSection && /* @__PURE__ */ jsx4("div", {
|
|
968
|
+
style: {
|
|
969
|
+
display: "flex",
|
|
970
|
+
alignItems: "center",
|
|
971
|
+
gap: "4px",
|
|
972
|
+
padding: "0 8px",
|
|
973
|
+
backgroundColor: theme.colors.backgroundSecondary,
|
|
974
|
+
borderLeft: `1px solid ${theme.colors.border}`,
|
|
975
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
976
|
+
boxSizing: "border-box"
|
|
977
|
+
},
|
|
978
|
+
children: rightSection
|
|
979
|
+
}) : onNewTab && /* @__PURE__ */ jsx4("div", {
|
|
980
|
+
style: {
|
|
981
|
+
display: "flex",
|
|
982
|
+
alignItems: "center",
|
|
983
|
+
gap: "4px",
|
|
984
|
+
padding: "0 8px",
|
|
985
|
+
backgroundColor: theme.colors.backgroundSecondary,
|
|
986
|
+
borderLeft: `1px solid ${theme.colors.border}`,
|
|
987
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
988
|
+
boxSizing: "border-box"
|
|
989
|
+
},
|
|
990
|
+
children: /* @__PURE__ */ jsx4("button", {
|
|
991
|
+
onClick: onNewTab,
|
|
992
|
+
style: {
|
|
993
|
+
display: "flex",
|
|
994
|
+
alignItems: "center",
|
|
995
|
+
justifyContent: "center",
|
|
996
|
+
width: "28px",
|
|
997
|
+
height: "28px",
|
|
998
|
+
border: "none",
|
|
999
|
+
borderRadius: "4px",
|
|
1000
|
+
backgroundColor: "transparent",
|
|
1001
|
+
cursor: "pointer",
|
|
1002
|
+
color: theme.colors.textSecondary
|
|
1003
|
+
},
|
|
1004
|
+
onMouseEnter: (e) => {
|
|
1005
|
+
e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
|
|
1006
|
+
},
|
|
1007
|
+
onMouseLeave: (e) => {
|
|
1008
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
1009
|
+
},
|
|
1010
|
+
title: "New Tab (⌘T)",
|
|
1011
|
+
children: /* @__PURE__ */ jsx4(Plus, {
|
|
1012
|
+
size: 14
|
|
1013
|
+
})
|
|
1014
|
+
})
|
|
1015
|
+
})
|
|
1016
|
+
]
|
|
1017
|
+
});
|
|
1018
|
+
};
|
|
1019
|
+
TabBar.displayName = "TabBar";
|
|
1020
|
+
// src/types/mixed-tab.ts
|
|
1021
|
+
function isTabOfType(tab, contentType) {
|
|
1022
|
+
return tab.contentType === contentType;
|
|
1023
|
+
}
|
|
1024
|
+
// src/hooks/useTabKeyboardShortcuts.ts
|
|
1025
|
+
import { useEffect as useEffect2 } from "react";
|
|
1026
|
+
var useTabKeyboardShortcuts = ({
|
|
1027
|
+
onNewTab,
|
|
1028
|
+
onCloseTab,
|
|
1029
|
+
onSwitchToTab,
|
|
1030
|
+
enabled = true
|
|
1031
|
+
}) => {
|
|
1032
|
+
useEffect2(() => {
|
|
1033
|
+
if (!enabled)
|
|
1034
|
+
return;
|
|
1035
|
+
const handleKeyDown = (e) => {
|
|
1036
|
+
const isCmdOrCtrl = e.metaKey || e.ctrlKey;
|
|
1037
|
+
if (isCmdOrCtrl && e.key === "t" && onNewTab) {
|
|
1038
|
+
e.preventDefault();
|
|
1039
|
+
e.stopPropagation();
|
|
1040
|
+
onNewTab();
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
if (isCmdOrCtrl && e.key === "w" && onCloseTab) {
|
|
1044
|
+
e.preventDefault();
|
|
1045
|
+
e.stopPropagation();
|
|
1046
|
+
onCloseTab();
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
if (isCmdOrCtrl && /^[1-9]$/.test(e.key) && onSwitchToTab) {
|
|
1050
|
+
e.preventDefault();
|
|
1051
|
+
e.stopPropagation();
|
|
1052
|
+
const index = parseInt(e.key, 10) - 1;
|
|
1053
|
+
onSwitchToTab(index);
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
1058
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1059
|
+
}, [enabled, onNewTab, onCloseTab, onSwitchToTab]);
|
|
1060
|
+
};
|
|
1061
|
+
// src/panels/TerminalPanel.tsx
|
|
1062
|
+
import { useTheme as useTheme5 } from "@principal-ade/industry-theme";
|
|
805
1063
|
import { Lock, Unlock, ArrowDown } from "lucide-react";
|
|
806
|
-
import { useEffect as
|
|
1064
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
807
1065
|
|
|
808
1066
|
// src/panel-types/index.ts
|
|
809
1067
|
function getTerminalSessions(context) {
|
|
@@ -838,19 +1096,19 @@ function getTerminalSlice(context) {
|
|
|
838
1096
|
}
|
|
839
1097
|
|
|
840
1098
|
// src/panels/TerminalPanel.tsx
|
|
841
|
-
import { jsx as
|
|
1099
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
842
1100
|
var TerminalPanel = ({
|
|
843
1101
|
context,
|
|
844
1102
|
actions,
|
|
845
1103
|
events: _events,
|
|
846
1104
|
terminalScope = "repository"
|
|
847
1105
|
}) => {
|
|
848
|
-
const { theme } =
|
|
849
|
-
const [sessionId, setSessionId] =
|
|
850
|
-
const [error, setError] =
|
|
851
|
-
const [isInitializing, setIsInitializing] =
|
|
852
|
-
const [usingMessagePort, setUsingMessagePort] =
|
|
853
|
-
const [scrollPosition, setScrollPosition] =
|
|
1106
|
+
const { theme } = useTheme5();
|
|
1107
|
+
const [sessionId, setSessionId] = useState3(null);
|
|
1108
|
+
const [error, setError] = useState3(null);
|
|
1109
|
+
const [isInitializing, setIsInitializing] = useState3(true);
|
|
1110
|
+
const [usingMessagePort, setUsingMessagePort] = useState3(false);
|
|
1111
|
+
const [scrollPosition, setScrollPosition] = useState3({
|
|
854
1112
|
isAtTop: false,
|
|
855
1113
|
isAtBottom: true,
|
|
856
1114
|
isScrollLocked: false
|
|
@@ -859,7 +1117,7 @@ var TerminalPanel = ({
|
|
|
859
1117
|
const dataPortRef = useRef2(null);
|
|
860
1118
|
const terminalDirectory = getTerminalDirectory(context, terminalScope);
|
|
861
1119
|
const pendingSessionIdRef = useRef2(null);
|
|
862
|
-
|
|
1120
|
+
useEffect3(() => {
|
|
863
1121
|
let mounted = true;
|
|
864
1122
|
let unsubscribePortReady = null;
|
|
865
1123
|
const initTerminal = async () => {
|
|
@@ -917,7 +1175,7 @@ var TerminalPanel = ({
|
|
|
917
1175
|
}
|
|
918
1176
|
};
|
|
919
1177
|
}, []);
|
|
920
|
-
|
|
1178
|
+
useEffect3(() => {
|
|
921
1179
|
if (usingMessagePort)
|
|
922
1180
|
return;
|
|
923
1181
|
if (!sessionId)
|
|
@@ -930,7 +1188,7 @@ var TerminalPanel = ({
|
|
|
930
1188
|
}, 5000);
|
|
931
1189
|
return () => clearTimeout(timeout);
|
|
932
1190
|
}, [sessionId, usingMessagePort]);
|
|
933
|
-
|
|
1191
|
+
useEffect3(() => {
|
|
934
1192
|
if (!usingMessagePort || !dataPortRef.current)
|
|
935
1193
|
return;
|
|
936
1194
|
const port = dataPortRef.current;
|
|
@@ -988,7 +1246,7 @@ var TerminalPanel = ({
|
|
|
988
1246
|
hasNotifiedPtyRef.current = true;
|
|
989
1247
|
}
|
|
990
1248
|
};
|
|
991
|
-
|
|
1249
|
+
useEffect3(() => {
|
|
992
1250
|
hasNotifiedPtyRef.current = false;
|
|
993
1251
|
}, [sessionId]);
|
|
994
1252
|
const handleScrollPositionChange = (position) => {
|
|
@@ -996,7 +1254,7 @@ var TerminalPanel = ({
|
|
|
996
1254
|
};
|
|
997
1255
|
const sessionInfo = sessionId ? getTerminalSession(context, sessionId) : undefined;
|
|
998
1256
|
if (error) {
|
|
999
|
-
return /* @__PURE__ */
|
|
1257
|
+
return /* @__PURE__ */ jsxs4("div", {
|
|
1000
1258
|
style: {
|
|
1001
1259
|
padding: "20px",
|
|
1002
1260
|
color: "#ef4444",
|
|
@@ -1009,11 +1267,11 @@ var TerminalPanel = ({
|
|
|
1009
1267
|
gap: "10px"
|
|
1010
1268
|
},
|
|
1011
1269
|
children: [
|
|
1012
|
-
/* @__PURE__ */
|
|
1270
|
+
/* @__PURE__ */ jsx5("div", {
|
|
1013
1271
|
style: { fontSize: "16px", fontWeight: "bold" },
|
|
1014
1272
|
children: "Terminal Error"
|
|
1015
1273
|
}),
|
|
1016
|
-
/* @__PURE__ */
|
|
1274
|
+
/* @__PURE__ */ jsx5("div", {
|
|
1017
1275
|
style: { fontSize: "14px", opacity: 0.8 },
|
|
1018
1276
|
children: error
|
|
1019
1277
|
})
|
|
@@ -1021,7 +1279,7 @@ var TerminalPanel = ({
|
|
|
1021
1279
|
});
|
|
1022
1280
|
}
|
|
1023
1281
|
if (isInitializing || !sessionId) {
|
|
1024
|
-
return /* @__PURE__ */
|
|
1282
|
+
return /* @__PURE__ */ jsx5("div", {
|
|
1025
1283
|
style: {
|
|
1026
1284
|
padding: "20px",
|
|
1027
1285
|
color: "#a0a0a0",
|
|
@@ -1047,10 +1305,10 @@ var TerminalPanel = ({
|
|
|
1047
1305
|
terminalRef.current?.scrollToBottom();
|
|
1048
1306
|
}
|
|
1049
1307
|
};
|
|
1050
|
-
return /* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ jsxs4("div", {
|
|
1051
1309
|
style: { height: "100%", width: "100%", display: "flex", flexDirection: "column" },
|
|
1052
1310
|
children: [
|
|
1053
|
-
/* @__PURE__ */
|
|
1311
|
+
/* @__PURE__ */ jsxs4("div", {
|
|
1054
1312
|
style: {
|
|
1055
1313
|
display: "flex",
|
|
1056
1314
|
gap: "8px",
|
|
@@ -1060,7 +1318,7 @@ var TerminalPanel = ({
|
|
|
1060
1318
|
alignItems: "center"
|
|
1061
1319
|
},
|
|
1062
1320
|
children: [
|
|
1063
|
-
/* @__PURE__ */
|
|
1321
|
+
/* @__PURE__ */ jsxs4("span", {
|
|
1064
1322
|
style: {
|
|
1065
1323
|
fontSize: "12px",
|
|
1066
1324
|
color: theme.colors.textSecondary,
|
|
@@ -1073,7 +1331,7 @@ var TerminalPanel = ({
|
|
|
1073
1331
|
sessionInfo?.shell
|
|
1074
1332
|
]
|
|
1075
1333
|
}),
|
|
1076
|
-
/* @__PURE__ */
|
|
1334
|
+
/* @__PURE__ */ jsxs4("button", {
|
|
1077
1335
|
onClick: handleToggleScrollLock,
|
|
1078
1336
|
style: {
|
|
1079
1337
|
display: "flex",
|
|
@@ -1092,17 +1350,17 @@ var TerminalPanel = ({
|
|
|
1092
1350
|
onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
|
|
1093
1351
|
title: scrollPosition.isScrollLocked ? "Click to unlock scroll" : "Click to lock scroll to bottom",
|
|
1094
1352
|
children: [
|
|
1095
|
-
scrollPosition.isScrollLocked ? /* @__PURE__ */
|
|
1353
|
+
scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx5(Lock, {
|
|
1096
1354
|
size: 12
|
|
1097
|
-
}) : /* @__PURE__ */
|
|
1355
|
+
}) : /* @__PURE__ */ jsx5(Unlock, {
|
|
1098
1356
|
size: 12
|
|
1099
1357
|
}),
|
|
1100
|
-
/* @__PURE__ */
|
|
1358
|
+
/* @__PURE__ */ jsx5("span", {
|
|
1101
1359
|
children: scrollPosition.isScrollLocked ? "Locked" : "Unlocked"
|
|
1102
1360
|
})
|
|
1103
1361
|
]
|
|
1104
1362
|
}),
|
|
1105
|
-
/* @__PURE__ */
|
|
1363
|
+
/* @__PURE__ */ jsxs4("button", {
|
|
1106
1364
|
onClick: handleScrollToBottom,
|
|
1107
1365
|
disabled: scrollPosition.isAtBottom,
|
|
1108
1366
|
style: {
|
|
@@ -1123,19 +1381,19 @@ var TerminalPanel = ({
|
|
|
1123
1381
|
onMouseLeave: (e) => !scrollPosition.isAtBottom && (e.currentTarget.style.opacity = "1"),
|
|
1124
1382
|
title: "Scroll to bottom and lock",
|
|
1125
1383
|
children: [
|
|
1126
|
-
/* @__PURE__ */
|
|
1384
|
+
/* @__PURE__ */ jsx5(ArrowDown, {
|
|
1127
1385
|
size: 12
|
|
1128
1386
|
}),
|
|
1129
|
-
/* @__PURE__ */
|
|
1387
|
+
/* @__PURE__ */ jsx5("span", {
|
|
1130
1388
|
children: "Bottom"
|
|
1131
1389
|
})
|
|
1132
1390
|
]
|
|
1133
1391
|
})
|
|
1134
1392
|
]
|
|
1135
1393
|
}),
|
|
1136
|
-
/* @__PURE__ */
|
|
1394
|
+
/* @__PURE__ */ jsx5("div", {
|
|
1137
1395
|
style: { flex: 1 },
|
|
1138
|
-
children: /* @__PURE__ */
|
|
1396
|
+
children: /* @__PURE__ */ jsx5(ThemedTerminalWithProvider, {
|
|
1139
1397
|
ref: terminalRef,
|
|
1140
1398
|
onData: handleTerminalData,
|
|
1141
1399
|
onResize: handleTerminalResize,
|
|
@@ -1153,28 +1411,28 @@ var TerminalPanel = ({
|
|
|
1153
1411
|
});
|
|
1154
1412
|
};
|
|
1155
1413
|
// src/panels/TabbedTerminalPanel.tsx
|
|
1156
|
-
import { useTheme as
|
|
1157
|
-
import { Terminal as TerminalIcon2,
|
|
1158
|
-
import
|
|
1159
|
-
useState as
|
|
1414
|
+
import { useTheme as useTheme6 } from "@principal-ade/industry-theme";
|
|
1415
|
+
import { Terminal as TerminalIcon2, Lock as Lock2, Unlock as Unlock2, Box, Boxes } from "lucide-react";
|
|
1416
|
+
import React2, {
|
|
1417
|
+
useState as useState4,
|
|
1160
1418
|
useCallback as useCallback2,
|
|
1161
|
-
useEffect as
|
|
1419
|
+
useEffect as useEffect4,
|
|
1162
1420
|
useRef as useRef3
|
|
1163
1421
|
} from "react";
|
|
1164
|
-
import { jsx as
|
|
1422
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1165
1423
|
function TerminalTabContentInner(props, ref) {
|
|
1166
1424
|
const { tab, sessionId, isActive, isVisible, actions, events, terminalContext, onSessionCreated, onScrollPositionChange, isForeign = false } = props;
|
|
1167
1425
|
const terminalRef = useRef3(null);
|
|
1168
|
-
const [localSessionId, setLocalSessionId] =
|
|
1169
|
-
const [isInitialized, setIsInitialized] =
|
|
1426
|
+
const [localSessionId, setLocalSessionId] = useState4(sessionId);
|
|
1427
|
+
const [isInitialized, setIsInitialized] = useState4(false);
|
|
1170
1428
|
const hasInitializedRef = useRef3(false);
|
|
1171
|
-
const [scrollPosition, setScrollPosition] =
|
|
1429
|
+
const [scrollPosition, setScrollPosition] = useState4({
|
|
1172
1430
|
isAtTop: false,
|
|
1173
1431
|
isAtBottom: true,
|
|
1174
1432
|
isScrollLocked: false
|
|
1175
1433
|
});
|
|
1176
|
-
const [shouldRenderTerminal, setShouldRenderTerminal] =
|
|
1177
|
-
const [ownerWindowId, setOwnerWindowId] =
|
|
1434
|
+
const [shouldRenderTerminal, setShouldRenderTerminal] = useState4(true);
|
|
1435
|
+
const [ownerWindowId, setOwnerWindowId] = useState4(null);
|
|
1178
1436
|
const needsRefreshOnResizeRef = useRef3(false);
|
|
1179
1437
|
const claimAndConnect = useCallback2(async (targetSessionId, force = false) => {
|
|
1180
1438
|
try {
|
|
@@ -1194,7 +1452,7 @@ function TerminalTabContentInner(props, ref) {
|
|
|
1194
1452
|
throw error;
|
|
1195
1453
|
}
|
|
1196
1454
|
}, [actions]);
|
|
1197
|
-
|
|
1455
|
+
useEffect4(() => {
|
|
1198
1456
|
if (hasInitializedRef.current) {
|
|
1199
1457
|
return;
|
|
1200
1458
|
}
|
|
@@ -1239,7 +1497,7 @@ function TerminalTabContentInner(props, ref) {
|
|
|
1239
1497
|
mounted = false;
|
|
1240
1498
|
};
|
|
1241
1499
|
}, []);
|
|
1242
|
-
|
|
1500
|
+
useEffect4(() => {
|
|
1243
1501
|
if (!localSessionId || !isInitialized || !shouldRenderTerminal) {
|
|
1244
1502
|
return;
|
|
1245
1503
|
}
|
|
@@ -1291,7 +1549,7 @@ function TerminalTabContentInner(props, ref) {
|
|
|
1291
1549
|
});
|
|
1292
1550
|
}
|
|
1293
1551
|
}, [localSessionId, events]);
|
|
1294
|
-
|
|
1552
|
+
useEffect4(() => {
|
|
1295
1553
|
if (!localSessionId || !actions.onOwnershipLost) {
|
|
1296
1554
|
return;
|
|
1297
1555
|
}
|
|
@@ -1341,12 +1599,12 @@ function TerminalTabContentInner(props, ref) {
|
|
|
1341
1599
|
terminalRef.current?.scrollToBottom();
|
|
1342
1600
|
}
|
|
1343
1601
|
}, [scrollPosition.isScrollLocked]);
|
|
1344
|
-
|
|
1602
|
+
React2.useImperativeHandle(ref, () => ({
|
|
1345
1603
|
scrollToBottom: handleScrollToBottom,
|
|
1346
1604
|
toggleScrollLock: handleToggleScrollLock
|
|
1347
1605
|
}), [handleScrollToBottom, handleToggleScrollLock]);
|
|
1348
1606
|
if (!isInitialized) {
|
|
1349
|
-
return /* @__PURE__ */
|
|
1607
|
+
return /* @__PURE__ */ jsx6("div", {
|
|
1350
1608
|
style: {
|
|
1351
1609
|
display: isActive ? "flex" : "none",
|
|
1352
1610
|
height: "100%",
|
|
@@ -1369,14 +1627,14 @@ function TerminalTabContentInner(props, ref) {
|
|
|
1369
1627
|
],
|
|
1370
1628
|
opacity: 1
|
|
1371
1629
|
} : undefined;
|
|
1372
|
-
return /* @__PURE__ */
|
|
1630
|
+
return /* @__PURE__ */ jsx6("div", {
|
|
1373
1631
|
style: {
|
|
1374
1632
|
display: isActive ? "flex" : "none",
|
|
1375
1633
|
flexDirection: "column",
|
|
1376
1634
|
height: "100%",
|
|
1377
1635
|
width: "100%"
|
|
1378
1636
|
},
|
|
1379
|
-
children: /* @__PURE__ */
|
|
1637
|
+
children: /* @__PURE__ */ jsx6(ThemedTerminalWithProvider, {
|
|
1380
1638
|
ref: terminalRef,
|
|
1381
1639
|
onData: shouldRenderTerminal ? handleData : undefined,
|
|
1382
1640
|
onResize: shouldRenderTerminal ? handleResize : undefined,
|
|
@@ -1397,7 +1655,7 @@ function TerminalTabContentInner(props, ref) {
|
|
|
1397
1655
|
});
|
|
1398
1656
|
}
|
|
1399
1657
|
var areTerminalTabContentPropsEqual = (prevProps, nextProps) => {
|
|
1400
|
-
const tabEqual = prevProps.tab.id === nextProps.tab.id && prevProps.tab.directory === nextProps.tab.directory && prevProps.tab.
|
|
1658
|
+
const tabEqual = prevProps.tab.id === nextProps.tab.id && prevProps.tab.directory === nextProps.tab.directory && prevProps.tab.label === nextProps.tab.label;
|
|
1401
1659
|
const changes = [];
|
|
1402
1660
|
if (!tabEqual)
|
|
1403
1661
|
changes.push("tab");
|
|
@@ -1413,8 +1671,8 @@ var areTerminalTabContentPropsEqual = (prevProps, nextProps) => {
|
|
|
1413
1671
|
changes.push("isForeign");
|
|
1414
1672
|
return changes.length === 0;
|
|
1415
1673
|
};
|
|
1416
|
-
var TerminalTabContentForwarded =
|
|
1417
|
-
var TerminalTabContent =
|
|
1674
|
+
var TerminalTabContentForwarded = React2.forwardRef(TerminalTabContentInner);
|
|
1675
|
+
var TerminalTabContent = React2.memo(TerminalTabContentForwarded, areTerminalTabContentPropsEqual);
|
|
1418
1676
|
TerminalTabContent.displayName = "TerminalTabContent";
|
|
1419
1677
|
var TabbedTerminalPanelInner = ({
|
|
1420
1678
|
context: _context,
|
|
@@ -1428,22 +1686,41 @@ var TabbedTerminalPanelInner = ({
|
|
|
1428
1686
|
initialTabs = [],
|
|
1429
1687
|
showAllTerminals = false,
|
|
1430
1688
|
onShowAllTerminalsChange,
|
|
1431
|
-
tabLabelPrefix
|
|
1689
|
+
tabLabelPrefix,
|
|
1690
|
+
renderTabContent
|
|
1432
1691
|
}) => {
|
|
1433
|
-
const { theme } =
|
|
1434
|
-
const [ownedTabs, setOwnedTabs] =
|
|
1435
|
-
const [foreignTabs, setForeignTabs] =
|
|
1436
|
-
const [activeTabId, setActiveTabId] =
|
|
1437
|
-
const [sessionIds, setSessionIds] =
|
|
1438
|
-
const [
|
|
1439
|
-
|
|
1692
|
+
const { theme } = useTheme6();
|
|
1693
|
+
const [ownedTabs, setOwnedTabs] = useState4(initialTabs);
|
|
1694
|
+
const [foreignTabs, setForeignTabs] = useState4([]);
|
|
1695
|
+
const [activeTabId, setActiveTabId] = useState4(null);
|
|
1696
|
+
const [sessionIds, setSessionIds] = useState4(new Map);
|
|
1697
|
+
const [scrollPositions, setScrollPositions] = useState4(new Map);
|
|
1698
|
+
useEffect4(() => {
|
|
1699
|
+
const customTabsFromProp = initialTabs.filter((tab) => tab.contentType !== "terminal");
|
|
1700
|
+
setOwnedTabs((prevTabs) => {
|
|
1701
|
+
const existingTerminalTabs = prevTabs.filter((tab) => tab.contentType === "terminal");
|
|
1702
|
+
const customTabIds = new Set(customTabsFromProp.map((t) => t.id));
|
|
1703
|
+
const existingCustomTabs = prevTabs.filter((tab) => tab.contentType !== "terminal" && !customTabIds.has(tab.id));
|
|
1704
|
+
const mergedTabs = [
|
|
1705
|
+
...existingTerminalTabs,
|
|
1706
|
+
...existingCustomTabs,
|
|
1707
|
+
...customTabsFromProp
|
|
1708
|
+
];
|
|
1709
|
+
const prevCustomTabs = prevTabs.filter((tab) => tab.contentType !== "terminal");
|
|
1710
|
+
const customTabsChanged = prevCustomTabs.length !== customTabsFromProp.length || !customTabsFromProp.every((tab) => prevCustomTabs.some((prev) => prev.id === tab.id));
|
|
1711
|
+
if (!customTabsChanged) {
|
|
1712
|
+
return prevTabs;
|
|
1713
|
+
}
|
|
1714
|
+
return mergedTabs;
|
|
1715
|
+
});
|
|
1716
|
+
}, [initialTabs]);
|
|
1440
1717
|
const getOwnedTabLabel = useCallback2((index, _directory) => {
|
|
1441
1718
|
if (tabLabelPrefix) {
|
|
1442
1719
|
return `${tabLabelPrefix} ${index + 1}`;
|
|
1443
1720
|
}
|
|
1444
1721
|
return `⌘ ${index + 1}`;
|
|
1445
1722
|
}, [tabLabelPrefix]);
|
|
1446
|
-
const tabs =
|
|
1723
|
+
const tabs = React2.useMemo(() => {
|
|
1447
1724
|
const labeledOwnedTabs = ownedTabs.map((tab, index) => ({
|
|
1448
1725
|
...tab,
|
|
1449
1726
|
label: getOwnedTabLabel(index, tab.directory)
|
|
@@ -1451,6 +1728,18 @@ var TabbedTerminalPanelInner = ({
|
|
|
1451
1728
|
const sortedForeignTabs = [...foreignTabs].sort((a, b) => a.label.localeCompare(b.label));
|
|
1452
1729
|
return [...labeledOwnedTabs, ...sortedForeignTabs];
|
|
1453
1730
|
}, [ownedTabs, foreignTabs, getOwnedTabLabel]);
|
|
1731
|
+
const genericTabs = React2.useMemo(() => {
|
|
1732
|
+
return tabs.map((tab) => ({
|
|
1733
|
+
id: tab.id,
|
|
1734
|
+
label: tab.label,
|
|
1735
|
+
closable: true,
|
|
1736
|
+
contentType: tab.contentType,
|
|
1737
|
+
metadata: {
|
|
1738
|
+
...tab.directory && { directory: tab.directory },
|
|
1739
|
+
...tab.command && { command: tab.command }
|
|
1740
|
+
}
|
|
1741
|
+
}));
|
|
1742
|
+
}, [tabs]);
|
|
1454
1743
|
const tabRefsMap = useRef3(new Map);
|
|
1455
1744
|
const refCallbacksMap = useRef3(new Map);
|
|
1456
1745
|
const getRefCallback = useCallback2((tabId) => {
|
|
@@ -1493,14 +1782,15 @@ var TabbedTerminalPanelInner = ({
|
|
|
1493
1782
|
if (ownedSessions.length > 0 && initialTabs.length === 0) {
|
|
1494
1783
|
const restoredTabs = [];
|
|
1495
1784
|
const restoredSessionIds = new Map;
|
|
1496
|
-
ownedSessions.forEach((session
|
|
1785
|
+
ownedSessions.forEach((session) => {
|
|
1497
1786
|
const tabId = `tab-restored-${session.id}`;
|
|
1498
1787
|
const sessionCwd = session.cwd || directory;
|
|
1499
1788
|
const tab = {
|
|
1500
1789
|
id: tabId,
|
|
1501
1790
|
label: sessionCwd.split("/").pop() || sessionCwd,
|
|
1791
|
+
contentType: "terminal",
|
|
1502
1792
|
directory: sessionCwd,
|
|
1503
|
-
|
|
1793
|
+
closable: true
|
|
1504
1794
|
};
|
|
1505
1795
|
restoredTabs.push(tab);
|
|
1506
1796
|
restoredSessionIds.set(tabId, session.id);
|
|
@@ -1511,7 +1801,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
1511
1801
|
onTabsChange?.(restoredTabs);
|
|
1512
1802
|
} else if (initialTabs.length > 0) {
|
|
1513
1803
|
setOwnedTabs(initialTabs);
|
|
1514
|
-
setActiveTabId(initialTabs
|
|
1804
|
+
setActiveTabId(initialTabs[0]?.id || null);
|
|
1515
1805
|
}
|
|
1516
1806
|
} catch (err) {
|
|
1517
1807
|
console.error("[TabbedTerminalPanel] Failed to restore owned sessions:", err);
|
|
@@ -1532,8 +1822,9 @@ var TabbedTerminalPanelInner = ({
|
|
|
1532
1822
|
const tab = {
|
|
1533
1823
|
id: tabId,
|
|
1534
1824
|
label: sessionCwd.split("/").pop() || sessionCwd,
|
|
1825
|
+
contentType: "terminal",
|
|
1535
1826
|
directory: sessionCwd,
|
|
1536
|
-
|
|
1827
|
+
closable: true
|
|
1537
1828
|
};
|
|
1538
1829
|
foreignTabsList.push(tab);
|
|
1539
1830
|
newSessionIds.set(tabId, session.id);
|
|
@@ -1559,13 +1850,13 @@ var TabbedTerminalPanelInner = ({
|
|
|
1559
1850
|
return [];
|
|
1560
1851
|
});
|
|
1561
1852
|
}, []);
|
|
1562
|
-
|
|
1853
|
+
useEffect4(() => {
|
|
1563
1854
|
if (hasInitializedRef.current)
|
|
1564
1855
|
return;
|
|
1565
1856
|
hasInitializedRef.current = true;
|
|
1566
1857
|
restoreOwnedSessions();
|
|
1567
1858
|
}, []);
|
|
1568
|
-
|
|
1859
|
+
useEffect4(() => {
|
|
1569
1860
|
const handleSessionCreated2 = (event) => {
|
|
1570
1861
|
const customEvent = event;
|
|
1571
1862
|
const { context } = customEvent.detail || {};
|
|
@@ -1579,7 +1870,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
1579
1870
|
window.removeEventListener("terminal-session-created", handleSessionCreated2);
|
|
1580
1871
|
};
|
|
1581
1872
|
}, [terminalContext, restoreOwnedSessions]);
|
|
1582
|
-
|
|
1873
|
+
useEffect4(() => {
|
|
1583
1874
|
if (showAllTerminals) {
|
|
1584
1875
|
fetchForeignSessions();
|
|
1585
1876
|
} else {
|
|
@@ -1603,17 +1894,16 @@ var TabbedTerminalPanelInner = ({
|
|
|
1603
1894
|
const newTab = {
|
|
1604
1895
|
id: `tab-${Date.now()}`,
|
|
1605
1896
|
label: label || directoryName,
|
|
1897
|
+
contentType: "terminal",
|
|
1606
1898
|
directory: targetDir,
|
|
1607
1899
|
command,
|
|
1608
|
-
|
|
1900
|
+
closable: true
|
|
1609
1901
|
};
|
|
1610
1902
|
setOwnedTabs((prevTabs) => {
|
|
1611
|
-
const
|
|
1612
|
-
const newTabs = [...updatedTabs, newTab];
|
|
1903
|
+
const newTabs = [...prevTabs, newTab];
|
|
1613
1904
|
onTabsChange?.(newTabs);
|
|
1614
1905
|
return newTabs;
|
|
1615
1906
|
});
|
|
1616
|
-
setForeignTabs((prevTabs) => prevTabs.map((t) => ({ ...t, isActive: false })));
|
|
1617
1907
|
setActiveTabId(newTab.id);
|
|
1618
1908
|
}, [directory, onTabsChange]);
|
|
1619
1909
|
const isForeignTab = useCallback2((tabId) => {
|
|
@@ -1648,11 +1938,8 @@ var TabbedTerminalPanelInner = ({
|
|
|
1648
1938
|
const nextActiveId = findNextActiveTab([...ownedTabs, ...newTabs]);
|
|
1649
1939
|
if (nextActiveId !== activeTabId) {
|
|
1650
1940
|
setActiveTabId(nextActiveId);
|
|
1651
|
-
if (nextActiveId) {
|
|
1652
|
-
setOwnedTabs((owned) => owned.map((t) => ({ ...t, isActive: t.id === nextActiveId })));
|
|
1653
|
-
}
|
|
1654
1941
|
}
|
|
1655
|
-
return newTabs
|
|
1942
|
+
return newTabs;
|
|
1656
1943
|
});
|
|
1657
1944
|
} else {
|
|
1658
1945
|
setOwnedTabs((prevTabs) => {
|
|
@@ -1660,71 +1947,74 @@ var TabbedTerminalPanelInner = ({
|
|
|
1660
1947
|
const nextActiveId = findNextActiveTab([...newTabs, ...foreignTabs]);
|
|
1661
1948
|
if (nextActiveId !== activeTabId) {
|
|
1662
1949
|
setActiveTabId(nextActiveId);
|
|
1663
|
-
if (nextActiveId) {
|
|
1664
|
-
setForeignTabs((foreign) => foreign.map((t) => ({ ...t, isActive: t.id === nextActiveId })));
|
|
1665
|
-
}
|
|
1666
1950
|
}
|
|
1667
1951
|
onTabsChange?.(newTabs);
|
|
1668
|
-
return newTabs
|
|
1952
|
+
return newTabs;
|
|
1669
1953
|
});
|
|
1670
1954
|
}
|
|
1671
1955
|
}, [activeTabId, sessionIds, actions, onTabsChange, isForeignTab, ownedTabs, foreignTabs]);
|
|
1672
1956
|
const handleSessionCreated = useCallback2((tabId, sessionId) => {
|
|
1673
1957
|
setSessionIds((prev) => new Map(prev).set(tabId, sessionId));
|
|
1674
1958
|
}, []);
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
const closeTabRef = useRef3(closeTab);
|
|
1679
|
-
const switchTabRef = useRef3(switchTab);
|
|
1680
|
-
useEffect3(() => {
|
|
1681
|
-
tabsRef.current = tabs;
|
|
1682
|
-
activeTabIdRef.current = activeTabId;
|
|
1683
|
-
addNewTabRef.current = addNewTab;
|
|
1684
|
-
closeTabRef.current = closeTab;
|
|
1685
|
-
switchTabRef.current = switchTab;
|
|
1686
|
-
}, [tabs, activeTabId, addNewTab, closeTab, switchTab]);
|
|
1687
|
-
useEffect3(() => {
|
|
1688
|
-
const handleKeyDown = (e) => {
|
|
1689
|
-
if ((e.metaKey || e.ctrlKey) && e.key === "t") {
|
|
1690
|
-
e.preventDefault();
|
|
1691
|
-
e.stopPropagation();
|
|
1692
|
-
if (isCreatingTabRef.current)
|
|
1693
|
-
return;
|
|
1694
|
-
isCreatingTabRef.current = true;
|
|
1695
|
-
addNewTabRef.current?.();
|
|
1696
|
-
setTimeout(() => {
|
|
1697
|
-
isCreatingTabRef.current = false;
|
|
1698
|
-
}, 500);
|
|
1699
|
-
return;
|
|
1700
|
-
}
|
|
1701
|
-
if ((e.metaKey || e.ctrlKey) && e.key === "w") {
|
|
1702
|
-
const currentActiveTabId = activeTabIdRef.current;
|
|
1703
|
-
const currentTabs = tabsRef.current;
|
|
1704
|
-
if (currentActiveTabId && currentTabs.length > 0) {
|
|
1705
|
-
e.preventDefault();
|
|
1706
|
-
e.stopPropagation();
|
|
1707
|
-
closeTabRef.current?.(currentActiveTabId);
|
|
1708
|
-
}
|
|
1959
|
+
useTabKeyboardShortcuts({
|
|
1960
|
+
onNewTab: () => {
|
|
1961
|
+
if (isCreatingTabRef.current)
|
|
1709
1962
|
return;
|
|
1963
|
+
isCreatingTabRef.current = true;
|
|
1964
|
+
addNewTab();
|
|
1965
|
+
setTimeout(() => {
|
|
1966
|
+
isCreatingTabRef.current = false;
|
|
1967
|
+
}, 500);
|
|
1968
|
+
},
|
|
1969
|
+
onCloseTab: () => {
|
|
1970
|
+
if (activeTabId && tabs.length > 0) {
|
|
1971
|
+
closeTab(activeTabId);
|
|
1710
1972
|
}
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
if (tabIndex >= 0 && tabIndex < currentTabs.length) {
|
|
1717
|
-
const targetTab = currentTabs[tabIndex];
|
|
1718
|
-
if (targetTab) {
|
|
1719
|
-
switchTabRef.current?.(targetTab.id);
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1973
|
+
},
|
|
1974
|
+
onSwitchToTab: (index) => {
|
|
1975
|
+
const tabIndex = index === 8 && tabs.length > 9 ? tabs.length - 1 : index;
|
|
1976
|
+
if (tabIndex >= 0 && tabIndex < tabs.length) {
|
|
1977
|
+
switchTab(tabs[tabIndex].id);
|
|
1722
1978
|
}
|
|
1723
|
-
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1979
|
+
}
|
|
1980
|
+
});
|
|
1981
|
+
const renderTabAccessory = useCallback2((tab) => {
|
|
1982
|
+
if (tab.id !== activeTabId)
|
|
1983
|
+
return null;
|
|
1984
|
+
const scrollPosition = scrollPositions.get(tab.id) ?? defaultScrollPosition;
|
|
1985
|
+
return /* @__PURE__ */ jsx6("button", {
|
|
1986
|
+
onClick: (e) => {
|
|
1987
|
+
e.stopPropagation();
|
|
1988
|
+
handleToggleScrollLock();
|
|
1989
|
+
},
|
|
1990
|
+
style: {
|
|
1991
|
+
display: "flex",
|
|
1992
|
+
alignItems: "center",
|
|
1993
|
+
justifyContent: "center",
|
|
1994
|
+
width: "16px",
|
|
1995
|
+
height: "16px",
|
|
1996
|
+
borderRadius: "3px",
|
|
1997
|
+
border: "none",
|
|
1998
|
+
backgroundColor: "transparent",
|
|
1999
|
+
cursor: "pointer",
|
|
2000
|
+
color: scrollPosition.isScrollLocked ? theme.colors.success : theme.colors.warning,
|
|
2001
|
+
padding: 0
|
|
2002
|
+
},
|
|
2003
|
+
onMouseEnter: (e) => {
|
|
2004
|
+
e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
|
|
2005
|
+
},
|
|
2006
|
+
onMouseLeave: (e) => {
|
|
2007
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
2008
|
+
},
|
|
2009
|
+
title: scrollPosition.isScrollLocked ? "Scroll locked" : "Scroll unlocked",
|
|
2010
|
+
children: scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx6(Lock2, {
|
|
2011
|
+
size: 10
|
|
2012
|
+
}) : /* @__PURE__ */ jsx6(Unlock2, {
|
|
2013
|
+
size: 10
|
|
2014
|
+
})
|
|
2015
|
+
});
|
|
2016
|
+
}, [activeTabId, scrollPositions, defaultScrollPosition, handleToggleScrollLock, theme]);
|
|
2017
|
+
return /* @__PURE__ */ jsxs5("div", {
|
|
1728
2018
|
style: {
|
|
1729
2019
|
display: "flex",
|
|
1730
2020
|
flexDirection: "column",
|
|
@@ -1732,205 +2022,50 @@ var TabbedTerminalPanelInner = ({
|
|
|
1732
2022
|
backgroundColor: theme.colors.background
|
|
1733
2023
|
},
|
|
1734
2024
|
children: [
|
|
1735
|
-
!hideHeader && /* @__PURE__ */
|
|
2025
|
+
!hideHeader && /* @__PURE__ */ jsx6("div", {
|
|
1736
2026
|
ref: headerRef,
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
/* @__PURE__ */ jsx4("div", {
|
|
2027
|
+
children: /* @__PURE__ */ jsx6(TabBar, {
|
|
2028
|
+
tabs: genericTabs,
|
|
2029
|
+
activeTabId,
|
|
2030
|
+
onTabClick: switchTab,
|
|
2031
|
+
onTabClose: closeTab,
|
|
2032
|
+
onNewTab: addNewTab,
|
|
2033
|
+
leftSection: /* @__PURE__ */ jsx6("button", {
|
|
2034
|
+
onClick: () => onShowAllTerminalsChange?.(!showAllTerminals),
|
|
1746
2035
|
style: {
|
|
1747
2036
|
display: "flex",
|
|
1748
2037
|
alignItems: "center",
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
style: {
|
|
1758
|
-
display: "flex",
|
|
1759
|
-
alignItems: "center",
|
|
1760
|
-
justifyContent: "center",
|
|
1761
|
-
width: "28px",
|
|
1762
|
-
height: "28px",
|
|
1763
|
-
border: "none",
|
|
1764
|
-
borderRadius: "4px",
|
|
1765
|
-
backgroundColor: showAllTerminals ? `${theme.colors.primary}22` : "transparent",
|
|
1766
|
-
cursor: "pointer",
|
|
1767
|
-
color: showAllTerminals ? theme.colors.primary : theme.colors.textSecondary
|
|
1768
|
-
},
|
|
1769
|
-
onMouseEnter: (e) => {
|
|
1770
|
-
if (!showAllTerminals) {
|
|
1771
|
-
e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
|
|
1772
|
-
}
|
|
1773
|
-
},
|
|
1774
|
-
onMouseLeave: (e) => {
|
|
1775
|
-
if (!showAllTerminals) {
|
|
1776
|
-
e.currentTarget.style.backgroundColor = "transparent";
|
|
1777
|
-
}
|
|
1778
|
-
},
|
|
1779
|
-
title: showAllTerminals ? "Showing all terminals (click to filter by context)" : "Show all terminals",
|
|
1780
|
-
children: showAllTerminals ? /* @__PURE__ */ jsx4(Boxes, {
|
|
1781
|
-
size: 14
|
|
1782
|
-
}) : /* @__PURE__ */ jsx4(Box, {
|
|
1783
|
-
size: 14
|
|
1784
|
-
})
|
|
1785
|
-
})
|
|
1786
|
-
}),
|
|
1787
|
-
/* @__PURE__ */ jsx4("div", {
|
|
1788
|
-
style: {
|
|
1789
|
-
display: "flex",
|
|
1790
|
-
alignItems: "center",
|
|
1791
|
-
flex: 1,
|
|
1792
|
-
overflow: "hidden",
|
|
1793
|
-
borderBottom: `1px solid ${theme.colors.border}`,
|
|
1794
|
-
boxSizing: "border-box"
|
|
1795
|
-
},
|
|
1796
|
-
children: tabs.map((tab) => /* @__PURE__ */ jsxs3("div", {
|
|
1797
|
-
onClick: (e) => {
|
|
1798
|
-
e.stopPropagation();
|
|
1799
|
-
switchTab(tab.id);
|
|
1800
|
-
},
|
|
1801
|
-
onMouseEnter: () => setHoveredTabId(tab.id),
|
|
1802
|
-
onMouseLeave: () => setHoveredTabId(null),
|
|
1803
|
-
style: {
|
|
1804
|
-
display: "flex",
|
|
1805
|
-
alignItems: "center",
|
|
1806
|
-
justifyContent: "center",
|
|
1807
|
-
gap: "6px",
|
|
1808
|
-
padding: "6px 8px",
|
|
1809
|
-
backgroundColor: tab.isActive ? theme.colors.background : theme.colors.backgroundSecondary,
|
|
1810
|
-
borderBottom: "none",
|
|
1811
|
-
cursor: "pointer",
|
|
1812
|
-
fontSize: theme.fontSizes[1],
|
|
1813
|
-
fontWeight: tab.isActive ? theme.fontWeights.semibold : theme.fontWeights.body,
|
|
1814
|
-
fontFamily: theme.fonts.body,
|
|
1815
|
-
color: tab.isActive ? theme.colors.text : theme.colors.textSecondary,
|
|
1816
|
-
whiteSpace: "nowrap",
|
|
1817
|
-
transition: "all 0.2s",
|
|
1818
|
-
flex: 1,
|
|
1819
|
-
minWidth: 0,
|
|
1820
|
-
height: "100%",
|
|
1821
|
-
position: "relative",
|
|
1822
|
-
boxSizing: "border-box"
|
|
1823
|
-
},
|
|
1824
|
-
children: [
|
|
1825
|
-
hoveredTabId === tab.id && /* @__PURE__ */ jsx4("button", {
|
|
1826
|
-
onClick: (e) => {
|
|
1827
|
-
e.stopPropagation();
|
|
1828
|
-
closeTab(tab.id);
|
|
1829
|
-
},
|
|
1830
|
-
style: {
|
|
1831
|
-
display: "flex",
|
|
1832
|
-
alignItems: "center",
|
|
1833
|
-
justifyContent: "center",
|
|
1834
|
-
width: "16px",
|
|
1835
|
-
height: "16px",
|
|
1836
|
-
borderRadius: "3px",
|
|
1837
|
-
border: "none",
|
|
1838
|
-
backgroundColor: "transparent",
|
|
1839
|
-
cursor: "pointer",
|
|
1840
|
-
color: theme.colors.textSecondary,
|
|
1841
|
-
padding: 0,
|
|
1842
|
-
position: "absolute",
|
|
1843
|
-
left: "8px"
|
|
1844
|
-
},
|
|
1845
|
-
onMouseEnter: (e) => {
|
|
1846
|
-
e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
|
|
1847
|
-
},
|
|
1848
|
-
onMouseLeave: (e) => {
|
|
1849
|
-
e.currentTarget.style.backgroundColor = "transparent";
|
|
1850
|
-
},
|
|
1851
|
-
children: /* @__PURE__ */ jsx4(X2, {
|
|
1852
|
-
size: 12
|
|
1853
|
-
})
|
|
1854
|
-
}),
|
|
1855
|
-
/* @__PURE__ */ jsx4("span", {
|
|
1856
|
-
title: tab.directory.split("/").pop() || tab.directory,
|
|
1857
|
-
children: tab.label
|
|
1858
|
-
}),
|
|
1859
|
-
tab.isActive && /* @__PURE__ */ jsx4("button", {
|
|
1860
|
-
onClick: (e) => {
|
|
1861
|
-
e.stopPropagation();
|
|
1862
|
-
handleToggleScrollLock();
|
|
1863
|
-
},
|
|
1864
|
-
style: {
|
|
1865
|
-
display: "flex",
|
|
1866
|
-
alignItems: "center",
|
|
1867
|
-
justifyContent: "center",
|
|
1868
|
-
width: "16px",
|
|
1869
|
-
height: "16px",
|
|
1870
|
-
borderRadius: "3px",
|
|
1871
|
-
border: "none",
|
|
1872
|
-
backgroundColor: "transparent",
|
|
1873
|
-
cursor: "pointer",
|
|
1874
|
-
color: (scrollPositions.get(tab.id) ?? defaultScrollPosition).isScrollLocked ? theme.colors.success : theme.colors.warning,
|
|
1875
|
-
padding: 0,
|
|
1876
|
-
position: "absolute",
|
|
1877
|
-
right: "8px"
|
|
1878
|
-
},
|
|
1879
|
-
onMouseEnter: (e) => {
|
|
1880
|
-
e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
|
|
1881
|
-
},
|
|
1882
|
-
onMouseLeave: (e) => {
|
|
1883
|
-
e.currentTarget.style.backgroundColor = "transparent";
|
|
1884
|
-
},
|
|
1885
|
-
title: (scrollPositions.get(tab.id) ?? defaultScrollPosition).isScrollLocked ? "Scroll locked" : "Scroll unlocked",
|
|
1886
|
-
children: (scrollPositions.get(tab.id) ?? defaultScrollPosition).isScrollLocked ? /* @__PURE__ */ jsx4(Lock2, {
|
|
1887
|
-
size: 10
|
|
1888
|
-
}) : /* @__PURE__ */ jsx4(Unlock2, {
|
|
1889
|
-
size: 10
|
|
1890
|
-
})
|
|
1891
|
-
})
|
|
1892
|
-
]
|
|
1893
|
-
}, tab.id))
|
|
1894
|
-
}),
|
|
1895
|
-
/* @__PURE__ */ jsx4("div", {
|
|
1896
|
-
style: {
|
|
1897
|
-
display: "flex",
|
|
1898
|
-
alignItems: "center",
|
|
1899
|
-
gap: "4px",
|
|
1900
|
-
padding: "0 8px",
|
|
1901
|
-
borderLeft: `1px solid ${theme.colors.border}`,
|
|
1902
|
-
borderBottom: `1px solid ${theme.colors.border}`,
|
|
1903
|
-
boxSizing: "border-box"
|
|
2038
|
+
justifyContent: "center",
|
|
2039
|
+
width: "28px",
|
|
2040
|
+
height: "28px",
|
|
2041
|
+
border: "none",
|
|
2042
|
+
borderRadius: "4px",
|
|
2043
|
+
backgroundColor: showAllTerminals ? `${theme.colors.primary}22` : "transparent",
|
|
2044
|
+
cursor: "pointer",
|
|
2045
|
+
color: showAllTerminals ? theme.colors.primary : theme.colors.textSecondary
|
|
1904
2046
|
},
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
style: {
|
|
1908
|
-
display: "flex",
|
|
1909
|
-
alignItems: "center",
|
|
1910
|
-
justifyContent: "center",
|
|
1911
|
-
width: "28px",
|
|
1912
|
-
height: "28px",
|
|
1913
|
-
border: "none",
|
|
1914
|
-
borderRadius: "4px",
|
|
1915
|
-
backgroundColor: "transparent",
|
|
1916
|
-
cursor: "pointer",
|
|
1917
|
-
color: theme.colors.textSecondary
|
|
1918
|
-
},
|
|
1919
|
-
onMouseEnter: (e) => {
|
|
2047
|
+
onMouseEnter: (e) => {
|
|
2048
|
+
if (!showAllTerminals) {
|
|
1920
2049
|
e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
|
|
1921
|
-
}
|
|
1922
|
-
|
|
2050
|
+
}
|
|
2051
|
+
},
|
|
2052
|
+
onMouseLeave: (e) => {
|
|
2053
|
+
if (!showAllTerminals) {
|
|
1923
2054
|
e.currentTarget.style.backgroundColor = "transparent";
|
|
1924
|
-
}
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
2055
|
+
}
|
|
2056
|
+
},
|
|
2057
|
+
title: showAllTerminals ? "Showing all terminals (click to filter by context)" : "Show all terminals",
|
|
2058
|
+
children: showAllTerminals ? /* @__PURE__ */ jsx6(Boxes, {
|
|
2059
|
+
size: 14
|
|
2060
|
+
}) : /* @__PURE__ */ jsx6(Box, {
|
|
2061
|
+
size: 14
|
|
1929
2062
|
})
|
|
1930
|
-
})
|
|
1931
|
-
|
|
2063
|
+
}),
|
|
2064
|
+
renderTabAccessory,
|
|
2065
|
+
showKeyboardHints: false
|
|
2066
|
+
})
|
|
1932
2067
|
}),
|
|
1933
|
-
/* @__PURE__ */
|
|
2068
|
+
/* @__PURE__ */ jsxs5("div", {
|
|
1934
2069
|
style: {
|
|
1935
2070
|
flex: 1,
|
|
1936
2071
|
display: "flex",
|
|
@@ -1940,20 +2075,74 @@ var TabbedTerminalPanelInner = ({
|
|
|
1940
2075
|
minHeight: 0
|
|
1941
2076
|
},
|
|
1942
2077
|
children: [
|
|
1943
|
-
tabs.map((tab) =>
|
|
1944
|
-
|
|
1945
|
-
tab
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
2078
|
+
tabs.map((tab) => {
|
|
2079
|
+
const isActive = tab.id === activeTabId;
|
|
2080
|
+
const sessionId = sessionIds.get(tab.id) || null;
|
|
2081
|
+
if (renderTabContent) {
|
|
2082
|
+
const customContent = renderTabContent(tab, isActive, sessionId);
|
|
2083
|
+
if (customContent === null && tab.contentType === "terminal") {
|
|
2084
|
+
return /* @__PURE__ */ jsx6(TerminalTabContent, {
|
|
2085
|
+
ref: getRefCallback(tab.id),
|
|
2086
|
+
tab,
|
|
2087
|
+
sessionId,
|
|
2088
|
+
isActive,
|
|
2089
|
+
isVisible,
|
|
2090
|
+
actions,
|
|
2091
|
+
events,
|
|
2092
|
+
terminalContext,
|
|
2093
|
+
onSessionCreated: handleSessionCreated,
|
|
2094
|
+
onScrollPositionChange: handleTabScrollPositionChange,
|
|
2095
|
+
isForeign: tab.id.startsWith("tab-foreign-")
|
|
2096
|
+
}, tab.id);
|
|
2097
|
+
}
|
|
2098
|
+
return /* @__PURE__ */ jsx6("div", {
|
|
2099
|
+
style: {
|
|
2100
|
+
display: isActive ? "flex" : "none",
|
|
2101
|
+
flexDirection: "column",
|
|
2102
|
+
height: "100%",
|
|
2103
|
+
width: "100%"
|
|
2104
|
+
},
|
|
2105
|
+
children: customContent
|
|
2106
|
+
}, tab.id);
|
|
2107
|
+
}
|
|
2108
|
+
if (tab.contentType === "terminal") {
|
|
2109
|
+
return /* @__PURE__ */ jsx6(TerminalTabContent, {
|
|
2110
|
+
ref: getRefCallback(tab.id),
|
|
2111
|
+
tab,
|
|
2112
|
+
sessionId,
|
|
2113
|
+
isActive,
|
|
2114
|
+
isVisible,
|
|
2115
|
+
actions,
|
|
2116
|
+
events,
|
|
2117
|
+
terminalContext,
|
|
2118
|
+
onSessionCreated: handleSessionCreated,
|
|
2119
|
+
onScrollPositionChange: handleTabScrollPositionChange,
|
|
2120
|
+
isForeign: tab.id.startsWith("tab-foreign-")
|
|
2121
|
+
}, tab.id);
|
|
2122
|
+
}
|
|
2123
|
+
return /* @__PURE__ */ jsxs5("div", {
|
|
2124
|
+
style: {
|
|
2125
|
+
display: isActive ? "flex" : "none",
|
|
2126
|
+
alignItems: "center",
|
|
2127
|
+
justifyContent: "center",
|
|
2128
|
+
height: "100%",
|
|
2129
|
+
color: theme.colors.textSecondary
|
|
2130
|
+
},
|
|
2131
|
+
children: [
|
|
2132
|
+
/* @__PURE__ */ jsxs5("p", {
|
|
2133
|
+
children: [
|
|
2134
|
+
"Unknown content type: ",
|
|
2135
|
+
tab.contentType
|
|
2136
|
+
]
|
|
2137
|
+
}),
|
|
2138
|
+
/* @__PURE__ */ jsx6("p", {
|
|
2139
|
+
style: { fontSize: theme.fontSizes[0], marginTop: "8px" },
|
|
2140
|
+
children: "Provide a renderTabContent prop to render custom tab types"
|
|
2141
|
+
})
|
|
2142
|
+
]
|
|
2143
|
+
}, tab.id);
|
|
2144
|
+
}),
|
|
2145
|
+
tabs.length === 0 && /* @__PURE__ */ jsxs5("div", {
|
|
1957
2146
|
style: {
|
|
1958
2147
|
display: "flex",
|
|
1959
2148
|
flexDirection: "column",
|
|
@@ -1963,14 +2152,14 @@ var TabbedTerminalPanelInner = ({
|
|
|
1963
2152
|
color: theme.colors.textSecondary
|
|
1964
2153
|
},
|
|
1965
2154
|
children: [
|
|
1966
|
-
/* @__PURE__ */
|
|
2155
|
+
/* @__PURE__ */ jsx6(TerminalIcon2, {
|
|
1967
2156
|
size: 32,
|
|
1968
2157
|
style: { opacity: 0.5, marginBottom: "16px" }
|
|
1969
2158
|
}),
|
|
1970
|
-
/* @__PURE__ */
|
|
2159
|
+
/* @__PURE__ */ jsx6("p", {
|
|
1971
2160
|
children: "No terminal sessions"
|
|
1972
2161
|
}),
|
|
1973
|
-
/* @__PURE__ */
|
|
2162
|
+
/* @__PURE__ */ jsx6("button", {
|
|
1974
2163
|
onClick: () => addNewTab(),
|
|
1975
2164
|
style: {
|
|
1976
2165
|
marginTop: "16px",
|
|
@@ -1993,7 +2182,7 @@ var TabbedTerminalPanelInner = ({
|
|
|
1993
2182
|
});
|
|
1994
2183
|
};
|
|
1995
2184
|
TabbedTerminalPanelInner.displayName = "TabbedTerminalPanelInner";
|
|
1996
|
-
var
|
|
2185
|
+
var TabbedTerminalPanelMemoized = React2.memo(TabbedTerminalPanelInner, (prevProps, nextProps) => {
|
|
1997
2186
|
const changes = [];
|
|
1998
2187
|
if (prevProps.terminalContext !== nextProps.terminalContext)
|
|
1999
2188
|
changes.push("terminalContext");
|
|
@@ -2015,9 +2204,12 @@ var TabbedTerminalPanel = React.memo(TabbedTerminalPanelInner, (prevProps, nextP
|
|
|
2015
2204
|
changes.push("onShowAllTerminalsChange");
|
|
2016
2205
|
if (prevProps.initialTabs !== nextProps.initialTabs)
|
|
2017
2206
|
changes.push("initialTabs");
|
|
2207
|
+
if (prevProps.renderTabContent !== nextProps.renderTabContent)
|
|
2208
|
+
changes.push("renderTabContent");
|
|
2018
2209
|
return changes.length === 0;
|
|
2019
2210
|
});
|
|
2020
|
-
|
|
2211
|
+
TabbedTerminalPanelMemoized.displayName = "TabbedTerminalPanel";
|
|
2212
|
+
var TabbedTerminalPanel = TabbedTerminalPanelMemoized;
|
|
2021
2213
|
// src/tools/index.ts
|
|
2022
2214
|
var createTerminalSessionTool = {
|
|
2023
2215
|
name: "create_terminal_session",
|
|
@@ -2200,12 +2392,14 @@ var onPackageUnload = async () => {
|
|
|
2200
2392
|
export {
|
|
2201
2393
|
writeToTerminalTool,
|
|
2202
2394
|
useThemedTerminal,
|
|
2395
|
+
useTabKeyboardShortcuts,
|
|
2203
2396
|
terminalPanelToolsMetadata,
|
|
2204
2397
|
terminalPanelTools,
|
|
2205
2398
|
panels,
|
|
2206
2399
|
onPackageUnload,
|
|
2207
2400
|
onPackageLoad,
|
|
2208
2401
|
isTerminalLoading,
|
|
2402
|
+
isTabOfType,
|
|
2209
2403
|
getWorkspacePath,
|
|
2210
2404
|
getTerminalSlice,
|
|
2211
2405
|
getTerminalSessions,
|
|
@@ -2221,5 +2415,7 @@ export {
|
|
|
2221
2415
|
ThemedTerminalWithProvider,
|
|
2222
2416
|
ThemedTerminal,
|
|
2223
2417
|
TerminalPanel,
|
|
2224
|
-
TabbedTerminalPanel
|
|
2418
|
+
TabbedTerminalPanel,
|
|
2419
|
+
TabButton,
|
|
2420
|
+
TabBar
|
|
2225
2421
|
};
|