termbeam 1.5.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -32
- package/bin/termbeam.js +27 -12
- package/package.json +1 -1
- package/public/css/themes.css +217 -0
- package/public/index.html +42 -242
- package/public/js/keybar.js +180 -0
- package/public/js/search.js +95 -0
- package/public/js/shared.js +39 -0
- package/public/js/terminal-themes.js +291 -0
- package/public/js/themes.js +54 -0
- package/public/terminal.html +74 -873
- package/src/cli.js +6 -0
- package/src/git.js +125 -0
- package/src/interactive.js +269 -0
- package/src/prompts.js +146 -0
- package/src/service.js +13 -129
- package/src/sessions.js +86 -1
package/public/terminal.html
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
/>
|
|
16
16
|
<link rel="manifest" href="/manifest.json" />
|
|
17
17
|
<link rel="apple-touch-icon" href="/icons/icon-192.png" />
|
|
18
|
+
<link rel="stylesheet" href="/css/themes.css" />
|
|
18
19
|
<title>TermBeam — Terminal</title>
|
|
19
20
|
<link
|
|
20
21
|
rel="stylesheet"
|
|
@@ -22,257 +23,23 @@
|
|
|
22
23
|
/>
|
|
23
24
|
<style>
|
|
24
25
|
:root {
|
|
25
|
-
--bg: #1e1e1e;
|
|
26
|
-
--surface: #252526;
|
|
27
|
-
--border: #3c3c3c;
|
|
28
|
-
--border-subtle: #474747;
|
|
29
|
-
--text: #d4d4d4;
|
|
30
|
-
--text-secondary: #858585;
|
|
31
|
-
--text-dim: #6e6e6e;
|
|
32
|
-
--text-muted: #555555;
|
|
33
|
-
--accent: #0078d4;
|
|
34
|
-
--accent-hover: #1a8ae8;
|
|
35
|
-
--accent-active: #005a9e;
|
|
36
|
-
--danger: #f14c4c;
|
|
37
|
-
--danger-hover: #d73a3a;
|
|
38
|
-
--success: #89d185;
|
|
39
26
|
--key-bg: #4a4a4c;
|
|
40
27
|
--key-border: #5a5a5c;
|
|
41
28
|
--key-shadow: rgba(0, 0, 0, 0.5);
|
|
42
29
|
--key-special-bg: #333335;
|
|
43
30
|
--overlay-bg: rgba(0, 0, 0, 0.85);
|
|
44
31
|
}
|
|
45
|
-
[data-theme='light'] {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
--accent-active: #005a9e;
|
|
57
|
-
--danger: #e51400;
|
|
58
|
-
--danger-hover: #c20000;
|
|
59
|
-
--success: #16825d;
|
|
60
|
-
--key-bg: #ffffff;
|
|
61
|
-
--key-border: #b5b5b5;
|
|
62
|
-
--key-shadow: rgba(0, 0, 0, 0.12);
|
|
63
|
-
--key-special-bg: #adb5bd;
|
|
64
|
-
--overlay-bg: rgba(0, 0, 0, 0.5);
|
|
65
|
-
}
|
|
66
|
-
[data-theme='monokai'] {
|
|
67
|
-
--bg: #272822;
|
|
68
|
-
--surface: #1e1f1c;
|
|
69
|
-
--border: #49483e;
|
|
70
|
-
--border-subtle: #5c5c4f;
|
|
71
|
-
--text: #f8f8f2;
|
|
72
|
-
--text-secondary: #a59f85;
|
|
73
|
-
--text-dim: #75715e;
|
|
74
|
-
--text-muted: #5a5854;
|
|
75
|
-
--accent: #a6e22e;
|
|
76
|
-
--accent-hover: #b8f53c;
|
|
77
|
-
--accent-active: #8acc16;
|
|
78
|
-
--danger: #f92672;
|
|
79
|
-
--danger-hover: #e0155d;
|
|
80
|
-
--success: #a6e22e;
|
|
81
|
-
--key-bg: #49483e;
|
|
82
|
-
--key-border: #5c5c4f;
|
|
83
|
-
--key-shadow: rgba(0, 0, 0, 0.4);
|
|
84
|
-
--key-special-bg: #3e3d32;
|
|
85
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
86
|
-
}
|
|
87
|
-
[data-theme='solarized-dark'] {
|
|
88
|
-
--bg: #002b36;
|
|
89
|
-
--surface: #073642;
|
|
90
|
-
--border: #586e75;
|
|
91
|
-
--border-subtle: #657b83;
|
|
92
|
-
--text: #839496;
|
|
93
|
-
--text-secondary: #657b83;
|
|
94
|
-
--text-dim: #586e75;
|
|
95
|
-
--text-muted: #4a5a62;
|
|
96
|
-
--accent: #268bd2;
|
|
97
|
-
--accent-hover: #379ce3;
|
|
98
|
-
--accent-active: #1a7abf;
|
|
99
|
-
--danger: #dc322f;
|
|
100
|
-
--danger-hover: #c8221f;
|
|
101
|
-
--success: #859900;
|
|
102
|
-
--key-bg: #073642;
|
|
103
|
-
--key-border: #586e75;
|
|
104
|
-
--key-shadow: rgba(0, 0, 0, 0.3);
|
|
105
|
-
--key-special-bg: #002b36;
|
|
106
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
107
|
-
}
|
|
108
|
-
[data-theme='solarized-light'] {
|
|
109
|
-
--bg: #fdf6e3;
|
|
110
|
-
--surface: #eee8d5;
|
|
111
|
-
--border: #93a1a1;
|
|
112
|
-
--border-subtle: #839496;
|
|
113
|
-
--text: #657b83;
|
|
114
|
-
--text-secondary: #93a1a1;
|
|
115
|
-
--text-dim: #a0a0a0;
|
|
116
|
-
--text-muted: #b0b0b0;
|
|
117
|
-
--accent: #268bd2;
|
|
118
|
-
--accent-hover: #379ce3;
|
|
119
|
-
--accent-active: #1a7abf;
|
|
120
|
-
--danger: #dc322f;
|
|
121
|
-
--danger-hover: #c8221f;
|
|
122
|
-
--success: #859900;
|
|
123
|
-
--key-bg: #ffffff;
|
|
124
|
-
--key-border: #b5b5b5;
|
|
125
|
-
--key-shadow: rgba(0, 0, 0, 0.12);
|
|
126
|
-
--key-special-bg: #adb5bd;
|
|
127
|
-
--overlay-bg: rgba(0, 0, 0, 0.4);
|
|
128
|
-
}
|
|
129
|
-
[data-theme='nord'] {
|
|
130
|
-
--bg: #2e3440;
|
|
131
|
-
--surface: #3b4252;
|
|
132
|
-
--border: #434c5e;
|
|
133
|
-
--border-subtle: #4c566a;
|
|
134
|
-
--text: #d8dee9;
|
|
135
|
-
--text-secondary: #b0bac9;
|
|
136
|
-
--text-dim: #7b88a1;
|
|
137
|
-
--text-muted: #5c6a85;
|
|
138
|
-
--accent: #88c0d0;
|
|
139
|
-
--accent-hover: #9fd4e4;
|
|
140
|
-
--accent-active: #6aafbf;
|
|
141
|
-
--danger: #bf616a;
|
|
142
|
-
--danger-hover: #a84d57;
|
|
143
|
-
--success: #a3be8c;
|
|
144
|
-
--key-bg: #434c5e;
|
|
145
|
-
--key-border: #4c566a;
|
|
146
|
-
--key-shadow: rgba(0, 0, 0, 0.3);
|
|
147
|
-
--key-special-bg: #3b4252;
|
|
148
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
149
|
-
}
|
|
150
|
-
[data-theme='dracula'] {
|
|
151
|
-
--bg: #282a36;
|
|
152
|
-
--surface: #343746;
|
|
153
|
-
--border: #44475a;
|
|
154
|
-
--border-subtle: #525568;
|
|
155
|
-
--text: #f8f8f2;
|
|
156
|
-
--text-secondary: #c1c4d2;
|
|
157
|
-
--text-dim: #8e92a4;
|
|
158
|
-
--text-muted: #6272a4;
|
|
159
|
-
--accent: #bd93f9;
|
|
160
|
-
--accent-hover: #d0b0ff;
|
|
161
|
-
--accent-active: #a77de7;
|
|
162
|
-
--danger: #ff5555;
|
|
163
|
-
--danger-hover: #e03d3d;
|
|
164
|
-
--success: #50fa7b;
|
|
165
|
-
--key-bg: #44475a;
|
|
166
|
-
--key-border: #525568;
|
|
167
|
-
--key-shadow: rgba(0, 0, 0, 0.4);
|
|
168
|
-
--key-special-bg: #343746;
|
|
169
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
170
|
-
}
|
|
171
|
-
[data-theme='github-dark'] {
|
|
172
|
-
--bg: #0d1117;
|
|
173
|
-
--surface: #161b22;
|
|
174
|
-
--border: #30363d;
|
|
175
|
-
--border-subtle: #3d444d;
|
|
176
|
-
--text: #c9d1d9;
|
|
177
|
-
--text-secondary: #8b949e;
|
|
178
|
-
--text-dim: #6e7681;
|
|
179
|
-
--text-muted: #484f58;
|
|
180
|
-
--accent: #58a6ff;
|
|
181
|
-
--accent-hover: #79b8ff;
|
|
182
|
-
--accent-active: #388bfd;
|
|
183
|
-
--danger: #f85149;
|
|
184
|
-
--danger-hover: #da3633;
|
|
185
|
-
--success: #3fb950;
|
|
186
|
-
--key-bg: #161b22;
|
|
187
|
-
--key-border: #30363d;
|
|
188
|
-
--key-shadow: rgba(0, 0, 0, 0.4);
|
|
189
|
-
--key-special-bg: #0d1117;
|
|
190
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
191
|
-
}
|
|
192
|
-
[data-theme='one-dark'] {
|
|
193
|
-
--bg: #282c34;
|
|
194
|
-
--surface: #21252b;
|
|
195
|
-
--border: #3e4452;
|
|
196
|
-
--border-subtle: #4b5263;
|
|
197
|
-
--text: #abb2bf;
|
|
198
|
-
--text-secondary: #7f848e;
|
|
199
|
-
--text-dim: #5c6370;
|
|
200
|
-
--text-muted: #4b5263;
|
|
201
|
-
--accent: #61afef;
|
|
202
|
-
--accent-hover: #7dc0ff;
|
|
203
|
-
--accent-active: #4d9ede;
|
|
204
|
-
--danger: #e06c75;
|
|
205
|
-
--danger-hover: #c95c67;
|
|
206
|
-
--success: #98c379;
|
|
207
|
-
--key-bg: #3e4452;
|
|
208
|
-
--key-border: #4b5263;
|
|
209
|
-
--key-shadow: rgba(0, 0, 0, 0.3);
|
|
210
|
-
--key-special-bg: #21252b;
|
|
211
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
212
|
-
}
|
|
213
|
-
[data-theme='catppuccin'] {
|
|
214
|
-
--bg: #1e1e2e;
|
|
215
|
-
--surface: #313244;
|
|
216
|
-
--border: #45475a;
|
|
217
|
-
--border-subtle: #585b70;
|
|
218
|
-
--text: #cdd6f4;
|
|
219
|
-
--text-secondary: #a6adc8;
|
|
220
|
-
--text-dim: #7f849c;
|
|
221
|
-
--text-muted: #585b70;
|
|
222
|
-
--accent: #89b4fa;
|
|
223
|
-
--accent-hover: #b4d0ff;
|
|
224
|
-
--accent-active: #5c9de3;
|
|
225
|
-
--danger: #f38ba8;
|
|
226
|
-
--danger-hover: #eb7c9d;
|
|
227
|
-
--success: #a6e3a1;
|
|
228
|
-
--key-bg: #45475a;
|
|
229
|
-
--key-border: #585b70;
|
|
230
|
-
--key-shadow: rgba(0, 0, 0, 0.3);
|
|
231
|
-
--key-special-bg: #313244;
|
|
232
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
233
|
-
}
|
|
234
|
-
[data-theme='gruvbox'] {
|
|
235
|
-
--bg: #282828;
|
|
236
|
-
--surface: #3c3836;
|
|
237
|
-
--border: #504945;
|
|
238
|
-
--border-subtle: #665c54;
|
|
239
|
-
--text: #ebdbb2;
|
|
240
|
-
--text-secondary: #d5c4a1;
|
|
241
|
-
--text-dim: #a89984;
|
|
242
|
-
--text-muted: #7c6f64;
|
|
243
|
-
--accent: #83a598;
|
|
244
|
-
--accent-hover: #9dbfb4;
|
|
245
|
-
--accent-active: #6a8f8a;
|
|
246
|
-
--danger: #fb4934;
|
|
247
|
-
--danger-hover: #e33826;
|
|
248
|
-
--success: #b8bb26;
|
|
249
|
-
--key-bg: #504945;
|
|
250
|
-
--key-border: #665c54;
|
|
251
|
-
--key-shadow: rgba(0, 0, 0, 0.4);
|
|
252
|
-
--key-special-bg: #3c3836;
|
|
253
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
254
|
-
}
|
|
255
|
-
[data-theme='night-owl'] {
|
|
256
|
-
--bg: #011627;
|
|
257
|
-
--surface: #0d2a45;
|
|
258
|
-
--border: #1d3b53;
|
|
259
|
-
--border-subtle: #264863;
|
|
260
|
-
--text: #d6deeb;
|
|
261
|
-
--text-secondary: #8badc1;
|
|
262
|
-
--text-dim: #5f7e97;
|
|
263
|
-
--text-muted: #3f5f7d;
|
|
264
|
-
--accent: #7fdbca;
|
|
265
|
-
--accent-hover: #9ff0e0;
|
|
266
|
-
--accent-active: #62c5b5;
|
|
267
|
-
--danger: #ef5350;
|
|
268
|
-
--danger-hover: #d83130;
|
|
269
|
-
--success: #addb67;
|
|
270
|
-
--key-bg: #1d3b53;
|
|
271
|
-
--key-border: #264863;
|
|
272
|
-
--key-shadow: rgba(0, 0, 0, 0.4);
|
|
273
|
-
--key-special-bg: #0d2a45;
|
|
274
|
-
--overlay-bg: rgba(0, 0, 0, 0.75);
|
|
275
|
-
}
|
|
32
|
+
[data-theme='light'] { --key-bg: #ffffff; --key-border: #b5b5b5; --key-shadow: rgba(0, 0, 0, 0.12); --key-special-bg: #adb5bd; --overlay-bg: rgba(0, 0, 0, 0.5); }
|
|
33
|
+
[data-theme='monokai'] { --key-bg: #49483e; --key-border: #5c5c4f; --key-shadow: rgba(0, 0, 0, 0.4); --key-special-bg: #3e3d32; }
|
|
34
|
+
[data-theme='solarized-dark'] { --key-bg: #073642; --key-border: #586e75; --key-shadow: rgba(0, 0, 0, 0.3); --key-special-bg: #002b36; }
|
|
35
|
+
[data-theme='solarized-light'] { --key-bg: #ffffff; --key-border: #b5b5b5; --key-shadow: rgba(0, 0, 0, 0.12); --key-special-bg: #adb5bd; }
|
|
36
|
+
[data-theme='nord'] { --key-bg: #434c5e; --key-border: #4c566a; --key-shadow: rgba(0, 0, 0, 0.3); --key-special-bg: #3b4252; }
|
|
37
|
+
[data-theme='dracula'] { --key-bg: #44475a; --key-border: #525568; --key-shadow: rgba(0, 0, 0, 0.4); --key-special-bg: #343746; }
|
|
38
|
+
[data-theme='github-dark'] { --key-bg: #161b22; --key-border: #30363d; --key-shadow: rgba(0, 0, 0, 0.4); --key-special-bg: #0d1117; }
|
|
39
|
+
[data-theme='one-dark'] { --key-bg: #3e4452; --key-border: #4b5263; --key-shadow: rgba(0, 0, 0, 0.3); --key-special-bg: #21252b; }
|
|
40
|
+
[data-theme='catppuccin'] { --key-bg: #45475a; --key-border: #585b70; --key-shadow: rgba(0, 0, 0, 0.3); --key-special-bg: #313244; }
|
|
41
|
+
[data-theme='gruvbox'] { --key-bg: #504945; --key-border: #665c54; --key-shadow: rgba(0, 0, 0, 0.4); --key-special-bg: #3c3836; }
|
|
42
|
+
[data-theme='night-owl'] { --key-bg: #1d3b53; --key-border: #264863; --key-shadow: rgba(0, 0, 0, 0.4); --key-special-bg: #0d2a45; }
|
|
276
43
|
@font-face {
|
|
277
44
|
font-family: 'NerdFont';
|
|
278
45
|
src: url('https://cdn.jsdelivr.net/gh/ryanoasis/nerd-fonts@latest/patched-fonts/JetBrainsMono/Ligatures/Regular/JetBrainsMonoNerdFont-Regular.ttf')
|
|
@@ -1730,6 +1497,30 @@
|
|
|
1730
1497
|
white-space: normal;
|
|
1731
1498
|
}
|
|
1732
1499
|
|
|
1500
|
+
.side-panel-card-git {
|
|
1501
|
+
display: flex;
|
|
1502
|
+
flex-wrap: wrap;
|
|
1503
|
+
gap: 3px 6px;
|
|
1504
|
+
padding: 0 12px 4px;
|
|
1505
|
+
font-size: 10px;
|
|
1506
|
+
color: var(--text-secondary);
|
|
1507
|
+
align-items: center;
|
|
1508
|
+
}
|
|
1509
|
+
.side-panel-card-git .git-badge {
|
|
1510
|
+
display: inline-flex;
|
|
1511
|
+
align-items: center;
|
|
1512
|
+
gap: 3px;
|
|
1513
|
+
background: var(--surface);
|
|
1514
|
+
padding: 1px 6px;
|
|
1515
|
+
border-radius: 3px;
|
|
1516
|
+
}
|
|
1517
|
+
.side-panel-card-git .git-status-clean {
|
|
1518
|
+
color: var(--success);
|
|
1519
|
+
}
|
|
1520
|
+
.side-panel-card-git .git-status-dirty {
|
|
1521
|
+
color: var(--warning, #fbbf24);
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1733
1524
|
@media (max-width: 640px) {
|
|
1734
1525
|
#panel-toggle {
|
|
1735
1526
|
display: flex;
|
|
@@ -2452,6 +2243,11 @@
|
|
|
2452
2243
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.10.0/lib/addon-fit.min.js"></script>
|
|
2453
2244
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0.11.0/lib/addon-web-links.min.js"></script>
|
|
2454
2245
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-search@0.15.0/lib/addon-search.min.js"></script>
|
|
2246
|
+
<script src="/js/shared.js"></script>
|
|
2247
|
+
<script src="/js/themes.js"></script>
|
|
2248
|
+
<script src="/js/terminal-themes.js"></script>
|
|
2249
|
+
<script src="/js/keybar.js"></script>
|
|
2250
|
+
<script src="/js/search.js"></script>
|
|
2455
2251
|
<script>
|
|
2456
2252
|
// ===== Constants =====
|
|
2457
2253
|
const SESSION_COLORS = [
|
|
@@ -2513,6 +2309,14 @@
|
|
|
2513
2309
|
document.body.removeChild(ta);
|
|
2514
2310
|
}
|
|
2515
2311
|
|
|
2312
|
+
// Hook into shared theme system to update xterm terminal themes
|
|
2313
|
+
window.onThemeApplied = function (theme) {
|
|
2314
|
+
const termTheme = TERM_THEMES[theme] || darkTermTheme;
|
|
2315
|
+
for (const [, ms] of managed) {
|
|
2316
|
+
ms.term.options.theme = termTheme;
|
|
2317
|
+
}
|
|
2318
|
+
};
|
|
2319
|
+
|
|
2516
2320
|
// ===== DOM Refs =====
|
|
2517
2321
|
const statusDot = document.getElementById('status-dot');
|
|
2518
2322
|
const statusText = document.getElementById('status-text');
|
|
@@ -2521,433 +2325,6 @@
|
|
|
2521
2325
|
const tabListEl = document.getElementById('tab-list');
|
|
2522
2326
|
const terminalsWrapper = document.getElementById('terminals-wrapper');
|
|
2523
2327
|
|
|
2524
|
-
// ===== Terminal Themes =====
|
|
2525
|
-
const darkTermTheme = {
|
|
2526
|
-
background: '#1e1e1e',
|
|
2527
|
-
foreground: '#d4d4d4',
|
|
2528
|
-
cursor: '#aeafad',
|
|
2529
|
-
cursorAccent: '#1e1e1e',
|
|
2530
|
-
selectionBackground: 'rgba(38, 79, 120, 0.5)',
|
|
2531
|
-
black: '#000000',
|
|
2532
|
-
red: '#cd3131',
|
|
2533
|
-
green: '#0dbc79',
|
|
2534
|
-
yellow: '#e5e510',
|
|
2535
|
-
blue: '#2472c8',
|
|
2536
|
-
magenta: '#bc3fbc',
|
|
2537
|
-
cyan: '#11a8cd',
|
|
2538
|
-
white: '#e5e5e5',
|
|
2539
|
-
brightBlack: '#666666',
|
|
2540
|
-
brightRed: '#f14c4c',
|
|
2541
|
-
brightGreen: '#23d18b',
|
|
2542
|
-
brightYellow: '#f5f543',
|
|
2543
|
-
brightBlue: '#3b8eea',
|
|
2544
|
-
brightMagenta: '#d670d6',
|
|
2545
|
-
brightCyan: '#29b8db',
|
|
2546
|
-
brightWhite: '#e5e5e5',
|
|
2547
|
-
};
|
|
2548
|
-
const lightTermTheme = {
|
|
2549
|
-
background: '#ffffff',
|
|
2550
|
-
foreground: '#1e1e1e',
|
|
2551
|
-
cursor: '#000000',
|
|
2552
|
-
cursorAccent: '#ffffff',
|
|
2553
|
-
selectionBackground: 'rgba(0, 120, 215, 0.3)',
|
|
2554
|
-
black: '#000000',
|
|
2555
|
-
red: '#cd3131',
|
|
2556
|
-
green: '#00bc7c',
|
|
2557
|
-
yellow: '#949800',
|
|
2558
|
-
blue: '#0451a5',
|
|
2559
|
-
magenta: '#bc05bc',
|
|
2560
|
-
cyan: '#0598bc',
|
|
2561
|
-
white: '#555555',
|
|
2562
|
-
brightBlack: '#666666',
|
|
2563
|
-
brightRed: '#cd3131',
|
|
2564
|
-
brightGreen: '#14ce14',
|
|
2565
|
-
brightYellow: '#b5ba00',
|
|
2566
|
-
brightBlue: '#0451a5',
|
|
2567
|
-
brightMagenta: '#bc05bc',
|
|
2568
|
-
brightCyan: '#0598bc',
|
|
2569
|
-
brightWhite: '#a5a5a5',
|
|
2570
|
-
};
|
|
2571
|
-
const monokaiTermTheme = {
|
|
2572
|
-
background: '#272822',
|
|
2573
|
-
foreground: '#f8f8f2',
|
|
2574
|
-
cursor: '#f8f8f0',
|
|
2575
|
-
cursorAccent: '#272822',
|
|
2576
|
-
selectionBackground: 'rgba(166, 226, 46, 0.3)',
|
|
2577
|
-
black: '#272822',
|
|
2578
|
-
red: '#f92672',
|
|
2579
|
-
green: '#a6e22e',
|
|
2580
|
-
yellow: '#f4bf75',
|
|
2581
|
-
blue: '#66d9e8',
|
|
2582
|
-
magenta: '#ae81ff',
|
|
2583
|
-
cyan: '#a1efe4',
|
|
2584
|
-
white: '#f8f8f2',
|
|
2585
|
-
brightBlack: '#75715e',
|
|
2586
|
-
brightRed: '#f92672',
|
|
2587
|
-
brightGreen: '#a6e22e',
|
|
2588
|
-
brightYellow: '#f4bf75',
|
|
2589
|
-
brightBlue: '#66d9e8',
|
|
2590
|
-
brightMagenta: '#ae81ff',
|
|
2591
|
-
brightCyan: '#a1efe4',
|
|
2592
|
-
brightWhite: '#f9f8f5',
|
|
2593
|
-
};
|
|
2594
|
-
const solarizedDarkTermTheme = {
|
|
2595
|
-
background: '#002b36',
|
|
2596
|
-
foreground: '#839496',
|
|
2597
|
-
cursor: '#839496',
|
|
2598
|
-
cursorAccent: '#002b36',
|
|
2599
|
-
selectionBackground: 'rgba(7, 54, 66, 0.8)',
|
|
2600
|
-
black: '#073642',
|
|
2601
|
-
red: '#dc322f',
|
|
2602
|
-
green: '#859900',
|
|
2603
|
-
yellow: '#b58900',
|
|
2604
|
-
blue: '#268bd2',
|
|
2605
|
-
magenta: '#d33682',
|
|
2606
|
-
cyan: '#2aa198',
|
|
2607
|
-
white: '#eee8d5',
|
|
2608
|
-
brightBlack: '#002b36',
|
|
2609
|
-
brightRed: '#cb4b16',
|
|
2610
|
-
brightGreen: '#586e75',
|
|
2611
|
-
brightYellow: '#657b83',
|
|
2612
|
-
brightBlue: '#839496',
|
|
2613
|
-
brightMagenta: '#6c71c4',
|
|
2614
|
-
brightCyan: '#93a1a1',
|
|
2615
|
-
brightWhite: '#fdf6e3',
|
|
2616
|
-
};
|
|
2617
|
-
const solarizedLightTermTheme = {
|
|
2618
|
-
background: '#fdf6e3',
|
|
2619
|
-
foreground: '#657b83',
|
|
2620
|
-
cursor: '#586e75',
|
|
2621
|
-
cursorAccent: '#fdf6e3',
|
|
2622
|
-
selectionBackground: 'rgba(238, 232, 213, 0.8)',
|
|
2623
|
-
black: '#073642',
|
|
2624
|
-
red: '#dc322f',
|
|
2625
|
-
green: '#859900',
|
|
2626
|
-
yellow: '#b58900',
|
|
2627
|
-
blue: '#268bd2',
|
|
2628
|
-
magenta: '#d33682',
|
|
2629
|
-
cyan: '#2aa198',
|
|
2630
|
-
white: '#eee8d5',
|
|
2631
|
-
brightBlack: '#002b36',
|
|
2632
|
-
brightRed: '#cb4b16',
|
|
2633
|
-
brightGreen: '#586e75',
|
|
2634
|
-
brightYellow: '#657b83',
|
|
2635
|
-
brightBlue: '#839496',
|
|
2636
|
-
brightMagenta: '#6c71c4',
|
|
2637
|
-
brightCyan: '#93a1a1',
|
|
2638
|
-
brightWhite: '#fdf6e3',
|
|
2639
|
-
};
|
|
2640
|
-
const nordTermTheme = {
|
|
2641
|
-
background: '#2e3440',
|
|
2642
|
-
foreground: '#d8dee9',
|
|
2643
|
-
cursor: '#d8dee9',
|
|
2644
|
-
cursorAccent: '#2e3440',
|
|
2645
|
-
selectionBackground: 'rgba(67, 76, 94, 0.5)',
|
|
2646
|
-
black: '#3b4252',
|
|
2647
|
-
red: '#bf616a',
|
|
2648
|
-
green: '#a3be8c',
|
|
2649
|
-
yellow: '#ebcb8b',
|
|
2650
|
-
blue: '#81a1c1',
|
|
2651
|
-
magenta: '#b48ead',
|
|
2652
|
-
cyan: '#88c0d0',
|
|
2653
|
-
white: '#e5e9f0',
|
|
2654
|
-
brightBlack: '#4c566a',
|
|
2655
|
-
brightRed: '#bf616a',
|
|
2656
|
-
brightGreen: '#a3be8c',
|
|
2657
|
-
brightYellow: '#ebcb8b',
|
|
2658
|
-
brightBlue: '#81a1c1',
|
|
2659
|
-
brightMagenta: '#b48ead',
|
|
2660
|
-
brightCyan: '#8fbcbb',
|
|
2661
|
-
brightWhite: '#eceff4',
|
|
2662
|
-
};
|
|
2663
|
-
const draculaTermTheme = {
|
|
2664
|
-
background: '#282a36',
|
|
2665
|
-
foreground: '#f8f8f2',
|
|
2666
|
-
cursor: '#f8f8f2',
|
|
2667
|
-
cursorAccent: '#282a36',
|
|
2668
|
-
selectionBackground: 'rgba(68, 71, 90, 0.7)',
|
|
2669
|
-
black: '#21222c',
|
|
2670
|
-
red: '#ff5555',
|
|
2671
|
-
green: '#50fa7b',
|
|
2672
|
-
yellow: '#f1fa8c',
|
|
2673
|
-
blue: '#bd93f9',
|
|
2674
|
-
magenta: '#ff79c6',
|
|
2675
|
-
cyan: '#8be9fd',
|
|
2676
|
-
white: '#f8f8f2',
|
|
2677
|
-
brightBlack: '#6272a4',
|
|
2678
|
-
brightRed: '#ff6e6e',
|
|
2679
|
-
brightGreen: '#69ff94',
|
|
2680
|
-
brightYellow: '#ffffa5',
|
|
2681
|
-
brightBlue: '#d6acff',
|
|
2682
|
-
brightMagenta: '#ff92df',
|
|
2683
|
-
brightCyan: '#a4ffff',
|
|
2684
|
-
brightWhite: '#ffffff',
|
|
2685
|
-
};
|
|
2686
|
-
const githubDarkTermTheme = {
|
|
2687
|
-
background: '#0d1117',
|
|
2688
|
-
foreground: '#c9d1d9',
|
|
2689
|
-
cursor: '#c9d1d9',
|
|
2690
|
-
cursorAccent: '#0d1117',
|
|
2691
|
-
selectionBackground: 'rgba(56, 139, 253, 0.3)',
|
|
2692
|
-
black: '#484f58',
|
|
2693
|
-
red: '#ff7b72',
|
|
2694
|
-
green: '#3fb950',
|
|
2695
|
-
yellow: '#d29922',
|
|
2696
|
-
blue: '#58a6ff',
|
|
2697
|
-
magenta: '#bc8cff',
|
|
2698
|
-
cyan: '#39c5cf',
|
|
2699
|
-
white: '#c9d1d9',
|
|
2700
|
-
brightBlack: '#6e7681',
|
|
2701
|
-
brightRed: '#ffa198',
|
|
2702
|
-
brightGreen: '#56d364',
|
|
2703
|
-
brightYellow: '#e3b341',
|
|
2704
|
-
brightBlue: '#79c0ff',
|
|
2705
|
-
brightMagenta: '#d2a8ff',
|
|
2706
|
-
brightCyan: '#56d4dd',
|
|
2707
|
-
brightWhite: '#f0f6fc',
|
|
2708
|
-
};
|
|
2709
|
-
const oneDarkTermTheme = {
|
|
2710
|
-
background: '#282c34',
|
|
2711
|
-
foreground: '#abb2bf',
|
|
2712
|
-
cursor: '#528bff',
|
|
2713
|
-
cursorAccent: '#282c34',
|
|
2714
|
-
selectionBackground: 'rgba(62, 68, 82, 0.7)',
|
|
2715
|
-
black: '#3f4451',
|
|
2716
|
-
red: '#e06c75',
|
|
2717
|
-
green: '#98c379',
|
|
2718
|
-
yellow: '#e5c07b',
|
|
2719
|
-
blue: '#61afef',
|
|
2720
|
-
magenta: '#c678dd',
|
|
2721
|
-
cyan: '#56b6c2',
|
|
2722
|
-
white: '#d7dae0',
|
|
2723
|
-
brightBlack: '#4f5666',
|
|
2724
|
-
brightRed: '#e06c75',
|
|
2725
|
-
brightGreen: '#98c379',
|
|
2726
|
-
brightYellow: '#e5c07b',
|
|
2727
|
-
brightBlue: '#61afef',
|
|
2728
|
-
brightMagenta: '#c678dd',
|
|
2729
|
-
brightCyan: '#56b6c2',
|
|
2730
|
-
brightWhite: '#ffffff',
|
|
2731
|
-
};
|
|
2732
|
-
const catppuccinTermTheme = {
|
|
2733
|
-
background: '#1e1e2e',
|
|
2734
|
-
foreground: '#cdd6f4',
|
|
2735
|
-
cursor: '#f5e0dc',
|
|
2736
|
-
cursorAccent: '#1e1e2e',
|
|
2737
|
-
selectionBackground: 'rgba(88, 91, 112, 0.5)',
|
|
2738
|
-
black: '#45475a',
|
|
2739
|
-
red: '#f38ba8',
|
|
2740
|
-
green: '#a6e3a1',
|
|
2741
|
-
yellow: '#f9e2af',
|
|
2742
|
-
blue: '#89b4fa',
|
|
2743
|
-
magenta: '#f5c2e7',
|
|
2744
|
-
cyan: '#94e2d5',
|
|
2745
|
-
white: '#bac2de',
|
|
2746
|
-
brightBlack: '#585b70',
|
|
2747
|
-
brightRed: '#f38ba8',
|
|
2748
|
-
brightGreen: '#a6e3a1',
|
|
2749
|
-
brightYellow: '#f9e2af',
|
|
2750
|
-
brightBlue: '#89b4fa',
|
|
2751
|
-
brightMagenta: '#f5c2e7',
|
|
2752
|
-
brightCyan: '#94e2d5',
|
|
2753
|
-
brightWhite: '#a6adc8',
|
|
2754
|
-
};
|
|
2755
|
-
const gruvboxTermTheme = {
|
|
2756
|
-
background: '#282828',
|
|
2757
|
-
foreground: '#ebdbb2',
|
|
2758
|
-
cursor: '#ebdbb2',
|
|
2759
|
-
cursorAccent: '#282828',
|
|
2760
|
-
selectionBackground: 'rgba(80, 73, 69, 0.7)',
|
|
2761
|
-
black: '#282828',
|
|
2762
|
-
red: '#cc241d',
|
|
2763
|
-
green: '#98971a',
|
|
2764
|
-
yellow: '#d79921',
|
|
2765
|
-
blue: '#458588',
|
|
2766
|
-
magenta: '#b16286',
|
|
2767
|
-
cyan: '#689d6a',
|
|
2768
|
-
white: '#a89984',
|
|
2769
|
-
brightBlack: '#928374',
|
|
2770
|
-
brightRed: '#fb4934',
|
|
2771
|
-
brightGreen: '#b8bb26',
|
|
2772
|
-
brightYellow: '#fabd2f',
|
|
2773
|
-
brightBlue: '#83a598',
|
|
2774
|
-
brightMagenta: '#d3869b',
|
|
2775
|
-
brightCyan: '#8ec07c',
|
|
2776
|
-
brightWhite: '#ebdbb2',
|
|
2777
|
-
};
|
|
2778
|
-
const nightOwlTermTheme = {
|
|
2779
|
-
background: '#011627',
|
|
2780
|
-
foreground: '#d6deeb',
|
|
2781
|
-
cursor: '#80a4c2',
|
|
2782
|
-
cursorAccent: '#011627',
|
|
2783
|
-
selectionBackground: 'rgba(29, 59, 83, 0.7)',
|
|
2784
|
-
black: '#010e1a',
|
|
2785
|
-
red: '#ef5350',
|
|
2786
|
-
green: '#22da6e',
|
|
2787
|
-
yellow: '#addb67',
|
|
2788
|
-
blue: '#82aaff',
|
|
2789
|
-
magenta: '#c792ea',
|
|
2790
|
-
cyan: '#21c7a8',
|
|
2791
|
-
white: '#d6deeb',
|
|
2792
|
-
brightBlack: '#575656',
|
|
2793
|
-
brightRed: '#ef5350',
|
|
2794
|
-
brightGreen: '#22da6e',
|
|
2795
|
-
brightYellow: '#ffeb95',
|
|
2796
|
-
brightBlue: '#82aaff',
|
|
2797
|
-
brightMagenta: '#c792ea',
|
|
2798
|
-
brightCyan: '#7fdbca',
|
|
2799
|
-
brightWhite: '#ffffff',
|
|
2800
|
-
};
|
|
2801
|
-
const TERM_THEMES = {
|
|
2802
|
-
dark: darkTermTheme,
|
|
2803
|
-
light: lightTermTheme,
|
|
2804
|
-
monokai: monokaiTermTheme,
|
|
2805
|
-
'solarized-dark': solarizedDarkTermTheme,
|
|
2806
|
-
'solarized-light': solarizedLightTermTheme,
|
|
2807
|
-
nord: nordTermTheme,
|
|
2808
|
-
dracula: draculaTermTheme,
|
|
2809
|
-
'github-dark': githubDarkTermTheme,
|
|
2810
|
-
'one-dark': oneDarkTermTheme,
|
|
2811
|
-
catppuccin: catppuccinTermTheme,
|
|
2812
|
-
gruvbox: gruvboxTermTheme,
|
|
2813
|
-
'night-owl': nightOwlTermTheme,
|
|
2814
|
-
};
|
|
2815
|
-
|
|
2816
|
-
// ===== Theme =====
|
|
2817
|
-
const THEMES = [
|
|
2818
|
-
{ id: 'dark', name: 'Dark', bg: '#1e1e1e' },
|
|
2819
|
-
{ id: 'light', name: 'Light', bg: '#f3f3f3' },
|
|
2820
|
-
{ id: 'monokai', name: 'Monokai', bg: '#272822' },
|
|
2821
|
-
{ id: 'solarized-dark', name: 'Solarized Dark', bg: '#002b36' },
|
|
2822
|
-
{ id: 'solarized-light', name: 'Solarized Light', bg: '#fdf6e3' },
|
|
2823
|
-
{ id: 'nord', name: 'Nord', bg: '#2e3440' },
|
|
2824
|
-
{ id: 'dracula', name: 'Dracula', bg: '#282a36' },
|
|
2825
|
-
{ id: 'github-dark', name: 'GitHub Dark', bg: '#0d1117' },
|
|
2826
|
-
{ id: 'one-dark', name: 'One Dark', bg: '#282c34' },
|
|
2827
|
-
{ id: 'catppuccin', name: 'Catppuccin', bg: '#1e1e2e' },
|
|
2828
|
-
{ id: 'gruvbox', name: 'Gruvbox', bg: '#282828' },
|
|
2829
|
-
{ id: 'night-owl', name: 'Night Owl', bg: '#011627' },
|
|
2830
|
-
];
|
|
2831
|
-
function getTheme() {
|
|
2832
|
-
return localStorage.getItem('termbeam-theme') || 'dark';
|
|
2833
|
-
}
|
|
2834
|
-
function applyTheme(theme) {
|
|
2835
|
-
document.documentElement.setAttribute('data-theme', theme);
|
|
2836
|
-
const t = THEMES.find((x) => x.id === theme) || THEMES[0];
|
|
2837
|
-
document.querySelector('meta[name="theme-color"]').content = t.bg;
|
|
2838
|
-
localStorage.setItem('termbeam-theme', theme);
|
|
2839
|
-
document.querySelectorAll('.theme-option').forEach((el) => {
|
|
2840
|
-
el.classList.toggle('active', el.dataset.themeOption === theme);
|
|
2841
|
-
});
|
|
2842
|
-
const termTheme = TERM_THEMES[theme] || darkTermTheme;
|
|
2843
|
-
for (const [, ms] of managed) {
|
|
2844
|
-
ms.term.options.theme = termTheme;
|
|
2845
|
-
}
|
|
2846
|
-
}
|
|
2847
|
-
applyTheme(getTheme());
|
|
2848
|
-
document.getElementById('theme-toggle').addEventListener('click', (e) => {
|
|
2849
|
-
e.stopPropagation();
|
|
2850
|
-
document.getElementById('theme-picker').classList.toggle('open');
|
|
2851
|
-
});
|
|
2852
|
-
document.addEventListener('click', () => {
|
|
2853
|
-
document.getElementById('theme-picker').classList.remove('open');
|
|
2854
|
-
});
|
|
2855
|
-
document.querySelectorAll('.theme-option').forEach((el) => {
|
|
2856
|
-
el.addEventListener('click', (e) => {
|
|
2857
|
-
e.stopPropagation();
|
|
2858
|
-
applyTheme(el.dataset.themeOption);
|
|
2859
|
-
});
|
|
2860
|
-
});
|
|
2861
|
-
|
|
2862
|
-
// ===== Terminal Search =====
|
|
2863
|
-
const searchBar = document.getElementById('search-bar');
|
|
2864
|
-
const searchInput = document.getElementById('search-input');
|
|
2865
|
-
const searchCount = document.getElementById('search-count');
|
|
2866
|
-
const searchRegexBtn = document.getElementById('search-regex');
|
|
2867
|
-
let searchRegex = false;
|
|
2868
|
-
let searchResultIndex = 0;
|
|
2869
|
-
let searchResultTotal = 0;
|
|
2870
|
-
|
|
2871
|
-
function getActiveSearchAddon() {
|
|
2872
|
-
if (!activeId) return null;
|
|
2873
|
-
const ms = managed.get(activeId);
|
|
2874
|
-
return ms ? ms.searchAddon : null;
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
|
-
function updateSearchCount(idx, total) {
|
|
2878
|
-
searchResultIndex = idx;
|
|
2879
|
-
searchResultTotal = total;
|
|
2880
|
-
searchCount.textContent = total > 0 ? idx + 1 + ' of ' + total : 'No results';
|
|
2881
|
-
}
|
|
2882
|
-
|
|
2883
|
-
function doSearch(direction) {
|
|
2884
|
-
const addon = getActiveSearchAddon();
|
|
2885
|
-
if (!addon) return;
|
|
2886
|
-
const query = searchInput.value;
|
|
2887
|
-
if (!query) {
|
|
2888
|
-
searchCount.textContent = '';
|
|
2889
|
-
return;
|
|
2890
|
-
}
|
|
2891
|
-
const opts = {
|
|
2892
|
-
regex: searchRegex,
|
|
2893
|
-
caseSensitive: false,
|
|
2894
|
-
incremental: direction === 'next',
|
|
2895
|
-
};
|
|
2896
|
-
let result;
|
|
2897
|
-
if (direction === 'prev') {
|
|
2898
|
-
result = addon.findPrevious(query, opts);
|
|
2899
|
-
} else {
|
|
2900
|
-
result = addon.findNext(query, opts);
|
|
2901
|
-
}
|
|
2902
|
-
// SearchAddon returns boolean; no match count API in v0.15
|
|
2903
|
-
searchCount.textContent = result ? 'Found' : 'No results';
|
|
2904
|
-
}
|
|
2905
|
-
|
|
2906
|
-
function openSearchBar() {
|
|
2907
|
-
searchBar.classList.add('visible');
|
|
2908
|
-
searchInput.focus();
|
|
2909
|
-
searchInput.select();
|
|
2910
|
-
}
|
|
2911
|
-
|
|
2912
|
-
function closeSearchBar() {
|
|
2913
|
-
searchBar.classList.remove('visible');
|
|
2914
|
-
searchCount.textContent = '';
|
|
2915
|
-
searchInput.value = '';
|
|
2916
|
-
const addon = getActiveSearchAddon();
|
|
2917
|
-
if (addon) addon.clearDecorations();
|
|
2918
|
-
// Re-focus terminal
|
|
2919
|
-
if (activeId) {
|
|
2920
|
-
const ms = managed.get(activeId);
|
|
2921
|
-
if (ms) ms.term.focus();
|
|
2922
|
-
}
|
|
2923
|
-
}
|
|
2924
|
-
|
|
2925
|
-
searchInput.addEventListener('input', () => doSearch('next'));
|
|
2926
|
-
searchInput.addEventListener('keydown', (e) => {
|
|
2927
|
-
if (e.key === 'Escape') {
|
|
2928
|
-
closeSearchBar();
|
|
2929
|
-
e.preventDefault();
|
|
2930
|
-
} else if (e.key === 'Enter') {
|
|
2931
|
-
e.preventDefault();
|
|
2932
|
-
doSearch(e.shiftKey ? 'prev' : 'next');
|
|
2933
|
-
}
|
|
2934
|
-
});
|
|
2935
|
-
document.getElementById('search-next').addEventListener('click', () => doSearch('next'));
|
|
2936
|
-
document.getElementById('search-prev').addEventListener('click', () => doSearch('prev'));
|
|
2937
|
-
document.getElementById('search-close').addEventListener('click', closeSearchBar);
|
|
2938
|
-
document.getElementById('search-regex').addEventListener('click', () => {
|
|
2939
|
-
searchRegex = !searchRegex;
|
|
2940
|
-
searchRegexBtn.classList.toggle('active', searchRegex);
|
|
2941
|
-
if (searchInput.value) doSearch('next');
|
|
2942
|
-
});
|
|
2943
|
-
|
|
2944
|
-
document.addEventListener('keydown', (e) => {
|
|
2945
|
-
if ((e.ctrlKey || e.metaKey) && e.key === 'f') {
|
|
2946
|
-
e.preventDefault();
|
|
2947
|
-
openSearchBar();
|
|
2948
|
-
}
|
|
2949
|
-
});
|
|
2950
|
-
|
|
2951
2328
|
// ===== Font Loading (non-blocking) =====
|
|
2952
2329
|
const nerdFont = new FontFace(
|
|
2953
2330
|
'NerdFont',
|
|
@@ -2966,11 +2343,6 @@
|
|
|
2966
2343
|
init();
|
|
2967
2344
|
|
|
2968
2345
|
// ===== Helpers =====
|
|
2969
|
-
function esc(str) {
|
|
2970
|
-
const d = document.createElement('div');
|
|
2971
|
-
d.textContent = str;
|
|
2972
|
-
return d.innerHTML;
|
|
2973
|
-
}
|
|
2974
2346
|
function escAttr(str) {
|
|
2975
2347
|
return String(str)
|
|
2976
2348
|
.replace(/&/g, '&')
|
|
@@ -3436,6 +2808,7 @@
|
|
|
3436
2808
|
shell: data.shell,
|
|
3437
2809
|
cwd: data.cwd,
|
|
3438
2810
|
pid: data.pid,
|
|
2811
|
+
git: data.git || null,
|
|
3439
2812
|
term,
|
|
3440
2813
|
fitAddon,
|
|
3441
2814
|
searchAddon,
|
|
@@ -3916,6 +3289,26 @@
|
|
|
3916
3289
|
'" title="Close session">×</button>' +
|
|
3917
3290
|
'</div>' +
|
|
3918
3291
|
(activity ? '<div class="side-panel-card-meta">' + activity + ' ago</div>' : '') +
|
|
3292
|
+
(ms.git
|
|
3293
|
+
? '<div class="side-panel-card-git">' +
|
|
3294
|
+
'<span class="git-badge"><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg> ' +
|
|
3295
|
+
esc(ms.git.branch || 'detached') +
|
|
3296
|
+
'</span>' +
|
|
3297
|
+
(ms.git.provider
|
|
3298
|
+
? '<span class="git-badge">' + esc(ms.git.provider) + '</span>'
|
|
3299
|
+
: '') +
|
|
3300
|
+
(ms.git.repoName
|
|
3301
|
+
? '<span class="git-badge">' + esc(ms.git.repoName) + '</span>'
|
|
3302
|
+
: '') +
|
|
3303
|
+
(ms.git.status
|
|
3304
|
+
? '<span class="git-badge ' +
|
|
3305
|
+
(ms.git.status.clean ? 'git-status-clean' : 'git-status-dirty') +
|
|
3306
|
+
'">' +
|
|
3307
|
+
(ms.git.status.clean ? '✓ clean' : esc(ms.git.status.summary)) +
|
|
3308
|
+
'</span>'
|
|
3309
|
+
: '') +
|
|
3310
|
+
'</div>'
|
|
3311
|
+
: '') +
|
|
3919
3312
|
previewContent +
|
|
3920
3313
|
'</div>'
|
|
3921
3314
|
);
|
|
@@ -4103,183 +3496,6 @@
|
|
|
4103
3496
|
renderTabs();
|
|
4104
3497
|
}
|
|
4105
3498
|
|
|
4106
|
-
// ===== Key Bar =====
|
|
4107
|
-
// Modifier state (shared with terminal onData)
|
|
4108
|
-
let ctrlActive = false;
|
|
4109
|
-
let shiftActive = false;
|
|
4110
|
-
function clearModifiers() {
|
|
4111
|
-
ctrlActive = false;
|
|
4112
|
-
shiftActive = false;
|
|
4113
|
-
const ctrlBtn = document.getElementById('ctrl-btn');
|
|
4114
|
-
const shiftBtn = document.getElementById('shift-btn');
|
|
4115
|
-
if (ctrlBtn) ctrlBtn.classList.remove('active');
|
|
4116
|
-
if (shiftBtn) shiftBtn.classList.remove('active');
|
|
4117
|
-
}
|
|
4118
|
-
|
|
4119
|
-
function setupKeyBar() {
|
|
4120
|
-
const keyBar = document.getElementById('key-bar');
|
|
4121
|
-
const ctrlBtn = document.getElementById('ctrl-btn');
|
|
4122
|
-
const shiftBtn = document.getElementById('shift-btn');
|
|
4123
|
-
let repeatTimer = null;
|
|
4124
|
-
let repeatInterval = null;
|
|
4125
|
-
|
|
4126
|
-
function toggleModifier(which) {
|
|
4127
|
-
if (which === 'ctrl') {
|
|
4128
|
-
ctrlActive = !ctrlActive;
|
|
4129
|
-
ctrlBtn.classList.toggle('active', ctrlActive);
|
|
4130
|
-
} else {
|
|
4131
|
-
shiftActive = !shiftActive;
|
|
4132
|
-
shiftBtn.classList.toggle('active', shiftActive);
|
|
4133
|
-
}
|
|
4134
|
-
}
|
|
4135
|
-
|
|
4136
|
-
function applyModifiers(key) {
|
|
4137
|
-
if (!ctrlActive && !shiftActive) return key;
|
|
4138
|
-
// Modifier param: Shift=2, Ctrl=5, Ctrl+Shift=6
|
|
4139
|
-
const mod = ctrlActive && shiftActive ? 6 : ctrlActive ? 5 : 2;
|
|
4140
|
-
// Arrow keys: \x1b[X → \x1b[1;{mod}X
|
|
4141
|
-
const csiMatch = key.match(/^\x1b\[([ABCD])$/);
|
|
4142
|
-
if (csiMatch) return '\x1b[1;' + mod + csiMatch[1];
|
|
4143
|
-
// Home/End: \x1bOH/\x1bOF → \x1b[1;{mod}H/F
|
|
4144
|
-
const ssMatch = key.match(/^\x1bO([HF])$/);
|
|
4145
|
-
if (ssMatch) return '\x1b[1;' + mod + ssMatch[1];
|
|
4146
|
-
// Tab with Shift → reverse tab
|
|
4147
|
-
if (key === '\x09' && shiftActive && !ctrlActive) return '\x1b[Z';
|
|
4148
|
-
return key;
|
|
4149
|
-
}
|
|
4150
|
-
|
|
4151
|
-
function flashBtn(btn) {
|
|
4152
|
-
btn.classList.add('flash');
|
|
4153
|
-
setTimeout(() => btn.classList.remove('flash'), 120);
|
|
4154
|
-
}
|
|
4155
|
-
|
|
4156
|
-
function sendKey(btn) {
|
|
4157
|
-
if (!btn || !btn.dataset.key) return;
|
|
4158
|
-
flashBtn(btn);
|
|
4159
|
-
let data =
|
|
4160
|
-
btn.dataset.key === 'enter'
|
|
4161
|
-
? '\r'
|
|
4162
|
-
: btn.dataset.key === 'tab'
|
|
4163
|
-
? '\x09'
|
|
4164
|
-
: btn.dataset.key;
|
|
4165
|
-
data = applyModifiers(data);
|
|
4166
|
-
const ms = managed.get(activeId);
|
|
4167
|
-
if (ms && ms.ws && ms.ws.readyState === 1) {
|
|
4168
|
-
ms.ws.send(JSON.stringify({ type: 'input', data }));
|
|
4169
|
-
}
|
|
4170
|
-
clearModifiers();
|
|
4171
|
-
}
|
|
4172
|
-
|
|
4173
|
-
function stopRepeat() {
|
|
4174
|
-
clearTimeout(repeatTimer);
|
|
4175
|
-
clearInterval(repeatInterval);
|
|
4176
|
-
repeatTimer = null;
|
|
4177
|
-
repeatInterval = null;
|
|
4178
|
-
}
|
|
4179
|
-
|
|
4180
|
-
function startRepeat(btn) {
|
|
4181
|
-
stopRepeat();
|
|
4182
|
-
sendKey(btn);
|
|
4183
|
-
repeatTimer = setTimeout(() => {
|
|
4184
|
-
repeatInterval = setInterval(() => sendKey(btn), 80);
|
|
4185
|
-
}, 400);
|
|
4186
|
-
}
|
|
4187
|
-
|
|
4188
|
-
ctrlBtn.addEventListener('click', (e) => {
|
|
4189
|
-
e.preventDefault();
|
|
4190
|
-
e.stopPropagation();
|
|
4191
|
-
toggleModifier('ctrl');
|
|
4192
|
-
});
|
|
4193
|
-
shiftBtn.addEventListener('click', (e) => {
|
|
4194
|
-
e.preventDefault();
|
|
4195
|
-
e.stopPropagation();
|
|
4196
|
-
toggleModifier('shift');
|
|
4197
|
-
});
|
|
4198
|
-
ctrlBtn.addEventListener('mousedown', (e) => e.preventDefault());
|
|
4199
|
-
shiftBtn.addEventListener('mousedown', (e) => e.preventDefault());
|
|
4200
|
-
ctrlBtn.addEventListener(
|
|
4201
|
-
'touchstart',
|
|
4202
|
-
(e) => {
|
|
4203
|
-
e.preventDefault();
|
|
4204
|
-
keyBarTouched = true;
|
|
4205
|
-
toggleModifier('ctrl');
|
|
4206
|
-
},
|
|
4207
|
-
{ passive: false },
|
|
4208
|
-
);
|
|
4209
|
-
shiftBtn.addEventListener(
|
|
4210
|
-
'touchstart',
|
|
4211
|
-
(e) => {
|
|
4212
|
-
e.preventDefault();
|
|
4213
|
-
keyBarTouched = true;
|
|
4214
|
-
toggleModifier('shift');
|
|
4215
|
-
},
|
|
4216
|
-
{ passive: false },
|
|
4217
|
-
);
|
|
4218
|
-
|
|
4219
|
-
let keyBarTouched = false;
|
|
4220
|
-
keyBar.addEventListener('mousedown', (e) => {
|
|
4221
|
-
if (keyBarTouched) {
|
|
4222
|
-
keyBarTouched = false;
|
|
4223
|
-
return;
|
|
4224
|
-
}
|
|
4225
|
-
const btn = e.target.closest('.key-btn');
|
|
4226
|
-
if (btn && btn.dataset.key) {
|
|
4227
|
-
e.preventDefault();
|
|
4228
|
-
startRepeat(btn);
|
|
4229
|
-
}
|
|
4230
|
-
});
|
|
4231
|
-
keyBar.addEventListener('mouseup', stopRepeat);
|
|
4232
|
-
keyBar.addEventListener('mouseleave', stopRepeat);
|
|
4233
|
-
|
|
4234
|
-
// Touch handling: allow native scroll when swiping, fire key only on tap
|
|
4235
|
-
const SWIPE_THRESHOLD = 10;
|
|
4236
|
-
let touchStartX = 0;
|
|
4237
|
-
let touchBtn = null;
|
|
4238
|
-
let touchMoved = false;
|
|
4239
|
-
|
|
4240
|
-
keyBar.addEventListener(
|
|
4241
|
-
'touchstart',
|
|
4242
|
-
(e) => {
|
|
4243
|
-
keyBarTouched = true;
|
|
4244
|
-
touchBtn = e.target.closest('.key-btn');
|
|
4245
|
-
touchMoved = false;
|
|
4246
|
-
touchStartX = e.touches[0].clientX;
|
|
4247
|
-
// Don't preventDefault — let the browser handle scroll
|
|
4248
|
-
},
|
|
4249
|
-
{ passive: true },
|
|
4250
|
-
);
|
|
4251
|
-
keyBar.addEventListener(
|
|
4252
|
-
'touchmove',
|
|
4253
|
-
(e) => {
|
|
4254
|
-
if (Math.abs(e.touches[0].clientX - touchStartX) > SWIPE_THRESHOLD) {
|
|
4255
|
-
touchMoved = true;
|
|
4256
|
-
stopRepeat();
|
|
4257
|
-
}
|
|
4258
|
-
},
|
|
4259
|
-
{ passive: true },
|
|
4260
|
-
);
|
|
4261
|
-
keyBar.addEventListener('touchend', (e) => {
|
|
4262
|
-
if (!touchMoved && touchBtn && touchBtn.dataset.key) {
|
|
4263
|
-
e.preventDefault();
|
|
4264
|
-
sendKey(touchBtn);
|
|
4265
|
-
}
|
|
4266
|
-
stopRepeat();
|
|
4267
|
-
touchBtn = null;
|
|
4268
|
-
});
|
|
4269
|
-
keyBar.addEventListener('touchcancel', () => {
|
|
4270
|
-
stopRepeat();
|
|
4271
|
-
touchBtn = null;
|
|
4272
|
-
});
|
|
4273
|
-
|
|
4274
|
-
keyBar.addEventListener('click', (e) => {
|
|
4275
|
-
const btn = e.target.closest('.key-btn');
|
|
4276
|
-
if (btn) {
|
|
4277
|
-
const ms = managed.get(activeId);
|
|
4278
|
-
if (ms) ms.term.focus();
|
|
4279
|
-
}
|
|
4280
|
-
});
|
|
4281
|
-
}
|
|
4282
|
-
|
|
4283
3499
|
// ===== Paste =====
|
|
4284
3500
|
function setupPaste() {
|
|
4285
3501
|
const pasteOverlay = document.getElementById('paste-overlay');
|
|
@@ -4747,7 +3963,9 @@
|
|
|
4747
3963
|
const ms = managed.get(s.id);
|
|
4748
3964
|
ms.name = s.name;
|
|
4749
3965
|
ms.color = s.color;
|
|
3966
|
+
ms.cwd = s.cwd;
|
|
4750
3967
|
ms.lastActivity = s.lastActivity;
|
|
3968
|
+
ms.git = s.git || null;
|
|
4751
3969
|
}
|
|
4752
3970
|
}
|
|
4753
3971
|
|
|
@@ -5030,22 +4248,7 @@
|
|
|
5030
4248
|
icon: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>',
|
|
5031
4249
|
label: 'Copy link',
|
|
5032
4250
|
category: 'Share',
|
|
5033
|
-
action:
|
|
5034
|
-
const url = location.href;
|
|
5035
|
-
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
5036
|
-
navigator.clipboard.writeText(url).then(
|
|
5037
|
-
() => showToast('Link copied!'),
|
|
5038
|
-
() => {
|
|
5039
|
-
if (copyToClipboardFallback(url)) showToast('Link copied!');
|
|
5040
|
-
else showShareUrlPrompt(url);
|
|
5041
|
-
},
|
|
5042
|
-
);
|
|
5043
|
-
} else if (copyToClipboardFallback(url)) {
|
|
5044
|
-
showToast('Link copied!');
|
|
5045
|
-
} else {
|
|
5046
|
-
showShareUrlPrompt(url);
|
|
5047
|
-
}
|
|
5048
|
-
},
|
|
4251
|
+
action: shareLink,
|
|
5049
4252
|
},
|
|
5050
4253
|
{
|
|
5051
4254
|
icon: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>',
|
|
@@ -5225,9 +4428,7 @@
|
|
|
5225
4428
|
})();
|
|
5226
4429
|
|
|
5227
4430
|
// ===== Service Worker =====
|
|
5228
|
-
|
|
5229
|
-
navigator.serviceWorker.register('/sw.js').catch(() => {});
|
|
5230
|
-
}
|
|
4431
|
+
registerServiceWorker();
|
|
5231
4432
|
</script>
|
|
5232
4433
|
</body>
|
|
5233
4434
|
</html>
|