UNPKG

@web-atoms/core

Version:
630 lines (629 loc) • 23.7 kB
System.register(["tslib", "../../core/AtomDisposableList", "../../core/InheritedProperty", "../../core/types", "../../core/XNode", "../controls/AtomControl", "./PopupService.global.css", "./PopupWindow"], function (_export, _context) { "use strict"; var __awaiter, __rest, AtomDisposableList, getOwnInheritedProperty, CancelToken, XNode, AtomControl, PopupWindowA, ConfirmPopup, PopupControl, PopupService, PopupWindow, popupCss, disableContain, popupId, lastTarget; function findHostAndPosition(opener) { let root = opener; const body = document.body; let rect = opener.getBoundingClientRect(); const offset = { x: rect.left, y: rect.top, handler: null, root }; do { root = root.parentElement; if (root === body) { break; } if (root.parentElement.classList.contains("page-host")) { break; } if (root.classList.contains("popup-host")) { break; } if (root.getAttribute("data-pop-up-host") === "yes") { break; } } while (true); rect = root.getBoundingClientRect(); offset.x -= rect.x; offset.y -= rect.y; offset.root = root; return offset; } function findHost(opener, offset) { var _a, _b; let host = opener.offsetParent; while (host) { const current = host; if (host === document.body) { return host; } if (host.classList.contains("popup-host")) { return host; } if (host.dataset.popUpHost === "yes") { return host; } const parent = (_a = host.offsetParent) !== null && _a !== void 0 ? _a : host.parentElement; host = parent; if (host.classList.contains("page-host")) { host = current; return host; } if (!host) { continue; } if (!offset) { continue; } offset.x += host.offsetLeft; offset.y += host.offsetTop - ((_b = parent === null || parent === void 0 ? void 0 : parent.scrollTop) !== null && _b !== void 0 ? _b : 0); } return host !== null && host !== void 0 ? host : document.body; } function closeHandler(host, opener, container, close) { let handler = null; handler = e => { var _a; if (container === null || container === void 0 ? void 0 : container.element) { const ce = new CustomEvent("outsideClick", { detail: e, cancelable: true, bubbles: true }); container.element.dispatchEvent(ce); if (ce.defaultPrevented) { return; } } let start = e.target; if (e.defaultPrevented) { return; } while (start) { if (start === host) { break; } if (start === opener) { return; } if (start === container.element) { return; } start = start.parentElement; } close(); e.preventDefault(); (_a = e.stopImmediatePropagation) === null || _a === void 0 ? void 0 : _a.call(e); }; document.body.addEventListener("click", handler, true); container.registerDisposable(() => document.body.removeEventListener("click", handler, true)); const onBack = e => { var _a; e.preventDefault(); (_a = e.stopImmediatePropagation) === null || _a === void 0 ? void 0 : _a.call(e); e.stopPropagation(); close(); }; window.addEventListener("backButton", onBack, true); container.registerDisposable(() => window.removeEventListener("backButton", onBack, true)); setTimeout(() => { container.registerDisposable(disableContain(container.element)); }, 10); } _export("PopupControl", void 0); return { setters: [function (_tslib) { __awaiter = _tslib.__awaiter; __rest = _tslib.__rest; }, function (_coreAtomDisposableList) { AtomDisposableList = _coreAtomDisposableList.AtomDisposableList; }, function (_coreInheritedProperty) { getOwnInheritedProperty = _coreInheritedProperty.getOwnInheritedProperty; }, function (_coreTypes) { CancelToken = _coreTypes.CancelToken; }, function (_coreXNode) { XNode = _coreXNode.default; }, function (_controlsAtomControl) { AtomControl = _controlsAtomControl.AtomControl; }, function (_PopupServiceGlobalCss) {}, function (_PopupWindow) { PopupWindowA = _PopupWindow.default; ConfirmPopup = _PopupWindow.ConfirmPopup; }], execute: function () { _export("PopupWindow", PopupWindow = PopupWindowA); document.body.addEventListener("click", e => { if (e.target.offsetParent) { PopupService.lastTarget = e.target; } }); popupCss = "web-atoms-popup-local"; _export("PopupControl", PopupControl = class PopupControl extends AtomControl { static showControl(opener, _a = {}) { var { onClick = "close" } = _a, options = __rest(_a, ["onClick"]); let openerElement = options === null || options === void 0 ? void 0 : options.parentElement; let app; if (opener instanceof AtomControl) { openerElement !== null && openerElement !== void 0 ? openerElement : openerElement = opener.element; app = opener.app; } else { openerElement !== null && openerElement !== void 0 ? openerElement : openerElement = opener; let start = opener; while (!start.atomControl) { start = start.parentElement; } if (!start) { return Promise.reject("Could not create popup as target is not attached"); } app = start.atomControl.app; } const popup = new this(app); if (onClick === "close") { popup.bindEvent(popup.element, "click", () => setTimeout(() => popup.close(), 10)); } else if (onClick === "cancel") { popup.bindEvent(popup.element, "click", () => setTimeout(() => popup.cancel(), 10)); } const p = PopupService.show(openerElement, popup.element, options); return new Promise((resolve, reject) => { let resolved = false; popup.close = r => { if (resolved) { return; } resolved = true; PopupService.lastTarget = openerElement; resolve(r); p.dispose(); }; popup.cancel = e => { if (resolved) { return; } resolved = true; PopupService.lastTarget = openerElement; reject(e); p.dispose(); }; }); } }); _export("disableContain", disableContain = ce => { const containNoneList = []; while (ce) { const style = window.getComputedStyle(ce); const isNotNone = style.contain !== "none"; if (isNotNone) { ce.setAttribute("data-force-contain", "none"); containNoneList.push(ce); } ce = ce.parentElement; } return () => { for (const iterator of containNoneList) { iterator.removeAttribute("data-force-contain"); } }; }); popupId = 1001; lastTarget = { element: null, x: 10, y: 10 }; PopupService = class PopupService { static get lastTarget() { var _a, _b, _c; const { element, x = 0, y = 0 } = lastTarget; if (element === null || element === void 0 ? void 0 : element.isConnected) { return element; } const targets = this.targetPath; if (targets) { for (;;) { const first = targets[0]; if (!first) { break; } if (first.isConnected) { lastTarget = { element: first, x, y }; return first; } targets.splice(0, 1); } } let e = (_b = (_a = document.elementFromPoint) === null || _a === void 0 ? void 0 : _a.call(document, x, y)) !== null && _b !== void 0 ? _b : document.body; if (((_c = this.defaultElementTarget) === null || _c === void 0 ? void 0 : _c.isConnected) && (e === document.documentElement || e === document.body)) { e = this.defaultElementTarget; } PopupService.lastTarget = e; return e; } static set lastTarget(element) { if (!element.isConnected) { return; } if (element === document.documentElement) { return; } let start = element; const targets = [start]; while (start) { start = start.parentElement; if (start) { targets.push(start); } } this.targetPath = targets; if (!this.defaultElementTarget && element !== document.body && element !== document.documentElement) { this.defaultElementTarget = element; } const rect = element.getBoundingClientRect(); lastTarget = { element, x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }; } static alert(_a) { return __awaiter(this, arguments, void 0, function* ({ message, detail, title = "Alert", yesLabel = "Ok" }) { var _b, _c; try { const isMsgXNode = message instanceof XNode; const isDetailXNode = detail && detail instanceof XNode; if (isMsgXNode) { ((_b = message.attributes) !== null && _b !== void 0 ? _b : message.attributes = {})["data-element"] = "message"; } if (isDetailXNode) { ((_c = detail.attributes) !== null && _c !== void 0 ? _c : detail.attributes = {})["data-element"] = "details"; } const popup = class extends ConfirmPopup { create() { this.render(XNode.create("div", null, isMsgXNode ? message : XNode.create("div", { "data-element": "message", text: message }), detail && (isDetailXNode ? detail : XNode.create("details", { "data-element": "details" }, XNode.create("pre", { text: detail }))))); } }; return yield popup.showModal({ parameters: { message, detail, yesLabel, noLabel: "" }, title }); } catch (e) { if (CancelToken.isCancelled(e)) { return false; } throw e; } }); } static confirm(_a) { return __awaiter(this, arguments, void 0, function* ({ message, title = "Confirm", yesLabel = "Yes", noLabel = "No", cancelLabel = null }) { try { const popup = class extends ConfirmPopup { create() { this.render(XNode.create("div", null, message instanceof XNode ? message : XNode.create("div", { text: message }))); } }; return yield popup.showModal({ parameters: { message, yesLabel, noLabel, cancelLabel }, title }); } catch (e) { if (CancelToken.isCancelled(e)) { return false; } throw e; } }); } static showWindow(opener, popupClass, popupOptions) { return new Promise((resolve, reject) => { var _a, _b; var _c; const activeElement = document.activeElement; const previousTarget = opener; const parent = AtomControl.from(opener); const control = new popupClass(parent.app, document.createElement("div")); const vm = (_a = getOwnInheritedProperty(control, "viewModel")) !== null && _a !== void 0 ? _a : "parameters" in control ? (_b = (_c = control).parameters) !== null && _b !== void 0 ? _b : _c.parameters = {} : control; let element = control.element; element.style.zIndex = `${popupId++}`; let resolved = false; const close = r => { setTimeout(() => { if (!resolved) { resolved = true; setTimeout(resolve, 1, r); if (control.element) { control.element.remove(); control.dispose(); } element === null || element === void 0 ? void 0 : element.remove(); element = undefined; PopupService.lastTarget = previousTarget; try { activeElement === null || activeElement === void 0 ? void 0 : activeElement.focus(); } catch (error) { console.error(error); } } }, 1); }; const cancel = r => { setTimeout(() => { if (!resolved) { resolved = true; setTimeout(reject, 1, r !== null && r !== void 0 ? r : "cancelled"); if (control.element) { control.element.remove(); control.dispose(); } element === null || element === void 0 ? void 0 : element.remove(); element = undefined; PopupService.lastTarget = previousTarget; try { activeElement === null || activeElement === void 0 ? void 0 : activeElement.focus(); } catch (error) { console.error(error); } } }, 1); }; let isModal = false; if (popupOptions) { const { width, height, minHeight, maxHeight, minWidth, maxWidth, maximize, title, parameters, cancelToken, modal } = popupOptions; if (title) { vm.title = title; } let widthSet = false; let heightSet = false; if (maximize) { element.setAttribute("data-maximize", "true"); widthSet = heightSet = true; } else { if (width) { element.style.width = typeof width === "number" ? width + "px" : width; widthSet = true; } if (height) { element.style.height = typeof height === "number" ? height + "px" : height; heightSet = true; } if (minWidth) { element.style.minWidth = typeof minWidth === "number" ? minWidth + "px" : minWidth; widthSet = true; } if (minHeight) { element.style.minHeight = typeof minHeight === "number" ? minHeight + "px" : minHeight; heightSet = true; } if (maxWidth) { element.style.maxWidth = typeof maxWidth === "number" ? maxWidth + "px" : maxWidth; widthSet = true; } if (maxHeight) { element.style.maxHeight = typeof maxHeight === "number" ? maxHeight + "px" : maxHeight; heightSet = true; } } if (!widthSet) { element.setAttribute("data-no-width", "true"); } if (!heightSet) { element.setAttribute("data-no-height", "true"); } if (parameters) { for (const key in parameters) { if (Object.prototype.hasOwnProperty.call(parameters, key)) { const e = parameters[key]; vm[key] = e; } } const init = control.init; if (init) { const c = control.init(); if (c === null || c === void 0 ? void 0 : c.then) { c.then(() => control.element.dispatchEvent(new CustomEvent("popupReady", { bubbles: true })), error => { control.element.dispatchEvent(new CustomEvent("popupReady", { bubbles: true })); if (!CancelToken.isCancelled(error)) { console.error(error); } }); } else { setTimeout(() => control.element.dispatchEvent(new CustomEvent("popupReady", { bubbles: true })), 1); } } else { setTimeout(() => control.element.dispatchEvent(new CustomEvent("popupReady", { bubbles: true })), 1); } } else { setTimeout(() => control.element.dispatchEvent(new CustomEvent("popupReady", { bubbles: true })), 1); } cancelToken === null || cancelToken === void 0 ? void 0 : cancelToken.registerForCancel(cancel); isModal = modal; } const host = findHost(opener); host.appendChild(control.element); vm.cancel = cancel; vm.close = close; if (vm !== control) { control.cancel = cancel; control.close = close; } if (isModal) { const bg = document.createElement("div"); bg.setAttribute("data-window-modal-background", "background"); host.appendChild(bg); const onBack = e => { var _a, _b, _c; e.preventDefault(); (_a = e.stopImmediatePropagation) === null || _a === void 0 ? void 0 : _a.call(e); e.stopPropagation(); (_c = (_b = control).requestCancel) === null || _c === void 0 ? void 0 : _c.call(_b); }; window.addEventListener("backButton", onBack, true); control.registerDisposable({ dispose: () => { bg.remove(); window.removeEventListener("backButton", onBack, true); } }); } else { closeHandler(host, opener, control, cancel); } }); } static show(opener, popup, options) { var _a, _b; const previousTarget = opener; const container = { element: document.createElement("div"), disposables: new AtomDisposableList(), registerDisposable: null, dispose: null }; container.registerDisposable = f => container.disposables.add(f); let alignment = (_a = options === null || options === void 0 ? void 0 : options.alignment) !== null && _a !== void 0 ? _a : "auto"; if (alignment === "auto") { const rect = opener.getBoundingClientRect(); const w = window.visualViewport.width; if (rect.left > w / 2) { alignment = "bottomRight"; } } const isCenterOfScreen = alignment === "centerOfScreen"; const popupStyle = (_b = options === null || options === void 0 ? void 0 : options.popupStyle) !== null && _b !== void 0 ? _b : popupCss; container.element._logicalParent = opener; container.element.classList.add(popupStyle); if (isCenterOfScreen) { container.element.dataset.centerPopup = "center"; } else { container.element.dataset.inlinePopup = "left"; const alignPopup = () => { switch (alignment) { case "bottomRight": container.element.style.top = opener.offsetTop + opener.offsetHeight + "px"; container.element.style.right = "0px"; container.element.dataset.inlinePopup = "right"; opener.insertAdjacentElement("afterend", container.element); break; case "topRight": case "right": container.element.style.top = opener.offsetTop + "px"; container.element.style.left = opener.offsetWidth + "px"; opener.insertAdjacentElement("afterend", container.element); break; case "bottomLeft": container.element.dataset.inlinePopup = "inline-left"; container.element.style.top = opener.offsetTop + opener.offsetHeight + "px"; opener.insertAdjacentElement("beforebegin", container.element); break; default: container.element.style.top = opener.offsetTop + opener.offsetHeight + "px"; opener.insertAdjacentElement("afterend", container.element); break; } }; if (opener.offsetParent !== opener.parentElement) { opener.parentElement.style.position = "relative"; setTimeout(alignPopup, 5); } else { alignPopup(); } } const parent = AtomControl.from(opener); if (popup instanceof XNode) { parent.render(popup, container); } else { container.element.appendChild(popup); } const style = container.element.style; style.zIndex = `${popupId++}`; container.dispose = () => { if (!container.disposables) { return; } container.disposables.dispose(); parent.dispose(container.element); container.element.remove(); container.disposables = null; PopupService.lastTarget = previousTarget; }; closeHandler(opener.parentElement, opener, container, () => { const e = container.element; container.dispose(); e.remove(); }); const ct = options === null || options === void 0 ? void 0 : options.cancelToken; if (ct) { ct.registerForCancel(() => container.dispose()); } return container; } }; PopupService.targetPath = []; _export("default", PopupService); } }; }); //# sourceMappingURL=PopupService.js.map