@limetech/lime-elements
Version:
287 lines (286 loc) • 9.04 kB
JavaScript
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
* @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() {
this.heading = undefined;
this.fullscreen = false;
this.open = false;
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", { 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", { hidden: true, id: "initialFocusEl" }), h("div", { class: "mdc-dialog__container" }, h("div", { class: "mdc-dialog__surface" }, h("input", { type: "button", id: "initialFocusElement" }), this.renderHeading(), h("div", { class: "mdc-dialog__content", id: 'limel-dialog-content-' + this.id }, h("slot", null)), this.renderFooter())), h("div", { 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();
}
isBadgeHeading(heading) {
return typeof heading === 'object' && !!heading.title && !!heading.icon;
}
renderHeading() {
if (this.isBadgeHeading(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 });
}
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"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "The heading for the dialog, if any."
},
"attribute": "heading",
"reflect": false
},
"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\"."
},
"attribute": "fullscreen",
"reflect": true,
"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."
},
"attribute": "open",
"reflect": true,
"defaultValue": "false"
},
"closingActions": {
"type": "unknown",
"mutable": false,
"complexType": {
"original": "ClosingActions",
"resolved": "ClosingActions",
"references": {
"ClosingActions": {
"location": "import",
"path": "./dialog.types"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Defines which action triggers a close-event."
},
"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"
}];
}
}
//# sourceMappingURL=dialog.js.map