@pstdio/ui 0.44.0-nightly.20261018030230 → 0.44.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.
Files changed (74) hide show
  1. package/dist/{MermaidComponent-DIHl8p85.js → MermaidComponent-DhNTaUMt.js} +2 -2
  2. package/dist/{MermaidComponent-DIHl8p85.js.map → MermaidComponent-DhNTaUMt.js.map} +1 -1
  3. package/dist/apply-theme-preference-B0vCu8zY.d.ts +26 -0
  4. package/dist/chat-ui.d.ts +50 -50
  5. package/dist/chat-ui.js +143 -141
  6. package/dist/chat-ui.js.map +1 -1
  7. package/dist/{collection-view-fields-Sa5HO5P7.d.ts → collection-view-fields-tMtZmuhS.d.ts} +0 -2
  8. package/dist/{collection-view-grouping-aKZhxYfX.js → collection-view-grouping-BKIr4QAb.js} +2 -2
  9. package/dist/{collection-view-grouping-aKZhxYfX.js.map → collection-view-grouping-BKIr4QAb.js.map} +1 -1
  10. package/dist/{collection-view-search-mHPkdyxT.js → collection-view-search-D7HFymZW.js} +160 -166
  11. package/dist/collection-view-search-D7HFymZW.js.map +1 -0
  12. package/dist/collection-view.d.ts +3 -90
  13. package/dist/collection-view.js +1 -1
  14. package/dist/data-table.d.ts +3 -2
  15. package/dist/data-table.js +98 -88
  16. package/dist/data-table.js.map +1 -1
  17. package/dist/{diff-drawer-BMl0zobj.js → diff-drawer-ByJsQg8F.js} +10 -10
  18. package/dist/diff-drawer-ByJsQg8F.js.map +1 -0
  19. package/dist/{diff-viewer-C5KXwq7E.js → diff-viewer-Cpiw-1ut.js} +4 -4
  20. package/dist/{diff-viewer-C5KXwq7E.js.map → diff-viewer-Cpiw-1ut.js.map} +1 -1
  21. package/dist/diff.js +2 -2
  22. package/dist/{display-sort-control-0_gG-W9g.js → display-sort-control-BuqijDAl.js} +3 -3
  23. package/dist/{display-sort-control-0_gG-W9g.js.map → display-sort-control-BuqijDAl.js.map} +1 -1
  24. package/dist/{edit-mode-data-table-BI_UDPfF.js → edit-mode-data-table-BwNTRik5.js} +147 -136
  25. package/dist/edit-mode-data-table-BwNTRik5.js.map +1 -0
  26. package/dist/host-storage-28AkEy1N.js +98 -0
  27. package/dist/host-storage-28AkEy1N.js.map +1 -0
  28. package/dist/index-3H4B61XK.d.ts +38 -0
  29. package/dist/{index-BTABZd25.d.ts → index-DTjRTEez.d.ts} +2 -2
  30. package/dist/index-kYQwGcym.d.ts +91 -0
  31. package/dist/index.d.ts +114 -101
  32. package/dist/index.js +763 -761
  33. package/dist/index.js.map +1 -1
  34. package/dist/kanban-renderer.d.ts +2 -2
  35. package/dist/kanban-renderer.js +509 -494
  36. package/dist/kanban-renderer.js.map +1 -1
  37. package/dist/list-row-BDDAVuVd.js +1228 -0
  38. package/dist/list-row-BDDAVuVd.js.map +1 -0
  39. package/dist/{markdown-editor-Dx41ftfs.js → markdown-editor-DUBUE7M-.js} +150 -138
  40. package/dist/markdown-editor-DUBUE7M-.js.map +1 -0
  41. package/dist/{param-editor-C4IUuO77.js → param-editor-DK1uCOh3.js} +2 -2
  42. package/dist/{param-editor-C4IUuO77.js.map → param-editor-DK1uCOh3.js.map} +1 -1
  43. package/dist/{param-editor-field-uBStVJ48.js → param-editor-field-B5z6200g.js} +278 -282
  44. package/dist/param-editor-field-B5z6200g.js.map +1 -0
  45. package/dist/param-editor.js +2 -2
  46. package/dist/{rich-text-Dlv0q1r_.js → rich-text-2c_ra5gK.js} +3 -3
  47. package/dist/{rich-text-Dlv0q1r_.js.map → rich-text-2c_ra5gK.js.map} +1 -1
  48. package/dist/rich-text.js +3 -3
  49. package/dist/terminal.d.ts +28 -0
  50. package/dist/terminal.js +59 -32
  51. package/dist/terminal.js.map +1 -1
  52. package/dist/{theme-DJE3KvWt.js → theme-Chgjys_o.js} +124 -96
  53. package/dist/theme-Chgjys_o.js.map +1 -0
  54. package/dist/theme.d.ts +1 -1
  55. package/dist/theme.js +1 -1
  56. package/dist/{tree-list-Ces1hpRd.js → tree-list-B8Gtot1M.js} +99 -99
  57. package/dist/tree-list-B8Gtot1M.js.map +1 -0
  58. package/dist/{use-virtualizer-CfDHoDer.js → use-virtualizer-CqDYJolY.js} +8 -3
  59. package/dist/use-virtualizer-CqDYJolY.js.map +1 -0
  60. package/dist/{workspace-badge-CvQBU6Hs.d.ts → workspace-badge-BMjS8ii4.d.ts} +6 -1
  61. package/package.json +2 -2
  62. package/dist/collection-view-search-mHPkdyxT.js.map +0 -1
  63. package/dist/diff-drawer-BMl0zobj.js.map +0 -1
  64. package/dist/edit-mode-data-table-BI_UDPfF.js.map +0 -1
  65. package/dist/host-storage-BIo5azql.js +0 -31
  66. package/dist/host-storage-BIo5azql.js.map +0 -1
  67. package/dist/index-Dd6e8lU_.d.ts +0 -61
  68. package/dist/list-row-F8kBQGB-.js +0 -1232
  69. package/dist/list-row-F8kBQGB-.js.map +0 -1
  70. package/dist/markdown-editor-Dx41ftfs.js.map +0 -1
  71. package/dist/param-editor-field-uBStVJ48.js.map +0 -1
  72. package/dist/theme-DJE3KvWt.js.map +0 -1
  73. package/dist/tree-list-Ces1hpRd.js.map +0 -1
  74. package/dist/use-virtualizer-CfDHoDer.js.map +0 -1
package/dist/rich-text.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./markdown-editor-Dx41ftfs.js";
2
- import { m as t } from "./param-editor-field-uBStVJ48.js";
3
- import { a as n, c as r, i, l as a, n as o, o as s, r as c, s as l, t as u, u as d } from "./rich-text-Dlv0q1r_.js";
1
+ import { t as e } from "./markdown-editor-DUBUE7M-.js";
2
+ import { m as t } from "./param-editor-field-B5z6200g.js";
3
+ import { a as n, c as r, i, l as a, n as o, o as s, r as c, s as l, t as u, u as d } from "./rich-text-2c_ra5gK.js";
4
4
  export { d as CollaborativeMarkdownEditor, c as DefaultRichTextCodeEditor, i as DefaultRichTextDataTable, t as LazyMarkdownEditor, e as MarkdownEditor, s as MarkdownPreview, s as RichMessage, l as PromptEditor, n as ResourceActivityFeed, r as generateEditorStateFromString, a as getTextFromSerializedEditorState, o as inferResourceTypeFromMediaType, u as mediaTypeFromPath };
@@ -1,3 +1,4 @@
1
+ import { r as ThemePreferenceOption } from "./apply-theme-preference-B0vCu8zY.js";
1
2
  import { TerminalBridge, TerminalSessionAdapter, TerminalSessionError, TerminalSessionExit, TerminalSessionRequest } from "@pstdio/sdk/api";
2
3
  import { ITheme } from "@xterm/xterm";
3
4
  //#region src/components/terminal/bind-session.d.ts
@@ -81,6 +82,33 @@ type TerminalThemeName = "light" | "dark";
81
82
  export declare const lightTerminalTheme: ITheme;
82
83
  export declare const darkTerminalTheme: ITheme;
83
84
  export declare const terminalThemes: Record<TerminalThemeName, ITheme>;
85
+ /** Resolve concrete xterm colors from the theme's mode and contributed VS Code tokens. */
86
+ export declare const createTerminalThemeFromPreference: (preference: ThemePreferenceOption) => {
87
+ foreground?: string;
88
+ background?: string;
89
+ cursor?: string;
90
+ cursorAccent?: string;
91
+ selectionBackground?: string;
92
+ selectionForeground?: string;
93
+ selectionInactiveBackground?: string;
94
+ black?: string;
95
+ red?: string;
96
+ green?: string;
97
+ yellow?: string;
98
+ blue?: string;
99
+ magenta?: string;
100
+ cyan?: string;
101
+ white?: string;
102
+ brightBlack?: string;
103
+ brightRed?: string;
104
+ brightGreen?: string;
105
+ brightYellow?: string;
106
+ brightBlue?: string;
107
+ brightMagenta?: string;
108
+ brightCyan?: string;
109
+ brightWhite?: string;
110
+ extendedAnsi?: string[];
111
+ };
84
112
  export declare const resolveTerminalTheme: (theme: TerminalThemeName | ITheme | undefined) => ITheme;
85
113
  //#endregion
86
114
  //#region src/components/terminal/terminal.d.ts
package/dist/terminal.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./split-panel-motion-context-YB0sduVv.js";
2
- import { t } from "./theme-DJE3KvWt.js";
2
+ import { t } from "./theme-Chgjys_o.js";
3
3
  import { c as n } from "react/compiler-runtime";
4
4
  import { jsx as r } from "react/jsx-runtime";
5
5
  import { useContext as i, useEffect as a, useRef as o, useState as s } from "react";
@@ -112,15 +112,42 @@ var d = (e, t, n = {}) => {
112
112
  }, x = b("light"), S = b("dark"), C = {
113
113
  light: x,
114
114
  dark: S
115
- }, w = (e) => e ? typeof e == "string" ? C[e] : e : C.dark, T = (e) => JSON.stringify({
115
+ }, w = (e) => {
116
+ let t = e.tokens ?? {}, n = { ...C[e.mode] }, r = t["colors.vscode.terminal.foreground"] ?? t["colors.fg"], i = t["colors.vscode.terminal.background"] ?? t["colors.bg"], a = {
117
+ background: i,
118
+ foreground: r,
119
+ cursor: t["colors.vscode.terminalCursor.foreground"] ?? r,
120
+ cursorAccent: t["colors.vscode.terminalCursor.background"] ?? i,
121
+ selectionBackground: t["colors.vscode.terminal.selectionBackground"],
122
+ selectionForeground: t["colors.vscode.terminal.selectionForeground"]
123
+ };
124
+ for (let e of Object.keys(a)) {
125
+ let t = a[e];
126
+ t && (n[e] = t);
127
+ }
128
+ for (let e of [
129
+ "black",
130
+ "red",
131
+ "green",
132
+ "yellow",
133
+ "blue",
134
+ "magenta",
135
+ "cyan",
136
+ "white"
137
+ ]) {
138
+ let r = `${e[0].toUpperCase()}${e.slice(1)}`, i = t[`colors.vscode.terminal.ansi${r}`], a = t[`colors.vscode.terminal.ansiBright${r}`];
139
+ i && (n[e] = i), a && (n[`bright${r}`] = a);
140
+ }
141
+ return n;
142
+ }, T = (e) => e ? typeof e == "string" ? C[e] : e : C.dark, E = (e) => JSON.stringify({
116
143
  command: e.command,
117
144
  cwd: e.cwd,
118
145
  env: e.env ? Object.fromEntries(Object.entries(e.env).sort(([e], [t]) => e.localeCompare(t))) : void 0,
119
146
  cols: e.cols,
120
147
  rows: e.rows
121
- }), E = (e) => JSON.parse(e), D = (e) => {
148
+ }), D = (e) => JSON.parse(e), O = (e) => {
122
149
  let t = n(8), { bridge: r, request: i, killOnUnmount: o } = e, c = o === void 0 || o, l;
123
- t[0] === i ? l = t[1] : (l = T(i), t[0] = i, t[1] = l);
150
+ t[0] === i ? l = t[1] : (l = E(i), t[0] = i, t[1] = l);
124
151
  let u = l, d;
125
152
  t[2] === Symbol.for("react.memo_cache_sentinel") ? (d = {
126
153
  session: null,
@@ -146,7 +173,7 @@ var d = (e, t, n = {}) => {
146
173
  exit: null,
147
174
  error: null
148
175
  });
149
- let a = E(u);
176
+ let a = D(u);
150
177
  return r.openSession(a).then((r) => {
151
178
  if (e) {
152
179
  c && r.kill();
@@ -188,11 +215,11 @@ var d = (e, t, n = {}) => {
188
215
  u,
189
216
  c
190
217
  ], t[3] = r, t[4] = c, t[5] = u, t[6] = m, t[7] = h) : (m = t[6], h = t[7]), a(m, h), f;
191
- }, O = "\"JetBrains Mono\", \"Fira Code\", Menlo, Consolas, monospace", k = 13, A = 80, j = 24, M = (e) => ({
218
+ }, k = "\"JetBrains Mono\", \"Fira Code\", Menlo, Consolas, monospace", A = 13, j = 80, M = 24, N = (e) => ({
192
219
  ...e,
193
- cols: e?.cols ?? A,
194
- rows: e?.rows ?? j
195
- }), N = (e) => {
220
+ cols: e?.cols ?? j,
221
+ rows: e?.rows ?? M
222
+ }), P = (e) => {
196
223
  let t = /* @__PURE__ */ new Set(), n = [], r = e.onData((e) => {
197
224
  if (t.size === 0) {
198
225
  n.push(e);
@@ -216,50 +243,50 @@ var d = (e, t, n = {}) => {
216
243
  r.dispose(), t.clear(), n.length = 0;
217
244
  }
218
245
  };
219
- }, P = (e, t) => {
220
- (e.ctrlKey || e.metaKey) && window.open(t, "_blank", "noopener,noreferrer");
221
246
  }, F = (e, t) => {
247
+ (e.ctrlKey || e.metaKey) && window.open(t, "_blank", "noopener,noreferrer");
248
+ }, I = (e, t) => {
222
249
  if (!t?.getAnimations().some((e) => e instanceof CSSTransition && e.transitionProperty === "--split-size")) try {
223
250
  e?.fit();
224
251
  } catch {}
225
- }, I = (e, t) => {
252
+ }, L = (e, t) => {
226
253
  t.resize(e.cols, e.rows);
227
- }, L = (e, t, n, r) => {
254
+ }, R = (e, t, n, r) => {
228
255
  let i = d(t, n, { onExit: r.onSessionExit });
229
- return I(e, n), r.onSessionOpen?.(n.id), i;
230
- }, R = (e, t, n, r) => L(e, t, n, {
256
+ return L(e, n), r.onSessionOpen?.(n.id), i;
257
+ }, z = (e, t, n, r) => R(e, t, n, {
231
258
  onSessionOpen: (e) => r.onSessionOpen.current?.(e),
232
259
  onSessionExit: (e) => r.onSessionExit.current?.(e)
233
- }), z = (t) => {
234
- let { bridge: n, request: d, theme: f, fontFamily: p = O, fontSize: m = k, killOnUnmount: h = !0, autoFocus: g = !0, className: _, style: v, onSessionOpen: y, onSessionExit: b } = t, x = o(null), S = o(null), C = o(null), T = o(null), [E, I] = s(!1), L = o(null), z = o(y), B = o(b);
235
- z.current = y, B.current = b, L.current ||= M(d);
236
- let V = w(f), H = i(e);
260
+ }), B = (t) => {
261
+ let { bridge: n, request: d, theme: f, fontFamily: p = k, fontSize: m = A, killOnUnmount: h = !0, autoFocus: g = !0, className: _, style: v, onSessionOpen: y, onSessionExit: b } = t, x = o(null), S = o(null), C = o(null), w = o(null), [E, D] = s(!1), L = o(null), R = o(y), B = o(b);
262
+ R.current = y, B.current = b, L.current ||= N(d);
263
+ let V = T(f), H = i(e);
237
264
  a(() => {
238
265
  let e = x.current;
239
266
  if (!e) return;
240
- let t, n, r, i, a, o = H?.current, s = () => F(C.current, o), d = (e) => {
267
+ let t, n, r, i, a, o = H?.current, s = () => I(C.current, o), d = (e) => {
241
268
  e.target === o && e.propertyName === "--split-size" && s();
242
269
  };
243
270
  o?.addEventListener("transitionend", d), o?.addEventListener("transitioncancel", d);
244
271
  let f = window.requestAnimationFrame(() => {
245
272
  t = new u({
246
- cols: A,
247
- rows: j,
273
+ cols: j,
274
+ rows: M,
248
275
  cursorBlink: !0,
249
276
  convertEol: !0,
250
277
  allowProposedApi: !0,
251
- linkHandler: { activate: P }
278
+ linkHandler: { activate: F }
252
279
  });
253
280
  let o = new c();
254
- t.loadAddon(o), t.loadAddon(new l(P)), t.open(e), n = N(t), S.current = t, C.current = o, T.current = n, s(), r = window.requestAnimationFrame(s), i = window.setTimeout(s, 50), a = new ResizeObserver(s), a.observe(e), I(!0);
281
+ t.loadAddon(o), t.loadAddon(new l(F)), t.open(e), n = P(t), S.current = t, C.current = o, w.current = n, s(), r = window.requestAnimationFrame(s), i = window.setTimeout(s, 50), a = new ResizeObserver(s), a.observe(e), D(!0);
255
282
  });
256
283
  return () => {
257
- window.cancelAnimationFrame(f), r !== void 0 && window.cancelAnimationFrame(r), i !== void 0 && window.clearTimeout(i), a?.disconnect(), o?.removeEventListener("transitionend", d), o?.removeEventListener("transitioncancel", d), n?.dispose(), t?.dispose(), S.current = null, C.current = null, T.current = null;
284
+ window.cancelAnimationFrame(f), r !== void 0 && window.cancelAnimationFrame(r), i !== void 0 && window.clearTimeout(i), a?.disconnect(), o?.removeEventListener("transitionend", d), o?.removeEventListener("transitioncancel", d), n?.dispose(), t?.dispose(), S.current = null, C.current = null, w.current = null;
258
285
  };
259
286
  }, [H]), a(() => {
260
287
  if (!E) return;
261
288
  let e = S.current;
262
- e && (e.options.theme = V, e.options.fontFamily = p, e.options.fontSize = m, F(C.current, H?.current));
289
+ e && (e.options.theme = V, e.options.fontFamily = p, e.options.fontSize = m, I(C.current, H?.current));
263
290
  }, [
264
291
  E,
265
292
  V,
@@ -267,18 +294,18 @@ var d = (e, t, n = {}) => {
267
294
  m,
268
295
  H
269
296
  ]);
270
- let { session: U } = D({
297
+ let { session: U } = O({
271
298
  bridge: n,
272
299
  request: L.current,
273
300
  killOnUnmount: h
274
301
  });
275
302
  return a(() => {
276
303
  if (!E) return;
277
- let e = S.current, t = T.current;
304
+ let e = S.current, t = w.current;
278
305
  if (!e || !t || !U) return;
279
- F(C.current, H?.current);
280
- let n = window.requestAnimationFrame(() => F(C.current, H?.current)), r = R(e, t, U, {
281
- onSessionOpen: z,
306
+ I(C.current, H?.current);
307
+ let n = window.requestAnimationFrame(() => I(C.current, H?.current)), r = z(e, t, U, {
308
+ onSessionOpen: R,
282
309
  onSessionExit: B
283
310
  });
284
311
  return () => {
@@ -310,6 +337,6 @@ var d = (e, t, n = {}) => {
310
337
  });
311
338
  };
312
339
  //#endregion
313
- export { z as Terminal, d as bindSessionToSink, y as createScriptedTerminalBridge, S as darkTerminalTheme, x as lightTerminalTheme, w as resolveTerminalTheme, C as terminalThemes, D as useTerminalSession };
340
+ export { B as Terminal, d as bindSessionToSink, y as createScriptedTerminalBridge, w as createTerminalThemeFromPreference, S as darkTerminalTheme, x as lightTerminalTheme, T as resolveTerminalTheme, C as terminalThemes, O as useTerminalSession };
314
341
 
315
342
  //# sourceMappingURL=terminal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.js","names":["TerminalSessionAdapter","TerminalSink","write","data","Uint8Array","onInput","handler","onResize","size","cols","rows","BindSessionOptions","onExit","exit","code","signal","onError","error","message","bindSessionToSink","sink","session","options","disposers","Array","push","onData","chunk","resize","length","dispose","pop","TerminalBridge","TerminalSessionAdapter","TerminalSessionError","TerminalSessionExit","ScriptedTerminalStep","data","Uint8Array","delayMs","exit","code","signal","error","ScriptedBridgeOptions","initial","onInput","input","onResize","size","cols","rows","onKill","encoder","TextEncoder","toChunk","encode","wait","ms","Promise","resolve","setTimeout","defaultEcho","replace","SessionEmitter","isExited","emitData","chunk","emitExit","emitError","runStep","emitter","step","undefined","message","playSteps","steps","createScriptedSession","options","NonNullable","dataHandlers","Set","exitHandlers","errorHandlers","exited","startedInitial","handler","session","id","crypto","randomUUID","write","text","TextDecoder","decode","response","resize","kill","onData","add","delete","onExit","onError","createScriptedTerminalBridge","openSession","_request","ITheme","psTheme","TerminalThemeName","createTerminalTheme","preset","color","name","token","background","foreground","cursor","cursorAccent","selectionBackground","selectionForeground","undefined","black","red","green","yellow","blue","magenta","cyan","white","brightBlack","brightRed","brightGreen","brightYellow","brightBlue","brightMagenta","brightCyan","brightWhite","lightTerminalTheme","darkTerminalTheme","terminalThemes","Record","light","dark","resolveTerminalTheme","theme","psTheme","useEffect","useState","TerminalBridge","TerminalSessionAdapter","TerminalSessionError","TerminalSessionExit","TerminalSessionRequest","TerminalSessionStatus","UseTerminalSessionResult","session","status","exit","error","UseTerminalSessionOptions","bridge","request","killOnUnmount","createTerminalSessionRequestKey","JSON","stringify","command","cwd","env","Object","fromEntries","entries","sort","left","right","localeCompare","undefined","cols","rows","readTerminalSessionRequestKey","requestKey","parse","useTerminalSession","t0","$","_c","t1","t2","t3","Symbol","for","state","setState","t4","t5","cancelled","activeSession","terminalState","disposers","requestSnapshot","openSession","then","kill","push","onExit","prev","onError","prev_0","catch","cause","message","Error","String","length","pop","_c","FitAddon","WebLinksAddon","ITheme","Terminal","Xterm","useContext","useEffect","useRef","useState","SplitPanelMotionContext","bindSessionToSink","TerminalSink","resolveTerminalTheme","TerminalThemeName","TerminalBridge","TerminalSessionAdapter","TerminalSessionRequest","useTerminalSession","DEFAULT_FONT_FAMILY","DEFAULT_FONT_SIZE","DEFAULT_COLS","DEFAULT_ROWS","createInitialTerminalSessionRequest","request","Partial","cols","rows","createTerminalSink","xterm","Pick","inputHandlers","Set","data","pendingInput","inputDisposable","onData","size","push","handler","write","Uint8Array","onInput","add","length","shift","delete","onResize","disposable","dispose","clear","openTerminalLink","event","MouseEvent","uri","ctrlKey","metaKey","window","open","fitTerminal","fit","motionRoot","HTMLDivElement","getAnimations","some","animation","CSSTransition","transitionProperty","resizeSessionToTerminalGeometry","terminal","session","resize","bindTerminalSession","sink","options","TerminalProps","unbind","onExit","onSessionExit","onSessionOpen","id","TerminalSessionCallbackRefs","React","RefObject","bindTerminalSessionWithCallbackRefs","callbackRefs","sessionId","current","exit","bridge","theme","fontFamily","fontSize","killOnUnmount","autoFocus","className","style","CSSProperties","code","signal","props","containerRef","xtermRef","fitRef","sinkRef","ReturnType","terminalReady","setTerminalReady","initialSessionRequestRef","onSessionOpenRef","onSessionExitRef","resolvedTheme","motionRootRef","container","measureAnimationFrame","measureTimeout","observer","ResizeObserver","measure","handleMotionEnd","TransitionEvent","target","propertyName","addEventListener","initializationFrame","requestAnimationFrame","cursorBlink","convertEol","allowProposedApi","linkHandler","activate","loadAddon","setTimeout","observe","cancelAnimationFrame","undefined","clearTimeout","disconnect","removeEventListener","animationFrame","focus","position","width","height","backgroundColor","background","inset","Xterm","SplitPanelMotionContext","Terminal$1","bindSessionToSink","disposers","session","sink","chunk","data","options","cols","rows","dispose","encoder","toChunk","wait","ms","resolve","defaultEcho","input","runStep","step","emitter","playSteps","steps","createScriptedSession","dataHandlers","exitHandlers","errorHandlers","exited","startedInitial","handler","exit","error","response","onInput","signal","createScriptedTerminalBridge","createTerminalTheme","color","theme_default","preset","name","lightTerminalTheme","darkTerminalTheme","terminalThemes","resolveTerminalTheme","theme","createTerminalSessionRequestKey","request","left","right","readTerminalSessionRequestKey","requestKey","useTerminalSession","$","c","t1","t0","killOnUnmount","t2","t3","state","setState","useState","t4","t5","bridge","cancelled","activeSession","terminalState","requestSnapshot","prev","prev_0","message","cause","useEffect","DEFAULT_FONT_FAMILY","DEFAULT_FONT_SIZE","DEFAULT_COLS","DEFAULT_ROWS","createInitialTerminalSessionRequest","createTerminalSink","inputHandlers","pendingInput","inputDisposable","xterm","disposable","openTerminalLink","event","uri","fitTerminal","animation","resizeSessionToTerminalGeometry","terminal","bindTerminalSession","unbind","bindTerminalSessionWithCallbackRefs","callbackRefs","sessionId","Terminal","props","containerRef","useRef","xtermRef","fitRef","sinkRef","terminalReady","setTerminalReady","initialSessionRequestRef","onSessionOpenRef","onSessionOpen","onSessionExitRef","onSessionExit","resolvedTheme","motionRootRef","useContext","container","measureAnimationFrame","measureTimeout","observer","motionRoot","measure","handleMotionEnd","initializationFrame","fit","FitAddon","WebLinksAddon","xterm_0","fontFamily","fontSize","xterm_1","sink_0","animationFrame","autoFocus","style"],"sources":["../src/components/terminal/bind-session.ts","../src/components/terminal/scripted-bridge.ts","../src/components/terminal/terminal-theme.ts","../src/components/terminal/use-terminal-session.ts","../src/components/terminal/terminal.tsx"],"sourcesContent":["import type { TerminalSessionAdapter } from \"./types\";\n\n/**\n * Minimal subset of xterm.js that the binding needs. Tests substitute a fake\n * sink so the wire-up logic can be exercised without a DOM.\n */\nexport interface TerminalSink {\n write(data: string | Uint8Array): void;\n onInput(handler: (data: string) => void): () => void;\n onResize(handler: (size: { cols: number; rows: number }) => void): () => void;\n}\n\nexport interface BindSessionOptions {\n /** Forwarded to the session when the user types in the sink. */\n onInput?: (data: string) => void;\n /** Called once the session exits; useful for surfacing status. */\n onExit?: (exit: { code: number | null; signal: string | null }) => void;\n /** Called on transport errors. */\n onError?: (error: { message: string }) => void;\n}\n\n/**\n * Wires a {@link TerminalSink} (typically xterm.js) to a\n * {@link TerminalSessionAdapter}. Returns a disposer that detaches every\n * subscription it created. The session itself is *not* killed — owning the\n * session lifecycle is the caller's responsibility.\n */\nexport const bindSessionToSink = (\n sink: TerminalSink,\n session: TerminalSessionAdapter,\n options: BindSessionOptions = {},\n) => {\n const disposers: Array<() => void> = [];\n\n disposers.push(session.onData((chunk) => sink.write(chunk)));\n\n disposers.push(\n sink.onInput((data) => {\n session.write(data);\n options.onInput?.(data);\n }),\n );\n\n disposers.push(\n sink.onResize(({ cols, rows }) => {\n session.resize(cols, rows);\n }),\n );\n\n if (options.onExit) disposers.push(session.onExit(options.onExit));\n if (options.onError) disposers.push(session.onError(options.onError));\n\n return () => {\n while (disposers.length > 0) {\n const dispose = disposers.pop();\n try {\n dispose?.();\n } catch {\n // Disposer errors during teardown are intentionally swallowed so a\n // partially-bound session still cleans up the remaining subscriptions.\n }\n }\n };\n};\n","import type { TerminalBridge, TerminalSessionAdapter, TerminalSessionError, TerminalSessionExit } from \"./types\";\n\nexport interface ScriptedTerminalStep {\n /** Bytes the host pushes back to the renderer (utf-8 string is encoded for you). */\n data?: string | Uint8Array;\n /** Milliseconds to wait before delivering this step. */\n delayMs?: number;\n /** Marks the session as exited after this step. */\n exit?: { code: number | null; signal?: string | null };\n /** Delivers a transport error after this step. */\n error?: string;\n}\n\nexport interface ScriptedBridgeOptions {\n /** Initial script delivered after the first data subscriber attaches. */\n initial?: ScriptedTerminalStep[];\n /**\n * Responds to user input. Return additional steps to play, or `undefined`\n * to ignore. Defaults to echoing the input followed by a newline.\n */\n onInput?: (input: string) => ScriptedTerminalStep[] | undefined;\n /** Called whenever the renderer requests a resize. */\n onResize?: (size: { cols: number; rows: number }) => void;\n /** Called once when the renderer kills the session. */\n onKill?: (signal?: string) => void;\n}\n\nconst encoder = new TextEncoder();\n\nconst toChunk = (data: string | Uint8Array) => (typeof data === \"string\" ? encoder.encode(data) : data);\n\nconst wait = (ms: number) => (ms > 0 ? new Promise<void>((resolve) => setTimeout(resolve, ms)) : Promise.resolve());\n\nconst defaultEcho = (input: string): ScriptedTerminalStep[] => [{ data: input.replace(/\\r/g, \"\\r\\n\") }];\n\ninterface SessionEmitter {\n isExited(): boolean;\n emitData(chunk: Uint8Array): void;\n emitExit(exit: TerminalSessionExit): void;\n emitError(error: TerminalSessionError): void;\n}\n\nconst runStep = (emitter: SessionEmitter, step: ScriptedTerminalStep) => {\n if (step.data !== undefined) emitter.emitData(toChunk(step.data));\n if (step.error !== undefined) emitter.emitError({ message: step.error });\n if (step.exit !== undefined) emitter.emitExit({ code: step.exit.code, signal: step.exit.signal ?? null });\n};\n\nconst playSteps = async (emitter: SessionEmitter, steps: ScriptedTerminalStep[]) => {\n for (const step of steps) {\n if (emitter.isExited()) return;\n await wait(step.delayMs ?? 0);\n if (emitter.isExited()) return;\n runStep(emitter, step);\n }\n};\n\nconst createScriptedSession = (\n options: ScriptedBridgeOptions,\n onInput: NonNullable<ScriptedBridgeOptions[\"onInput\"]>,\n) => {\n const dataHandlers = new Set<(chunk: Uint8Array) => void>();\n const exitHandlers = new Set<(exit: TerminalSessionExit) => void>();\n const errorHandlers = new Set<(error: TerminalSessionError) => void>();\n let exited = false;\n let startedInitial = false;\n\n const emitter: SessionEmitter = {\n isExited: () => exited,\n emitData(chunk) {\n for (const handler of dataHandlers) handler(chunk);\n },\n emitExit(exit) {\n if (exited) return;\n exited = true;\n for (const handler of exitHandlers) handler(exit);\n },\n emitError(error) {\n for (const handler of errorHandlers) handler(error);\n },\n };\n\n const session: TerminalSessionAdapter = {\n id: crypto.randomUUID(),\n write(data) {\n if (exited) return;\n const text = typeof data === \"string\" ? data : new TextDecoder().decode(data);\n const response = onInput(text);\n if (response) void playSteps(emitter, response);\n },\n resize(cols, rows) {\n options.onResize?.({ cols, rows });\n },\n kill(signal) {\n if (exited) return;\n options.onKill?.(signal);\n emitter.emitExit({ code: null, signal: signal ?? null });\n },\n onData(handler) {\n dataHandlers.add(handler);\n if (!startedInitial && options.initial) {\n startedInitial = true;\n void playSteps(emitter, options.initial);\n }\n return () => dataHandlers.delete(handler);\n },\n onExit(handler) {\n exitHandlers.add(handler);\n return () => exitHandlers.delete(handler);\n },\n onError(handler) {\n errorHandlers.add(handler);\n return () => errorHandlers.delete(handler);\n },\n };\n\n return { session };\n};\n\n/**\n * Deterministic in-memory bridge. Used by stories and tests to exercise the\n * terminal UI without a real PTY supervisor.\n */\nexport const createScriptedTerminalBridge = (options: ScriptedBridgeOptions = {}): TerminalBridge => {\n const onInput = options.onInput ?? defaultEcho;\n\n return {\n async openSession(_request) {\n const { session } = createScriptedSession(options, onInput);\n return session;\n },\n };\n};\n","import type { ITheme } from \"@xterm/xterm\";\nimport psTheme from \"../../theme/theme\";\n\n/**\n * xterm theme presets built from the `colors.terminal.<preset>` tokens so the\n * terminal blends with the surrounding chrome without the consuming extension\n * touching xterm directly. Consumers can still pass any `ITheme` they like via\n * the `theme` prop.\n */\nexport type TerminalThemeName = \"light\" | \"dark\";\n\nconst createTerminalTheme = (preset: TerminalThemeName) => {\n // xterm parses color strings itself, so resolve raw token values instead of CSS variables.\n const color = (name: string) => psTheme.token(`colors.terminal.${preset}.${name}`);\n\n return {\n background: color(\"background\"),\n foreground: color(\"foreground\"),\n cursor: color(\"cursor\"),\n cursorAccent: color(\"cursorAccent\"),\n selectionBackground: color(\"selectionBackground\"),\n selectionForeground: undefined,\n black: color(\"black\"),\n red: color(\"red\"),\n green: color(\"green\"),\n yellow: color(\"yellow\"),\n blue: color(\"blue\"),\n magenta: color(\"magenta\"),\n cyan: color(\"cyan\"),\n white: color(\"white\"),\n brightBlack: color(\"brightBlack\"),\n brightRed: color(\"brightRed\"),\n brightGreen: color(\"brightGreen\"),\n brightYellow: color(\"brightYellow\"),\n brightBlue: color(\"brightBlue\"),\n brightMagenta: color(\"brightMagenta\"),\n brightCyan: color(\"brightCyan\"),\n brightWhite: color(\"brightWhite\"),\n };\n};\n\nexport const lightTerminalTheme: ITheme = createTerminalTheme(\"light\");\n\nexport const darkTerminalTheme: ITheme = createTerminalTheme(\"dark\");\n\nexport const terminalThemes: Record<TerminalThemeName, ITheme> = {\n light: lightTerminalTheme,\n dark: darkTerminalTheme,\n};\n\nexport const resolveTerminalTheme = (theme: TerminalThemeName | ITheme | undefined) => {\n if (!theme) return terminalThemes.dark;\n if (typeof theme === \"string\") return terminalThemes[theme];\n return theme;\n};\n","import { useEffect, useState } from \"react\";\nimport type {\n TerminalBridge,\n TerminalSessionAdapter,\n TerminalSessionError,\n TerminalSessionExit,\n TerminalSessionRequest,\n} from \"./types\";\n\nexport type TerminalSessionStatus = \"idle\" | \"opening\" | \"open\" | \"exited\" | \"error\";\n\nexport interface UseTerminalSessionResult {\n session: TerminalSessionAdapter | null;\n status: TerminalSessionStatus;\n exit: TerminalSessionExit | null;\n error: TerminalSessionError | null;\n}\n\nexport interface UseTerminalSessionOptions {\n bridge: TerminalBridge | null;\n request: TerminalSessionRequest;\n /** Set to false to keep the session alive when the hook unmounts. */\n killOnUnmount?: boolean;\n}\n\nexport const createTerminalSessionRequestKey = (request: TerminalSessionRequest) =>\n JSON.stringify({\n command: request.command,\n cwd: request.cwd,\n env: request.env\n ? Object.fromEntries(Object.entries(request.env).sort(([left], [right]) => left.localeCompare(right)))\n : undefined,\n cols: request.cols,\n rows: request.rows,\n });\n\nconst readTerminalSessionRequestKey = (requestKey: string): TerminalSessionRequest => JSON.parse(requestKey);\n\n/**\n * Opens a terminal session via the provided bridge and surfaces its lifecycle\n * for the renderer. The session is killed on unmount unless explicitly opted\n * out; switching bridges or request contents triggers a fresh open.\n */\nexport const useTerminalSession = ({ bridge, request, killOnUnmount = true }: UseTerminalSessionOptions) => {\n const requestKey = createTerminalSessionRequestKey(request);\n const [state, setState] = useState<UseTerminalSessionResult>({\n session: null,\n status: \"idle\",\n exit: null,\n error: null,\n });\n\n useEffect(() => {\n if (!bridge) {\n setState({ session: null, status: \"idle\", exit: null, error: null });\n return;\n }\n\n let cancelled = false;\n let activeSession: TerminalSessionAdapter | null = null;\n let terminalState: TerminalSessionStatus = \"opening\";\n const disposers: Array<() => void> = [];\n\n setState({ session: null, status: \"opening\", exit: null, error: null });\n const requestSnapshot = readTerminalSessionRequestKey(requestKey);\n\n bridge\n .openSession(requestSnapshot)\n .then((session) => {\n if (cancelled) {\n if (killOnUnmount) void session.kill();\n return;\n }\n activeSession = session;\n disposers.push(\n session.onExit((exit) => {\n terminalState = \"exited\";\n setState((prev) => ({ ...prev, status: \"exited\", exit }));\n }),\n session.onError((error) => {\n terminalState = \"error\";\n setState((prev) => ({ ...prev, status: \"error\", error }));\n }),\n );\n terminalState = \"open\";\n setState({ session, status: \"open\", exit: null, error: null });\n })\n .catch((cause: unknown) => {\n if (cancelled) return;\n const message = cause instanceof Error ? cause.message : String(cause);\n terminalState = \"error\";\n setState({ session: null, status: \"error\", exit: null, error: { message } });\n });\n\n return () => {\n cancelled = true;\n while (disposers.length > 0) disposers.pop()?.();\n if (killOnUnmount && activeSession && terminalState !== \"exited\") void activeSession.kill();\n };\n }, [bridge, requestKey, killOnUnmount]);\n\n return state;\n};\n","import { FitAddon } from \"@xterm/addon-fit\";\nimport { WebLinksAddon } from \"@xterm/addon-web-links\";\nimport type { ITheme } from \"@xterm/xterm\";\nimport { Terminal as Xterm } from \"@xterm/xterm\";\nimport \"@xterm/xterm/css/xterm.css\";\nimport \"./terminal.css\";\nimport { useContext, useEffect, useRef, useState } from \"react\";\nimport { SplitPanelMotionContext } from \"../layout/split-panel-motion-context\";\nimport { bindSessionToSink, type TerminalSink } from \"./bind-session\";\nimport { resolveTerminalTheme, type TerminalThemeName } from \"./terminal-theme\";\nimport type { TerminalBridge, TerminalSessionAdapter, TerminalSessionRequest } from \"./types\";\nimport { useTerminalSession } from \"./use-terminal-session\";\n\nconst DEFAULT_FONT_FAMILY = '\"JetBrains Mono\", \"Fira Code\", Menlo, Consolas, monospace';\nconst DEFAULT_FONT_SIZE = 13;\nconst DEFAULT_COLS = 80;\nconst DEFAULT_ROWS = 24;\n\nexport const createInitialTerminalSessionRequest = (\n request?: Partial<TerminalSessionRequest>,\n): TerminalSessionRequest => ({\n ...request,\n cols: request?.cols ?? DEFAULT_COLS,\n rows: request?.rows ?? DEFAULT_ROWS,\n});\n\nexport const createTerminalSink = (xterm: Pick<Xterm, \"write\" | \"onData\" | \"onResize\">) => {\n const inputHandlers = new Set<(data: string) => void>();\n const pendingInput: string[] = [];\n const inputDisposable = xterm.onData((data) => {\n if (inputHandlers.size === 0) {\n pendingInput.push(data);\n return;\n }\n for (const handler of inputHandlers) handler(data);\n });\n\n return {\n write(data: string | Uint8Array) {\n xterm.write(data);\n },\n onInput(handler: (data: string) => void) {\n inputHandlers.add(handler);\n while (pendingInput.length > 0) handler(pendingInput.shift() as string);\n return () => inputHandlers.delete(handler);\n },\n onResize(handler: (size: { cols: number; rows: number }) => void) {\n const disposable = xterm.onResize(handler);\n return () => disposable.dispose();\n },\n dispose() {\n inputDisposable.dispose();\n inputHandlers.clear();\n pendingInput.length = 0;\n },\n } satisfies TerminalSink & { dispose(): void };\n};\n\n// Plain URLs and OSC 8 hyperlinks share this handler. xterm's default OSC 8 handler\n// asks with confirm() and opens a blank window first, which the desktop app blocks.\nconst openTerminalLink = (event: MouseEvent, uri: string) => {\n if (event.ctrlKey || event.metaKey) window.open(uri, \"_blank\", \"noopener,noreferrer\");\n};\n\nconst fitTerminal = (fit: FitAddon | null, motionRoot?: HTMLDivElement | null) => {\n // Fit at the final size, while divider dragging and reduced motion stay direct.\n if (\n motionRoot\n ?.getAnimations()\n .some((animation) => animation instanceof CSSTransition && animation.transitionProperty === \"--split-size\")\n )\n return;\n try {\n fit?.fit();\n } catch {\n // fit() throws if the container has zero size (e.g. hidden via CSS).\n }\n};\n\nexport const resizeSessionToTerminalGeometry = (\n terminal: Pick<Xterm, \"cols\" | \"rows\">,\n session: Pick<TerminalSessionAdapter, \"resize\">,\n) => {\n session.resize(terminal.cols, terminal.rows);\n};\n\nexport const bindTerminalSession = (\n terminal: Pick<Xterm, \"cols\" | \"rows\">,\n sink: TerminalSink,\n session: TerminalSessionAdapter,\n options: Pick<TerminalProps, \"onSessionOpen\" | \"onSessionExit\">,\n) => {\n const unbind = bindSessionToSink(sink, session, {\n onExit: options.onSessionExit,\n });\n resizeSessionToTerminalGeometry(terminal, session);\n options.onSessionOpen?.(session.id);\n return unbind;\n};\n\nexport interface TerminalSessionCallbackRefs {\n onSessionOpen: React.RefObject<TerminalProps[\"onSessionOpen\"]>;\n onSessionExit: React.RefObject<TerminalProps[\"onSessionExit\"]>;\n}\n\nexport const bindTerminalSessionWithCallbackRefs = (\n terminal: Pick<Xterm, \"cols\" | \"rows\">,\n sink: TerminalSink,\n session: TerminalSessionAdapter,\n callbackRefs: TerminalSessionCallbackRefs,\n) =>\n bindTerminalSession(terminal, sink, session, {\n onSessionOpen: (sessionId) => callbackRefs.onSessionOpen.current?.(sessionId),\n onSessionExit: (exit) => callbackRefs.onSessionExit.current?.(exit),\n });\n\nexport interface TerminalProps {\n /** Bridge adapter the component opens its session through. */\n bridge: TerminalBridge;\n /**\n * Optional initial session request overrides. `cols`/`rows` default to\n * 80x24; container resizes are forwarded after the session opens.\n */\n request?: Partial<TerminalSessionRequest>;\n /** Theme preset name or full xterm theme. */\n theme?: TerminalThemeName | ITheme;\n /** Monospace font family. */\n fontFamily?: string;\n fontSize?: number;\n /** Whether to kill the session when the component unmounts. Defaults to true. */\n killOnUnmount?: boolean;\n /** Focus the terminal while it is the active surface. Defaults to true. */\n autoFocus?: boolean;\n /** Forwarded to the container element. */\n className?: string;\n style?: React.CSSProperties;\n /** Called once the session is open; useful for imperative refs. */\n onSessionOpen?: (sessionId: string) => void;\n /** Called once the session exits. */\n onSessionExit?: (exit: { code: number | null; signal: string | null }) => void;\n}\n\n/**\n * High-level terminal component. Mounts xterm.js inside a `<div>` and binds it\n * to the session opened from `bridge.openSession(...)`. Resize is driven by\n * `ResizeObserver` so the terminal fills its container and the host PTY\n * geometry stays in sync.\n */\nexport const Terminal = (props: TerminalProps) => {\n const {\n bridge,\n request,\n theme,\n fontFamily = DEFAULT_FONT_FAMILY,\n fontSize = DEFAULT_FONT_SIZE,\n killOnUnmount = true,\n autoFocus = true,\n className,\n style,\n onSessionOpen,\n onSessionExit,\n } = props;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const xtermRef = useRef<Xterm | null>(null);\n const fitRef = useRef<FitAddon | null>(null);\n const sinkRef = useRef<ReturnType<typeof createTerminalSink> | null>(null);\n const [terminalReady, setTerminalReady] = useState(false);\n const initialSessionRequestRef = useRef<TerminalSessionRequest | null>(null);\n const onSessionOpenRef = useRef(onSessionOpen);\n const onSessionExitRef = useRef(onSessionExit);\n\n onSessionOpenRef.current = onSessionOpen;\n onSessionExitRef.current = onSessionExit;\n\n if (!initialSessionRequestRef.current) {\n initialSessionRequestRef.current = createInitialTerminalSessionRequest(request);\n }\n\n const resolvedTheme = resolveTerminalTheme(theme);\n const motionRootRef = useContext(SplitPanelMotionContext);\n\n // Mount xterm once on the container. Theme, font, and size updates flow\n // through the dedicated options-sync effect below to avoid a full remount on\n // every prop change.\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n let xterm: Xterm | undefined;\n let sink: ReturnType<typeof createTerminalSink> | undefined;\n let measureAnimationFrame: number | undefined;\n let measureTimeout: number | undefined;\n let observer: ResizeObserver | undefined;\n const motionRoot = motionRootRef?.current;\n const measure = () => fitTerminal(fitRef.current, motionRoot);\n const handleMotionEnd = (event: TransitionEvent) => {\n if (event.target === motionRoot && event.propertyName === \"--split-size\") measure();\n };\n motionRoot?.addEventListener(\"transitionend\", handleMotionEnd);\n motionRoot?.addEventListener(\"transitioncancel\", handleMotionEnd);\n\n // Deferring construction skips React Strict Mode's disposable probe mount.\n // xterm schedules internal viewport work during construction that otherwise\n // runs after the probe instance has already been disposed.\n const initializationFrame = window.requestAnimationFrame(() => {\n xterm = new Xterm({\n cols: DEFAULT_COLS,\n rows: DEFAULT_ROWS,\n cursorBlink: true,\n convertEol: true,\n allowProposedApi: true,\n linkHandler: { activate: openTerminalLink },\n });\n const fit = new FitAddon();\n xterm.loadAddon(fit);\n xterm.loadAddon(new WebLinksAddon(openTerminalLink));\n xterm.open(container);\n sink = createTerminalSink(xterm);\n\n xtermRef.current = xterm;\n fitRef.current = fit;\n sinkRef.current = sink;\n\n measure();\n measureAnimationFrame = window.requestAnimationFrame(measure);\n measureTimeout = window.setTimeout(measure, 50);\n observer = new ResizeObserver(measure);\n observer.observe(container);\n setTerminalReady(true);\n });\n\n return () => {\n window.cancelAnimationFrame(initializationFrame);\n if (measureAnimationFrame !== undefined) window.cancelAnimationFrame(measureAnimationFrame);\n if (measureTimeout !== undefined) window.clearTimeout(measureTimeout);\n observer?.disconnect();\n motionRoot?.removeEventListener(\"transitionend\", handleMotionEnd);\n motionRoot?.removeEventListener(\"transitioncancel\", handleMotionEnd);\n sink?.dispose();\n xterm?.dispose();\n xtermRef.current = null;\n fitRef.current = null;\n sinkRef.current = null;\n };\n }, [motionRootRef]);\n\n useEffect(() => {\n if (!terminalReady) return;\n const xterm = xtermRef.current;\n if (!xterm) return;\n xterm.options.theme = resolvedTheme;\n xterm.options.fontFamily = fontFamily;\n xterm.options.fontSize = fontSize;\n fitTerminal(fitRef.current, motionRootRef?.current);\n }, [terminalReady, resolvedTheme, fontFamily, fontSize, motionRootRef]);\n\n const { session } = useTerminalSession({ bridge, request: initialSessionRequestRef.current, killOnUnmount });\n\n useEffect(() => {\n if (!terminalReady) return;\n const xterm = xtermRef.current;\n const sink = sinkRef.current;\n if (!xterm || !sink || !session) return;\n fitTerminal(fitRef.current, motionRootRef?.current);\n const animationFrame = window.requestAnimationFrame(() => fitTerminal(fitRef.current, motionRootRef?.current));\n const unbind = bindTerminalSessionWithCallbackRefs(xterm, sink, session, {\n onSessionOpen: onSessionOpenRef,\n onSessionExit: onSessionExitRef,\n });\n return () => {\n window.cancelAnimationFrame(animationFrame);\n unbind();\n };\n }, [session, terminalReady, motionRootRef]);\n\n useEffect(() => {\n if (terminalReady && autoFocus) xtermRef.current?.focus();\n }, [autoFocus, terminalReady]);\n\n // The mount element fills its box absolutely so xterm sizes to the panel\n // rather than growing it: inside a scrollable host, a self-sized terminal\n // would define its own height and never fit, leaving the host to scroll it.\n return (\n <div\n className={className}\n style={{\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: typeof resolvedTheme.background === \"string\" ? resolvedTheme.background : undefined,\n ...style,\n }}\n >\n <div ref={containerRef} className=\"pstdio-terminal\" style={{ position: \"absolute\", inset: 0 }} />\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"terminal.js","names":["TerminalSessionAdapter","TerminalSink","write","data","Uint8Array","onInput","handler","onResize","size","cols","rows","BindSessionOptions","onExit","exit","code","signal","onError","error","message","bindSessionToSink","sink","session","options","disposers","Array","push","onData","chunk","resize","length","dispose","pop","TerminalBridge","TerminalSessionAdapter","TerminalSessionError","TerminalSessionExit","ScriptedTerminalStep","data","Uint8Array","delayMs","exit","code","signal","error","ScriptedBridgeOptions","initial","onInput","input","onResize","size","cols","rows","onKill","encoder","TextEncoder","toChunk","encode","wait","ms","Promise","resolve","setTimeout","defaultEcho","replace","SessionEmitter","isExited","emitData","chunk","emitExit","emitError","runStep","emitter","step","undefined","message","playSteps","steps","createScriptedSession","options","NonNullable","dataHandlers","Set","exitHandlers","errorHandlers","exited","startedInitial","handler","session","id","crypto","randomUUID","write","text","TextDecoder","decode","response","resize","kill","onData","add","delete","onExit","onError","createScriptedTerminalBridge","openSession","_request","ITheme","psTheme","ThemePreferenceOption","TerminalThemeName","createTerminalTheme","preset","color","name","token","background","foreground","cursor","cursorAccent","selectionBackground","selectionForeground","undefined","black","red","green","yellow","blue","magenta","cyan","white","brightBlack","brightRed","brightGreen","brightYellow","brightBlue","brightMagenta","brightCyan","brightWhite","lightTerminalTheme","darkTerminalTheme","terminalThemes","Record","light","dark","createTerminalThemeFromPreference","preference","tokens","theme","mode","colors","Object","keys","value","const","ansiName","toUpperCase","slice","Capitalize","normal","bright","resolveTerminalTheme","psTheme","useEffect","useState","TerminalBridge","TerminalSessionAdapter","TerminalSessionError","TerminalSessionExit","TerminalSessionRequest","TerminalSessionStatus","UseTerminalSessionResult","session","status","exit","error","UseTerminalSessionOptions","bridge","request","killOnUnmount","createTerminalSessionRequestKey","JSON","stringify","command","cwd","env","Object","fromEntries","entries","sort","left","right","localeCompare","undefined","cols","rows","readTerminalSessionRequestKey","requestKey","parse","useTerminalSession","t0","$","_c","t1","t2","t3","Symbol","for","state","setState","t4","t5","cancelled","activeSession","terminalState","disposers","requestSnapshot","openSession","then","kill","push","onExit","prev","onError","prev_0","catch","cause","message","Error","String","length","pop","_c","FitAddon","WebLinksAddon","ITheme","Terminal","Xterm","useContext","useEffect","useRef","useState","SplitPanelMotionContext","bindSessionToSink","TerminalSink","resolveTerminalTheme","TerminalThemeName","TerminalBridge","TerminalSessionAdapter","TerminalSessionRequest","useTerminalSession","DEFAULT_FONT_FAMILY","DEFAULT_FONT_SIZE","DEFAULT_COLS","DEFAULT_ROWS","createInitialTerminalSessionRequest","request","Partial","cols","rows","createTerminalSink","xterm","Pick","inputHandlers","Set","data","pendingInput","inputDisposable","onData","size","push","handler","write","Uint8Array","onInput","add","length","shift","delete","onResize","disposable","dispose","clear","openTerminalLink","event","MouseEvent","uri","ctrlKey","metaKey","window","open","fitTerminal","fit","motionRoot","HTMLDivElement","getAnimations","some","animation","CSSTransition","transitionProperty","resizeSessionToTerminalGeometry","terminal","session","resize","bindTerminalSession","sink","options","TerminalProps","unbind","onExit","onSessionExit","onSessionOpen","id","TerminalSessionCallbackRefs","React","RefObject","bindTerminalSessionWithCallbackRefs","callbackRefs","sessionId","current","exit","bridge","theme","fontFamily","fontSize","killOnUnmount","autoFocus","className","style","CSSProperties","code","signal","props","containerRef","xtermRef","fitRef","sinkRef","ReturnType","terminalReady","setTerminalReady","initialSessionRequestRef","onSessionOpenRef","onSessionExitRef","resolvedTheme","motionRootRef","container","measureAnimationFrame","measureTimeout","observer","ResizeObserver","measure","handleMotionEnd","TransitionEvent","target","propertyName","addEventListener","initializationFrame","requestAnimationFrame","cursorBlink","convertEol","allowProposedApi","linkHandler","activate","loadAddon","setTimeout","observe","cancelAnimationFrame","undefined","clearTimeout","disconnect","removeEventListener","animationFrame","focus","position","width","height","backgroundColor","background","inset","Xterm","SplitPanelMotionContext","Terminal$1","bindSessionToSink","disposers","session","sink","chunk","data","options","cols","rows","dispose","encoder","toChunk","wait","ms","resolve","defaultEcho","input","runStep","step","emitter","playSteps","steps","createScriptedSession","dataHandlers","exitHandlers","errorHandlers","exited","startedInitial","handler","exit","error","response","onInput","signal","createScriptedTerminalBridge","createTerminalTheme","color","theme_default","preset","name","lightTerminalTheme","darkTerminalTheme","terminalThemes","createTerminalThemeFromPreference","tokens","preference","theme","foreground","background","colors","value","ansiName","normal","bright","resolveTerminalTheme","createTerminalSessionRequestKey","request","left","right","readTerminalSessionRequestKey","requestKey","useTerminalSession","$","c","t1","t0","killOnUnmount","t2","t3","state","setState","useState","t4","t5","bridge","cancelled","activeSession","terminalState","requestSnapshot","prev","prev_0","message","cause","useEffect","DEFAULT_FONT_FAMILY","DEFAULT_FONT_SIZE","DEFAULT_COLS","DEFAULT_ROWS","createInitialTerminalSessionRequest","createTerminalSink","inputHandlers","pendingInput","inputDisposable","xterm","disposable","openTerminalLink","event","uri","fitTerminal","animation","resizeSessionToTerminalGeometry","terminal","bindTerminalSession","unbind","bindTerminalSessionWithCallbackRefs","callbackRefs","sessionId","Terminal","props","containerRef","useRef","xtermRef","fitRef","sinkRef","terminalReady","setTerminalReady","initialSessionRequestRef","onSessionOpenRef","onSessionOpen","onSessionExitRef","onSessionExit","resolvedTheme","motionRootRef","useContext","container","measureAnimationFrame","measureTimeout","observer","motionRoot","measure","handleMotionEnd","initializationFrame","fit","FitAddon","WebLinksAddon","xterm_0","fontFamily","fontSize","xterm_1","sink_0","animationFrame","autoFocus","style"],"sources":["../src/components/terminal/bind-session.ts","../src/components/terminal/scripted-bridge.ts","../src/components/terminal/terminal-theme.ts","../src/components/terminal/use-terminal-session.ts","../src/components/terminal/terminal.tsx"],"sourcesContent":["import type { TerminalSessionAdapter } from \"./types\";\n\n/**\n * Minimal subset of xterm.js that the binding needs. Tests substitute a fake\n * sink so the wire-up logic can be exercised without a DOM.\n */\nexport interface TerminalSink {\n write(data: string | Uint8Array): void;\n onInput(handler: (data: string) => void): () => void;\n onResize(handler: (size: { cols: number; rows: number }) => void): () => void;\n}\n\nexport interface BindSessionOptions {\n /** Forwarded to the session when the user types in the sink. */\n onInput?: (data: string) => void;\n /** Called once the session exits; useful for surfacing status. */\n onExit?: (exit: { code: number | null; signal: string | null }) => void;\n /** Called on transport errors. */\n onError?: (error: { message: string }) => void;\n}\n\n/**\n * Wires a {@link TerminalSink} (typically xterm.js) to a\n * {@link TerminalSessionAdapter}. Returns a disposer that detaches every\n * subscription it created. The session itself is *not* killed — owning the\n * session lifecycle is the caller's responsibility.\n */\nexport const bindSessionToSink = (\n sink: TerminalSink,\n session: TerminalSessionAdapter,\n options: BindSessionOptions = {},\n) => {\n const disposers: Array<() => void> = [];\n\n disposers.push(session.onData((chunk) => sink.write(chunk)));\n\n disposers.push(\n sink.onInput((data) => {\n session.write(data);\n options.onInput?.(data);\n }),\n );\n\n disposers.push(\n sink.onResize(({ cols, rows }) => {\n session.resize(cols, rows);\n }),\n );\n\n if (options.onExit) disposers.push(session.onExit(options.onExit));\n if (options.onError) disposers.push(session.onError(options.onError));\n\n return () => {\n while (disposers.length > 0) {\n const dispose = disposers.pop();\n try {\n dispose?.();\n } catch {\n // Disposer errors during teardown are intentionally swallowed so a\n // partially-bound session still cleans up the remaining subscriptions.\n }\n }\n };\n};\n","import type { TerminalBridge, TerminalSessionAdapter, TerminalSessionError, TerminalSessionExit } from \"./types\";\n\nexport interface ScriptedTerminalStep {\n /** Bytes the host pushes back to the renderer (utf-8 string is encoded for you). */\n data?: string | Uint8Array;\n /** Milliseconds to wait before delivering this step. */\n delayMs?: number;\n /** Marks the session as exited after this step. */\n exit?: { code: number | null; signal?: string | null };\n /** Delivers a transport error after this step. */\n error?: string;\n}\n\nexport interface ScriptedBridgeOptions {\n /** Initial script delivered after the first data subscriber attaches. */\n initial?: ScriptedTerminalStep[];\n /**\n * Responds to user input. Return additional steps to play, or `undefined`\n * to ignore. Defaults to echoing the input followed by a newline.\n */\n onInput?: (input: string) => ScriptedTerminalStep[] | undefined;\n /** Called whenever the renderer requests a resize. */\n onResize?: (size: { cols: number; rows: number }) => void;\n /** Called once when the renderer kills the session. */\n onKill?: (signal?: string) => void;\n}\n\nconst encoder = new TextEncoder();\n\nconst toChunk = (data: string | Uint8Array) => (typeof data === \"string\" ? encoder.encode(data) : data);\n\nconst wait = (ms: number) => (ms > 0 ? new Promise<void>((resolve) => setTimeout(resolve, ms)) : Promise.resolve());\n\nconst defaultEcho = (input: string): ScriptedTerminalStep[] => [{ data: input.replace(/\\r/g, \"\\r\\n\") }];\n\ninterface SessionEmitter {\n isExited(): boolean;\n emitData(chunk: Uint8Array): void;\n emitExit(exit: TerminalSessionExit): void;\n emitError(error: TerminalSessionError): void;\n}\n\nconst runStep = (emitter: SessionEmitter, step: ScriptedTerminalStep) => {\n if (step.data !== undefined) emitter.emitData(toChunk(step.data));\n if (step.error !== undefined) emitter.emitError({ message: step.error });\n if (step.exit !== undefined) emitter.emitExit({ code: step.exit.code, signal: step.exit.signal ?? null });\n};\n\nconst playSteps = async (emitter: SessionEmitter, steps: ScriptedTerminalStep[]) => {\n for (const step of steps) {\n if (emitter.isExited()) return;\n await wait(step.delayMs ?? 0);\n if (emitter.isExited()) return;\n runStep(emitter, step);\n }\n};\n\nconst createScriptedSession = (\n options: ScriptedBridgeOptions,\n onInput: NonNullable<ScriptedBridgeOptions[\"onInput\"]>,\n) => {\n const dataHandlers = new Set<(chunk: Uint8Array) => void>();\n const exitHandlers = new Set<(exit: TerminalSessionExit) => void>();\n const errorHandlers = new Set<(error: TerminalSessionError) => void>();\n let exited = false;\n let startedInitial = false;\n\n const emitter: SessionEmitter = {\n isExited: () => exited,\n emitData(chunk) {\n for (const handler of dataHandlers) handler(chunk);\n },\n emitExit(exit) {\n if (exited) return;\n exited = true;\n for (const handler of exitHandlers) handler(exit);\n },\n emitError(error) {\n for (const handler of errorHandlers) handler(error);\n },\n };\n\n const session: TerminalSessionAdapter = {\n id: crypto.randomUUID(),\n write(data) {\n if (exited) return;\n const text = typeof data === \"string\" ? data : new TextDecoder().decode(data);\n const response = onInput(text);\n if (response) void playSteps(emitter, response);\n },\n resize(cols, rows) {\n options.onResize?.({ cols, rows });\n },\n kill(signal) {\n if (exited) return;\n options.onKill?.(signal);\n emitter.emitExit({ code: null, signal: signal ?? null });\n },\n onData(handler) {\n dataHandlers.add(handler);\n if (!startedInitial && options.initial) {\n startedInitial = true;\n void playSteps(emitter, options.initial);\n }\n return () => dataHandlers.delete(handler);\n },\n onExit(handler) {\n exitHandlers.add(handler);\n return () => exitHandlers.delete(handler);\n },\n onError(handler) {\n errorHandlers.add(handler);\n return () => errorHandlers.delete(handler);\n },\n };\n\n return { session };\n};\n\n/**\n * Deterministic in-memory bridge. Used by stories and tests to exercise the\n * terminal UI without a real PTY supervisor.\n */\nexport const createScriptedTerminalBridge = (options: ScriptedBridgeOptions = {}): TerminalBridge => {\n const onInput = options.onInput ?? defaultEcho;\n\n return {\n async openSession(_request) {\n const { session } = createScriptedSession(options, onInput);\n return session;\n },\n };\n};\n","import type { ITheme } from \"@xterm/xterm\";\nimport psTheme from \"../../theme/theme\";\nimport type { ThemePreferenceOption } from \"../../utils/apply-theme-preference\";\n\n/**\n * xterm theme presets built from the `colors.terminal.<preset>` tokens so the\n * terminal blends with the surrounding chrome without the consuming extension\n * touching xterm directly. Consumers can still pass any `ITheme` they like via\n * the `theme` prop.\n */\nexport type TerminalThemeName = \"light\" | \"dark\";\n\nconst createTerminalTheme = (preset: TerminalThemeName) => {\n // xterm parses color strings itself, so resolve raw token values instead of CSS variables.\n const color = (name: string) => psTheme.token(`colors.terminal.${preset}.${name}`);\n\n return {\n background: color(\"background\"),\n foreground: color(\"foreground\"),\n cursor: color(\"cursor\"),\n cursorAccent: color(\"cursorAccent\"),\n selectionBackground: color(\"selectionBackground\"),\n selectionForeground: undefined,\n black: color(\"black\"),\n red: color(\"red\"),\n green: color(\"green\"),\n yellow: color(\"yellow\"),\n blue: color(\"blue\"),\n magenta: color(\"magenta\"),\n cyan: color(\"cyan\"),\n white: color(\"white\"),\n brightBlack: color(\"brightBlack\"),\n brightRed: color(\"brightRed\"),\n brightGreen: color(\"brightGreen\"),\n brightYellow: color(\"brightYellow\"),\n brightBlue: color(\"brightBlue\"),\n brightMagenta: color(\"brightMagenta\"),\n brightCyan: color(\"brightCyan\"),\n brightWhite: color(\"brightWhite\"),\n };\n};\n\nexport const lightTerminalTheme: ITheme = createTerminalTheme(\"light\");\n\nexport const darkTerminalTheme: ITheme = createTerminalTheme(\"dark\");\n\nexport const terminalThemes: Record<TerminalThemeName, ITheme> = {\n light: lightTerminalTheme,\n dark: darkTerminalTheme,\n};\n\n/** Resolve concrete xterm colors from the theme's mode and contributed VS Code tokens. */\nexport const createTerminalThemeFromPreference = (preference: ThemePreferenceOption) => {\n const tokens = preference.tokens ?? {};\n const theme = { ...terminalThemes[preference.mode] };\n const foreground = tokens[\"colors.vscode.terminal.foreground\"] ?? tokens[\"colors.fg\"];\n const background = tokens[\"colors.vscode.terminal.background\"] ?? tokens[\"colors.bg\"];\n const colors = {\n background,\n foreground,\n cursor: tokens[\"colors.vscode.terminalCursor.foreground\"] ?? foreground,\n cursorAccent: tokens[\"colors.vscode.terminalCursor.background\"] ?? background,\n selectionBackground: tokens[\"colors.vscode.terminal.selectionBackground\"],\n selectionForeground: tokens[\"colors.vscode.terminal.selectionForeground\"],\n };\n for (const name of Object.keys(colors) as (keyof typeof colors)[]) {\n const value = colors[name];\n if (value) theme[name] = value;\n }\n for (const name of [\"black\", \"red\", \"green\", \"yellow\", \"blue\", \"magenta\", \"cyan\", \"white\"] as const) {\n const ansiName = `${name[0].toUpperCase()}${name.slice(1)}` as Capitalize<typeof name>;\n const normal = tokens[`colors.vscode.terminal.ansi${ansiName}`];\n const bright = tokens[`colors.vscode.terminal.ansiBright${ansiName}`];\n if (normal) theme[name] = normal;\n if (bright) theme[`bright${ansiName}`] = bright;\n }\n return theme;\n};\n\nexport const resolveTerminalTheme = (theme: TerminalThemeName | ITheme | undefined) => {\n if (!theme) return terminalThemes.dark;\n if (typeof theme === \"string\") return terminalThemes[theme];\n return theme;\n};\n","import { useEffect, useState } from \"react\";\nimport type {\n TerminalBridge,\n TerminalSessionAdapter,\n TerminalSessionError,\n TerminalSessionExit,\n TerminalSessionRequest,\n} from \"./types\";\n\nexport type TerminalSessionStatus = \"idle\" | \"opening\" | \"open\" | \"exited\" | \"error\";\n\nexport interface UseTerminalSessionResult {\n session: TerminalSessionAdapter | null;\n status: TerminalSessionStatus;\n exit: TerminalSessionExit | null;\n error: TerminalSessionError | null;\n}\n\nexport interface UseTerminalSessionOptions {\n bridge: TerminalBridge | null;\n request: TerminalSessionRequest;\n /** Set to false to keep the session alive when the hook unmounts. */\n killOnUnmount?: boolean;\n}\n\nexport const createTerminalSessionRequestKey = (request: TerminalSessionRequest) =>\n JSON.stringify({\n command: request.command,\n cwd: request.cwd,\n env: request.env\n ? Object.fromEntries(Object.entries(request.env).sort(([left], [right]) => left.localeCompare(right)))\n : undefined,\n cols: request.cols,\n rows: request.rows,\n });\n\nconst readTerminalSessionRequestKey = (requestKey: string): TerminalSessionRequest => JSON.parse(requestKey);\n\n/**\n * Opens a terminal session via the provided bridge and surfaces its lifecycle\n * for the renderer. The session is killed on unmount unless explicitly opted\n * out; switching bridges or request contents triggers a fresh open.\n */\nexport const useTerminalSession = ({ bridge, request, killOnUnmount = true }: UseTerminalSessionOptions) => {\n const requestKey = createTerminalSessionRequestKey(request);\n const [state, setState] = useState<UseTerminalSessionResult>({\n session: null,\n status: \"idle\",\n exit: null,\n error: null,\n });\n\n useEffect(() => {\n if (!bridge) {\n setState({ session: null, status: \"idle\", exit: null, error: null });\n return;\n }\n\n let cancelled = false;\n let activeSession: TerminalSessionAdapter | null = null;\n let terminalState: TerminalSessionStatus = \"opening\";\n const disposers: Array<() => void> = [];\n\n setState({ session: null, status: \"opening\", exit: null, error: null });\n const requestSnapshot = readTerminalSessionRequestKey(requestKey);\n\n bridge\n .openSession(requestSnapshot)\n .then((session) => {\n if (cancelled) {\n if (killOnUnmount) void session.kill();\n return;\n }\n activeSession = session;\n disposers.push(\n session.onExit((exit) => {\n terminalState = \"exited\";\n setState((prev) => ({ ...prev, status: \"exited\", exit }));\n }),\n session.onError((error) => {\n terminalState = \"error\";\n setState((prev) => ({ ...prev, status: \"error\", error }));\n }),\n );\n terminalState = \"open\";\n setState({ session, status: \"open\", exit: null, error: null });\n })\n .catch((cause: unknown) => {\n if (cancelled) return;\n const message = cause instanceof Error ? cause.message : String(cause);\n terminalState = \"error\";\n setState({ session: null, status: \"error\", exit: null, error: { message } });\n });\n\n return () => {\n cancelled = true;\n while (disposers.length > 0) disposers.pop()?.();\n if (killOnUnmount && activeSession && terminalState !== \"exited\") void activeSession.kill();\n };\n }, [bridge, requestKey, killOnUnmount]);\n\n return state;\n};\n","import { FitAddon } from \"@xterm/addon-fit\";\nimport { WebLinksAddon } from \"@xterm/addon-web-links\";\nimport type { ITheme } from \"@xterm/xterm\";\nimport { Terminal as Xterm } from \"@xterm/xterm\";\nimport \"@xterm/xterm/css/xterm.css\";\nimport \"./terminal.css\";\nimport { useContext, useEffect, useRef, useState } from \"react\";\nimport { SplitPanelMotionContext } from \"../layout/split-panel-motion-context\";\nimport { bindSessionToSink, type TerminalSink } from \"./bind-session\";\nimport { resolveTerminalTheme, type TerminalThemeName } from \"./terminal-theme\";\nimport type { TerminalBridge, TerminalSessionAdapter, TerminalSessionRequest } from \"./types\";\nimport { useTerminalSession } from \"./use-terminal-session\";\n\nconst DEFAULT_FONT_FAMILY = '\"JetBrains Mono\", \"Fira Code\", Menlo, Consolas, monospace';\nconst DEFAULT_FONT_SIZE = 13;\nconst DEFAULT_COLS = 80;\nconst DEFAULT_ROWS = 24;\n\nexport const createInitialTerminalSessionRequest = (\n request?: Partial<TerminalSessionRequest>,\n): TerminalSessionRequest => ({\n ...request,\n cols: request?.cols ?? DEFAULT_COLS,\n rows: request?.rows ?? DEFAULT_ROWS,\n});\n\nexport const createTerminalSink = (xterm: Pick<Xterm, \"write\" | \"onData\" | \"onResize\">) => {\n const inputHandlers = new Set<(data: string) => void>();\n const pendingInput: string[] = [];\n const inputDisposable = xterm.onData((data) => {\n if (inputHandlers.size === 0) {\n pendingInput.push(data);\n return;\n }\n for (const handler of inputHandlers) handler(data);\n });\n\n return {\n write(data: string | Uint8Array) {\n xterm.write(data);\n },\n onInput(handler: (data: string) => void) {\n inputHandlers.add(handler);\n while (pendingInput.length > 0) handler(pendingInput.shift() as string);\n return () => inputHandlers.delete(handler);\n },\n onResize(handler: (size: { cols: number; rows: number }) => void) {\n const disposable = xterm.onResize(handler);\n return () => disposable.dispose();\n },\n dispose() {\n inputDisposable.dispose();\n inputHandlers.clear();\n pendingInput.length = 0;\n },\n } satisfies TerminalSink & { dispose(): void };\n};\n\n// Plain URLs and OSC 8 hyperlinks share this handler. xterm's default OSC 8 handler\n// asks with confirm() and opens a blank window first, which the desktop app blocks.\nconst openTerminalLink = (event: MouseEvent, uri: string) => {\n if (event.ctrlKey || event.metaKey) window.open(uri, \"_blank\", \"noopener,noreferrer\");\n};\n\nconst fitTerminal = (fit: FitAddon | null, motionRoot?: HTMLDivElement | null) => {\n // Fit at the final size, while divider dragging and reduced motion stay direct.\n if (\n motionRoot\n ?.getAnimations()\n .some((animation) => animation instanceof CSSTransition && animation.transitionProperty === \"--split-size\")\n )\n return;\n try {\n fit?.fit();\n } catch {\n // fit() throws if the container has zero size (e.g. hidden via CSS).\n }\n};\n\nexport const resizeSessionToTerminalGeometry = (\n terminal: Pick<Xterm, \"cols\" | \"rows\">,\n session: Pick<TerminalSessionAdapter, \"resize\">,\n) => {\n session.resize(terminal.cols, terminal.rows);\n};\n\nexport const bindTerminalSession = (\n terminal: Pick<Xterm, \"cols\" | \"rows\">,\n sink: TerminalSink,\n session: TerminalSessionAdapter,\n options: Pick<TerminalProps, \"onSessionOpen\" | \"onSessionExit\">,\n) => {\n const unbind = bindSessionToSink(sink, session, {\n onExit: options.onSessionExit,\n });\n resizeSessionToTerminalGeometry(terminal, session);\n options.onSessionOpen?.(session.id);\n return unbind;\n};\n\nexport interface TerminalSessionCallbackRefs {\n onSessionOpen: React.RefObject<TerminalProps[\"onSessionOpen\"]>;\n onSessionExit: React.RefObject<TerminalProps[\"onSessionExit\"]>;\n}\n\nexport const bindTerminalSessionWithCallbackRefs = (\n terminal: Pick<Xterm, \"cols\" | \"rows\">,\n sink: TerminalSink,\n session: TerminalSessionAdapter,\n callbackRefs: TerminalSessionCallbackRefs,\n) =>\n bindTerminalSession(terminal, sink, session, {\n onSessionOpen: (sessionId) => callbackRefs.onSessionOpen.current?.(sessionId),\n onSessionExit: (exit) => callbackRefs.onSessionExit.current?.(exit),\n });\n\nexport interface TerminalProps {\n /** Bridge adapter the component opens its session through. */\n bridge: TerminalBridge;\n /**\n * Optional initial session request overrides. `cols`/`rows` default to\n * 80x24; container resizes are forwarded after the session opens.\n */\n request?: Partial<TerminalSessionRequest>;\n /** Theme preset name or full xterm theme. */\n theme?: TerminalThemeName | ITheme;\n /** Monospace font family. */\n fontFamily?: string;\n fontSize?: number;\n /** Whether to kill the session when the component unmounts. Defaults to true. */\n killOnUnmount?: boolean;\n /** Focus the terminal while it is the active surface. Defaults to true. */\n autoFocus?: boolean;\n /** Forwarded to the container element. */\n className?: string;\n style?: React.CSSProperties;\n /** Called once the session is open; useful for imperative refs. */\n onSessionOpen?: (sessionId: string) => void;\n /** Called once the session exits. */\n onSessionExit?: (exit: { code: number | null; signal: string | null }) => void;\n}\n\n/**\n * High-level terminal component. Mounts xterm.js inside a `<div>` and binds it\n * to the session opened from `bridge.openSession(...)`. Resize is driven by\n * `ResizeObserver` so the terminal fills its container and the host PTY\n * geometry stays in sync.\n */\nexport const Terminal = (props: TerminalProps) => {\n const {\n bridge,\n request,\n theme,\n fontFamily = DEFAULT_FONT_FAMILY,\n fontSize = DEFAULT_FONT_SIZE,\n killOnUnmount = true,\n autoFocus = true,\n className,\n style,\n onSessionOpen,\n onSessionExit,\n } = props;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const xtermRef = useRef<Xterm | null>(null);\n const fitRef = useRef<FitAddon | null>(null);\n const sinkRef = useRef<ReturnType<typeof createTerminalSink> | null>(null);\n const [terminalReady, setTerminalReady] = useState(false);\n const initialSessionRequestRef = useRef<TerminalSessionRequest | null>(null);\n const onSessionOpenRef = useRef(onSessionOpen);\n const onSessionExitRef = useRef(onSessionExit);\n\n onSessionOpenRef.current = onSessionOpen;\n onSessionExitRef.current = onSessionExit;\n\n if (!initialSessionRequestRef.current) {\n initialSessionRequestRef.current = createInitialTerminalSessionRequest(request);\n }\n\n const resolvedTheme = resolveTerminalTheme(theme);\n const motionRootRef = useContext(SplitPanelMotionContext);\n\n // Mount xterm once on the container. Theme, font, and size updates flow\n // through the dedicated options-sync effect below to avoid a full remount on\n // every prop change.\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n let xterm: Xterm | undefined;\n let sink: ReturnType<typeof createTerminalSink> | undefined;\n let measureAnimationFrame: number | undefined;\n let measureTimeout: number | undefined;\n let observer: ResizeObserver | undefined;\n const motionRoot = motionRootRef?.current;\n const measure = () => fitTerminal(fitRef.current, motionRoot);\n const handleMotionEnd = (event: TransitionEvent) => {\n if (event.target === motionRoot && event.propertyName === \"--split-size\") measure();\n };\n motionRoot?.addEventListener(\"transitionend\", handleMotionEnd);\n motionRoot?.addEventListener(\"transitioncancel\", handleMotionEnd);\n\n // Deferring construction skips React Strict Mode's disposable probe mount.\n // xterm schedules internal viewport work during construction that otherwise\n // runs after the probe instance has already been disposed.\n const initializationFrame = window.requestAnimationFrame(() => {\n xterm = new Xterm({\n cols: DEFAULT_COLS,\n rows: DEFAULT_ROWS,\n cursorBlink: true,\n convertEol: true,\n allowProposedApi: true,\n linkHandler: { activate: openTerminalLink },\n });\n const fit = new FitAddon();\n xterm.loadAddon(fit);\n xterm.loadAddon(new WebLinksAddon(openTerminalLink));\n xterm.open(container);\n sink = createTerminalSink(xterm);\n\n xtermRef.current = xterm;\n fitRef.current = fit;\n sinkRef.current = sink;\n\n measure();\n measureAnimationFrame = window.requestAnimationFrame(measure);\n measureTimeout = window.setTimeout(measure, 50);\n observer = new ResizeObserver(measure);\n observer.observe(container);\n setTerminalReady(true);\n });\n\n return () => {\n window.cancelAnimationFrame(initializationFrame);\n if (measureAnimationFrame !== undefined) window.cancelAnimationFrame(measureAnimationFrame);\n if (measureTimeout !== undefined) window.clearTimeout(measureTimeout);\n observer?.disconnect();\n motionRoot?.removeEventListener(\"transitionend\", handleMotionEnd);\n motionRoot?.removeEventListener(\"transitioncancel\", handleMotionEnd);\n sink?.dispose();\n xterm?.dispose();\n xtermRef.current = null;\n fitRef.current = null;\n sinkRef.current = null;\n };\n }, [motionRootRef]);\n\n useEffect(() => {\n if (!terminalReady) return;\n const xterm = xtermRef.current;\n if (!xterm) return;\n xterm.options.theme = resolvedTheme;\n xterm.options.fontFamily = fontFamily;\n xterm.options.fontSize = fontSize;\n fitTerminal(fitRef.current, motionRootRef?.current);\n }, [terminalReady, resolvedTheme, fontFamily, fontSize, motionRootRef]);\n\n const { session } = useTerminalSession({ bridge, request: initialSessionRequestRef.current, killOnUnmount });\n\n useEffect(() => {\n if (!terminalReady) return;\n const xterm = xtermRef.current;\n const sink = sinkRef.current;\n if (!xterm || !sink || !session) return;\n fitTerminal(fitRef.current, motionRootRef?.current);\n const animationFrame = window.requestAnimationFrame(() => fitTerminal(fitRef.current, motionRootRef?.current));\n const unbind = bindTerminalSessionWithCallbackRefs(xterm, sink, session, {\n onSessionOpen: onSessionOpenRef,\n onSessionExit: onSessionExitRef,\n });\n return () => {\n window.cancelAnimationFrame(animationFrame);\n unbind();\n };\n }, [session, terminalReady, motionRootRef]);\n\n useEffect(() => {\n if (terminalReady && autoFocus) xtermRef.current?.focus();\n }, [autoFocus, terminalReady]);\n\n // The mount element fills its box absolutely so xterm sizes to the panel\n // rather than growing it: inside a scrollable host, a self-sized terminal\n // would define its own height and never fit, leaving the host to scroll it.\n return (\n <div\n className={className}\n style={{\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: typeof resolvedTheme.background === \"string\" ? resolvedTheme.background : undefined,\n ...style,\n }}\n >\n <div ref={containerRef} className=\"pstdio-terminal\" style={{ position: \"absolute\", inset: 0 }} />\n </div>\n );\n};\n"],"mappings":"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"}