UNPKG

@limetech/lime-elements

Version:
306 lines (305 loc) • 11.7 kB
import { MDCDialog } from "@material/dialog"; import { h, } from "@stencil/core"; import { isEqual } from "lodash-es"; import { dispatchResizeEvent } from "../../util/dispatch-resize-event"; import { createRandomString } from "../../util/random-string"; /** * :::note * Regarding the `close` event: When putting other elements that emit `close` * events inside a dialog, those events must be caught and stopped inside the * dialog. If not, they will bubble to the event handler listening for `close` * events on the dialog, which will close the dialog too. * * See the example _Nested `close` events_. * ::: * * :::important * Are you developing for * [Lime CRM](https://www.lime-technologies.com/en/lime-crm/)? Please note that * you should use the [DialogRenderer](https://lundalogik.github.io/lime-web-components/versions/latest/interfaces/DialogRenderer.html) * from Lime Web Components to open dialogs in Lime CRM. * ::: * * @exampleComponent limel-example-dialog-basic * @exampleComponent limel-example-dialog-nested-close-events * @exampleComponent limel-example-dialog-heading * @exampleComponent limel-example-dialog-heading-actions * @exampleComponent limel-example-dialog-form * @exampleComponent limel-example-dialog-size * @exampleComponent limel-example-dialog-fullscreen * @exampleComponent limel-example-dialog-closing-actions * @exampleComponent limel-example-dialog-action-buttons * @slot - Content to put inside the dialog * @slot header-actions - The dialog header buttons * @slot button - The dialog buttons */ export class Dialog { constructor() { /** * Set to `true` to make the dialog "fullscreen". */ this.fullscreen = false; /** * `true` if the dialog is open, `false` otherwise. */ this.open = false; /** * Defines which action triggers a close-event. */ this.closingActions = { escapeKey: true, scrimClick: true, }; this.handleMdcOpened = this.handleMdcOpened.bind(this); this.handleMdcClosed = this.handleMdcClosed.bind(this); this.handleMdcClosing = this.handleMdcClosing.bind(this); } connectedCallback() { this.initialize(); } componentWillLoad() { this.id = createRandomString(); } componentDidLoad() { this.initialize(); } initialize() { const element = this.host.shadowRoot.querySelector('.mdc-dialog'); if (!element) { return; } this.mdcDialog = new MDCDialog(element); if (this.open) { this.mdcDialog.open(); } this.mdcDialog.listen('MDCDialog:opened', this.handleMdcOpened); this.mdcDialog.listen('MDCDialog:closed', this.handleMdcClosed); this.mdcDialog.listen('MDCDialog:closing', this.handleMdcClosing); this.setClosingActions(); } disconnectedCallback() { this.mdcDialog.unlisten('MDCDialog:opened', this.handleMdcOpened); this.mdcDialog.unlisten('MDCDialog:closed', this.handleMdcClosed); this.mdcDialog.unlisten('MDCDialog:closing', this.handleMdcClosing); this.mdcDialog.destroy(); } render() { return (h("div", { key: '748566bd65db98ee75a743a7deedc7d0c9f80a90', class: { 'mdc-dialog': true, 'full-screen': !!this.fullscreen, }, role: "alertdialog", "aria-modal": "true", "aria-labelledby": 'limel-dialog-title-' + this.id, "aria-describedby": 'limel-dialog-content-' + this.id }, h("input", { key: '15d2c40108a2348f54066eab22d507c6a9b3eda9', hidden: true, id: "initialFocusEl" }), h("div", { key: 'f46ee440d02b257bde93273936ce1dfe8dc324ea', class: "mdc-dialog__container" }, h("div", { key: '9ba9919b2b880039ede217c0608d9f780d6ca770', class: "mdc-dialog__surface" }, h("input", { key: '07bb68ae4c7b8d91cb7f0fd02105738160bd9e8f', type: "button", id: "initialFocusElement" }), this.renderHeading(), h("div", { key: '1729cb0f7f442b3ee56272387de42b462926275c', class: "mdc-dialog__content", id: 'limel-dialog-content-' + this.id }, h("slot", { key: 'a5554b316a4e57700a2902ae4499f594045f267d' })), this.renderFooter())), h("div", { key: '85ecb0922ece938a5de20b804b6a2590f98032df', class: "mdc-dialog__scrim" }))); } watchHandler(newValue, oldValue) { if (oldValue === newValue) { return; } if (!this.mdcDialog) { return; } if (newValue) { this.mdcDialog.open(); } else { this.mdcDialog.close(); } } closingActionsChanged(newValue, oldValue) { if (isEqual(newValue, oldValue)) { return; } this.setClosingActions(); } handleMdcOpened() { // When the opening-animation has completed, dispatch a // resize-event so that any content that depends on // javascript for layout has a chance to update to the // final layout of the dialog. /Ads const waitForUiToRender = 100; setTimeout(dispatchResizeEvent, waitForUiToRender); } handleMdcClosed() { if (this.open) { this.close.emit(); } this.open = false; } handleMdcClosing() { this.closing.emit(); } isDialogHeadingObject(heading) { return typeof heading === 'object' && !!heading.title; } renderHeading() { if (this.isDialogHeadingObject(this.heading)) { const { title, subtitle, supportingText, icon } = this.heading; return (h("limel-header", { icon: icon, heading: title, subheading: subtitle, supportingText: supportingText }, h("slot", { name: "header-actions", slot: "actions" }))); } else if (typeof this.heading === 'string') { return (h("limel-header", { heading: this.heading }, h("slot", { name: "header-actions", slot: "actions" }))); } return null; } renderFooter() { return (h("footer", { class: "mdc-dialog__actions" }, h("slot", { name: "button" }))); } setClosingActions() { this.mdcDialog.scrimClickAction = ''; if (this.closingActions.scrimClick) { this.mdcDialog.scrimClickAction = 'close'; } this.mdcDialog.escapeKeyAction = ''; if (this.closingActions.escapeKey) { this.mdcDialog.escapeKeyAction = 'close'; } } static get is() { return "limel-dialog"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["dialog.scss"] }; } static get styleUrls() { return { "$": ["dialog.css"] }; } static get properties() { return { "heading": { "type": "string", "mutable": false, "complexType": { "original": "string | DialogHeading", "resolved": "DialogHeading | string", "references": { "DialogHeading": { "location": "import", "path": "./dialog.types", "id": "src/components/dialog/dialog.types.ts::DialogHeading", "referenceLocation": "DialogHeading" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "The heading for the dialog, if any." }, "getter": false, "setter": false, "reflect": false, "attribute": "heading" }, "fullscreen": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Set to `true` to make the dialog \"fullscreen\"." }, "getter": false, "setter": false, "reflect": true, "attribute": "fullscreen", "defaultValue": "false" }, "open": { "type": "boolean", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "`true` if the dialog is open, `false` otherwise." }, "getter": false, "setter": false, "reflect": true, "attribute": "open", "defaultValue": "false" }, "closingActions": { "type": "unknown", "mutable": false, "complexType": { "original": "ClosingActions", "resolved": "ClosingActions", "references": { "ClosingActions": { "location": "import", "path": "./dialog.types", "id": "src/components/dialog/dialog.types.ts::ClosingActions", "referenceLocation": "ClosingActions" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Defines which action triggers a close-event." }, "getter": false, "setter": false, "defaultValue": "{\n escapeKey: true,\n scrimClick: true,\n }" } }; } static get events() { return [{ "method": "close", "name": "close", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when the dialog is closed from inside the component.\n(*Not* emitted when the consumer sets the `open`-property to `false`.)" }, "complexType": { "original": "void", "resolved": "void", "references": {} } }, { "method": "closing", "name": "closing", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when the dialog is in the process of being closed." }, "complexType": { "original": "void", "resolved": "void", "references": {} } }]; } static get elementRef() { return "host"; } static get watchers() { return [{ "propName": "open", "methodName": "watchHandler" }, { "propName": "closingActions", "methodName": "closingActionsChanged" }]; } }