1interface FileEditorDismissalOptions {
2 root: HTMLElement;
3 editor: {
4 setSelections: (selections: []) => void;
5 };
6 isBlocked: () => boolean;
7 onDismiss: () => void;
8}
9
10function dismissFileEditorInteraction({
11 root,
12 editor,
13 onDismiss,
14}: Pick<FileEditorDismissalOptions, "root" | "editor" | "onDismiss">): void {
15 onDismiss();
16 editor.setSelections([]);
17
18 const file = root.querySelector<HTMLElement>("diffs-container");
19 const activeElement = file?.shadowRoot?.activeElement;
20 if (activeElement instanceof HTMLElement) {
21 activeElement.blur();
22 }
23}
24
25function isFileEditorFocused(root: HTMLElement): boolean {
26 const file = root.querySelector<HTMLElement>("diffs-container");
27 return file?.shadowRoot?.activeElement?.hasAttribute("data-content") === true;
28}
29
30export function installFileEditorDismissal({
31 root,
32 editor,
33 isBlocked,
34 onDismiss,
35}: FileEditorDismissalOptions): () => void {
36 const handlePointerDown = (event: PointerEvent) => {
37 if (isBlocked() || event.composedPath().includes(root)) return;
38 dismissFileEditorInteraction({ root, editor, onDismiss });
39 };
40 const handleKeyDown = (event: KeyboardEvent) => {
41 if (event.key !== "Escape" || isBlocked() || !isFileEditorFocused(root)) return;
42 event.preventDefault();
43 event.stopImmediatePropagation();
44 dismissFileEditorInteraction({ root, editor, onDismiss });
45 };
46
47 document.addEventListener("pointerdown", handlePointerDown, true);
48 document.addEventListener("keydown", handleKeyDown, true);
49 return () => {
50 document.removeEventListener("pointerdown", handlePointerDown, true);
51 document.removeEventListener("keydown", handleKeyDown, true);
52 };
53}