@rendiv/studio 0.1.3 → 0.1.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin-studio.d.ts","sourceRoot":"","sources":["../src/vite-plugin-studio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMnC,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AA4HD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAyKvE"}
1
+ {"version":3,"file":"vite-plugin-studio.d.ts","sourceRoot":"","sources":["../src/vite-plugin-studio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMnC,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAgKD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAyPvE"}
@@ -5,6 +5,36 @@ let renderJobs = [];
5
5
  let nextJobId = 1;
6
6
  let activeJobId = null;
7
7
  let activeAbortController = null;
8
+ // --- Server-side terminal state (in-memory, survives page refresh) ---
9
+ let terminalProcess = null;
10
+ let terminalCols = 80;
11
+ let terminalRows = 24;
12
+ async function tryImportNodePty() {
13
+ try {
14
+ const pty = await import('node-pty');
15
+ // Ensure spawn-helper has execute permission (pnpm may strip it)
16
+ if (process.platform !== 'win32') {
17
+ try {
18
+ const { createRequire } = await import('module');
19
+ const { resolve, dirname } = await import('path');
20
+ const { chmodSync, statSync } = await import('fs');
21
+ const ptyDir = dirname(createRequire(import.meta.url).resolve('node-pty'));
22
+ const helperPath = resolve(ptyDir, 'prebuilds', `${process.platform}-${process.arch}`, 'spawn-helper');
23
+ const st = statSync(helperPath, { throwIfNoEntry: false });
24
+ if (st && !(st.mode & 0o111)) {
25
+ chmodSync(helperPath, st.mode | 0o755);
26
+ }
27
+ }
28
+ catch {
29
+ // Best-effort; if it fails, the spawn error will surface later
30
+ }
31
+ }
32
+ return pty;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
8
38
  function readBody(req) {
9
39
  return new Promise((resolve, reject) => {
10
40
  const chunks = [];
@@ -176,9 +206,77 @@ export function rendivStudioPlugin(options) {
176
206
  catch {
177
207
  // File doesn't exist yet — that's fine, watch will be set up when it's first created
178
208
  }
179
- // Clean up watcher when server closes
209
+ // Clean up watcher and terminal when server closes
180
210
  server.httpServer?.on('close', () => {
181
211
  overridesWatcher?.close();
212
+ if (terminalProcess) {
213
+ terminalProcess.kill();
214
+ terminalProcess = null;
215
+ }
216
+ });
217
+ // --- Terminal PTY WebSocket handlers ---
218
+ server.ws.on('rendiv:terminal-start', async (data) => {
219
+ if (terminalProcess) {
220
+ server.ws.send({ type: 'custom', event: 'rendiv:terminal-started', data: { pid: terminalProcess.pid } });
221
+ return;
222
+ }
223
+ const pty = await tryImportNodePty();
224
+ if (!pty) {
225
+ server.ws.send({ type: 'custom', event: 'rendiv:terminal-error', data: { message: 'node-pty is not installed. Run: pnpm add node-pty' } });
226
+ return;
227
+ }
228
+ terminalCols = data.cols ?? 80;
229
+ terminalRows = data.rows ?? 24;
230
+ const shell = process.env.SHELL || '/bin/zsh';
231
+ try {
232
+ terminalProcess = pty.spawn(shell, ['-l'], {
233
+ name: 'xterm-256color',
234
+ cols: terminalCols,
235
+ rows: terminalRows,
236
+ cwd: process.cwd(),
237
+ env: { ...process.env },
238
+ });
239
+ }
240
+ catch (err) {
241
+ const msg = err instanceof Error ? err.message : String(err);
242
+ server.ws.send({ type: 'custom', event: 'rendiv:terminal-error', data: { message: `Failed to spawn terminal: ${msg}` } });
243
+ return;
244
+ }
245
+ terminalProcess.onData((output) => {
246
+ server.ws.send({ type: 'custom', event: 'rendiv:terminal-output', data: { data: output } });
247
+ });
248
+ terminalProcess.onExit(({ exitCode, signal }) => {
249
+ terminalProcess = null;
250
+ server.ws.send({ type: 'custom', event: 'rendiv:terminal-exited', data: { exitCode, signal } });
251
+ });
252
+ server.ws.send({ type: 'custom', event: 'rendiv:terminal-started', data: { pid: terminalProcess.pid } });
253
+ // Launch claude in the shell after a short delay to let the shell initialize
254
+ setTimeout(() => {
255
+ terminalProcess?.write('claude\n');
256
+ }, 300);
257
+ });
258
+ server.ws.on('rendiv:terminal-input', (data) => {
259
+ terminalProcess?.write(data.data);
260
+ });
261
+ server.ws.on('rendiv:terminal-resize', (data) => {
262
+ if (terminalProcess && data.cols > 0 && data.rows > 0) {
263
+ terminalCols = data.cols;
264
+ terminalRows = data.rows;
265
+ terminalProcess.resize(data.cols, data.rows);
266
+ }
267
+ });
268
+ server.ws.on('rendiv:terminal-stop', () => {
269
+ if (terminalProcess) {
270
+ terminalProcess.kill();
271
+ terminalProcess = null;
272
+ }
273
+ });
274
+ server.ws.on('rendiv:terminal-status', () => {
275
+ server.ws.send({
276
+ type: 'custom',
277
+ event: 'rendiv:terminal-status-response',
278
+ data: { running: terminalProcess !== null, pid: terminalProcess?.pid ?? null },
279
+ });
182
280
  });
183
281
  // Render queue API endpoints
184
282
  server.middlewares.use((req, res, next) => {
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin-studio.js","sourceRoot":"","sources":["../src/vite-plugin-studio.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vite-plugin-studio.js","sourceRoot":"","sources":["../src/vite-plugin-studio.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rendiv/studio",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,9 +17,12 @@
17
17
  ],
18
18
  "dependencies": {
19
19
  "@vitejs/plugin-react": "^4.3.0",
20
+ "@xterm/xterm": "^5.5.0",
21
+ "@xterm/addon-fit": "^0.10.0",
22
+ "node-pty": "^1.0.0",
20
23
  "vite": "^6.0.0",
21
- "@rendiv/bundler": "0.1.3",
22
- "@rendiv/renderer": "0.1.3"
24
+ "@rendiv/renderer": "0.1.4",
25
+ "@rendiv/bundler": "0.1.4"
23
26
  },
24
27
  "devDependencies": {
25
28
  "@types/node": "^22.0.0",
@@ -19,8 +19,6 @@ export interface RenderJob {
19
19
 
20
20
  interface RenderQueueProps {
21
21
  jobs: RenderJob[];
22
- open: boolean;
23
- onToggle: () => void;
24
22
  onCancel: (jobId: string) => void;
25
23
  onRemove: (jobId: string) => void;
26
24
  onClear: () => void;
@@ -77,13 +75,10 @@ function overallProgress(job: RenderJob): number {
77
75
 
78
76
  export const RenderQueue: React.FC<RenderQueueProps> = ({
79
77
  jobs,
80
- open,
81
- onToggle,
82
78
  onCancel,
83
79
  onRemove,
84
80
  onClear,
85
81
  }) => {
86
- const activeCount = jobs.filter((j) => j.status === 'queued' || j.status === 'bundling' || j.status === 'rendering' || j.status === 'encoding').length;
87
82
  const hasFinished = jobs.some((j) => j.status === 'done' || j.status === 'error' || j.status === 'cancelled');
88
83
 
89
84
  const handleCancel = useCallback((e: React.MouseEvent, jobId: string) => {
@@ -96,41 +91,21 @@ export const RenderQueue: React.FC<RenderQueueProps> = ({
96
91
  onRemove(jobId);
97
92
  }, [onRemove]);
98
93
 
99
- if (!open) return null;
100
-
101
94
  return (
102
- <div style={panelStyle}>
103
- {/* Header */}
104
- <div style={headerStyle}>
105
- <span style={{ fontWeight: 600, fontSize: 11, textTransform: 'uppercase' as const, letterSpacing: '0.05em' }}>
106
- Render Queue
107
- {activeCount > 0 && (
108
- <span style={{ marginLeft: 6, color: colors.accent, fontWeight: 600 }}>
109
- ({activeCount})
110
- </span>
111
- )}
112
- </span>
113
- <div style={{ display: 'flex', gap: 8 }}>
114
- {hasFinished && (
115
- <button
116
- type="button"
117
- style={clearBtnStyle}
118
- onClick={onClear}
119
- title="Clear finished jobs"
120
- >
121
- Clear
122
- </button>
123
- )}
95
+ <div style={contentStyle}>
96
+ {/* Actions bar */}
97
+ {hasFinished && (
98
+ <div style={actionsBarStyle}>
124
99
  <button
125
100
  type="button"
126
- style={closeBtnStyle}
127
- onClick={onToggle}
128
- title="Close panel"
101
+ style={clearBtnStyle}
102
+ onClick={onClear}
103
+ title="Clear finished jobs"
129
104
  >
130
- {'\u2715'}
105
+ Clear finished
131
106
  </button>
132
107
  </div>
133
- </div>
108
+ )}
134
109
 
135
110
  {/* Job list */}
136
111
  <div style={listStyle}>
@@ -221,23 +196,17 @@ export const RenderQueue: React.FC<RenderQueueProps> = ({
221
196
 
222
197
  // Styles
223
198
 
224
- const panelStyle: React.CSSProperties = {
225
- width: 300,
226
- minWidth: 300,
227
- height: '100%',
228
- backgroundColor: colors.surface,
229
- borderLeft: `1px solid ${colors.border}`,
199
+ const contentStyle: React.CSSProperties = {
230
200
  display: 'flex',
231
201
  flexDirection: 'column',
232
- flexShrink: 0,
202
+ flex: 1,
203
+ overflow: 'hidden',
233
204
  };
234
205
 
235
- const headerStyle: React.CSSProperties = {
206
+ const actionsBarStyle: React.CSSProperties = {
236
207
  display: 'flex',
237
- justifyContent: 'space-between',
238
- alignItems: 'center',
239
- padding: '12px 16px',
240
- color: colors.textSecondary,
208
+ justifyContent: 'flex-end',
209
+ padding: '6px 8px',
241
210
  borderBottom: `1px solid ${colors.border}`,
242
211
  flexShrink: 0,
243
212
  };
@@ -277,15 +246,6 @@ const progressBarStyle: React.CSSProperties = {
277
246
  transition: 'width 0.3s ease',
278
247
  };
279
248
 
280
- const closeBtnStyle: React.CSSProperties = {
281
- background: 'none',
282
- border: 'none',
283
- color: colors.textSecondary,
284
- cursor: 'pointer',
285
- fontSize: 12,
286
- padding: '2px 4px',
287
- };
288
-
289
249
  const clearBtnStyle: React.CSSProperties = {
290
250
  background: 'none',
291
251
  border: `1px solid ${colors.border}`,
package/ui/StudioApp.tsx CHANGED
@@ -13,7 +13,8 @@ import { TopBar } from './TopBar';
13
13
  import { Timeline } from './Timeline';
14
14
  import { TimelineEditor } from './TimelineEditor';
15
15
  import { RenderQueue, type RenderJob } from './RenderQueue';
16
- import { layoutStyles, scrollbarCSS } from './styles';
16
+ import { Terminal } from './Terminal';
17
+ import { layoutStyles, scrollbarCSS, colors, fonts } from './styles';
17
18
 
18
19
  // Read the entry point from the generated code's data attribute (set by studio-entry-code)
19
20
  const ENTRY_POINT = (window as Record<string, unknown>).__RENDIV_STUDIO_ENTRY__ as string ?? 'src/index.tsx';
@@ -73,9 +74,22 @@ const StudioApp: React.FC = () => {
73
74
 
74
75
  // Render queue state (server-driven)
75
76
  const [renderJobs, setRenderJobs] = useState<RenderJob[]>([]);
76
- const [queueOpen, setQueueOpen] = useState(false);
77
77
  const hasActiveRef = useRef(false);
78
78
 
79
+ // Right panel state — tabbed panel for Queue and Agent
80
+ const [rightPanel, setRightPanel] = useState<'queue' | 'agent' | null>(() => {
81
+ const stored = localStorage.getItem('rendiv-studio:right-panel');
82
+ if (stored === 'queue' || stored === 'agent') return stored;
83
+ return null;
84
+ });
85
+ const [rightPanelWidth, setRightPanelWidth] = useState(() => {
86
+ const stored = localStorage.getItem('rendiv-studio:right-panel-width');
87
+ return stored ? Number(stored) : 360;
88
+ });
89
+ const isDraggingPanel = useRef(false);
90
+ const panelDragStartX = useRef(0);
91
+ const panelDragStartWidth = useRef(0);
92
+
79
93
  const handleResizeMouseDown = useCallback((e: React.MouseEvent) => {
80
94
  e.preventDefault();
81
95
  isDraggingTimeline.current = true;
@@ -83,11 +97,23 @@ const StudioApp: React.FC = () => {
83
97
  dragStartHeight.current = timelineHeight;
84
98
  }, [timelineHeight]);
85
99
 
100
+ const handlePanelResizeMouseDown = useCallback((e: React.MouseEvent) => {
101
+ e.preventDefault();
102
+ isDraggingPanel.current = true;
103
+ panelDragStartX.current = e.clientX;
104
+ panelDragStartWidth.current = rightPanelWidth;
105
+ }, [rightPanelWidth]);
106
+
86
107
  useEffect(() => {
87
108
  const handleMouseMove = (e: MouseEvent) => {
88
- if (!isDraggingTimeline.current) return;
89
- const delta = dragStartY.current - e.clientY;
90
- setTimelineHeight(Math.max(120, dragStartHeight.current + delta));
109
+ if (isDraggingTimeline.current) {
110
+ const delta = dragStartY.current - e.clientY;
111
+ setTimelineHeight(Math.max(120, dragStartHeight.current + delta));
112
+ }
113
+ if (isDraggingPanel.current) {
114
+ const delta = panelDragStartX.current - e.clientX;
115
+ setRightPanelWidth(Math.max(280, Math.min(800, panelDragStartWidth.current + delta)));
116
+ }
91
117
  };
92
118
  const handleMouseUp = () => {
93
119
  if (isDraggingTimeline.current) {
@@ -97,6 +123,13 @@ const StudioApp: React.FC = () => {
97
123
  return h;
98
124
  });
99
125
  }
126
+ if (isDraggingPanel.current) {
127
+ isDraggingPanel.current = false;
128
+ setRightPanelWidth((w) => {
129
+ localStorage.setItem('rendiv-studio:right-panel-width', String(w));
130
+ return w;
131
+ });
132
+ }
100
133
  };
101
134
  window.addEventListener('mousemove', handleMouseMove);
102
135
  window.addEventListener('mouseup', handleMouseUp);
@@ -351,7 +384,8 @@ const StudioApp: React.FC = () => {
351
384
  totalFrames: selectedComposition.durationInFrames,
352
385
  }),
353
386
  });
354
- setQueueOpen(true);
387
+ setRightPanel('queue');
388
+ localStorage.setItem('rendiv-studio:right-panel-tab', 'queue');
355
389
  }, [selectedComposition, inputProps]);
356
390
 
357
391
  const handleCancelJob = useCallback((jobId: string) => {
@@ -366,8 +400,18 @@ const StudioApp: React.FC = () => {
366
400
  fetch('/__rendiv_api__/render/queue/clear', { method: 'POST' });
367
401
  }, []);
368
402
 
369
- const handleToggleQueue = useCallback(() => {
370
- setQueueOpen((prev) => !prev);
403
+ const handleTogglePanel = useCallback(() => {
404
+ setRightPanel((prev) => {
405
+ if (prev !== null) {
406
+ // Close panel
407
+ localStorage.setItem('rendiv-studio:right-panel', '');
408
+ return null;
409
+ }
410
+ // Open to last active tab (default 'queue')
411
+ const tab = (localStorage.getItem('rendiv-studio:right-panel-tab') as 'queue' | 'agent') || 'queue';
412
+ localStorage.setItem('rendiv-studio:right-panel', tab);
413
+ return tab;
414
+ });
371
415
  }, []);
372
416
 
373
417
  const queueCount = renderJobs.filter((j) =>
@@ -384,8 +428,8 @@ const StudioApp: React.FC = () => {
384
428
  entryPoint={ENTRY_POINT}
385
429
  onRender={handleAddRender}
386
430
  queueCount={queueCount}
387
- queueOpen={queueOpen}
388
- onToggleQueue={handleToggleQueue}
431
+ panelOpen={rightPanel !== null}
432
+ onTogglePanel={handleTogglePanel}
389
433
  />
390
434
 
391
435
  <div style={layoutStyles.body}>
@@ -411,14 +455,67 @@ const StudioApp: React.FC = () => {
411
455
  </div>
412
456
  )}
413
457
 
414
- <RenderQueue
415
- jobs={renderJobs}
416
- open={queueOpen}
417
- onToggle={handleToggleQueue}
418
- onCancel={handleCancelJob}
419
- onRemove={handleRemoveJob}
420
- onClear={handleClearFinished}
421
- />
458
+ {/* Right panel — tabbed: Queue / Agent */}
459
+ {rightPanel !== null && (
460
+ <div style={{ ...rightPanelStyle, width: rightPanelWidth, minWidth: 280 }}>
461
+ <div
462
+ style={panelResizeHandleStyle}
463
+ onMouseDown={handlePanelResizeMouseDown}
464
+ />
465
+ <div style={tabBarStyle}>
466
+ <div style={{ display: 'flex', gap: 2, padding: 2, backgroundColor: colors.bg, borderRadius: 6 }}>
467
+ {(['queue', 'agent'] as const).map((tab) => (
468
+ <button
469
+ key={tab}
470
+ onClick={() => {
471
+ setRightPanel(tab);
472
+ localStorage.setItem('rendiv-studio:right-panel', tab);
473
+ localStorage.setItem('rendiv-studio:right-panel-tab', tab);
474
+ }}
475
+ style={{
476
+ padding: '3px 10px',
477
+ fontSize: 11,
478
+ fontWeight: 500,
479
+ border: 'none',
480
+ borderRadius: 4,
481
+ cursor: 'pointer',
482
+ backgroundColor: rightPanel === tab ? colors.border : 'transparent',
483
+ color: rightPanel === tab ? colors.textPrimary : colors.textSecondary,
484
+ fontFamily: fonts.sans,
485
+ }}
486
+ >
487
+ {tab === 'queue' ? 'Queue' : 'Agent'}
488
+ {tab === 'queue' && queueCount > 0 && (
489
+ <span style={{ marginLeft: 4, color: colors.accent, fontWeight: 600 }}>({queueCount})</span>
490
+ )}
491
+ </button>
492
+ ))}
493
+ </div>
494
+ <button
495
+ type="button"
496
+ onClick={() => {
497
+ setRightPanel(null);
498
+ localStorage.setItem('rendiv-studio:right-panel', '');
499
+ }}
500
+ style={tabCloseStyle}
501
+ title="Close panel"
502
+ >
503
+ {'\u2715'}
504
+ </button>
505
+ </div>
506
+ <div style={{ display: rightPanel === 'queue' ? 'flex' : 'none', flex: 1, flexDirection: 'column' as const, overflow: 'hidden' }}>
507
+ <RenderQueue
508
+ jobs={renderJobs}
509
+ onCancel={handleCancelJob}
510
+ onRemove={handleRemoveJob}
511
+ onClear={handleClearFinished}
512
+ />
513
+ </div>
514
+ <div style={{ display: rightPanel === 'agent' ? 'flex' : 'none', flex: 1, flexDirection: 'column' as const, overflow: 'hidden' }}>
515
+ <Terminal open={rightPanel === 'agent'} />
516
+ </div>
517
+ </div>
518
+ )}
422
519
  </div>
423
520
 
424
521
  {/* Timeline — full-width resizable row */}
@@ -475,6 +572,44 @@ const StudioApp: React.FC = () => {
475
572
  );
476
573
  };
477
574
 
575
+ const rightPanelStyle: React.CSSProperties = {
576
+ position: 'relative',
577
+ height: '100%',
578
+ backgroundColor: colors.surface,
579
+ borderLeft: `1px solid ${colors.border}`,
580
+ display: 'flex',
581
+ flexDirection: 'column',
582
+ flexShrink: 0,
583
+ };
584
+
585
+ const panelResizeHandleStyle: React.CSSProperties = {
586
+ position: 'absolute',
587
+ top: 0,
588
+ left: 0,
589
+ width: 4,
590
+ height: '100%',
591
+ cursor: 'col-resize',
592
+ zIndex: 10,
593
+ };
594
+
595
+ const tabBarStyle: React.CSSProperties = {
596
+ display: 'flex',
597
+ justifyContent: 'space-between',
598
+ alignItems: 'center',
599
+ padding: '6px 8px',
600
+ borderBottom: `1px solid ${colors.border}`,
601
+ flexShrink: 0,
602
+ };
603
+
604
+ const tabCloseStyle: React.CSSProperties = {
605
+ background: 'none',
606
+ border: 'none',
607
+ color: colors.textSecondary,
608
+ cursor: 'pointer',
609
+ fontSize: 12,
610
+ padding: '2px 4px',
611
+ };
612
+
478
613
  export function createStudioApp(container: HTMLElement | null): void {
479
614
  if (!container) {
480
615
  throw new Error('Rendiv Studio: Could not find #root element');
@@ -0,0 +1,266 @@
1
+ import React, { useRef, useEffect, useCallback, useState } from 'react';
2
+ import { Terminal as XTerm } from '@xterm/xterm';
3
+ import { FitAddon } from '@xterm/addon-fit';
4
+ import '@xterm/xterm/css/xterm.css';
5
+ import { colors, fonts } from './styles';
6
+
7
+ export interface TerminalProps {
8
+ open: boolean;
9
+ }
10
+
11
+ type TerminalStatus = 'idle' | 'starting' | 'running' | 'exited' | 'error';
12
+
13
+ export const Terminal: React.FC<TerminalProps> = ({ open }) => {
14
+ const containerRef = useRef<HTMLDivElement>(null);
15
+ const xtermRef = useRef<XTerm | null>(null);
16
+ const fitAddonRef = useRef<FitAddon | null>(null);
17
+ const [status, setStatus] = useState<TerminalStatus>('idle');
18
+ const [errorMessage, setErrorMessage] = useState<string | null>(null);
19
+ const attachedRef = useRef(false);
20
+
21
+ // Create xterm instance once on mount
22
+ useEffect(() => {
23
+ const term = new XTerm({
24
+ cursorBlink: true,
25
+ fontSize: 11,
26
+ fontFamily: fonts.mono,
27
+ theme: {
28
+ background: colors.bg,
29
+ foreground: colors.textPrimary,
30
+ cursor: colors.accent,
31
+ cursorAccent: colors.bg,
32
+ selectionBackground: 'rgba(88, 166, 255, 0.3)',
33
+ black: '#484f58',
34
+ red: '#ff7b72',
35
+ green: '#3fb950',
36
+ yellow: '#d29922',
37
+ blue: '#58a6ff',
38
+ magenta: '#bc8cff',
39
+ cyan: '#39c5cf',
40
+ white: '#b1bac4',
41
+ brightBlack: '#6e7681',
42
+ brightRed: '#ffa198',
43
+ brightGreen: '#56d364',
44
+ brightYellow: '#e3b341',
45
+ brightBlue: '#79c0ff',
46
+ brightMagenta: '#d2a8ff',
47
+ brightCyan: '#56d4dd',
48
+ brightWhite: '#f0f6fc',
49
+ },
50
+ });
51
+
52
+ const fitAddon = new FitAddon();
53
+ term.loadAddon(fitAddon);
54
+
55
+ // Forward user keystrokes to server
56
+ term.onData((data) => {
57
+ const hot = (import.meta as any).hot;
58
+ hot?.send('rendiv:terminal-input', { data });
59
+ });
60
+
61
+ xtermRef.current = term;
62
+ fitAddonRef.current = fitAddon;
63
+
64
+ return () => {
65
+ term.dispose();
66
+ xtermRef.current = null;
67
+ fitAddonRef.current = null;
68
+ attachedRef.current = false;
69
+ };
70
+ }, []);
71
+
72
+ // Listen for server events (once, independent of open state)
73
+ useEffect(() => {
74
+ const hot = (import.meta as any).hot;
75
+ if (!hot) return;
76
+
77
+ const onOutput = (data: { data: string }) => {
78
+ xtermRef.current?.write(data.data);
79
+ };
80
+ const onStarted = () => {
81
+ setStatus('running');
82
+ setErrorMessage(null);
83
+ };
84
+ const onExited = () => {
85
+ setStatus('exited');
86
+ };
87
+ const onError = (data: { message: string }) => {
88
+ setStatus('error');
89
+ setErrorMessage(data.message);
90
+ };
91
+ const onStatusResponse = (data: { running: boolean }) => {
92
+ if (data.running) setStatus('running');
93
+ };
94
+
95
+ hot.on('rendiv:terminal-output', onOutput);
96
+ hot.on('rendiv:terminal-started', onStarted);
97
+ hot.on('rendiv:terminal-exited', onExited);
98
+ hot.on('rendiv:terminal-error', onError);
99
+ hot.on('rendiv:terminal-status-response', onStatusResponse);
100
+
101
+ // Check if terminal is already running (re-attach after page refresh)
102
+ hot.send('rendiv:terminal-status', {});
103
+
104
+ return () => {
105
+ hot.off?.('rendiv:terminal-output', onOutput);
106
+ hot.off?.('rendiv:terminal-started', onStarted);
107
+ hot.off?.('rendiv:terminal-exited', onExited);
108
+ hot.off?.('rendiv:terminal-error', onError);
109
+ hot.off?.('rendiv:terminal-status-response', onStatusResponse);
110
+ };
111
+ }, []);
112
+
113
+ // Attach/detach xterm to DOM when panel opens/closes
114
+ useEffect(() => {
115
+ if (!open || !containerRef.current || !xtermRef.current) return;
116
+
117
+ if (!attachedRef.current) {
118
+ xtermRef.current.open(containerRef.current);
119
+ attachedRef.current = true;
120
+ }
121
+
122
+ // Fit after a frame to ensure container has layout dimensions
123
+ requestAnimationFrame(() => {
124
+ fitAddonRef.current?.fit();
125
+ });
126
+ }, [open]);
127
+
128
+ // Resize terminal when container size changes
129
+ useEffect(() => {
130
+ if (!open || !containerRef.current) return;
131
+
132
+ const observer = new ResizeObserver(() => {
133
+ const term = xtermRef.current;
134
+ const fitAddon = fitAddonRef.current;
135
+ if (!term || !fitAddon) return;
136
+
137
+ fitAddon.fit();
138
+ const hot = (import.meta as any).hot;
139
+ hot?.send('rendiv:terminal-resize', { cols: term.cols, rows: term.rows });
140
+ });
141
+
142
+ observer.observe(containerRef.current);
143
+ return () => observer.disconnect();
144
+ }, [open]);
145
+
146
+ const handleStart = useCallback(() => {
147
+ setStatus('starting');
148
+ const term = xtermRef.current;
149
+ const hot = (import.meta as any).hot;
150
+ hot?.send('rendiv:terminal-start', {
151
+ cols: term?.cols ?? 80,
152
+ rows: term?.rows ?? 24,
153
+ });
154
+ }, []);
155
+
156
+ const handleRestart = useCallback(() => {
157
+ const hot = (import.meta as any).hot;
158
+ hot?.send('rendiv:terminal-stop', {});
159
+ xtermRef.current?.clear();
160
+ setTimeout(() => {
161
+ setStatus('starting');
162
+ const term = xtermRef.current;
163
+ hot?.send('rendiv:terminal-start', {
164
+ cols: term?.cols ?? 80,
165
+ rows: term?.rows ?? 24,
166
+ });
167
+ }, 300);
168
+ }, []);
169
+
170
+ const showOverlay = status === 'idle' || status === 'error' || status === 'exited';
171
+
172
+ return (
173
+ <div style={panelStyle}>
174
+ {/* Actions bar — only when there's something to act on */}
175
+ {(status === 'running' || status === 'exited') && (
176
+ <div style={actionsBarStyle}>
177
+ <button style={actionBtnStyle} onClick={handleRestart}>Restart</button>
178
+ </div>
179
+ )}
180
+
181
+ <div style={terminalBodyStyle}>
182
+ {showOverlay && (
183
+ <div style={overlayStyle}>
184
+ {status === 'error' && errorMessage && (
185
+ <div style={{ color: colors.error, fontSize: 13, marginBottom: 12, textAlign: 'center' as const }}>
186
+ {errorMessage}
187
+ </div>
188
+ )}
189
+ {status === 'exited' && (
190
+ <div style={{ color: colors.textSecondary, fontSize: 13, marginBottom: 12 }}>
191
+ Claude Code has exited
192
+ </div>
193
+ )}
194
+ <button style={startBtnStyle} onClick={status === 'exited' ? handleRestart : handleStart}>
195
+ {status === 'exited' ? 'Restart Claude Code' : status === 'error' ? 'Retry' : 'Launch Claude Code'}
196
+ </button>
197
+ </div>
198
+ )}
199
+ <div ref={containerRef} style={xtermContainerStyle} />
200
+ </div>
201
+ </div>
202
+ );
203
+ };
204
+
205
+ const panelStyle: React.CSSProperties = {
206
+ display: 'flex',
207
+ flexDirection: 'column',
208
+ flex: 1,
209
+ overflow: 'hidden',
210
+ };
211
+
212
+ const actionsBarStyle: React.CSSProperties = {
213
+ display: 'flex',
214
+ justifyContent: 'flex-end',
215
+ padding: '4px 8px',
216
+ borderBottom: `1px solid ${colors.border}`,
217
+ flexShrink: 0,
218
+ };
219
+
220
+ const terminalBodyStyle: React.CSSProperties = {
221
+ flex: 1,
222
+ position: 'relative',
223
+ backgroundColor: colors.bg,
224
+ overflow: 'hidden',
225
+ };
226
+
227
+ const xtermContainerStyle: React.CSSProperties = {
228
+ width: '100%',
229
+ height: '100%',
230
+ padding: '4px 0 4px 4px',
231
+ };
232
+
233
+ const overlayStyle: React.CSSProperties = {
234
+ position: 'absolute',
235
+ inset: 0,
236
+ display: 'flex',
237
+ flexDirection: 'column',
238
+ alignItems: 'center',
239
+ justifyContent: 'center',
240
+ zIndex: 10,
241
+ backgroundColor: colors.bg,
242
+ };
243
+
244
+ const startBtnStyle: React.CSSProperties = {
245
+ padding: '8px 20px',
246
+ fontSize: 13,
247
+ fontWeight: 600,
248
+ color: '#fff',
249
+ backgroundColor: colors.accentMuted,
250
+ border: 'none',
251
+ borderRadius: 6,
252
+ cursor: 'pointer',
253
+ fontFamily: fonts.sans,
254
+ };
255
+
256
+ const actionBtnStyle: React.CSSProperties = {
257
+ background: 'none',
258
+ border: `1px solid ${colors.border}`,
259
+ color: colors.textSecondary,
260
+ cursor: 'pointer',
261
+ fontSize: 10,
262
+ padding: '2px 8px',
263
+ borderRadius: 4,
264
+ fontFamily: fonts.sans,
265
+ };
266
+
package/ui/TopBar.tsx CHANGED
@@ -9,8 +9,8 @@ interface TopBarProps {
9
9
  entryPoint: string;
10
10
  onRender: () => void;
11
11
  queueCount: number;
12
- queueOpen: boolean;
13
- onToggleQueue: () => void;
12
+ panelOpen: boolean;
13
+ onTogglePanel: () => void;
14
14
  }
15
15
 
16
16
  const RenderIcon: React.FC = () => (
@@ -19,14 +19,14 @@ const RenderIcon: React.FC = () => (
19
19
  </svg>
20
20
  );
21
21
 
22
- const QueueIcon: React.FC<{ open: boolean }> = ({ open }) => (
22
+ const PanelIcon: React.FC<{ open: boolean }> = ({ open }) => (
23
23
  <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
24
24
  <rect x="10" y="2" width="4" height="12" rx="1" fill={open ? 'currentColor' : 'none'} stroke="currentColor" strokeWidth="1.5" />
25
25
  <rect x="2" y="2" width="6" height="12" rx="1" stroke="currentColor" strokeWidth="1.5" />
26
26
  </svg>
27
27
  );
28
28
 
29
- export const TopBar: React.FC<TopBarProps> = ({ composition, entryPoint, onRender, queueCount, queueOpen, onToggleQueue }) => {
29
+ export const TopBar: React.FC<TopBarProps> = ({ composition, entryPoint, onRender, queueCount, panelOpen, onTogglePanel }) => {
30
30
  const [copied, setCopied] = useState(false);
31
31
 
32
32
  const handleCopyCommand = useCallback(() => {
@@ -94,13 +94,13 @@ export const TopBar: React.FC<TopBarProps> = ({ composition, entryPoint, onRende
94
94
  alignItems: 'center',
95
95
  gap: 6,
96
96
  position: 'relative' as const,
97
- color: queueOpen ? colors.accent : colors.textPrimary,
98
- borderColor: queueOpen ? colors.accent : colors.border,
97
+ color: panelOpen ? colors.accent : colors.textPrimary,
98
+ borderColor: panelOpen ? colors.accent : colors.border,
99
99
  }}
100
- onClick={onToggleQueue}
101
- title="Toggle render queue panel"
100
+ onClick={onTogglePanel}
101
+ title="Toggle side panel"
102
102
  >
103
- <QueueIcon open={queueOpen} />
103
+ <PanelIcon open={panelOpen} />
104
104
  {queueCount > 0 && (
105
105
  <span style={badgeStyle}>{queueCount}</span>
106
106
  )}