UNPKG

vue3-modal-manager

Version:

A flexible and powerful modal manager for Vue 3

820 lines (819 loc) 30.8 kB
var v = Object.defineProperty; var b = (d, t, e) => t in d ? v(d, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : d[t] = e; var l = (d, t, e) => b(d, typeof t != "symbol" ? t + "" : t, e); import { createVNode as E, render as y } from "vue"; class D { //最小高度 /** * 初始化函數 * @param currentModal modal */ constructor(t) { l(this, "currentModal"); //modal l(this, "resizeHandlers", /* @__PURE__ */ new Map()); //儲存個方位拖曳節點 l(this, "resizing", !1); //是否正在改變大小 l(this, "resizeDirection", ""); //當前調整大小的方位 l(this, "initialSize"); //初始大小及位置 l(this, "initialMouse", { x: 0, y: 0 }); //初始滑鼠位置 l(this, "minWidth", 100); //最小寬度 l(this, "minHeight", 100); //==================================拖曳中================================== /** * 拖曳中(正在調整大小) * @param e 滑鼠事件 * @returns */ l(this, "handleResize", (t) => { this.resizing && (t.preventDefault(), requestAnimationFrame(() => { this.performResize(t); })); }); //==================================拖曳結束================================== /** * 拖曳結束(結束調整大小) */ l(this, "stopResize", () => { if (!this.resizing) return; const { container: t, id: e } = this.currentModal; t.classList.remove("modal-resizing"); const i = t.querySelector(`#${e}`); i && this.updateHandlesPosition(i); const n = t.getBoundingClientRect(); this.emitResizeEndEvent(this.currentModal, n.width, n.height), this.resizing = !1, this.resizeDirection = "", document.removeEventListener("mousemove", this.handleResize), document.removeEventListener("mouseup", this.stopResize); }); this.currentModal = t, this.initialSize = this.createEmptyModalSize(), this.createResizeHandles(t.id), this.bindResize(t.id); } //==================================物件初始化================================== /** * 初始預設大小及位置 */ createEmptyModalSize() { return { width: 0, height: 0, left: 0, top: 0, right: 0, bottom: 0, mouseLimits: { limitX: { min: 0, max: 0 }, limitY: { min: 0, max: 0 }, limitXY: { x: { min: 0, max: 0 }, y: { min: 0, max: 0 } } } }; } /** * 創建調整大小的手柄 * @param modalId modal的ID * @returns 是否成功創建 */ createResizeHandles(t) { const e = ["e", "s", "se", "w", "n", "ne", "sw", "nw"], i = this.currentModal.container.querySelector(`#${t}`); return i ? (i.querySelectorAll(".resize-handle").length > 0 || (window.getComputedStyle(i).position === "static" && (i.style.position = "relative"), e.forEach((o) => { const r = document.createElement("div"); r.setAttribute("modalResizeArea", t), r.setAttribute("data-direction", o), r.className = `resize-handle resize-${o}`, Object.assign(r.style, { position: "absolute", background: "transparent", pointerEvents: "auto", zIndex: "1001" }), this.setHandleStyle(r, o), i.appendChild(r); })), !0) : (console.warn(`Modal body element with id ${t} not found`), !1); } /** * 設定調整大小節點 * @param handle 節點dom * @param direction 方位 */ setHandleStyle(t, e) { const n = { e: { top: "0", right: "0", width: "5px", height: "100%", cursor: "e-resize" }, s: { bottom: "0", left: "0", width: "100%", height: "5px", cursor: "s-resize" }, se: { bottom: "0", right: "0", width: "10px", height: "10px", cursor: "se-resize" }, w: { top: "0", left: "0", width: "5px", height: "100%", cursor: "w-resize" }, n: { top: "0", left: "0", width: "100%", height: "5px", cursor: "n-resize" }, ne: { top: "0", right: "0", width: "10px", height: "10px", cursor: "ne-resize" }, sw: { bottom: "0", left: "0", width: "10px", height: "10px", cursor: "sw-resize" }, nw: { top: "0", left: "0", width: "10px", height: "10px", cursor: "nw-resize" } }[e]; n && Object.assign(t.style, n); } /** * 重置modal物件 * @param currentModal 當前Modal */ setCurrentModal(t) { const e = this.currentModal.id; this.unbindResize(e), this.currentModal = t, this.createResizeHandles(t.id), this.bindResize(t.id); } //==================================功能綁定================================== /** * 綁定調整大小事件 * @param modalId modal的ID * @returns 是否成功綁定 */ bindResize(t) { const e = this.currentModal.container.querySelector(`#${t}`); if (!e) return console.warn(`Modal body not found for ${t}`), !1; const i = e.querySelectorAll( `[modalResizeArea="${t}"]` ); return i.length === 0 ? (console.warn(`No resize handles found for modal ${t}`), !1) : (this.resizeHandlers.clear(), i.forEach((n) => { const s = n.dataset.direction || "", o = (a) => this.startResize(a, s), r = `${t}-${s}`; this.resizeHandlers.set(r, o), n.addEventListener("mousedown", o); }), !0); } /** * 解除綁定 * @param modalId modal的ID */ unbindResize(t) { this.resizing && this.forceStopResize(); const e = this.currentModal.container.querySelector(`#${t}`); e && e.querySelectorAll( `[modalResizeArea="${t}"]` ).forEach((n) => { const s = n.dataset.direction || "", o = `${t}-${s}`, r = this.resizeHandlers.get(o); r && (n.removeEventListener("mousedown", r), this.resizeHandlers.delete(o)), n.remove(); }), this.resizeHandlers.clear(); } //==================================開始拖曳================================== /** * 開始拖曳(開始調整大小) * @param e 滑鼠事件 * @param direction 方位 * @returns */ startResize(t, e) { if (this.resizing || t.button !== 0) return; t.preventDefault(), t.stopPropagation(), this.initialMouse = { x: t.clientX, y: t.clientY }; const i = this.calculateInitialPosition(); this.initialSize = { width: i.width, height: i.height, left: i.left, top: i.top, right: i.right, bottom: i.bottom, mouseLimits: i.mouseLimits }, this.resizing = !0, this.resizeDirection = e, document.addEventListener("mousemove", this.handleResize), document.addEventListener("mouseup", this.stopResize), this.currentModal.container.classList.add("modal-resizing"); } /** * 紀錄拖曳初始位置 */ calculateInitialPosition() { const t = this.currentModal.container, e = this.currentModal.boxElement, i = t.getBoundingClientRect(), n = e.getBoundingClientRect(), o = window.getComputedStyle(t).transform; let r, a, u, h; if (o !== "none" && o !== "") { t.style.transform = "none"; const g = i.left + i.width / 2, M = i.top + i.height / 2; r = g - i.width / 2 - n.left, a = M - i.height / 2 - n.top, u = n.width - (r + i.width), h = n.height - (a + i.height), t.style.left = "auto", t.style.top = "auto", t.style.inset = `${a}px ${u}px ${h}px ${r}px`; } else r = i.left - n.left, a = i.top - n.top, u = n.width - (r + i.width), h = n.height - (a + i.height); const c = { limitX: { min: n.left + 5, max: n.width + n.left - 5 }, limitY: { min: n.top + 5, max: n.height + n.top - 5 }, limitXY: { x: { min: n.left + 9, max: n.width + n.left - 9 }, y: { min: n.top + 9, max: n.height + n.top - 9 } } }; return { width: i.width, height: i.height, left: r, top: a, right: u, bottom: h, mouseLimits: c }; } /** * 動態計算modal大小和位置 * @param e 滑鼠事件 */ performResize(t) { const e = t.clientX, i = t.clientY; let n = e - this.initialMouse.x, s = i - this.initialMouse.y; const o = this.calcMouseMoveRange(); "min" in o ? this.resizeDirection === "e" || this.resizeDirection === "w" ? n = Math.max(o.min, Math.min(n, o.max)) : s = Math.max(o.min, Math.min(s, o.max)) : (n = Math.max(o.x.min, Math.min(n, o.x.max)), s = Math.max(o.y.min, Math.min(s, o.y.max))); const r = this.calculateNewSizes(n, s), a = this.currentModal.container.querySelector( `#${this.currentModal.id}` ); a && (a.style.width = `${r.width}px`, a.style.height = `${r.height}px`, this.currentModal.container.style.inset = `${r.top}px ${r.right}px ${r.bottom}px ${r.left}px`, this.updateHandlesPosition(a), this.emitResizeEvent(this.currentModal, r.width, r.height)); } /** * 計算新的尺寸及大小 * @param deltaX x軸位移 * @param deltaY y軸位移 * @returns */ calculateNewSizes(t, e) { let i = this.initialSize.width, n = this.initialSize.height, s = this.initialSize.left, o = this.initialSize.top, r = this.initialSize.right, a = this.initialSize.bottom; switch (this.resizeDirection) { case "e": i = Math.max(this.minWidth, this.initialSize.width + t), r = this.initialSize.right - (i - this.initialSize.width); break; case "w": i = Math.max(this.minWidth, this.initialSize.width - t), s = this.initialSize.left + (this.initialSize.width - i); break; case "s": n = Math.max(this.minHeight, this.initialSize.height + e), a = this.initialSize.bottom - (n - this.initialSize.height); break; case "n": n = Math.max(this.minHeight, this.initialSize.height - e), o = this.initialSize.top + (this.initialSize.height - n); break; case "se": i = Math.max(this.minWidth, this.initialSize.width + t), n = Math.max(this.minHeight, this.initialSize.height + e), r = this.initialSize.right - (i - this.initialSize.width), a = this.initialSize.bottom - (n - this.initialSize.height); break; case "sw": i = Math.max(this.minWidth, this.initialSize.width - t), n = Math.max(this.minHeight, this.initialSize.height + e), s = this.initialSize.left + (this.initialSize.width - i), a = this.initialSize.bottom - (n - this.initialSize.height); break; case "ne": i = Math.max(this.minWidth, this.initialSize.width + t), n = Math.max(this.minHeight, this.initialSize.height - e), r = this.initialSize.right - (i - this.initialSize.width), o = this.initialSize.top + (this.initialSize.height - n); break; case "nw": i = Math.max(this.minWidth, this.initialSize.width - t), n = Math.max(this.minHeight, this.initialSize.height - e), s = this.initialSize.left + (this.initialSize.width - i), o = this.initialSize.top + (this.initialSize.height - n); break; } return { width: i, height: n, left: s, top: o, right: r, bottom: a }; } /** * 計算各方位滑鼠移動限制 * @returns */ calcMouseMoveRange() { switch (this.resizeDirection) { case "e": return { min: this.minWidth - this.initialSize.width, max: this.initialSize.mouseLimits.limitX.max - this.initialMouse.x }; case "w": return { min: this.initialSize.mouseLimits.limitX.min - this.initialMouse.x, max: -(this.minWidth - this.initialSize.width) }; case "s": return { min: this.minHeight - this.initialSize.height, max: this.initialSize.mouseLimits.limitY.max - this.initialMouse.y }; case "n": return { min: this.initialSize.mouseLimits.limitY.min - this.initialMouse.y, max: -(this.minHeight - this.initialSize.height) }; case "se": case "sw": case "ne": case "nw": const t = { x: { min: 0, max: 0 }, y: { min: 0, max: 0 } }; return this.resizeDirection.includes("e") ? (t.x.min = this.minWidth - this.initialSize.width, t.x.max = this.initialSize.mouseLimits.limitXY.x.max - this.initialMouse.x) : (t.x.min = this.initialSize.mouseLimits.limitXY.x.min - this.initialMouse.x, t.x.max = -(this.minWidth - this.initialSize.width)), this.resizeDirection.includes("s") ? (t.y.min = this.minHeight - this.initialSize.height, t.y.max = this.initialSize.mouseLimits.limitXY.y.max - this.initialMouse.y) : (t.y.min = this.initialSize.mouseLimits.limitXY.y.min - this.initialMouse.y, t.y.max = -(this.minHeight - this.initialSize.height)), t; default: return { min: 0, max: 0 }; } } /** * 更新節點(handles)位置 * @param modalBody modal元素 */ updateHandlesPosition(t) { t.querySelectorAll(".resize-handle").forEach((i) => { const n = i.dataset.direction; n && this.setHandleStyle(i, n); }); } /** * 強制結束拖曳 */ forceStopResize() { this.resizing = !1, this.resizeDirection = "", this.currentModal.container.classList.remove("modal-resizing"), document.removeEventListener("mousemove", this.handleResize), document.removeEventListener("mouseup", this.stopResize); } //==================================發送事件================================== /** * 發送正在調整大小事件 * @param modal modal資訊 * @param width 寬度 * @param height 高度 */ emitResizeEvent(t, e, i) { const n = new CustomEvent("modal-resize", { detail: { modalId: t.id, width: e, height: i } }); t.container.dispatchEvent(n); } /** * 發送調整大小結束事件 * @param modal modal資訊 * @param width 寬度 * @param height 高度 */ emitResizeEndEvent(t, e, i) { const n = new CustomEvent("modal-resize-end", { detail: { modalId: t.id, width: e, height: i } }); t.container.dispatchEvent(n); } //==================================銷毀物件================================== /** * 銷毀物件 */ destroy() { this.unbindResize(this.currentModal.id), this.forceStopResize(); } } class L { //是否正在拖曳 /** * 初始化函數 * @param currentModal modal */ constructor(t) { l(this, "currentModal"); //modal l(this, "modalHeader", null); //modal header元素 l(this, "handleDrag", null); //拖曳事件方法 l(this, "initPosition"); //初始位置 l(this, "isDragging", !1); //==================================開始拖曳================================== /** * 開始拖曳 * @param e 滑鼠事件 * @param modalId modal Id * @returns */ l(this, "startDrag", (t) => { if (this.isDragging || t.button !== 0) return; this.isDragging = !0; const { container: e } = this.currentModal, i = e.getBoundingClientRect(); this.initPosition = { initialMouseX: t.clientX, initialMouseY: t.clientY, initialModalX: i.left, initialModalY: i.top }, document.addEventListener("mousemove", this.calcMouseDisplacement), document.addEventListener("mouseup", this.stopDrag), t.preventDefault(), t.stopPropagation(), e.classList.add("modal-dragging"); }); //==================================拖曳中================================== /** * 計算拖曳modal元件的位移 * @param e 滑鼠事件 * @returns */ l(this, "calcMouseDisplacement", (t) => { if (!this.isDragging) return; const { container: e, boxElement: i } = this.currentModal, { initialMouseX: n, initialMouseY: s, initialModalX: o, initialModalY: r } = this.initPosition, a = t.clientX - n, u = t.clientY - s; let h = o + a, m = r + u; const c = i.getBoundingClientRect(), g = e.getBoundingClientRect(), M = c.left, p = c.right - g.width, w = c.top, S = c.bottom - g.height; h = Math.max(M, Math.min(h, p)), m = Math.max(w, Math.min(m, S)); const z = h - c.left, x = m - c.top; e.style.left = `${z}px`, e.style.top = `${x}px`, e.style.transform = "none", this.emitDragEvent(z, x); }); //==================================拖曳結束================================== /** * 停止拖曳 */ l(this, "stopDrag", () => { if (!this.isDragging) return; const { container: t } = this.currentModal; this.isDragging = !1, document.removeEventListener("mousemove", this.calcMouseDisplacement), document.removeEventListener("mouseup", this.stopDrag), t.classList.remove("modal-dragging"); const e = t.getBoundingClientRect(), i = this.currentModal.boxElement.getBoundingClientRect(), n = e.left - i.left, s = e.top - i.top; this.emitDragEndEvent(n, s); }); this.currentModal = t, this.initPosition = {}, this.bindDrag(); } //==================================物件初始化================================== /** * 設置當前modal * @param currentModal modal */ setCurrentModal(t) { this.currentModal = t, this.modalHeader && (this.unbindDrag(), this.bindDrag()); } //==================================功能綁定================================== /** * 綁定拖曳功能 * modal元件需在拖曳處加上modalDraggableArea='modalId' * @returns */ bindDrag() { const { id: t, container: e } = this.currentModal; return this.modalHeader = e.querySelector(`[modalDraggableArea="${t}"]`), this.modalHeader ? (this.modalHeader.style.cursor = "move", this.handleDrag || (this.handleDrag = (i) => this.startDrag(i)), this.modalHeader.addEventListener("mousedown", this.handleDrag), !0) : (console.warn(`Modal drag area not found for modal: ${t}`), !1); } /** * 解除拖曳功能 * @returns */ unbindDrag() { this.modalHeader && (this.modalHeader.style.cursor = "", this.handleDrag && this.modalHeader.removeEventListener("mousedown", this.handleDrag), this.isDragging && this.forceStopDrag()); } /** * 強制停止拖曳 */ forceStopDrag() { this.isDragging = !1, document.removeEventListener("mousemove", this.calcMouseDisplacement), document.removeEventListener("mouseup", this.stopDrag); } //==================================發送事件================================== /** * 發送拖拽事件 * @param x 當前X坐標 * @param y 當前Y坐標 */ emitDragEvent(t, e) { const i = new CustomEvent("modal-drag", { detail: { modalId: this.currentModal.id, x: t, y: e } }); this.currentModal.container.dispatchEvent(i); } /** * 發送拖拽結束事件 * @param x 最終X坐標 * @param y 最終Y坐標 */ emitDragEndEvent(t, e) { const i = new CustomEvent("modal-drag-end", { detail: { modalId: this.currentModal.id, x: t, y: e } }); this.currentModal.container.dispatchEvent(i); } //==================================銷毀物件================================== /** * 銷毀物件 */ destroy() { this.unbindDrag(), this.forceStopDrag(); } } class f { //z-index 預設值 /** * 初始化函數 * @param options modal router */ constructor(t) { //ModalManager物件 l(this, "appContext"); //vue生成資訊 l(this, "modalRoutes"); //modal rotes l(this, "ModalList"); //modal 管理列表 l(this, "baseZIndex", 1e3); this.modalRoutes = t, this.ModalList = /* @__PURE__ */ new Map(), this.appContext = null; } install(t) { t.config.globalProperties.$modalManager = this, t.provide("modalManager", this); const e = t.mount; t.mount = (...i) => { const n = e.call(t, ...i); return setTimeout(() => { t._container && t._container._vnode ? this.appContext = t._container._vnode.appContext : console.warn("Modal Manager: Unable to get appContext"); }, 0), n; }; } //==========================================創建modal外層元素=================================================== /** * 建立modal ID * @param name modal元件名稱 * @returns modal ID */ generateId(t) { const e = Date.now(), i = Math.floor(Math.random() * 1e3); return `${t}-${e}-${i}`; } /** * 建立modal div(固定)元素 * @param modalId modal ID * @param direction 方位 * @returns HTMLDivElement */ createDivByFixed(t, e = "center") { const i = document.createElement("div"); return i.setAttribute("data-modalId", t), i.style.position = "fixed", i.style.zIndex = "1000", i.style.width = "100%", i.style.height = "100%", i.style.display = "flex", i.style.backgroundColor = "rgba(0, 0, 0, 0.6)", this.applyFixedModalStyles(i, e), i; } /** * modal div(固定)樣式 */ applyFixedModalStyles(t, e) { const n = { center: { top: "50%", left: "50%", transform: "translate(-50%, -50%)", alignItems: "center", justifyContent: "center" }, top: { top: "0", left: "0", alignItems: "flex-start", justifyContent: "center" }, bottom: { top: "0", left: "0", alignItems: "flex-end", justifyContent: "center" }, left: { top: "0", left: "0", alignItems: "center", justifyContent: "flex-start" }, right: { top: "0", left: "0", alignItems: "center", justifyContent: "flex-end" } }[e]; n && Object.assign(t.style, n); } /** * 建立modal div(拖拽)元素 */ createDivByDraggable(t, e) { const i = document.createElement("div"); return i.setAttribute("data-modalId", t), i.style.position = "absolute", i.style.zIndex = `${this.baseZIndex + this.ModalList.size}`, i.style.width = "max-content", i.style.height = "max-content", e ? this.applyCustomPosition(i, e) : this.applyCenterPosition(i), i; } /** * modal div(拖拽)樣式-自訂義position */ applyCustomPosition(t, e) { t.style.top = e.top ?? "auto", t.style.bottom = e.bottom ?? "auto", t.style.left = e.left ?? "auto", t.style.right = e.right ?? "auto", t.style.transform = ""; } /** * modal div(拖拽)樣式-置中 */ applyCenterPosition(t) { const e = window.scrollX + window.innerWidth / 2, i = window.scrollY + window.innerHeight / 2; t.style.left = `${e}px`, t.style.top = `${i}px`, t.style.transform = "translate(-50%, -50%)"; } async openModal(t, e, i) { try { if (e === "fixed") { const n = i; return await this.createFixedModal(t, n); } else if (e === "draggable") { const n = i; return await this.createDraggableModal(t, n); } else throw new Error(`Unsupported modal mode: ${e}`); } catch (n) { return console.error(`Failed to load modal ${t}:`, n), { success: !1, msg: "Failed to load modal", modalId: "" }; } } /** * 建立modal(固定) * @param name modal route名稱 * @param params 配置參數 * @returns */ async createFixedModal(t, e) { const i = this.modalRoutes.find((n) => n.name === t); if (!i) return console.error(`Modal ${t} not found`), { success: !1, msg: "not found Modal", modalId: "" }; try { const n = this.generateId(t), s = this.createDivByFixed(n, (e == null ? void 0 : e.direction) || "center"); if (!this.mountContainer(s, e == null ? void 0 : e.id)) return { success: !1, msg: "Failed to mount container", modalId: "" }; const r = e != null && e.id ? document.getElementById(e.id) : null; return this.ModalList.set(n, { id: n, container: s, name: t, boxElement: r || document.body }), await this.renderComponent(i, n, e) ? { success: !0, msg: "success", modalId: n } : (this.cleanupFailedModal(n), { success: !1, msg: "Failed to render component", modalId: "" }); } catch (n) { return console.error(`Failed to load modal ${t}:`, n), { success: !1, msg: "Failed to load modal", modalId: "" }; } } /** * 建立modal(拖曳) * @param name modal route名稱 * @param params 配置參數 * @returns */ async createDraggableModal(t, e) { const i = this.modalRoutes.find((n) => n.name === t); if (!i) return console.error(`Modal ${t} not found`), { success: !1, msg: "not found Modal", modalId: "" }; try { const n = this.generateId(t), s = this.createDivByDraggable(n, e == null ? void 0 : e.position); if (s.addEventListener("click", () => this.bringToFront(n)), !this.mountContainer(s, e == null ? void 0 : e.id, e == null ? void 0 : e.position)) return { success: !1, msg: "Failed to mount container", modalId: "" }; const r = e != null && e.id ? document.getElementById(e.id) : null; return this.ModalList.set(n, { id: n, container: s, name: t, boxElement: r || document.body }), await this.renderComponent(i, n, e) ? (await this.setupDraggableModalFeatures(n, e), { success: !0, msg: "success", modalId: n }) : (this.cleanupFailedModal(n), { success: !1, msg: "Failed to render component", modalId: "" }); } catch (n) { return console.error(`Failed to load modal ${t}:`, n), { success: !1, msg: "Failed to load modal", modalId: "" }; } } /** * 掛載容器至指定元素位置 */ mountContainer(t, e, i) { try { const n = e ? document.getElementById(e) : null; return n ? (n.style.position = "relative", n.appendChild(t)) : document.body.appendChild(t), i ? this.applyCustomPosition(t, i) : (t.style.top = "50%", t.style.left = "50%", t.style.transform = "translate(-50%, -50%)"), !0; } catch (n) { return console.error("Failed to mount container:", n), !1; } } /** * 渲染组件 */ async renderComponent(t, e, i) { try { const n = await t.component(), s = this.extractComponent(n); if (!s) throw new Error("Failed to extract component from module"); const o = this.buildEventProps(e, i), r = this.ModalList.get(e); if (!r) return !1; const a = E(s, o); return this.appContext && (a.appContext = this.appContext), y(a, r.container), !0; } catch (n) { return console.error("Failed to load and render component:", n), !1; } } /** * 提取組件 */ extractComponent(t) { return t != null && t.default ? t.default : this.isValidComponent(t) ? t : null; } /** * 检查是否為有效组件 */ isValidComponent(t) { return typeof t == "function" || t && typeof t == "object" && (t.render || t.template || t.setup); } /** * 添加props參數 emit事件 */ buildEventProps(t, e) { const i = { ...e == null ? void 0 : e.props, modalId: t, onClosed: () => this.closeModal(t) }; return e != null && e.events && Object.entries(e.events).forEach(([n, s]) => { const o = `on${n.charAt(0).toUpperCase() + n.slice(1)}`; i[o] = s; }), i; } /** * 設置modal(拖曳)可選功能 */ async setupDraggableModalFeatures(t, e) { const i = this.ModalList.get(t); if (!(!i || !e)) try { e.drag && (i.drag = new L(i)), e.resize && (i.resize = new D(i)); } catch (n) { console.error(`Failed to setup draggable features for modal ${t}:`, n); } } /** * 清除建置失败的modal */ cleanupFailedModal(t) { var i, n, s, o; const e = this.ModalList.get(t); e && (e.container.parentNode && e.container.parentNode.removeChild(e.container), e.drag && ((n = (i = e.drag).destroy) == null || n.call(i)), e.resize && ((o = (s = e.resize).destroy) == null || o.call(s)), this.ModalList.delete(t)); } //==========================================關閉modal=================================================== /** * 關閉modal * @param modalId modal Id * @returns 返回结果 */ closeModal(t) { var i, n, s, o; const e = this.ModalList.get(t); if (!e) return console.warn(`Modal ${t} not found`), !1; try { return e.drag && ((n = (i = e.drag).destroy) == null || n.call(i)), e.resize && ((o = (s = e.resize).destroy) == null || o.call(s)), y(null, e.container), e.container.parentNode && e.container.parentNode.removeChild(e.container), e.boxElement.querySelectorAll("div[data-modalId]").length === 0 && (e.boxElement.style.position = ""), this.ModalList.delete(t), !0; } catch (r) { return console.error(`Failed to close modal ${t}:`, r), !1; } } /** * 關閉所有modal * @returns 返回關閉数量 */ removeAllModal() { const t = [...this.ModalList.values()]; let e = 0; return t.forEach((i) => { this.closeModal(i.id) && e++; }), console.log(`%c 移除了 ${e} 個modal`, "color: green; font-size: 14px"), e; } //==========================================modal位置=================================================== /** * 移動視窗至指定容器 * @param modalId * @param target * @returns 返回結果 */ moveToLayers(t, e) { const i = this.ModalList.get(t); if (!i) return console.warn(`Modal ${t} not found`), !1; const n = document.getElementById(e); if (!n) return console.warn(`Target container ${e} not found`), !1; try { return i.boxElement.style.position = "", n.style.position = "relative", n.appendChild(i.container), this.applyCenterPosition(i.container), i.boxElement = n, i.resize && i.resize.setCurrentModal(i), i.drag && i.drag.setCurrentModal(i), !0; } catch (s) { return console.error(`Failed to move modal ${t} to ${e}:`, s), !1; } } /** * 計算modal元件階層 * @param modalId modal Id * @returns 返回結果 */ bringToFront(t) { const e = this.ModalList.get(t); if (!e) return !1; const i = parseInt(e.container.style.zIndex), n = this.baseZIndex + this.ModalList.size; return i >= n ? !1 : (this.ModalList.forEach((s) => { const o = parseInt(s.container.style.zIndex); s.id === t ? s.container.style.zIndex = `${n}` : o > i && (s.container.style.zIndex = `${o - 1}`); }), !0); } //==========================================工具方法=================================================== /** * 已開啟的modal狀態列表 */ getOpenModals() { return Array.from(this.ModalList.values()); } /** * 檢查modal是否存在 */ hasModal(t) { return this.ModalList.has(t); } /** * 已開啟modal數量 */ getModalCount() { return this.ModalList.size; } } l(f, "modalManager"); const R = (d) => { const t = new f(d); return f.modalManager = t, t; }, H = () => { const d = f.modalManager; if (!d) throw new Error("Modal Manager not initialized. Call createModalManager first."); return d; }; export { R as createModalManager, H as useModalManager };