624 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			624 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * @copyright  (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
 | |
|  * @license    GNU General Public License version 2 or later; see LICENSE.txt
 | |
|  */
 | |
| 
 | |
| // Default template for the popup
 | |
| const popupTemplate = `<div class="joomla-dialog-container">
 | |
|   <header class="joomla-dialog-header"></header>
 | |
|   <section class="joomla-dialog-body"></section>
 | |
|   <footer class="joomla-dialog-footer"></footer>
 | |
| </div>`;
 | |
| 
 | |
| /**
 | |
|  * JoomlaDialog class for Joomla Dialog implementation.
 | |
|  * With use of <joomla-dialog> custom element as dialog holder.
 | |
|  */
 | |
| class JoomlaDialog extends HTMLElement {
 | |
|   /**
 | |
|    * The popup type, supported: inline, iframe, image, ajax.
 | |
|    * @type {string}
 | |
|    */
 | |
|   // popupType = 'inline';
 | |
| 
 | |
|   /**
 | |
|    * An optional text for header.
 | |
|    * @type {string}
 | |
|    */
 | |
|   // textHeader = '';
 | |
| 
 | |
|   /**
 | |
|    * An optional text for close button. Applied when no Buttons provided.
 | |
|    * @type {string}
 | |
|    */
 | |
|   // textClose = 'Close';
 | |
| 
 | |
|   /**
 | |
|    * Content string (html) for inline type popup.
 | |
|    * @type {string}
 | |
|    */
 | |
|   // popupContent = '';
 | |
| 
 | |
|   /**
 | |
|    * Source path for iframe, image, ajax.
 | |
|    * @type {string}
 | |
|    */
 | |
|   // src = '';
 | |
| 
 | |
|   /**
 | |
|    * An optional list of buttons, to be rendered in footer or header, or bottom or top of the popup body.
 | |
|    * Example:
 | |
|    *   [{label: 'Yes', onClick: () => popup.close()},
 | |
|    *   {label: 'No', onClick: () => popup.close(), className: 'btn btn-danger'},
 | |
|    *   {label: 'Click me', onClick: () => popup.close(), location: 'header'}]
 | |
|    * @type {[]}
 | |
|    */
 | |
|   // popupButtons = [];
 | |
| 
 | |
|   /**
 | |
|    * Whether popup can be closed by Esc button.
 | |
|    *
 | |
|    * @type {boolean}
 | |
|    */
 | |
|   // cancelable = true;
 | |
| 
 | |
|   /**
 | |
|    * An optional limit for the popup width, any valid CSS value.
 | |
|    * @type {string}
 | |
|    */
 | |
|   // width = '';
 | |
| 
 | |
|   /**
 | |
|    * An optional height for the popup, any valid CSS value.
 | |
|    * @type {string}
 | |
|    */
 | |
|   // height = '';
 | |
| 
 | |
|   /**
 | |
|    * An optional Class names for header icon.
 | |
|    *
 | |
|    * @type {string}
 | |
|    */
 | |
|   // iconHeader = '';
 | |
| 
 | |
|   /**
 | |
|    * A template for the popup.
 | |
|    * @type {string|HTMLTemplateElement}
 | |
|    */
 | |
|   // popupTemplate = popupTemplate;
 | |
| 
 | |
|   /**
 | |
|    * The element where to attach the dialog, for cases when no parentElement exist, see show().
 | |
|    * This allows to keep the dialog in the same branch of DOM as the popupContent.
 | |
|    * @type {string|HTMLElement}
 | |
|    */
 | |
|   // preferredParent = null;
 | |
| 
 | |
|   /**
 | |
|    * Class constructor
 | |
|    * @param {Object} config
 | |
|    */
 | |
|   constructor(config) {
 | |
|     super();
 | |
| 
 | |
|     // Define default params (doing it here because browser support of public props)
 | |
|     this.popupType = this.getAttribute('type') || 'inline';
 | |
|     this.textHeader = this.getAttribute('text-header') || '';
 | |
|     this.iconHeader = '';
 | |
|     this.textClose = Joomla.Text._('JCLOSE', 'Close');
 | |
|     this.popupContent = '';
 | |
|     this.src = this.getAttribute('src') || '';
 | |
|     this.popupButtons = [];
 | |
|     this.cancelable = !this.hasAttribute('not-cancelable');
 | |
|     this.width = this.getAttribute('width') || '';
 | |
|     this.height = this.getAttribute('height') || '';
 | |
|     this.popupTemplate = popupTemplate;
 | |
|     this.preferredParent = null;
 | |
|     // @internal. Parent of the popupContent for cases when it is HTMLElement. Need for recovery on destroy().
 | |
|     this.popupContentSrcLocation = null;
 | |
|     if (!config) return;
 | |
| 
 | |
|     // Check configurable properties
 | |
|     ['popupType', 'textHeader', 'textClose', 'popupContent', 'src', 'popupButtons', 'cancelable', 'width', 'height', 'popupTemplate', 'iconHeader', 'id', 'preferredParent'].forEach(key => {
 | |
|       if (config[key] !== undefined) {
 | |
|         this[key] = config[key];
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     // Check class name
 | |
|     if (config.className) {
 | |
|       this.classList.add(...config.className.split(' '));
 | |
|     }
 | |
| 
 | |
|     // Check dataset properties
 | |
|     if (config.data) {
 | |
|       Object.entries(config.data).forEach(([k, v]) => {
 | |
|         this.dataset[k] = v;
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Internal. Connected Callback.
 | |
|    */
 | |
|   connectedCallback() {
 | |
|     this.renderLayout();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Internal. Render a main layout, based on given template.
 | |
|    * @returns {JoomlaDialog}
 | |
|    */
 | |
|   renderLayout() {
 | |
|     if (this.dialog) return this;
 | |
| 
 | |
|     // On close callback
 | |
|     const onClose = () => {
 | |
|       this.dispatchEvent(new CustomEvent('joomla-dialog:close', {
 | |
|         bubbles: true
 | |
|       }));
 | |
|     };
 | |
|     const onCancel = event => {
 | |
|       if (!this.cancelable) {
 | |
|         // Prevent closing by Esc
 | |
|         event.preventDefault();
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     // Check for existing layout
 | |
|     if (this.firstElementChild && this.firstElementChild.nodeName === 'DIALOG') {
 | |
|       this.dialog = this.firstElementChild;
 | |
|       this.dialog.addEventListener('cancel', onCancel);
 | |
|       this.dialog.addEventListener('close', onClose);
 | |
|       this.popupTmplB = this.querySelector('.joomla-dialog-body') || this.dialog;
 | |
|       this.popupContentElement = this.popupTmplB;
 | |
|       return this;
 | |
|     }
 | |
| 
 | |
|     // Render a template
 | |
|     let templateContent;
 | |
|     if (this.popupTemplate.tagName && this.popupTemplate.tagName === 'TEMPLATE') {
 | |
|       templateContent = this.popupTemplate.content.cloneNode(true);
 | |
|     } else {
 | |
|       const template = document.createElement('template');
 | |
|       template.innerHTML = this.popupTemplate;
 | |
|       templateContent = template.content;
 | |
|     }
 | |
|     this.dialog = document.createElement('dialog');
 | |
|     this.dialog.appendChild(templateContent);
 | |
|     this.dialog.addEventListener('cancel', onCancel);
 | |
|     this.dialog.addEventListener('close', onClose);
 | |
|     this.appendChild(this.dialog);
 | |
| 
 | |
|     // Get template parts
 | |
|     this.popupTmplH = this.dialog.querySelector('.joomla-dialog-header');
 | |
|     this.popupTmplB = this.dialog.querySelector('.joomla-dialog-body');
 | |
|     this.popupTmplF = this.dialog.querySelector('.joomla-dialog-footer');
 | |
|     this.popupContentElement = null;
 | |
|     if (!this.popupTmplB) {
 | |
|       throw new Error('The popup body not found in the template.');
 | |
|     }
 | |
| 
 | |
|     // Set the header
 | |
|     if (this.popupTmplH && this.textHeader) {
 | |
|       const h = document.createElement('h3');
 | |
|       h.insertAdjacentHTML('afterbegin', this.textHeader);
 | |
|       this.popupTmplH.insertAdjacentElement('afterbegin', h);
 | |
|       if (this.iconHeader) {
 | |
|         const i = document.createElement('span');
 | |
|         i.ariaHidden = true;
 | |
|         i.classList.add('header-icon');
 | |
|         i.classList.add(...this.iconHeader.split(' '));
 | |
|         this.popupTmplH.insertAdjacentElement('afterbegin', i);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     // Set the body
 | |
|     this.renderBodyContent();
 | |
|     this.setAttribute('type', this.popupType);
 | |
| 
 | |
|     // Create buttons if any
 | |
|     const buttons = this.popupButtons || [];
 | |
| 
 | |
|     // Add at least one button to close the popup
 | |
|     if (!buttons.length) {
 | |
|       buttons.push({
 | |
|         label: '',
 | |
|         ariaLabel: this.textClose,
 | |
|         className: 'button-close btn-close',
 | |
|         data: {
 | |
|           buttonClose: ''
 | |
|         },
 | |
|         onClick: () => this.close(),
 | |
|         location: 'header'
 | |
|       });
 | |
|     }
 | |
| 
 | |
|     // Buttons holders
 | |
|     const btnHHolder = document.createElement('div');
 | |
|     const btnFHolder = document.createElement('div');
 | |
|     btnHHolder.classList.add('buttons-holder');
 | |
|     btnFHolder.classList.add('buttons-holder');
 | |
|     this.popupButtons.forEach(btnData => {
 | |
|       const btn = document.createElement('button');
 | |
|       btn.type = 'button';
 | |
|       btn.textContent = btnData.label || '';
 | |
|       btn.ariaLabel = btnData.ariaLabel || null;
 | |
|       if (btnData.className) {
 | |
|         btn.classList.add(...btnData.className.split(' '));
 | |
|       } else {
 | |
|         btn.classList.add('button', 'button-primary', 'btn', 'btn-primary');
 | |
|       }
 | |
|       if (btnData.data) {
 | |
|         Object.entries(btnData.data).forEach(([k, v]) => {
 | |
|           btn.dataset[k] = v;
 | |
|         });
 | |
|         if (btnData.data.dialogClose !== undefined) {
 | |
|           btnData.onClick = () => this.close();
 | |
|         }
 | |
|         if (btnData.data.dialogDestroy !== undefined) {
 | |
|           btnData.onClick = () => this.destroy();
 | |
|         }
 | |
|       }
 | |
|       if (btnData.onClick) {
 | |
|         btn.addEventListener('click', btnData.onClick);
 | |
|       }
 | |
|       if (btnData.location === 'header') {
 | |
|         btnHHolder.appendChild(btn);
 | |
|       } else {
 | |
|         btnFHolder.appendChild(btn);
 | |
|       }
 | |
|     });
 | |
|     if (btnHHolder.children.length) {
 | |
|       if (this.popupType === 'image' && !this.textHeader) {
 | |
|         this.popupTmplB.insertAdjacentElement('afterbegin', btnHHolder);
 | |
|       } else if (this.popupTmplH) {
 | |
|         this.popupTmplH.insertAdjacentElement('beforeend', btnHHolder);
 | |
|       } else {
 | |
|         this.popupTmplB.insertAdjacentElement('afterbegin', btnHHolder);
 | |
|       }
 | |
|     }
 | |
|     if (btnFHolder.children.length) {
 | |
|       (this.popupTmplF || this.popupTmplB).insertAdjacentElement('beforeend', btnFHolder);
 | |
|     }
 | |
| 
 | |
|     // Adjust the sizes if requested
 | |
|     if (this.width) {
 | |
|       this.dialog.style.width = '100%';
 | |
|       this.dialog.style.maxWidth = this.width;
 | |
|     }
 | |
|     if (this.height) {
 | |
|       this.dialog.style.height = this.height;
 | |
|     }
 | |
| 
 | |
|     // Mark an empty template elements
 | |
|     if (this.popupTmplH && !this.popupTmplH.children.length) {
 | |
|       this.popupTmplH.classList.add('empty');
 | |
|     }
 | |
|     if (this.popupTmplF && !this.popupTmplF.children.length) {
 | |
|       this.popupTmplF.classList.add('empty');
 | |
|     }
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Internal. Render the body content, based on popupType.
 | |
|    * @returns {JoomlaDialog}
 | |
|    */
 | |
|   renderBodyContent() {
 | |
|     if (!this.popupTmplB || this.popupContentElement) return this;
 | |
| 
 | |
|     // Callback for loaded content event listener
 | |
|     const onLoad = () => {
 | |
|       this.classList.add('loaded');
 | |
|       this.classList.remove('loading');
 | |
|       this.popupContentElement.removeEventListener('load', onLoad);
 | |
|       this.dispatchEvent(new CustomEvent('joomla-dialog:load'));
 | |
|       if (this.popupType === 'inline' || this.popupType === 'ajax') {
 | |
|         // Dispatch joomla:updated for inline content
 | |
|         this.popupContentElement.dispatchEvent(new CustomEvent('joomla:updated', {
 | |
|           bubbles: true,
 | |
|           cancelable: true
 | |
|         }));
 | |
|       }
 | |
|     };
 | |
|     this.classList.add('loading');
 | |
|     switch (this.popupType) {
 | |
|       // Create an Inline content
 | |
|       case 'inline':
 | |
|         {
 | |
|           let inlineContent = this.popupContent;
 | |
| 
 | |
|           // Check for content selector: src: '#content-selector' or src: '.content-selector'
 | |
|           if (!inlineContent && this.src && (this.src[0] === '.' || this.src[0] === '#')) {
 | |
|             inlineContent = document.querySelector(this.src);
 | |
|             this.popupContent = inlineContent;
 | |
|           }
 | |
|           if (inlineContent instanceof HTMLElement) {
 | |
|             // Render content provided as HTMLElement
 | |
|             if (inlineContent.nodeName === 'TEMPLATE') {
 | |
|               this.popupTmplB.appendChild(inlineContent.content.cloneNode(true));
 | |
|             } else {
 | |
|               // Store parent reference to be able to recover after the popup is destroyed
 | |
|               this.popupContentSrcLocation = {
 | |
|                 parent: inlineContent.parentElement,
 | |
|                 nextSibling: inlineContent.nextSibling
 | |
|               };
 | |
|               this.popupTmplB.appendChild(inlineContent);
 | |
|             }
 | |
|           } else {
 | |
|             // Render content string
 | |
|             this.popupTmplB.insertAdjacentHTML('afterbegin', Joomla.sanitizeHtml(inlineContent));
 | |
|           }
 | |
|           this.popupContentElement = this.popupTmplB;
 | |
|           onLoad();
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|       // Create an IFrame content
 | |
|       case 'iframe':
 | |
|         {
 | |
|           const frame = document.createElement('iframe');
 | |
|           frame.addEventListener('load', onLoad);
 | |
|           frame.src = this.src;
 | |
|           // Enlarge default size of iframe, make sure it is usable without extra styling
 | |
|           frame.width = '100%';
 | |
|           frame.height = '720';
 | |
|           if (!this.width) {
 | |
|             frame.style.maxWidth = '100%';
 | |
|             frame.width = '1024';
 | |
|           }
 | |
|           frame.classList.add('iframe-content');
 | |
|           this.popupContentElement = frame;
 | |
|           this.popupTmplB.appendChild(frame);
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|       // Create an Image content
 | |
|       case 'image':
 | |
|         {
 | |
|           const img = document.createElement('img');
 | |
|           img.addEventListener('load', onLoad);
 | |
|           img.src = this.src;
 | |
|           this.popupContentElement = img;
 | |
|           this.popupTmplB.appendChild(img);
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|       // Create an AJAX content
 | |
|       case 'ajax':
 | |
|         {
 | |
|           fetch(this.src).then(response => {
 | |
|             if (response.status !== 200) {
 | |
|               throw new Error(response.statusText);
 | |
|             }
 | |
|             return response.text();
 | |
|           }).then(text => {
 | |
|             this.popupTmplB.insertAdjacentHTML('afterbegin', Joomla.sanitizeHtml(text));
 | |
|             this.popupContentElement = this.popupTmplB;
 | |
|             onLoad();
 | |
|           }).catch(error => {
 | |
|             throw error;
 | |
|           });
 | |
|           break;
 | |
|         }
 | |
|       default:
 | |
|         {
 | |
|           throw new Error('Unknown popup type requested');
 | |
|         }
 | |
|     }
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Internal. Find an Element to be used as parent element,
 | |
|    * for cases when Dialog does not have one already. See show().
 | |
|    *
 | |
|    * @returns {HTMLElement|boolean}
 | |
|    */
 | |
|   findPreferredParent() {
 | |
|     let parent;
 | |
|     if (this.preferredParent instanceof HTMLElement) {
 | |
|       // We have configured one already
 | |
|       parent = this.preferredParent;
 | |
|     } else if (this.preferredParent) {
 | |
|       // Query Document
 | |
|       parent = document.querySelector(this.preferredParent);
 | |
|     } else if (this.popupType === 'inline') {
 | |
|       // Pick the parent element of the Content
 | |
|       let inlineContent = this.popupContent;
 | |
|       // Check for content selector: src: '#content-selector' or src: '.content-selector'
 | |
|       if (!inlineContent && this.src && (this.src[0] === '.' || this.src[0] === '#')) {
 | |
|         inlineContent = document.querySelector(this.src);
 | |
|         parent = inlineContent ? inlineContent.parentElement : false;
 | |
|       }
 | |
|     }
 | |
|     return parent || false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the popup header element.
 | |
|    * @returns {HTMLElement|boolean}
 | |
|    */
 | |
|   getHeader() {
 | |
|     this.renderLayout();
 | |
|     return this.popupTmplH || false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the popup body element.
 | |
|    * @returns {HTMLElement}
 | |
|    */
 | |
|   getBody() {
 | |
|     this.renderLayout();
 | |
|     return this.popupTmplB;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the popup content element, or body for inline and ajax types.
 | |
|    * @returns {HTMLElement}
 | |
|    */
 | |
|   getBodyContent() {
 | |
|     this.renderLayout();
 | |
|     return this.popupContentElement || this.popupTmplB;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the popup footer element.
 | |
|    * @returns {HTMLElement|boolean}
 | |
|    */
 | |
|   getFooter() {
 | |
|     this.renderLayout();
 | |
|     return this.popupTmplF || false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Open the popup as modal window.
 | |
|    * Will append the element to Document body if not appended before.
 | |
|    *
 | |
|    * @returns {JoomlaDialog}
 | |
|    */
 | |
|   show() {
 | |
|     // Check whether the element already attached to DOM
 | |
|     if (!this.parentElement) {
 | |
|       // Check for preferred parent to attach to DOM
 | |
|       const parent = this.findPreferredParent();
 | |
|       (parent || document.body).appendChild(this);
 | |
|     }
 | |
|     this.dialog.showModal();
 | |
|     this.dispatchEvent(new CustomEvent('joomla-dialog:open', {
 | |
|       bubbles: true
 | |
|     }));
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Alias for show() method.
 | |
|    * @returns {JoomlaDialog}
 | |
|    */
 | |
|   open() {
 | |
|     return this.show();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Closes the popup
 | |
|    *
 | |
|    * @returns {JoomlaDialog}
 | |
|    */
 | |
|   close() {
 | |
|     if (!this.dialog) {
 | |
|       throw new Error('Calling close for non opened dialog is discouraged.');
 | |
|     }
 | |
|     this.dialog.close();
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Alias for close() method.
 | |
|    * @returns {JoomlaDialog}
 | |
|    */
 | |
|   hide() {
 | |
|     return this.close();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Destroys the popup.
 | |
|    */
 | |
|   destroy() {
 | |
|     if (!this.dialog) {
 | |
|       return;
 | |
|     }
 | |
|     this.dialog.close();
 | |
|     this.removeChild(this.dialog);
 | |
|     this.parentElement.removeChild(this);
 | |
| 
 | |
|     // Restore original location of the popup content element
 | |
|     if (this.popupContentSrcLocation && this.popupContent) {
 | |
|       const {
 | |
|         parent,
 | |
|         nextSibling
 | |
|       } = this.popupContentSrcLocation;
 | |
|       parent.insertBefore(this.popupContent, nextSibling);
 | |
|     }
 | |
|     this.dialog = null;
 | |
|     this.popupTmplH = null;
 | |
|     this.popupTmplB = null;
 | |
|     this.popupTmplF = null;
 | |
|     this.popupContentElement = null;
 | |
|     this.popupContentSrcLocation = null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Helper method to show an Alert.
 | |
|    *
 | |
|    * @param {String} message
 | |
|    * @param {String} title
 | |
|    * @returns {Promise}
 | |
|    */
 | |
|   static alert(message, title) {
 | |
|     return new Promise(resolve => {
 | |
|       const popup = new this();
 | |
|       popup.popupType = 'inline';
 | |
|       popup.popupContent = message;
 | |
|       popup.textHeader = title || Joomla.Text._('INFO', 'Info');
 | |
|       popup.popupButtons = [{
 | |
|         label: Joomla.Text._('JOK', 'Okay'),
 | |
|         data: {
 | |
|           buttonOk: ''
 | |
|         },
 | |
|         onClick: () => popup.close()
 | |
|       }];
 | |
|       popup.classList.add('joomla-dialog-alert');
 | |
|       popup.addEventListener('joomla-dialog:close', () => {
 | |
|         popup.destroy();
 | |
|         resolve();
 | |
|       });
 | |
|       popup.show();
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Helper method to show a Confirmation popup.
 | |
|    *
 | |
|    * @param {String} message
 | |
|    * @param {String} title
 | |
|    * @returns {Promise}
 | |
|    */
 | |
|   static confirm(message, title) {
 | |
|     return new Promise(resolve => {
 | |
|       let result = false;
 | |
|       const popup = new this();
 | |
|       popup.popupType = 'inline';
 | |
|       popup.popupContent = message;
 | |
|       popup.textHeader = title || Joomla.Text._('INFO', 'Info');
 | |
|       popup.popupButtons = [{
 | |
|         label: Joomla.Text._('JYES', 'Yes'),
 | |
|         data: {
 | |
|           buttonOk: ''
 | |
|         },
 | |
|         onClick: () => {
 | |
|           result = true;
 | |
|           popup.destroy();
 | |
|         }
 | |
|       }, {
 | |
|         label: Joomla.Text._('JNO', 'No'),
 | |
|         data: {
 | |
|           buttonCancel: ''
 | |
|         },
 | |
|         onClick: () => {
 | |
|           result = false;
 | |
|           popup.destroy();
 | |
|         },
 | |
|         className: 'button button-secondary btn btn-outline-secondary'
 | |
|       }];
 | |
|       popup.cancelable = false;
 | |
|       popup.classList.add('joomla-dialog-confirm');
 | |
|       popup.addEventListener('joomla-dialog:close', () => resolve(result));
 | |
|       popup.show();
 | |
|     });
 | |
|   }
 | |
| }
 | |
| customElements.define('joomla-dialog', JoomlaDialog);
 | |
| 
 | |
| export { JoomlaDialog as default };
 |