Skip to content

Commit 5d9e68c

Browse files
authored
fix: clear text selection when clicking outside canvas (#46)
1 parent c941889 commit 5d9e68c

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

lib/selection-manager.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export class SelectionManager {
5151
// Store bound event handlers for cleanup
5252
private boundMouseUpHandler: ((e: MouseEvent) => void) | null = null;
5353
private boundContextMenuHandler: ((e: MouseEvent) => void) | null = null;
54+
private boundClickHandler: ((e: MouseEvent) => void) | null = null;
5455

5556
constructor(
5657
terminal: Terminal,
@@ -291,6 +292,12 @@ export class SelectionManager {
291292
this.boundContextMenuHandler = null;
292293
}
293294

295+
// Clean up document click listener
296+
if (this.boundClickHandler) {
297+
document.removeEventListener('click', this.boundClickHandler);
298+
this.boundClickHandler = null;
299+
}
300+
294301
// Canvas event listeners will be cleaned up when canvas is removed from DOM
295302
}
296303

@@ -444,6 +451,21 @@ export class SelectionManager {
444451
};
445452

446453
canvas.addEventListener('contextmenu', this.boundContextMenuHandler);
454+
455+
// Click outside canvas - clear selection
456+
// This allows users to deselect by clicking anywhere outside the terminal
457+
this.boundClickHandler = (e: MouseEvent) => {
458+
// Check if the click is outside the canvas
459+
const target = e.target as Node;
460+
if (!canvas.contains(target)) {
461+
// Clicked outside the canvas - clear selection
462+
if (this.hasSelection()) {
463+
this.clearSelection();
464+
}
465+
}
466+
};
467+
468+
document.addEventListener('click', this.boundClickHandler);
447469
}
448470

449471
/**

lib/terminal.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,29 @@ describe('select()', () => {
666666
expect(fired).toBe(true);
667667
term.dispose();
668668
});
669+
670+
test('should clear selection when clicking outside canvas', async () => {
671+
const term = new Terminal({ cols: 80, rows: 24 });
672+
// Using shared container from beforeEach
673+
if (!container) return;
674+
await term.open(container);
675+
676+
// Create a selection
677+
term.select(0, 0, 10);
678+
expect(term.hasSelection()).toBe(true);
679+
680+
// Simulate click outside the canvas (on document body)
681+
const clickEvent = new MouseEvent('click', {
682+
bubbles: true,
683+
cancelable: true,
684+
view: window,
685+
});
686+
document.body.dispatchEvent(clickEvent);
687+
688+
// Selection should be cleared
689+
expect(term.hasSelection()).toBe(false);
690+
term.dispose();
691+
});
669692
});
670693
});
671694

0 commit comments

Comments
 (0)