diff --git a/packages/uui-modal/lib/uui-modal-container.ts b/packages/uui-modal/lib/uui-modal-container.ts index 2cae8e5ed..ee21110bd 100644 --- a/packages/uui-modal/lib/uui-modal-container.ts +++ b/packages/uui-modal/lib/uui-modal-container.ts @@ -1,7 +1,7 @@ import { LitElement, PropertyValueMap, css, html } from 'lit'; import { property, query, state } from 'lit/decorators.js'; import { UUIModalSidebarElement } from './uui-modal-sidebar.element'; -import { UUIModalElement } from './uui-modal.element'; +import { UUIModalCloseEvent, UUIModalElement } from './uui-modal.element'; import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; @defineElement('uui-modal-container') @@ -23,7 +23,7 @@ export class UUIModalContainerElement extends LitElement { constructor() { super(); - this.addEventListener('close', this.#onClose); + this.addEventListener(UUIModalCloseEvent, this.#onCloseModalClose); } protected firstUpdated( @@ -38,6 +38,8 @@ export class UUIModalContainerElement extends LitElement { } #onSlotChange = () => { + const existingModals = this._modals ?? []; + this._modals = (this.modalSlot ?.assignedElements({ flatten: true }) @@ -45,6 +47,20 @@ export class UUIModalContainerElement extends LitElement { el => el instanceof UUIModalElement ) as Array) ?? []; + const oldModals = existingModals.filter( + modal => this._modals!.indexOf(modal) === -1 + ); + oldModals.forEach(modal => + modal.removeEventListener(UUIModalCloseEvent, this.#onCloseModalClose) + ); + + const newModals = this._modals.filter( + modal => existingModals.indexOf(modal) === -1 + ); + newModals.forEach(modal => + modal.addEventListener(UUIModalCloseEvent, this.#onCloseModalClose) + ); + this._sidebars = this._modals.filter( el => el instanceof UUIModalSidebarElement ) as Array; @@ -58,7 +74,13 @@ export class UUIModalContainerElement extends LitElement { this.#updateSidebars(); }; - #onClose = () => { + #onCloseModalClose = (event: Event) => { + event.stopImmediatePropagation(); + + event.target?.removeEventListener( + UUIModalCloseEvent, + this.#onCloseModalClose + ); if (!this._modals || this._modals.length <= 1) { this.removeAttribute('backdrop'); return; @@ -99,7 +121,15 @@ export class UUIModalContainerElement extends LitElement { for (let i = 0; i < reversed.length; i++) { const sidebar = reversed[i]; const nextSidebar = reversed[i + 1]; - sidebar.style.setProperty('--uui-modal-offset', sidebarOffset + 'px'); + const tempSidebarOffset = sidebarOffset; // Cache to prevent it from being overwritten before the updateComplete. + // The sidebar checks it's own width at sets it's --uui-modal-offset to negative that width. + // This enables it to slide in from the right. So we need to set the new --uui-modal-offset after the updateComplete. + sidebar.updateComplete.then(() => { + sidebar.style.setProperty( + '--uui-modal-offset', + tempSidebarOffset + 'px' + ); + }); // Stop the calculations if the next sidebar is hidden if (nextSidebar?.hasAttribute('hide')) break; diff --git a/packages/uui-modal/lib/uui-modal-sidebar.element.ts b/packages/uui-modal/lib/uui-modal-sidebar.element.ts index a0747c360..499030d6a 100644 --- a/packages/uui-modal/lib/uui-modal-sidebar.element.ts +++ b/packages/uui-modal/lib/uui-modal-sidebar.element.ts @@ -1,6 +1,6 @@ import { css, html, PropertyValueMap } from 'lit'; import { property } from 'lit/decorators.js'; -import { UUIModalElement } from './uui-modal.element'; +import { UUIModalCloseEvent, UUIModalElement } from './uui-modal.element'; import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; export type UUIModalSidebarSize = 'small' | 'medium' | 'large' | 'full'; @@ -15,7 +15,7 @@ export class UUIModalSidebarElement extends UUIModalElement { constructor() { super(); - this.addEventListener('close', this.#onClose.bind(this)); + this.addEventListener(UUIModalCloseEvent, this.#onClose.bind(this)); } protected firstUpdated( diff --git a/packages/uui-modal/lib/uui-modal.element.ts b/packages/uui-modal/lib/uui-modal.element.ts index 5c4e07c9e..4c26d46da 100644 --- a/packages/uui-modal/lib/uui-modal.element.ts +++ b/packages/uui-modal/lib/uui-modal.element.ts @@ -1,5 +1,7 @@ import { LitElement, css } from 'lit'; import { property, query } from 'lit/decorators.js'; + +export const UUIModalCloseEvent = 'uui:modal-close'; export class UUIModalElement extends LitElement { @query('dialog') protected _dialogElement?: HTMLDialogElement; @@ -58,7 +60,7 @@ export class UUIModalElement extends LitElement { event?.preventDefault(); event?.stopImmediatePropagation(); - const closeEvent = new CustomEvent('close', { + const closeEvent = new CustomEvent(UUIModalCloseEvent, { cancelable: true, }); this.dispatchEvent(closeEvent);