Introduce a global dialog stack to correctly manage dismissal through the esc key.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@tp/tp-dialog",
|
"name": "@tp/tp-dialog",
|
||||||
"version": "1.4.0",
|
"version": "1.5.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "tp-dialog.js",
|
"main": "tp-dialog.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
71
tp-dialog.js
71
tp-dialog.js
@@ -9,6 +9,21 @@ import { LitElement, html, css, svg } from 'lit';
|
|||||||
import { EventHelpers } from '@tp/helpers/event-helpers.js';
|
import { EventHelpers } from '@tp/helpers/event-helpers.js';
|
||||||
import { closest } from '@tp/helpers/closest.js';
|
import { closest } from '@tp/helpers/closest.js';
|
||||||
|
|
||||||
|
// Global stack to track opened dialogs with closeOnEsc
|
||||||
|
const dialogStack = [];
|
||||||
|
let escKeyListener = null;
|
||||||
|
|
||||||
|
// Global escape key handler
|
||||||
|
function handleGlobalEscKey(event) {
|
||||||
|
if (event.key === 'Escape' && dialogStack.length > 0) {
|
||||||
|
// Get the most recently opened dialog
|
||||||
|
const lastDialog = dialogStack[dialogStack.length - 1];
|
||||||
|
if (lastDialog && lastDialog.closeOnEsc) {
|
||||||
|
lastDialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TpDialog extends EventHelpers(LitElement) {
|
class TpDialog extends EventHelpers(LitElement) {
|
||||||
static get styles() {
|
static get styles() {
|
||||||
return [
|
return [
|
||||||
@@ -83,7 +98,6 @@ class TpDialog extends EventHelpers(LitElement) {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._handleEscKey = this._handleEscKey.bind(this);
|
|
||||||
this._currentPromise = null;
|
this._currentPromise = null;
|
||||||
this._resolvePromise = null;
|
this._resolvePromise = null;
|
||||||
}
|
}
|
||||||
@@ -103,9 +117,8 @@ class TpDialog extends EventHelpers(LitElement) {
|
|||||||
this.unlisten(this, 'confirmed', '_handleConfirmed');
|
this.unlisten(this, 'confirmed', '_handleConfirmed');
|
||||||
this.unlisten(this, 'dismissed', '_handleDismissed');
|
this.unlisten(this, 'dismissed', '_handleDismissed');
|
||||||
|
|
||||||
if (this.closeOnEsc) {
|
// Remove this dialog from the stack
|
||||||
document.removeEventListener('keydown', this._handleEscKey);
|
this._removeFromDialogStack();
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up promise if dialog is removed while open
|
// Clean up promise if dialog is removed while open
|
||||||
if (this._currentPromise && this._resolvePromise) {
|
if (this._currentPromise && this._resolvePromise) {
|
||||||
@@ -119,9 +132,8 @@ class TpDialog extends EventHelpers(LitElement) {
|
|||||||
this.dialog.show();
|
this.dialog.show();
|
||||||
this.open = true;
|
this.open = true;
|
||||||
|
|
||||||
if (this.closeOnEsc) {
|
// Add to dialog stack if closeOnEsc is enabled
|
||||||
document.addEventListener('keydown', this._handleEscKey, { once: true });
|
this._addToDialogStack();
|
||||||
}
|
|
||||||
|
|
||||||
// Create and return a new promise
|
// Create and return a new promise
|
||||||
this._currentPromise = new Promise((resolve) => {
|
this._currentPromise = new Promise((resolve) => {
|
||||||
@@ -135,9 +147,8 @@ class TpDialog extends EventHelpers(LitElement) {
|
|||||||
this.dialog.showModal();
|
this.dialog.showModal();
|
||||||
this.open = true;
|
this.open = true;
|
||||||
|
|
||||||
if (this.closeOnEsc) {
|
// Add to dialog stack if closeOnEsc is enabled
|
||||||
document.addEventListener('keydown', this._handleEscKey, { once: true });
|
this._addToDialogStack();
|
||||||
}
|
|
||||||
|
|
||||||
if (this.closeOnOutsideClick) {
|
if (this.closeOnOutsideClick) {
|
||||||
this.addEventListener('click', this._handleOutsideClick, { once: true });
|
this.addEventListener('click', this._handleOutsideClick, { once: true });
|
||||||
@@ -161,6 +172,9 @@ class TpDialog extends EventHelpers(LitElement) {
|
|||||||
this.dispatchEvent(new CustomEvent('closed', { detail: null, bubbles: true, composed: true }));
|
this.dispatchEvent(new CustomEvent('closed', { detail: null, bubbles: true, composed: true }));
|
||||||
this.open = false;
|
this.open = false;
|
||||||
|
|
||||||
|
// Remove from dialog stack
|
||||||
|
this._removeFromDialogStack();
|
||||||
|
|
||||||
// If closed without explicit confirm/dismiss (like ESC key), treat as dismissed
|
// If closed without explicit confirm/dismiss (like ESC key), treat as dismissed
|
||||||
if (this._currentPromise && this._resolvePromise) {
|
if (this._currentPromise && this._resolvePromise) {
|
||||||
this._resolvePromise('dismissed');
|
this._resolvePromise('dismissed');
|
||||||
@@ -185,6 +199,35 @@ class TpDialog extends EventHelpers(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_addToDialogStack() {
|
||||||
|
if (this.closeOnEsc) {
|
||||||
|
// Remove if already in stack (shouldn't happen, but just in case)
|
||||||
|
this._removeFromDialogStack();
|
||||||
|
|
||||||
|
// Add to the end of the stack
|
||||||
|
dialogStack.push(this);
|
||||||
|
|
||||||
|
// Set up global listener if this is the first dialog
|
||||||
|
if (dialogStack.length === 1 && !escKeyListener) {
|
||||||
|
escKeyListener = handleGlobalEscKey;
|
||||||
|
document.addEventListener('keydown', escKeyListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeFromDialogStack() {
|
||||||
|
const index = dialogStack.indexOf(this);
|
||||||
|
if (index > -1) {
|
||||||
|
dialogStack.splice(index, 1);
|
||||||
|
|
||||||
|
// Remove global listener if no more dialogs with closeOnEsc
|
||||||
|
if (dialogStack.length === 0 && escKeyListener) {
|
||||||
|
document.removeEventListener('keydown', escKeyListener);
|
||||||
|
escKeyListener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_onDialogClick(event) {
|
_onDialogClick(event) {
|
||||||
if (this.closeOnOutsideClick) {
|
if (this.closeOnOutsideClick) {
|
||||||
const path = event.composedPath();
|
const path = event.composedPath();
|
||||||
@@ -217,10 +260,10 @@ class TpDialog extends EventHelpers(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleEscKey(event) {
|
_handleOutsideClick(event) {
|
||||||
if (event.key === 'Escape' && this.closeOnEsc) {
|
// This method should be implemented if closeOnOutsideClick functionality is needed
|
||||||
this.close();
|
// For now, just close the dialog when clicking outside
|
||||||
}
|
this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user