@matechat/core
Version:
前端智能化场景解决方案UI库,轻松构建你的AI应用。
128 lines (127 loc) • 5.33 kB
JavaScript
class h {
constructor(t = {}) {
this.config = t, this.mermaidInstance = null, this.isLoading = !1, this.lastValidResult = "", this.viewStateMap = /* @__PURE__ */ new WeakMap(), this.containerHeight = 400;
}
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, s = "light") {
const a = await this.renderMermaid(e, s);
t.innerHTML = a;
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 s = e.getAttribute("viewBox"), a = 0, i = 0;
if (s) {
const l = s.split(/\s+/);
a = parseFloat(l[2]), i = parseFloat(l[3]);
} else
a = 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;
a && i && o && r && (n = Math.min(o / a, 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 s = this.viewStateMap.get(t);
s && (e.style.position = "absolute", e.style.left = "50%", e.style.top = "50%", e.style.transform = `translate(-50%, -50%) translate(${s.offsetX}px, ${s.offsetY}px) scale(${s.scale})`, e.style.transformOrigin = "center center", e.style.cursor = s.dragging ? "grabbing" : "grab");
}
zoomIn(t) {
const e = t.querySelector("svg"), s = this.viewStateMap.get(t);
e && s && (s.scale = Math.min(s.scale + 0.2, 3), this.applyTransform(t, e));
}
zoomOut(t) {
const e = t.querySelector("svg"), s = this.viewStateMap.get(t);
e && s && (s.scale = Math.max(s.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 s = t.querySelector("svg");
if (s)
try {
const a = s.cloneNode(!0), i = new XMLSerializer().serializeToString(a), o = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(i)}`, r = new Image();
await new Promise((d, m) => {
r.onload = () => d(), r.onerror = (c) => m(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((d) => {
if (!d) {
console.error("Failed to create blob from canvas");
return;
}
const m = URL.createObjectURL(d), c = document.createElement("a");
c.href = m, c.download = e, document.body.appendChild(c), c.click(), setTimeout(() => {
document.body.removeChild(c), URL.revokeObjectURL(m);
}, 100);
}, "image/png");
} catch (a) {
console.error("Failed to download diagram:", a);
}
}
onSvgMouseDown(t, e, s) {
const a = this.viewStateMap.get(e);
if (!a) return;
a.dragging = !0, a.dragStart = { x: t.clientX, y: t.clientY }, a.lastOffset = { x: a.offsetX, y: a.offsetY };
const i = (r) => this.onSvgMouseMove(r, e, s), o = () => this.onSvgMouseUp(e, s, i, o);
document.addEventListener("mousemove", i), document.addEventListener("mouseup", o), this.applyTransform(e, s);
}
onSvgMouseMove(t, e, s) {
const a = this.viewStateMap.get(e);
!a || !a.dragging || (a.offsetX = a.lastOffset.x + (t.clientX - a.dragStart.x), a.offsetY = a.lastOffset.y + (t.clientY - a.dragStart.y), this.applyTransform(e, s));
}
onSvgMouseUp(t, e, s, a) {
const i = this.viewStateMap.get(t);
i && (i.dragging = !1, document.removeEventListener("mousemove", s), document.removeEventListener("mouseup", a), this.applyTransform(t, e));
}
async renderMermaid(t, e = "light") {
try {
const s = await this.loadMermaid();
this.config.theme !== e && (this.config.theme = e, s.initialize({
startOnLoad: !1,
suppressErrorRendering: !0,
theme: e === "dark" ? "dark" : "default",
...this.config
}));
const a = `mc_mermaid_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, { svg: i } = await s.render(a, t);
return this.lastValidResult = i, i;
} catch {
return this.lastValidResult;
}
}
}
export {
h as MermaidService
};