|
| 1 | +import { state } from '../state'; |
| 2 | + |
1 | 3 | // ── Central popup coordinator (issue #15) ───────────────────────────────────── |
2 | 4 | // The grid has several transient popups: the column and row context menus, the |
3 | 5 | // Export and Delimiter dropdowns, the column-chooser and go-to-row popovers and |
@@ -28,3 +30,38 @@ export function closeAllPopups(except?: string): void { |
28 | 30 | document.getElementById(id)?.classList.add('hidden'); |
29 | 31 | } |
30 | 32 | } |
| 33 | + |
| 34 | +// Checks if any coordinated popup is currently visible. |
| 35 | +// This ensures the global Esc handler only consumes the keystroke when |
| 36 | +// there is actually a popup to dismiss, leaving Esc free for standard |
| 37 | +// tasks (like canceling a cell edit). |
| 38 | +export function isAnyPopupOpen(): boolean { |
| 39 | + return POPUP_IDS.some(id => { |
| 40 | + const el = document.getElementById(id); |
| 41 | + return el != null && !el.classList.contains('hidden'); |
| 42 | + }); |
| 43 | +} |
| 44 | + |
| 45 | +// Sets up a global Esc key listener to dismiss all popups (wired once at startup). |
| 46 | +// - Uses the capture phase (true) to intercept the event before AG Grid consumes it. |
| 47 | +// - Does NOT call stopPropagation to allow input-focused popups (rename, go-to-row) |
| 48 | +// to run their own focus-bound Escape handlers and state cleanup. |
| 49 | +// Other popups (context menus, dropdowns) are simply hidden by closeAllPopups(). |
| 50 | +export function setupPopups(): void { |
| 51 | + document.addEventListener('keydown', (e) => { |
| 52 | + if (e.key !== 'Escape') return; |
| 53 | + |
| 54 | + // AG Grid's filter panel lives outside POPUP_IDS (it has no fixed id). |
| 55 | + // Detect it in the DOM and let AG Grid close it. |
| 56 | + const agOpen = document.querySelector('.ag-popup .ag-menu, .ag-popup .ag-filter'); |
| 57 | + if (agOpen) { |
| 58 | + (state.gridApi as any)?.hidePopupMenu?.(); |
| 59 | + e.preventDefault(); |
| 60 | + return; |
| 61 | + } |
| 62 | + |
| 63 | + if (!isAnyPopupOpen()) return; |
| 64 | + closeAllPopups(); |
| 65 | + e.preventDefault(); |
| 66 | + }, true); |
| 67 | +} |
0 commit comments