diff --git a/demo/client.ts b/demo/client.ts
index 8500386b..e1f3f065 100644
--- a/demo/client.ts
+++ b/demo/client.ts
@@ -206,21 +206,21 @@ if (document.location.pathname === '/test') {
const typedTerm = createTerminal();
controlBar = new ControlBar(document.getElementById('sidebar'), document.querySelector('.banner-tabs'), []);
- addonsWindow = new AddonsWindow();
+ addonsWindow = new AddonsWindow(typedTerm, addons);
controlBar.registerWindow(addonsWindow);
actionElements = {
findNext: addonsWindow.findNextInput,
findPrevious: addonsWindow.findPreviousInput,
findResults: addonsWindow.findResultsSpan
};
- gpuWindow = new GpuWindow();
+ gpuWindow = new GpuWindow(typedTerm, addons);
controlBar.registerWindow(gpuWindow, { afterId: 'addons', hidden: true, smallTab: true });
- optionsWindow = new OptionsWindow(updateTerminalSize, updateTerminalContainerBackground);
- const styleWindow = controlBar.registerWindow(new StyleWindow());
+ optionsWindow = new OptionsWindow(typedTerm, addons, { updateTerminalSize, updateTerminalContainerBackground });
+ const styleWindow = controlBar.registerWindow(new StyleWindow(typedTerm, addons));
paddingElement = styleWindow.paddingElement;
controlBar.registerWindow(optionsWindow);
controlBar.registerWindow(new TestWindow(typedTerm, addons, { disposeRecreateButtonHandler, createNewWindowButtonHandler }));
- vtWindow = new VtWindow();
+ vtWindow = new VtWindow(typedTerm, addons);
controlBar.registerWindow(vtWindow);
vtWindow.initTerminal(term);
controlBar.activateDefaultTab();
@@ -351,7 +351,7 @@ function createTerminal(): Terminal {
// fit is called within a setTimeout, cols and rows need this.
setTimeout(async () => {
- optionsWindow.initOptions(term, addDomListener);
+ optionsWindow.initOptions(addDomListener);
// Set terminal size again to set the specific dimensions on the demo
updateTerminalSize();
diff --git a/demo/components/controlBar.ts b/demo/components/controlBar.ts
index fba37af5..1d695f60 100644
--- a/demo/components/controlBar.ts
+++ b/demo/components/controlBar.ts
@@ -3,6 +3,11 @@
* @license MIT
*/
+///
+
+import type { Terminal } from '@xterm/xterm';
+import type { AddonCollection } from 'types';
+
export interface ITabConfig {
id: string;
label: string;
@@ -12,6 +17,7 @@ export interface IControlWindow {
readonly id: string;
readonly label: string;
build(container: HTMLElement): void;
+ setTerminal(terminal: Terminal): void;
}
export class ControlBar {
diff --git a/demo/components/window/addonsWindow.ts b/demo/components/window/addonsWindow.ts
index c94a6f03..415dd5a4 100644
--- a/demo/components/window/addonsWindow.ts
+++ b/demo/components/window/addonsWindow.ts
@@ -3,10 +3,10 @@
* @license MIT
*/
-import type { Terminal } from '@xterm/xterm';
+import { BaseWindow } from './baseWindow';
import type { IControlWindow } from '../controlBar';
-export class AddonsWindow implements IControlWindow {
+export class AddonsWindow extends BaseWindow implements IControlWindow {
public readonly id = 'addons';
public readonly label = 'Addons';
diff --git a/demo/components/window/baseWindow.ts b/demo/components/window/baseWindow.ts
new file mode 100644
index 00000000..c541977c
--- /dev/null
+++ b/demo/components/window/baseWindow.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2025 The xterm.js authors. All rights reserved.
+ * @license MIT
+ */
+
+///
+
+import type { AddonCollection } from '../../types';
+import type { IControlWindow } from '../controlBar';
+import type { Terminal } from '@xterm/xterm';
+
+export abstract class BaseWindow implements IControlWindow {
+ protected get _terminal(): Terminal { return this.__terminal; }
+
+ constructor(
+ private __terminal: Terminal,
+ protected readonly _addons: AddonCollection,
+ ) {
+
+ }
+
+ setTerminal(terminal: Terminal): void {
+ this.__terminal = terminal;
+ }
+
+ abstract id: string;
+ abstract label: string;
+ abstract build(container: HTMLElement): void;
+}
\ No newline at end of file
diff --git a/demo/components/window/gpuWindow.ts b/demo/components/window/gpuWindow.ts
index 4fa74ff8..95d178fa 100644
--- a/demo/components/window/gpuWindow.ts
+++ b/demo/components/window/gpuWindow.ts
@@ -3,9 +3,10 @@
* @license MIT
*/
+import { BaseWindow } from './baseWindow';
import type { IControlWindow } from '../controlBar';
-export class GpuWindow implements IControlWindow {
+export class GpuWindow extends BaseWindow implements IControlWindow {
public readonly id = 'gpu';
public readonly label = 'GPU';
diff --git a/demo/components/window/optionsWindow.ts b/demo/components/window/optionsWindow.ts
index 7a5a24fc..1e3d1622 100644
--- a/demo/components/window/optionsWindow.ts
+++ b/demo/components/window/optionsWindow.ts
@@ -3,8 +3,10 @@
* @license MIT
*/
+import { BaseWindow } from './baseWindow';
import type { Terminal, ITheme } from '@xterm/xterm';
import type { IControlWindow } from '../controlBar';
+import type { AddonCollection } from 'types';
const xtermjsTheme: ITheme = {
foreground: '#F8F8F8',
@@ -29,23 +31,23 @@ const xtermjsTheme: ITheme = {
brightWhite: '#FFFFFF'
};
-export class OptionsWindow implements IControlWindow {
+export class OptionsWindow extends BaseWindow implements IControlWindow {
public readonly id = 'options';
public readonly label = 'Options';
private _container: HTMLElement;
private _optionsContainer: HTMLElement;
- private _term: Terminal;
private _autoResize: boolean = true;
- private _updateTerminalSize: () => void;
- private _updateTerminalContainerBackground: () => void;
constructor(
- updateTerminalSize: () => void,
- updateTerminalContainerBackground: () => void
+ terminal: Terminal,
+ addons: AddonCollection,
+ private readonly _handlers: {
+ updateTerminalSize: () => void,
+ updateTerminalContainerBackground: () => void
+ },
) {
- this._updateTerminalSize = updateTerminalSize;
- this._updateTerminalContainerBackground = updateTerminalContainerBackground;
+ super(terminal, addons)
}
public build(container: HTMLElement): void {
@@ -64,9 +66,7 @@ export class OptionsWindow implements IControlWindow {
container.appendChild(this._optionsContainer);
}
- public initOptions(term: Terminal, addDomListener: (el: HTMLElement, type: string, handler: (...args: any[]) => any) => void): void {
- this._term = term;
-
+ public initOptions(addDomListener: (el: HTMLElement, type: string, handler: (...args: any[]) => any) => void): void {
const blacklistedOptions = [
'cancelEvents',
'convertEol',
@@ -91,11 +91,11 @@ export class OptionsWindow implements IControlWindow {
wordSeparator: null,
colsRows: null
};
- const options = Object.getOwnPropertyNames(term.options);
+ const options = Object.getOwnPropertyNames(this._terminal.options);
const booleanOptions: string[] = [];
const numberOptions: string[] = [];
options.filter(o => blacklistedOptions.indexOf(o) === -1).forEach(o => {
- switch (typeof term.options[o]) {
+ switch (typeof this._terminal.options[o]) {
case 'boolean':
booleanOptions.push(o);
break;
@@ -112,21 +112,21 @@ export class OptionsWindow implements IControlWindow {
let html = '';
html += '
';
Object.keys(stringOptions).forEach(o => {
if (o === 'colsRows') {
html += `
`;
} else if (stringOptions[o]) {
- const selectedOption = o === 'theme' ? 'xtermjs' : term.options[o];
+ const selectedOption = o === 'theme' ? 'xtermjs' : this._terminal.options[o];
html += `
`;
} else {
- html += `
`;
+ html += `
`;
}
});
html += '
';
@@ -138,7 +138,7 @@ export class OptionsWindow implements IControlWindow {
const input = document.getElementById(`opt-${o}`) as HTMLInputElement;
addDomListener(input, 'change', () => {
console.log('change', o, input.checked);
- term.options[o] = input.checked;
+ this._terminal.options[o] = input.checked;
});
});
numberOptions.forEach(o => {
@@ -146,16 +146,16 @@ export class OptionsWindow implements IControlWindow {
addDomListener(input, 'change', () => {
console.log('change', o, input.value);
if (o === 'lineHeight') {
- term.options.lineHeight = parseFloat(input.value);
+ this._terminal.options.lineHeight = parseFloat(input.value);
} else if (o === 'scrollSensitivity') {
- term.options.scrollSensitivity = parseFloat(input.value);
+ this._terminal.options.scrollSensitivity = parseFloat(input.value);
} else if (o === 'scrollback') {
- term.options.scrollback = parseInt(input.value);
- setTimeout(() => this._updateTerminalSize(), 5);
+ this._terminal.options.scrollback = parseInt(input.value);
+ setTimeout(() => this._handlers.updateTerminalSize(), 5);
} else {
- term.options[o] = parseInt(input.value);
+ this._terminal.options[o] = parseInt(input.value);
}
- this._updateTerminalSize();
+ this._handlers.updateTerminalSize();
});
});
Object.keys(stringOptions).forEach(o => {
@@ -167,11 +167,11 @@ export class OptionsWindow implements IControlWindow {
const m = input.value.match(/^([0-9]+)x([0-9]+)$/);
if (m) {
this._autoResize = false;
- term.resize(parseInt(m[1]), parseInt(m[2]));
+ this._terminal.resize(parseInt(m[1]), parseInt(m[2]));
} else {
this._autoResize = true;
input.value = 'auto';
- this._updateTerminalSize();
+ this._handlers.updateTerminalSize();
}
} else if (o === 'theme') {
switch (input.value) {
@@ -232,9 +232,9 @@ export class OptionsWindow implements IControlWindow {
break;
}
}
- term.options[o] = value;
+ this._terminal.options[o] = value;
if (o === 'theme') {
- this._updateTerminalContainerBackground();
+ this._handlers.updateTerminalContainerBackground();
}
});
});
diff --git a/demo/components/window/styleWindow.ts b/demo/components/window/styleWindow.ts
index 7f9811b9..cc36dd7c 100644
--- a/demo/components/window/styleWindow.ts
+++ b/demo/components/window/styleWindow.ts
@@ -3,9 +3,10 @@
* @license MIT
*/
+import { BaseWindow } from './baseWindow';
import type { IControlWindow } from '../controlBar';
-export class StyleWindow implements IControlWindow {
+export class StyleWindow extends BaseWindow implements IControlWindow {
public readonly id = 'style';
public readonly label = 'Style';
diff --git a/demo/components/window/testWindow.ts b/demo/components/window/testWindow.ts
index b711e18b..bbd1c3d0 100644
--- a/demo/components/window/testWindow.ts
+++ b/demo/components/window/testWindow.ts
@@ -7,21 +7,23 @@
import { writeUnicodeTable } from 'unicodeTable';
import type { IControlWindow } from '../controlBar';
+import { BaseWindow } from './baseWindow';
import type { IDisposable, Terminal } from '@xterm/xterm';
import type { AddonCollection } from 'types';
-export class TestWindow implements IControlWindow {
+export class TestWindow extends BaseWindow implements IControlWindow {
public readonly id = 'test';
public readonly label = 'Test';
constructor(
- private readonly _terminal: Terminal,
- private readonly _addons: AddonCollection,
+ terminal: Terminal,
+ addons: AddonCollection,
private readonly _handlers: {
disposeRecreateButtonHandler: () => void,
createNewWindowButtonHandler: () => void,
},
) {
+ super(terminal, addons);
}
public build(container: HTMLElement): void {
diff --git a/demo/components/window/vtWindow.ts b/demo/components/window/vtWindow.ts
index 18614e55..787c4b86 100644
--- a/demo/components/window/vtWindow.ts
+++ b/demo/components/window/vtWindow.ts
@@ -3,10 +3,11 @@
* @license MIT
*/
+import { BaseWindow } from './baseWindow';
import type { IControlWindow } from '../controlBar';
import type { Terminal } from '@xterm/xterm';
-export class VtWindow implements IControlWindow {
+export class VtWindow extends BaseWindow implements IControlWindow {
public readonly id = 'vt';
public readonly label = 'VT';