treesap 0.1.13 → 0.2.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/README.md +31 -192
- package/dist/app.d.ts +28 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +184 -0
- package/dist/app.js.map +1 -0
- package/dist/context.d.ts +36 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +95 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/middleware/cors.d.ts +11 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +34 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/serve-static.d.ts +6 -0
- package/dist/middleware/serve-static.d.ts.map +1 -0
- package/dist/middleware/serve-static.js +68 -0
- package/dist/middleware/serve-static.js.map +1 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +52 -0
- package/dist/node.js.map +1 -0
- package/dist/path.d.ts +10 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +45 -0
- package/dist/path.js.map +1 -0
- package/dist/vite.d.ts +31 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +278 -0
- package/dist/vite.js.map +1 -0
- package/package.json +33 -40
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -137
- package/dist/cli.js.map +0 -1
- package/dist/components/BaseHead.d.ts +0 -5
- package/dist/components/BaseHead.d.ts.map +0 -1
- package/dist/components/BaseHead.js +0 -161
- package/dist/components/BaseHead.js.map +0 -1
- package/dist/components/ChatInput.d.ts +0 -7
- package/dist/components/ChatInput.d.ts.map +0 -1
- package/dist/components/ChatInput.js +0 -11
- package/dist/components/ChatInput.js.map +0 -1
- package/dist/components/Sidebar.d.ts +0 -8
- package/dist/components/Sidebar.d.ts.map +0 -1
- package/dist/components/Sidebar.js +0 -7
- package/dist/components/Sidebar.js.map +0 -1
- package/dist/components/SimpleLivePreview.d.ts +0 -7
- package/dist/components/SimpleLivePreview.d.ts.map +0 -1
- package/dist/components/SimpleLivePreview.js +0 -7
- package/dist/components/SimpleLivePreview.js.map +0 -1
- package/dist/components/Terminal.d.ts +0 -7
- package/dist/components/Terminal.d.ts.map +0 -1
- package/dist/components/Terminal.js +0 -14
- package/dist/components/Terminal.js.map +0 -1
- package/dist/components/VoiceRecorder.d.ts +0 -4
- package/dist/components/VoiceRecorder.d.ts.map +0 -1
- package/dist/components/VoiceRecorder.js +0 -5
- package/dist/components/VoiceRecorder.js.map +0 -1
- package/dist/components/icons/GeminiLogo.d.ts +0 -7
- package/dist/components/icons/GeminiLogo.d.ts.map +0 -1
- package/dist/components/icons/GeminiLogo.js +0 -5
- package/dist/components/icons/GeminiLogo.js.map +0 -1
- package/dist/components/icons/OllamaLogo.d.ts +0 -2
- package/dist/components/icons/OllamaLogo.d.ts.map +0 -1
- package/dist/components/icons/OllamaLogo.js +0 -5
- package/dist/components/icons/OllamaLogo.js.map +0 -1
- package/dist/layouts/Layout.d.ts +0 -9
- package/dist/layouts/Layout.d.ts.map +0 -1
- package/dist/layouts/Layout.js +0 -9
- package/dist/layouts/Layout.js.map +0 -1
- package/dist/layouts/NotFoundLayout.d.ts +0 -2
- package/dist/layouts/NotFoundLayout.d.ts.map +0 -1
- package/dist/layouts/NotFoundLayout.js +0 -6
- package/dist/layouts/NotFoundLayout.js.map +0 -1
- package/dist/pages/Code.d.ts +0 -7
- package/dist/pages/Code.d.ts.map +0 -1
- package/dist/pages/Code.js +0 -8
- package/dist/pages/Code.js.map +0 -1
- package/dist/pages/Home.d.ts +0 -7
- package/dist/pages/Home.d.ts.map +0 -1
- package/dist/pages/Home.js +0 -8
- package/dist/pages/Home.js.map +0 -1
- package/dist/pages/Welcome.d.ts +0 -2
- package/dist/pages/Welcome.d.ts.map +0 -1
- package/dist/pages/Welcome.js +0 -6
- package/dist/pages/Welcome.js.map +0 -1
- package/dist/server.d.ts +0 -11
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -434
- package/dist/server.js.map +0 -1
- package/dist/services/dev-server.d.ts +0 -29
- package/dist/services/dev-server.d.ts.map +0 -1
- package/dist/services/dev-server.js +0 -201
- package/dist/services/dev-server.js.map +0 -1
- package/dist/services/terminal.d.ts +0 -46
- package/dist/services/terminal.d.ts.map +0 -1
- package/dist/services/terminal.js +0 -264
- package/dist/services/terminal.js.map +0 -1
- package/dist/services/websocket.d.ts +0 -48
- package/dist/services/websocket.d.ts.map +0 -1
- package/dist/services/websocket.js +0 -332
- package/dist/services/websocket.js.map +0 -1
- package/dist/static/components/ChatInput.js +0 -237
- package/dist/static/components/Sidebar.js +0 -225
- package/dist/static/components/SimpleLivePreview.js +0 -305
- package/dist/static/components/Terminal.js +0 -461
- package/dist/static/components/TerminalTabs.js +0 -383
- package/dist/static/favicon.svg +0 -14
- package/dist/static/signals/LivePreviewSignal.js +0 -71
- package/dist/static/signals/SidebarSignal.js +0 -123
- package/dist/static/signals/TerminalSignal.js +0 -273
- package/dist/static/styles/main.css +0 -1761
- package/src/cli.ts +0 -155
- package/src/components/BaseHead.ts +0 -164
- package/src/components/ChatInput.tsx +0 -56
- package/src/components/Sidebar.tsx +0 -99
- package/src/components/SimpleLivePreview.tsx +0 -40
- package/src/components/Terminal.tsx +0 -40
- package/src/components/VoiceRecorder.tsx +0 -33
- package/src/components/icons/GeminiLogo.tsx +0 -10
- package/src/components/icons/OllamaLogo.tsx +0 -5
- package/src/index.tsx +0 -12
- package/src/layouts/Layout.tsx +0 -41
- package/src/layouts/NotFoundLayout.tsx +0 -15
- package/src/pages/Code.tsx +0 -34
- package/src/pages/Welcome.tsx +0 -56
- package/src/server.tsx +0 -519
- package/src/services/dev-server.ts +0 -234
- package/src/services/terminal.ts +0 -325
- package/src/services/websocket.ts +0 -405
- package/src/static/components/ChatInput.js +0 -237
- package/src/static/components/Sidebar.js +0 -225
- package/src/static/components/SimpleLivePreview.js +0 -305
- package/src/static/components/Terminal.js +0 -461
- package/src/static/components/TerminalTabs.js +0 -383
- package/src/static/favicon.svg +0 -14
- package/src/static/signals/LivePreviewSignal.js +0 -71
- package/src/static/signals/SidebarSignal.js +0 -123
- package/src/static/signals/TerminalSignal.js +0 -273
- package/src/static/styles/main.css +0 -1761
- package/src/styles/input.css +0 -3
- package/tailwind.config.ts +0 -22
- package/tsconfig.json +0 -37
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
// Terminal tabs management
|
|
2
|
-
import { terminalStore } from '/signals/TerminalSignal.js';
|
|
3
|
-
|
|
4
|
-
class TerminalTabManager {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.maxTerminals = 3;
|
|
7
|
-
this.activeTerminalIndex = 1;
|
|
8
|
-
|
|
9
|
-
this.init();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
init() {
|
|
13
|
-
console.log('TerminalTabManager initialized');
|
|
14
|
-
|
|
15
|
-
// Set up event listeners
|
|
16
|
-
this.setupEventListeners();
|
|
17
|
-
|
|
18
|
-
// Subscribe to terminal store changes
|
|
19
|
-
this.subscribeToStore();
|
|
20
|
-
|
|
21
|
-
// Initialize first terminal
|
|
22
|
-
this.showTerminal(1);
|
|
23
|
-
|
|
24
|
-
// Update button visibility
|
|
25
|
-
this.updateAddButtonVisibility();
|
|
26
|
-
this.updateCloseButtonsVisibility();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setupEventListeners() {
|
|
30
|
-
// Terminal tab click handlers
|
|
31
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
32
|
-
const tabBtn = document.getElementById(`terminal-tab-${i}`);
|
|
33
|
-
if (tabBtn) {
|
|
34
|
-
tabBtn.addEventListener('click', (e) => {
|
|
35
|
-
// Prevent event bubbling to close button
|
|
36
|
-
if (!e.target.closest('.terminal-close-btn')) {
|
|
37
|
-
this.switchToTerminal(i);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Close button handlers
|
|
43
|
-
const closeBtns = document.querySelectorAll(`[data-terminal-index="${i}"].terminal-close-btn`);
|
|
44
|
-
closeBtns.forEach(btn => {
|
|
45
|
-
btn.addEventListener('click', async (e) => {
|
|
46
|
-
e.stopPropagation();
|
|
47
|
-
await this.closeTerminal(i);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Add terminal button
|
|
53
|
-
const addBtn = document.getElementById('add-terminal-btn');
|
|
54
|
-
if (addBtn) {
|
|
55
|
-
addBtn.addEventListener('click', () => {
|
|
56
|
-
this.addTerminal();
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Keyboard shortcuts
|
|
61
|
-
document.addEventListener('keydown', (e) => {
|
|
62
|
-
// Ctrl+Shift+` to create new terminal
|
|
63
|
-
if (e.ctrlKey && e.shiftKey && e.code === 'Backquote') {
|
|
64
|
-
e.preventDefault();
|
|
65
|
-
this.addTerminal();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Ctrl+Shift+W to close current terminal
|
|
69
|
-
if (e.ctrlKey && e.shiftKey && e.key === 'W') {
|
|
70
|
-
e.preventDefault();
|
|
71
|
-
this.closeTerminal(this.activeTerminalIndex);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// Window resize handler to fit terminals
|
|
76
|
-
window.addEventListener('resize', () => {
|
|
77
|
-
// Resize the currently active terminal
|
|
78
|
-
setTimeout(() => {
|
|
79
|
-
if (window.terminalManagers) {
|
|
80
|
-
const activeManager = window.terminalManagers.get(`terminal-${this.activeTerminalIndex}`);
|
|
81
|
-
if (activeManager && activeManager.terminal) {
|
|
82
|
-
activeManager.fitTerminal();
|
|
83
|
-
console.log(`Resized active terminal-${this.activeTerminalIndex} due to window resize`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}, 100);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
subscribeToStore() {
|
|
91
|
-
// Watch for active terminal changes in the store
|
|
92
|
-
terminalStore.activeTerminalId.subscribe((terminalId) => {
|
|
93
|
-
if (terminalId) {
|
|
94
|
-
const match = terminalId.match(/terminal-(\d+)/);
|
|
95
|
-
if (match) {
|
|
96
|
-
const index = parseInt(match[1]);
|
|
97
|
-
this.updateActiveTabVisual(index);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
switchToTerminal(index) {
|
|
104
|
-
if (index < 1 || index > this.maxTerminals) return;
|
|
105
|
-
|
|
106
|
-
console.log(`Switching to terminal ${index}`);
|
|
107
|
-
|
|
108
|
-
// Update store
|
|
109
|
-
terminalStore.setActiveTerminal(`terminal-${index}`);
|
|
110
|
-
|
|
111
|
-
// Show the terminal
|
|
112
|
-
this.showTerminal(index);
|
|
113
|
-
|
|
114
|
-
// Update active index
|
|
115
|
-
this.activeTerminalIndex = index;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
showTerminal(index) {
|
|
119
|
-
// Hide all terminal containers
|
|
120
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
121
|
-
const container = document.getElementById(`terminal-container-${i}`);
|
|
122
|
-
if (container) {
|
|
123
|
-
container.style.display = 'none';
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Show the active terminal container
|
|
128
|
-
const activeContainer = document.getElementById(`terminal-container-${index}`);
|
|
129
|
-
if (activeContainer) {
|
|
130
|
-
activeContainer.style.display = 'block';
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Update tab visuals
|
|
134
|
-
this.updateActiveTabVisual(index);
|
|
135
|
-
|
|
136
|
-
// Focus and resize the terminal
|
|
137
|
-
setTimeout(() => {
|
|
138
|
-
const terminalElement = document.getElementById(`terminal-${index}-xterm`);
|
|
139
|
-
if (terminalElement && window.terminalManagers) {
|
|
140
|
-
const manager = window.terminalManagers.get(`terminal-${index}`);
|
|
141
|
-
if (manager && manager.terminal) {
|
|
142
|
-
// Fit the terminal to its container
|
|
143
|
-
manager.fitTerminal();
|
|
144
|
-
// Focus the terminal
|
|
145
|
-
manager.terminal.focus();
|
|
146
|
-
console.log(`Focused and resized terminal-${index}`);
|
|
147
|
-
} else {
|
|
148
|
-
console.warn(`Terminal manager not found for terminal-${index}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}, 150);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
updateActiveTabVisual(activeIndex) {
|
|
155
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
156
|
-
const tab = document.getElementById(`terminal-tab-${i}`);
|
|
157
|
-
if (tab) {
|
|
158
|
-
if (i === activeIndex) {
|
|
159
|
-
// Active tab styling
|
|
160
|
-
tab.className = 'terminal-tab flex items-center px-3 py-1 text-sm text-white bg-[#1e1e1e] border-t-2 border-[#0e639c] rounded-t-sm hover:bg-[#2d2d30] transition-colors';
|
|
161
|
-
} else {
|
|
162
|
-
// Inactive tab styling
|
|
163
|
-
tab.className = 'terminal-tab flex items-center px-3 py-1 text-sm text-[#cccccc] hover:text-white hover:bg-[#2d2d30] transition-colors rounded-t-sm';
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
addTerminal() {
|
|
170
|
-
// Find the next available terminal slot
|
|
171
|
-
for (let i = 2; i <= this.maxTerminals; i++) {
|
|
172
|
-
const tab = document.getElementById(`terminal-tab-${i}`);
|
|
173
|
-
const container = document.getElementById(`terminal-container-${i}`);
|
|
174
|
-
|
|
175
|
-
if (tab && container && tab.style.display === 'none') {
|
|
176
|
-
console.log(`Adding terminal ${i}`);
|
|
177
|
-
|
|
178
|
-
// Show the tab
|
|
179
|
-
tab.style.display = 'flex';
|
|
180
|
-
|
|
181
|
-
// Add to store
|
|
182
|
-
terminalStore.addTerminal(i);
|
|
183
|
-
|
|
184
|
-
// Show the container temporarily to allow terminal initialization
|
|
185
|
-
container.style.display = 'block';
|
|
186
|
-
|
|
187
|
-
// Initialize the terminal by triggering the terminal manager to look for new terminals
|
|
188
|
-
setTimeout(() => {
|
|
189
|
-
if (window.initializeTerminals) {
|
|
190
|
-
window.initializeTerminals();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Switch to the new terminal after initialization (this will handle hiding/showing properly)
|
|
194
|
-
setTimeout(() => {
|
|
195
|
-
this.switchToTerminal(i);
|
|
196
|
-
|
|
197
|
-
// Force a resize after switching
|
|
198
|
-
setTimeout(() => {
|
|
199
|
-
if (window.terminalManagers) {
|
|
200
|
-
const manager = window.terminalManagers.get(`terminal-${i}`);
|
|
201
|
-
if (manager && manager.terminal) {
|
|
202
|
-
manager.fitTerminal();
|
|
203
|
-
console.log(`Force-resized new terminal-${i}`);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}, 100);
|
|
207
|
-
}, 200);
|
|
208
|
-
}, 100);
|
|
209
|
-
|
|
210
|
-
// Update add button visibility
|
|
211
|
-
this.updateAddButtonVisibility();
|
|
212
|
-
|
|
213
|
-
// Show close button for new terminal (except terminal 1)
|
|
214
|
-
this.updateCloseButtonsVisibility();
|
|
215
|
-
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
console.log('Maximum number of terminals reached');
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
async closeTerminal(index) {
|
|
224
|
-
if (index === 1) {
|
|
225
|
-
console.log('Cannot close terminal 1');
|
|
226
|
-
return; // Can't close the first terminal
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
console.log(`Closing terminal ${index}`);
|
|
230
|
-
|
|
231
|
-
const tab = document.getElementById(`terminal-tab-${index}`);
|
|
232
|
-
const container = document.getElementById(`terminal-container-${index}`);
|
|
233
|
-
|
|
234
|
-
if (tab && container) {
|
|
235
|
-
// Destroy server-side terminal session
|
|
236
|
-
const terminal = terminalStore.getTerminalByIndex(index);
|
|
237
|
-
if (terminal && terminal.sessionId) {
|
|
238
|
-
try {
|
|
239
|
-
const response = await fetch(`/terminal/session/${terminal.sessionId}`, {
|
|
240
|
-
method: 'DELETE'
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
if (response.ok) {
|
|
244
|
-
console.log(`Terminal session ${terminal.sessionId} destroyed on server`);
|
|
245
|
-
} else {
|
|
246
|
-
console.warn(`Failed to destroy terminal session ${terminal.sessionId} on server:`, await response.text());
|
|
247
|
-
}
|
|
248
|
-
} catch (error) {
|
|
249
|
-
console.error(`Error destroying terminal session ${terminal.sessionId}:`, error);
|
|
250
|
-
}
|
|
251
|
-
} else {
|
|
252
|
-
console.warn(`No terminal found with index ${index} to destroy session`);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Destroy the terminal manager instance
|
|
256
|
-
if (window.terminalManagers) {
|
|
257
|
-
const manager = window.terminalManagers.get(`terminal-${index}`);
|
|
258
|
-
if (manager) {
|
|
259
|
-
await manager.destroy();
|
|
260
|
-
window.terminalManagers.delete(`terminal-${index}`);
|
|
261
|
-
console.log(`Terminal manager for terminal-${index} destroyed`);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Hide the tab and container
|
|
266
|
-
tab.style.display = 'none';
|
|
267
|
-
container.style.display = 'none';
|
|
268
|
-
|
|
269
|
-
// Remove from store
|
|
270
|
-
terminalStore.removeTerminal(`terminal-${index}`);
|
|
271
|
-
|
|
272
|
-
// If we're closing the active terminal, switch to another one
|
|
273
|
-
if (this.activeTerminalIndex === index) {
|
|
274
|
-
// Find the next available terminal
|
|
275
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
276
|
-
const nextTab = document.getElementById(`terminal-tab-${i}`);
|
|
277
|
-
if (nextTab && nextTab.style.display !== 'none') {
|
|
278
|
-
this.switchToTerminal(i);
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Update add button visibility
|
|
285
|
-
this.updateAddButtonVisibility();
|
|
286
|
-
|
|
287
|
-
// Update close button visibility
|
|
288
|
-
this.updateCloseButtonsVisibility();
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
updateAddButtonVisibility() {
|
|
293
|
-
const addBtn = document.getElementById('add-terminal-btn');
|
|
294
|
-
if (!addBtn) return;
|
|
295
|
-
|
|
296
|
-
// Count visible terminals
|
|
297
|
-
let visibleCount = 0;
|
|
298
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
299
|
-
const tab = document.getElementById(`terminal-tab-${i}`);
|
|
300
|
-
if (tab && tab.style.display !== 'none') {
|
|
301
|
-
visibleCount++;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Hide add button if we have max terminals
|
|
306
|
-
addBtn.style.display = visibleCount >= this.maxTerminals ? 'none' : 'flex';
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
updateCloseButtonsVisibility() {
|
|
310
|
-
// Count visible terminals
|
|
311
|
-
let visibleCount = 0;
|
|
312
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
313
|
-
const tab = document.getElementById(`terminal-tab-${i}`);
|
|
314
|
-
if (tab && tab.style.display !== 'none') {
|
|
315
|
-
visibleCount++;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Show/hide close buttons - never show on terminal 1, only show on others if more than 1 terminal
|
|
320
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
321
|
-
const closeBtns = document.querySelectorAll(`[data-terminal-index="${i}"].terminal-close-btn`);
|
|
322
|
-
closeBtns.forEach(btn => {
|
|
323
|
-
if (i === 1) {
|
|
324
|
-
// Never show close button on Terminal 1
|
|
325
|
-
btn.style.display = 'none';
|
|
326
|
-
} else {
|
|
327
|
-
// Show close button on other terminals only if there are multiple terminals
|
|
328
|
-
const tab = document.getElementById(`terminal-tab-${i}`);
|
|
329
|
-
if (tab && tab.style.display !== 'none' && visibleCount > 1) {
|
|
330
|
-
btn.style.display = 'inline-flex';
|
|
331
|
-
} else {
|
|
332
|
-
btn.style.display = 'none';
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Get current state
|
|
340
|
-
getState() {
|
|
341
|
-
const visibleTerminals = [];
|
|
342
|
-
for (let i = 1; i <= this.maxTerminals; i++) {
|
|
343
|
-
const tab = document.getElementById(`terminal-tab-${i}`);
|
|
344
|
-
if (tab && tab.style.display !== 'none') {
|
|
345
|
-
visibleTerminals.push(i);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return {
|
|
350
|
-
visibleTerminals,
|
|
351
|
-
activeTerminalIndex: this.activeTerminalIndex,
|
|
352
|
-
maxTerminals: this.maxTerminals
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// Auto-initialize when script loads
|
|
358
|
-
let terminalTabManager;
|
|
359
|
-
|
|
360
|
-
function initializeTerminalTabs() {
|
|
361
|
-
// Wait for DOM elements to be ready
|
|
362
|
-
const terminalTab1 = document.getElementById('terminal-tab-1');
|
|
363
|
-
if (terminalTab1) {
|
|
364
|
-
console.log('Initializing TerminalTabManager...');
|
|
365
|
-
terminalTabManager = new TerminalTabManager();
|
|
366
|
-
} else {
|
|
367
|
-
console.log('Terminal tabs not found, retrying...');
|
|
368
|
-
setTimeout(initializeTerminalTabs, 100);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Initialize
|
|
373
|
-
if (document.readyState === 'loading') {
|
|
374
|
-
document.addEventListener('DOMContentLoaded', initializeTerminalTabs);
|
|
375
|
-
} else {
|
|
376
|
-
initializeTerminalTabs();
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Make available globally
|
|
380
|
-
window.terminalTabManager = terminalTabManager;
|
|
381
|
-
window.TerminalTabManager = TerminalTabManager;
|
|
382
|
-
|
|
383
|
-
export default TerminalTabManager;
|
package/dist/static/favicon.svg
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<style>
|
|
3
|
-
path {
|
|
4
|
-
fill: black;
|
|
5
|
-
}
|
|
6
|
-
@media (prefers-color-scheme: dark) {
|
|
7
|
-
path {
|
|
8
|
-
fill: white;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
</style>
|
|
12
|
-
<path d="M236.752 231.541L133.378 335.909C129.158 340.169 124.236 342.21 118.61 342.033C112.984 341.855 108.062 339.637 103.842 335.377C99.9747 331.117 97.953 326.147 97.7771 320.467C97.6013 314.787 99.6231 309.817 103.842 305.557L243.081 164.98C245.19 162.85 247.476 161.342 249.937 160.454C252.398 159.567 255.035 159.123 257.848 159.123C260.661 159.123 263.298 159.567 265.76 160.454C268.221 161.342 270.506 162.85 272.616 164.98L411.854 305.557C415.722 309.462 417.656 314.343 417.656 320.201C417.656 326.058 415.722 331.117 411.854 335.377C407.635 339.637 402.624 341.767 396.823 341.767C391.021 341.767 386.011 339.637 381.791 335.377L278.945 231.541V469.564C278.945 475.599 276.923 480.657 272.88 484.74C268.836 488.822 263.826 490.863 257.848 490.863C251.871 490.863 246.86 488.822 242.817 484.74C238.773 480.657 236.752 475.599 236.752 469.564V231.541Z" fill="currentColor"/>
|
|
13
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M258 62.2033L388.126 192.329C394.96 199.163 406.04 199.163 412.874 192.329C419.709 185.495 419.709 174.414 412.874 167.58L277.445 32.1512C266.706 21.4118 249.294 21.4118 238.555 32.1512L103.126 167.58C96.2915 174.414 96.2915 185.495 103.126 192.329C109.96 199.163 121.04 199.163 127.874 192.329L258 62.2033Z" fill="currentColor"/>
|
|
14
|
-
</svg>
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { signal, computed } from 'https://esm.sh/@preact/signals@1.2.2';
|
|
2
|
-
|
|
3
|
-
// Live Preview state management
|
|
4
|
-
class LivePreviewStore {
|
|
5
|
-
constructor() {
|
|
6
|
-
// Core state signals
|
|
7
|
-
this.refreshTrigger = signal(0);
|
|
8
|
-
this.previewPort = signal(5173); // Default port
|
|
9
|
-
this.currentUrl = signal('http://localhost:5173');
|
|
10
|
-
this.isMobileView = signal(false);
|
|
11
|
-
this.isLoading = signal(false);
|
|
12
|
-
|
|
13
|
-
// Computed values
|
|
14
|
-
this.shouldRefresh = computed(() => this.refreshTrigger.value);
|
|
15
|
-
this.baseUrl = computed(() => `http://localhost:${this.previewPort.value}`);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Actions for managing preview state
|
|
19
|
-
refresh() {
|
|
20
|
-
this.refreshTrigger.value = this.refreshTrigger.value + 1;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
setPreviewPort(port) {
|
|
24
|
-
this.previewPort.value = port;
|
|
25
|
-
// Update currentUrl to use new port if it was using the old port
|
|
26
|
-
const currentUrlValue = this.currentUrl.value;
|
|
27
|
-
const oldPort = currentUrlValue.match(/:(\d+)/)?.[1];
|
|
28
|
-
if (oldPort) {
|
|
29
|
-
this.currentUrl.value = currentUrlValue.replace(`:${oldPort}`, `:${port}`);
|
|
30
|
-
} else {
|
|
31
|
-
this.currentUrl.value = `http://localhost:${port}`;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
setUrl(url) {
|
|
36
|
-
this.currentUrl.value = url;
|
|
37
|
-
this.refresh(); // Auto-refresh when URL changes
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
toggleMobileView() {
|
|
41
|
-
this.isMobileView.value = !this.isMobileView.value;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
setLoading(isLoading) {
|
|
45
|
-
this.isLoading.value = isLoading;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Debug helpers
|
|
49
|
-
getState() {
|
|
50
|
-
return {
|
|
51
|
-
refreshTrigger: this.refreshTrigger.value,
|
|
52
|
-
previewPort: this.previewPort.value,
|
|
53
|
-
currentUrl: this.currentUrl.value,
|
|
54
|
-
isMobileView: this.isMobileView.value,
|
|
55
|
-
isLoading: this.isLoading.value,
|
|
56
|
-
baseUrl: this.baseUrl.value
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
logState() {
|
|
61
|
-
console.log('Live Preview State:', this.getState());
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Create and export singleton instance
|
|
66
|
-
export const livePreviewStore = new LivePreviewStore();
|
|
67
|
-
|
|
68
|
-
// Make it available globally for debugging
|
|
69
|
-
if (typeof window !== 'undefined') {
|
|
70
|
-
window.livePreviewStore = livePreviewStore;
|
|
71
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { signal, computed } from 'https://esm.sh/@preact/signals@1.2.2';
|
|
2
|
-
|
|
3
|
-
// Sidebar state management
|
|
4
|
-
class SidebarStore {
|
|
5
|
-
constructor() {
|
|
6
|
-
// Core state signals
|
|
7
|
-
this.isOpen = signal(true); // Default to open on desktop
|
|
8
|
-
this.isMobile = signal(false); // Track if we're in mobile viewport
|
|
9
|
-
this.mobileBreakpoint = signal(768); // Breakpoint for mobile/desktop detection
|
|
10
|
-
|
|
11
|
-
// Computed values
|
|
12
|
-
this.shouldShowBackdrop = computed(() => this.isMobile.value && this.isOpen.value);
|
|
13
|
-
this.shouldShowMobileToggle = computed(() => this.isMobile.value && !this.isOpen.value);
|
|
14
|
-
this.shouldShowFloatingButton = computed(() => !this.isMobile.value && !this.isOpen.value);
|
|
15
|
-
|
|
16
|
-
// Initialize mobile detection
|
|
17
|
-
this.initializeMobileDetection();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Initialize mobile detection and set initial state
|
|
21
|
-
initializeMobileDetection() {
|
|
22
|
-
if (typeof window !== 'undefined') {
|
|
23
|
-
this.updateMobileState();
|
|
24
|
-
|
|
25
|
-
// Listen for window resize
|
|
26
|
-
window.addEventListener('resize', () => {
|
|
27
|
-
this.updateMobileState();
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Update mobile state based on window width
|
|
33
|
-
updateMobileState() {
|
|
34
|
-
if (typeof window === 'undefined') return;
|
|
35
|
-
|
|
36
|
-
const wasMobile = this.isMobile.value;
|
|
37
|
-
const nowMobile = window.innerWidth < this.mobileBreakpoint.value;
|
|
38
|
-
|
|
39
|
-
this.isMobile.value = nowMobile;
|
|
40
|
-
|
|
41
|
-
// Handle initial state or breakpoint transitions
|
|
42
|
-
if (wasMobile === undefined) {
|
|
43
|
-
// First time: desktop shows sidebar, mobile hides it
|
|
44
|
-
this.isOpen.value = !nowMobile;
|
|
45
|
-
} else if (wasMobile !== nowMobile) {
|
|
46
|
-
// Breakpoint changed
|
|
47
|
-
if (wasMobile && !nowMobile) {
|
|
48
|
-
// Mobile to desktop: show sidebar
|
|
49
|
-
this.isOpen.value = true;
|
|
50
|
-
} else if (!wasMobile && nowMobile) {
|
|
51
|
-
// Desktop to mobile: hide sidebar
|
|
52
|
-
this.isOpen.value = false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Actions for managing sidebar state
|
|
58
|
-
toggle() {
|
|
59
|
-
this.isOpen.value = !this.isOpen.value;
|
|
60
|
-
console.log(`Sidebar toggled: ${this.isOpen.value ? 'open' : 'closed'}`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
open() {
|
|
64
|
-
this.isOpen.value = true;
|
|
65
|
-
console.log('Sidebar opened');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
close() {
|
|
69
|
-
this.isOpen.value = false;
|
|
70
|
-
console.log('Sidebar closed');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Set mobile breakpoint
|
|
74
|
-
setMobileBreakpoint(breakpoint) {
|
|
75
|
-
this.mobileBreakpoint.value = breakpoint;
|
|
76
|
-
this.updateMobileState();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Get current state (useful for components that need to read state once)
|
|
80
|
-
getState() {
|
|
81
|
-
return {
|
|
82
|
-
isOpen: this.isOpen.value,
|
|
83
|
-
isMobile: this.isMobile.value,
|
|
84
|
-
mobileBreakpoint: this.mobileBreakpoint.value,
|
|
85
|
-
shouldShowBackdrop: this.shouldShowBackdrop.value,
|
|
86
|
-
shouldShowMobileToggle: this.shouldShowMobileToggle.value,
|
|
87
|
-
shouldShowFloatingButton: this.shouldShowFloatingButton.value
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Debug helpers
|
|
92
|
-
logState() {
|
|
93
|
-
console.log('Sidebar Store State:', this.getState());
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Subscribe to state changes (for components that need to react to changes)
|
|
97
|
-
onStateChange(callback) {
|
|
98
|
-
// Create an effect that runs when any sidebar state changes
|
|
99
|
-
const unsubscribe = () => {
|
|
100
|
-
// This is a simple implementation - in a full app you might want more granular subscriptions
|
|
101
|
-
const state = this.getState();
|
|
102
|
-
callback(state);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Subscribe to all relevant signals
|
|
106
|
-
this.isOpen.subscribe(unsubscribe);
|
|
107
|
-
this.isMobile.subscribe(unsubscribe);
|
|
108
|
-
|
|
109
|
-
// Return unsubscribe function
|
|
110
|
-
return () => {
|
|
111
|
-
// Note: Preact signals don't have a direct unsubscribe method
|
|
112
|
-
// In a production app, you'd want to implement proper cleanup
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Create and export singleton instance
|
|
118
|
-
export const sidebarStore = new SidebarStore();
|
|
119
|
-
|
|
120
|
-
// Make it available globally for debugging
|
|
121
|
-
if (typeof window !== 'undefined') {
|
|
122
|
-
window.sidebarStore = sidebarStore;
|
|
123
|
-
}
|