fix: drag from inside to outside modal closes it (fixes #2715)

This commit is contained in:
David Wheatley 2022-01-01 16:56:06 +01:00
parent 58441b1d1f
commit d8841bba61
No known key found for this signature in database
GPG Key ID: DCC0FCE349280DFF

View File

@ -24,6 +24,8 @@ export default class ModalManager extends Component<IModalManagerAttrs> {
protected modalClosing: boolean = false; protected modalClosing: boolean = false;
protected clickStartedOnBackdrop: boolean = false;
view(vnode: Mithril.VnodeDOM<IModalManagerAttrs, this>): Mithril.Children { view(vnode: Mithril.VnodeDOM<IModalManagerAttrs, this>): Mithril.Children {
const modal = this.attrs.state.modal; const modal = this.attrs.state.modal;
const Tag = modal?.componentClass; const Tag = modal?.componentClass;
@ -77,7 +79,10 @@ export default class ModalManager extends Component<IModalManagerAttrs> {
dialogPolyfill.registerDialog(this.dialogElement); dialogPolyfill.registerDialog(this.dialogElement);
if (!dismissibleState.viaEscKey) this.dialogElement.addEventListener('cancel', this.preventEscPressHandler); if (!dismissibleState.viaEscKey) this.dialogElement.addEventListener('cancel', this.preventEscPressHandler);
if (dismissibleState.viaBackdropClick) this.dialogElement.addEventListener('click', (e) => this.handleBackdropClick.call(this, e)); if (dismissibleState.viaBackdropClick) {
this.dialogElement.addEventListener('mousedown', (e) => this.handleBackdropMouseDown.call(this, e));
this.dialogElement.addEventListener('click', (e) => this.handleBackdropClick.call(this, e));
}
this.dialogElement.addEventListener('transitionend', () => readyCallback(), { once: true }); this.dialogElement.addEventListener('transitionend', () => readyCallback(), { once: true });
// Ensure the modal state is ALWAYS notified about a closed modal // Ensure the modal state is ALWAYS notified about a closed modal
@ -115,21 +120,37 @@ export default class ModalManager extends Component<IModalManagerAttrs> {
this.dialogElement.classList.add('out'); this.dialogElement.classList.add('out');
} }
animateCloseHandler(this: this, e: Event) { protected animateCloseHandler(this: this, e: Event) {
e.preventDefault(); e.preventDefault();
this.animateHide(); this.animateHide();
} }
preventEscPressHandler(this: this, e: Event) { protected preventEscPressHandler(this: this, e: Event) {
e.preventDefault(); e.preventDefault();
} }
handleBackdropClick(this: this, e: MouseEvent) { protected handleBackdropMouseDown(this: this, e: MouseEvent) {
// If it's a click on the dialog element, the backdrop has been clicked. // If it's a mousedown on the dialog element, the backdrop has been clicked.
// If it was a click in the modal, the element would be `div.Modal-content` or some other element. // If it was a mousedown in the modal, the element would be `div.Modal-content` or some other element.
if (e.target !== this.dialogElement) return; if (e.target !== this.dialogElement) return;
this.clickStartedOnBackdrop = true;
window.addEventListener(
'mouseup',
() => {
if (e.target !== this.dialogElement) this.clickStartedOnBackdrop = false;
},
{ once: true }
);
}
protected handleBackdropClick(this: this, e: MouseEvent) {
// If it's a click on the dialog element, the backdrop has been clicked.
// If it was a click in the modal, the element would be `div.Modal-content` or some other element.
if (e.target !== this.dialogElement || !this.clickStartedOnBackdrop) return;
this.clickStartedOnBackdrop = false;
this.animateHide(); this.animateHide();
} }
} }