UNPKG

@matechat/core

Version:

前端智能化场景解决方案UI库,轻松构建你的AI应用。

143 lines (142 loc) 5.71 kB
var f = Object.defineProperty; var u = (d, t, e) => t in d ? f(d, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : d[t] = e; var m = (d, t, e) => u(d, typeof t != "symbol" ? t + "" : t, e); class v { constructor(t = {}) { m(this, "mermaidInstance", null); m(this, "isLoading", !1); m(this, "lastValidResult", ""); m(this, "viewStateMap", /* @__PURE__ */ new WeakMap()); m(this, "containerHeight", 400); this.config = t; } async loadMermaid() { if (this.mermaidInstance) return this.mermaidInstance; if (this.isLoading) return new Promise((t) => { const e = () => { this.mermaidInstance ? t(this.mermaidInstance) : setTimeout(e, 50); }; e(); }); this.isLoading = !0; try { const { default: t } = await import("mermaid"); return t.initialize({ theme: this.config.theme || "default", startOnLoad: !1, suppressErrorRendering: !0, ...this.config }), this.mermaidInstance = t, t; } catch (t) { throw console.error("Failed to load mermaid:", t), new Error("Failed to load mermaid library"); } finally { this.isLoading = !1; } } async renderToContainer(t, e, a = "light") { const s = await this.renderMermaid(e, a); t.innerHTML = s; const i = t.querySelector("svg"); i && (this.initViewState(t, i), this.applyTransform(t, i), i.addEventListener("mousedown", (o) => this.onSvgMouseDown(o, t, i))); } initViewState(t, e) { let a = e.getAttribute("viewBox"), s = 0, i = 0; if (a) { const l = a.split(/\s+/); s = parseFloat(l[2]), i = parseFloat(l[3]); } else s = e.width.baseVal.value || e.getBoundingClientRect().width, i = e.height.baseVal.value || e.getBoundingClientRect().height; const o = t.clientWidth || 0, r = this.containerHeight; let n = 1; s && i && o && r && (n = Math.min(o / s, r / i, 1)), this.viewStateMap.set(t, { scale: n, offsetX: 0, offsetY: 0, dragging: !1, dragStart: { x: 0, y: 0 }, lastOffset: { x: 0, y: 0 } }); } applyTransform(t, e) { const a = this.viewStateMap.get(t); a && (e.style.maxWidth = "90%", e.style.maxHeight = "90%", e.style.position = "absolute", e.style.left = "50%", e.style.top = "50%", e.style.transform = `translate(-50%, -50%) translate(${a.offsetX}px, ${a.offsetY}px) scale(${a.scale})`, e.style.transformOrigin = "center center", e.style.cursor = a.dragging ? "grabbing" : "grab"); } zoomIn(t) { const e = t.querySelector("svg"), a = this.viewStateMap.get(t); e && a && (a.scale = Math.min(a.scale + 0.2, 3), this.applyTransform(t, e)); } zoomOut(t) { const e = t.querySelector("svg"), a = this.viewStateMap.get(t); e && a && (a.scale = Math.max(a.scale - 0.2, 0.2), this.applyTransform(t, e)); } reset(t) { const e = t.querySelector("svg"); e && (this.initViewState(t, e), this.applyTransform(t, e)); } async download(t, e = "diagram.png") { const a = t.querySelector("svg"); if (a) try { const s = a.cloneNode(!0), i = new XMLSerializer().serializeToString(s), o = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(i)}`, r = new Image(); await new Promise((g, h) => { r.onload = () => g(), r.onerror = (c) => h(new Error("Image loading failed")), r.src = o; }); const n = document.createElement("canvas"), l = n.getContext("2d"); if (!l) throw new Error("Canvas context not available"); n.width = r.width * 2, n.height = r.height * 2, l.fillStyle = "white", l.fillRect(0, 0, n.width, n.height), l.drawImage(r, 0, 0), n.toBlob((g) => { if (!g) { console.error("Failed to create blob from canvas"); return; } const h = URL.createObjectURL(g), c = document.createElement("a"); c.href = h, c.download = e, document.body.appendChild(c), c.click(), setTimeout(() => { document.body.removeChild(c), URL.revokeObjectURL(h); }, 100); }, "image/png"); } catch (s) { console.error("Failed to download diagram:", s); } } onSvgMouseDown(t, e, a) { const s = this.viewStateMap.get(e); if (!s) return; s.dragging = !0, s.dragStart = { x: t.clientX, y: t.clientY }, s.lastOffset = { x: s.offsetX, y: s.offsetY }; const i = (r) => this.onSvgMouseMove(r, e, a), o = () => this.onSvgMouseUp(e, a, i, o); document.addEventListener("mousemove", i), document.addEventListener("mouseup", o), this.applyTransform(e, a); } onSvgMouseMove(t, e, a) { const s = this.viewStateMap.get(e); !s || !s.dragging || (s.offsetX = s.lastOffset.x + (t.clientX - s.dragStart.x), s.offsetY = s.lastOffset.y + (t.clientY - s.dragStart.y), this.applyTransform(e, a)); } onSvgMouseUp(t, e, a, s) { const i = this.viewStateMap.get(t); i && (i.dragging = !1, document.removeEventListener("mousemove", a), document.removeEventListener("mouseup", s), this.applyTransform(t, e)); } async renderMermaid(t, e = "light") { try { const a = await this.loadMermaid(); this.config.theme !== e && a.initialize({ startOnLoad: !1, suppressErrorRendering: !0, theme: e === "dark" ? "dark" : "default", ...this.config }); const s = `mc_mermaid_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, { svg: i } = await a.render(s, t); return this.lastValidResult = i, i; } catch { return this.lastValidResult; } } // 设置配置 setConfig(t = {}) { this.config = { theme: "default", ...t }; } } export { v as MermaidService };