@xiangfa/mindmap 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +534 -0
  2. package/README.zh-CN.md +534 -0
  3. package/dist/MindMap.d.ts +3 -0
  4. package/dist/components/MindMapContextMenu.d.ts +20 -0
  5. package/dist/components/MindMapControls.d.ts +16 -0
  6. package/dist/components/MindMapNode.d.ts +32 -0
  7. package/dist/components/icons.d.ts +8 -0
  8. package/dist/esm/MindMap2.js +713 -0
  9. package/dist/esm/components/MindMapContextMenu.js +123 -0
  10. package/dist/esm/components/MindMapControls.js +114 -0
  11. package/dist/esm/components/MindMapNode.js +588 -0
  12. package/dist/esm/components/icons.js +45 -0
  13. package/dist/esm/hooks/useDrag.js +346 -0
  14. package/dist/esm/hooks/useNewNodeAnimation.js +20 -0
  15. package/dist/esm/hooks/useNodeEdit.js +57 -0
  16. package/dist/esm/hooks/usePanZoom.js +85 -0
  17. package/dist/esm/hooks/useTheme.js +16 -0
  18. package/dist/esm/index.js +14 -0
  19. package/dist/esm/logo.svg +9 -0
  20. package/dist/esm/plugins/cross-link.js +65 -0
  21. package/dist/esm/plugins/dotted-line.js +23 -0
  22. package/dist/esm/plugins/folding.js +20 -0
  23. package/dist/esm/plugins/front-matter.js +19 -0
  24. package/dist/esm/plugins/index.js +19 -0
  25. package/dist/esm/plugins/latex.js +132 -0
  26. package/dist/esm/plugins/multi-line.js +39 -0
  27. package/dist/esm/plugins/runner.js +128 -0
  28. package/dist/esm/plugins/tags.js +55 -0
  29. package/dist/esm/style.css +2 -0
  30. package/dist/esm/utils/export.js +50 -0
  31. package/dist/esm/utils/i18n.js +61 -0
  32. package/dist/esm/utils/inline-markdown.js +189 -0
  33. package/dist/esm/utils/layout.js +208 -0
  34. package/dist/esm/utils/markdown.js +288 -0
  35. package/dist/esm/utils/theme.js +119 -0
  36. package/dist/esm/utils/tree-ops.js +136 -0
  37. package/dist/hooks/useDrag.d.ts +40 -0
  38. package/dist/hooks/useNewNodeAnimation.d.ts +2 -0
  39. package/dist/hooks/useNodeEdit.d.ts +17 -0
  40. package/dist/hooks/usePanZoom.d.ts +26 -0
  41. package/dist/hooks/useTheme.d.ts +3 -0
  42. package/dist/index.d.ts +16 -0
  43. package/dist/logo.svg +9 -0
  44. package/dist/mindmap.umd.cjs +24 -0
  45. package/dist/plugins/cross-link.d.ts +2 -0
  46. package/dist/plugins/dotted-line.d.ts +2 -0
  47. package/dist/plugins/folding.d.ts +2 -0
  48. package/dist/plugins/front-matter.d.ts +2 -0
  49. package/dist/plugins/index.d.ts +11 -0
  50. package/dist/plugins/latex.d.ts +20 -0
  51. package/dist/plugins/multi-line.d.ts +2 -0
  52. package/dist/plugins/runner.d.ts +30 -0
  53. package/dist/plugins/tags.d.ts +2 -0
  54. package/dist/plugins/types.d.ts +78 -0
  55. package/dist/style.css +2 -0
  56. package/dist/types.d.ts +105 -0
  57. package/dist/utils/export.d.ts +18 -0
  58. package/dist/utils/i18n.d.ts +22 -0
  59. package/dist/utils/inline-markdown.d.ts +66 -0
  60. package/dist/utils/layout.d.ts +14 -0
  61. package/dist/utils/markdown.d.ts +20 -0
  62. package/dist/utils/theme.d.ts +62 -0
  63. package/dist/utils/tree-ops.d.ts +36 -0
  64. package/package.json +65 -0
@@ -0,0 +1,19 @@
1
+ import { latexPlugin as e } from "./latex.js";
2
+ import { frontMatterPlugin as t } from "./front-matter.js";
3
+ import { dottedLinePlugin as n } from "./dotted-line.js";
4
+ import { foldingPlugin as r } from "./folding.js";
5
+ import { multiLinePlugin as i } from "./multi-line.js";
6
+ import { tagsPlugin as a } from "./tags.js";
7
+ import { crossLinkPlugin as o } from "./cross-link.js";
8
+ //#region src/components/MindMap/plugins/index.ts
9
+ var s = [
10
+ t,
11
+ n,
12
+ r,
13
+ i,
14
+ a,
15
+ o,
16
+ e
17
+ ];
18
+ //#endregion
19
+ export { s as allPlugins };
@@ -0,0 +1,132 @@
1
+ import { computeTokenLayouts as e, parseInlineMarkdown as t } from "../utils/inline-markdown.js";
2
+ import { jsx as n } from "react/jsx-runtime";
3
+ //#region src/components/MindMap/plugins/latex.tsx
4
+ var r = "'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace", i = null, a = !1, o = null, s = [];
5
+ function c() {
6
+ return o || (o = import("katex").then((e) => {
7
+ i = e.default || e, a = !0, d();
8
+ for (let e of s) e();
9
+ s = [];
10
+ }).catch(() => {
11
+ a = !0;
12
+ }), o);
13
+ }
14
+ function l() {
15
+ return i;
16
+ }
17
+ function u(e) {
18
+ a ? e() : s.push(e);
19
+ }
20
+ c();
21
+ function d() {
22
+ if (!(typeof document > "u") && !document.getElementById("katex-style")) {
23
+ let e = document.createElement("link");
24
+ e.id = "katex-style", e.rel = "stylesheet", e.href = "https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css", document.head.appendChild(e);
25
+ }
26
+ }
27
+ function f(e, t) {
28
+ let n = l();
29
+ if (!n) return null;
30
+ try {
31
+ return n.renderToString(e, {
32
+ throwOnError: !1,
33
+ displayMode: t
34
+ });
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+ function p(e, t) {
40
+ let n = l();
41
+ if (!n) return null;
42
+ try {
43
+ return n.renderToString(e, {
44
+ throwOnError: !1,
45
+ displayMode: t,
46
+ output: "mathml"
47
+ });
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+ var m = {
53
+ name: "latex",
54
+ inlineTokenPattern() {
55
+ return {
56
+ pattern: "\\$\\$(.+?)\\$\\$|\\$([^$]+?)\\$",
57
+ priority: 3
58
+ };
59
+ },
60
+ createInlineToken(e, t) {
61
+ let n = e[t + 1], r = e[t + 2];
62
+ return n === void 0 ? r === void 0 ? null : {
63
+ type: "latex-inline",
64
+ content: r
65
+ } : {
66
+ type: "latex-block",
67
+ content: n
68
+ };
69
+ },
70
+ renderInlineToken(e, t) {
71
+ let { token: i } = e;
72
+ return i.type !== "latex-inline" && i.type !== "latex-block" ? null : l() ? /* @__PURE__ */ n("tspan", {
73
+ opacity: 0,
74
+ children: i.content
75
+ }, t) : /* @__PURE__ */ n("tspan", {
76
+ fontFamily: r,
77
+ fontStyle: "italic",
78
+ fontSize: "0.9em",
79
+ children: i.content
80
+ }, t);
81
+ },
82
+ exportInlineToken(e, t) {
83
+ let { token: n } = e;
84
+ if (n.type !== "latex-inline" && n.type !== "latex-block") return "";
85
+ let i = n.content.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
86
+ return t ? `<tspan font-family="${r}" font-style="italic" font-size="0.9em">${i}</tspan>` : l() ? `<tspan opacity="0">${i}</tspan>` : `<tspan font-family="${r}" font-style="italic" font-size="0.9em">${i}</tspan>`;
87
+ },
88
+ exportNodeDecoration(n, r, i, a) {
89
+ if (a || !l()) return "";
90
+ let o = [], s = (r, a, s, c, l, u) => {
91
+ let d = e(t(r, i), a, s, c), f = d.length > 0 ? d[d.length - 1].x + d[d.length - 1].width : 0, m = a * .85, h = n.taskStatus ? 4 : 0, g = n.taskStatus ? m + h : 0, _ = a * .7, v = n.remark ? 4 : 0, y = n.remark ? _ + v : 0, b = -(g + f + y) / 2 + g;
92
+ for (let e of d) {
93
+ let { token: t } = e;
94
+ if (t.type !== "latex-inline" && t.type !== "latex-block") continue;
95
+ let n = p(t.content, t.type === "latex-block");
96
+ if (!n) continue;
97
+ let r = n.match(/<math[\s\S]*<\/math>/);
98
+ if (!r) continue;
99
+ let i = b + e.x + e.width / 2, s = Math.max(e.width * 2.5, 120), c = a * 2;
100
+ o.push(`<foreignObject x="${i - s / 2}" y="${u - c / 2}" width="${s}" height="${c}" style="overflow:visible"><div xmlns="http://www.w3.org/1999/xhtml" style="font-size:${a * .75}px;line-height:${c}px;color:${l};white-space:nowrap;text-align:center">` + r[0] + "</div></foreignObject>");
101
+ }
102
+ }, c = (n, r, a, s, c, l) => {
103
+ let u = e(t(n, i), r, a, s), d = -(u.length > 0 ? u[u.length - 1].x + u[u.length - 1].width : 0) / 2;
104
+ for (let e of u) {
105
+ let { token: t } = e;
106
+ if (t.type !== "latex-inline" && t.type !== "latex-block") continue;
107
+ let n = p(t.content, t.type === "latex-block");
108
+ if (!n) continue;
109
+ let i = n.match(/<math[\s\S]*<\/math>/);
110
+ if (!i) continue;
111
+ let a = d + e.x + e.width / 2, s = Math.max(e.width * 2.5, 120), u = r * 2;
112
+ o.push(`<foreignObject x="${a - s / 2}" y="${l - u / 2}" width="${s}" height="${u}" style="overflow:visible"><div xmlns="http://www.w3.org/1999/xhtml" style="font-size:${r * .75}px;line-height:${u}px;color:${c};white-space:nowrap;text-align:center;opacity:0.8">` + i[0] + "</div></foreignObject>");
113
+ }
114
+ }, u = n.depth === 0 ? r.root.fontSize : n.depth === 1 ? r.level1.fontSize : r.node.fontSize, d = n.depth === 0 ? r.root.fontWeight : n.depth === 1 ? r.level1.fontWeight : r.node.fontWeight, f = n.depth === 0 ? r.root.fontFamily : r.node.fontFamily, m = n.depth === 0 ? r.root.textColor : r.node.textColor;
115
+ if (s(n.text, u, d, f, m, 0), n.multiLineContent && n.multiLineContent.length > 0) {
116
+ let e = u * .85, t = u * 1.4, r = u / 2 + 8;
117
+ for (let i = 0; i < n.multiLineContent.length; i++) {
118
+ let a = r + i * t;
119
+ c(n.multiLineContent[i], e, 400, f, m, a);
120
+ }
121
+ }
122
+ return o.join("");
123
+ },
124
+ adjustNodeSize(e, t, n) {
125
+ return {
126
+ width: t,
127
+ height: n
128
+ };
129
+ }
130
+ };
131
+ //#endregion
132
+ export { l as getKatexSync, m as latexPlugin, d as loadKatexStyle, u as onKatexReady, f as renderLatexToHtml };
@@ -0,0 +1,39 @@
1
+ import { buildSvgTextLineString as e } from "../utils/inline-markdown.js";
2
+ //#region src/components/MindMap/plugins/multi-line.ts
3
+ var t = {
4
+ name: "multi-line",
5
+ collectFollowLines(e, t, n) {
6
+ let r = 0, i = [], a = t;
7
+ for (; a < e.length;) {
8
+ let t = e[a].match(/^(\s*)\|\s?(.*)$/);
9
+ if (t) i.push(t[2]), r++, a++;
10
+ else break;
11
+ }
12
+ return i.length > 0 && (n.multiLineContent = i), r;
13
+ },
14
+ serializeFollowLines(e, t) {
15
+ return !e.multiLineContent || e.multiLineContent.length === 0 ? [] : e.multiLineContent.map((e) => `| ${e}`);
16
+ },
17
+ adjustNodeSize(e, t, n, r) {
18
+ if (!e.multiLineContent || e.multiLineContent.length === 0) return {
19
+ width: t,
20
+ height: n
21
+ };
22
+ let i = r * 1.4;
23
+ return {
24
+ width: t,
25
+ height: n + e.multiLineContent.length * i
26
+ };
27
+ },
28
+ exportNodeDecoration(t, n, r) {
29
+ if (!t.multiLineContent || t.multiLineContent.length === 0) return "";
30
+ let i = t.depth === 0 ? n.root.fontSize : t.depth === 1 ? n.level1.fontSize : n.node.fontSize, a = t.depth === 0 ? n.root.fontFamily : n.node.fontFamily, o = t.depth === 0 ? n.root.textColor : n.node.textColor, s = i * .85, c = i * 1.4, l = i / 2 + 8, u = [];
31
+ for (let i = 0; i < t.multiLineContent.length; i++) {
32
+ let d = l + i * c;
33
+ u.push(e(t.multiLineContent[i], s, 400, a, o, d, r, n.highlight.textColor, n.highlight.bgColor, .8));
34
+ }
35
+ return u.join("");
36
+ }
37
+ };
38
+ //#endregion
39
+ export { t as multiLinePlugin };
@@ -0,0 +1,128 @@
1
+ //#region src/components/MindMap/plugins/runner.ts
2
+ function e(e, t, n) {
3
+ for (let r of e) r.preParseMarkdown && (t = r.preParseMarkdown(t, n));
4
+ return t;
5
+ }
6
+ function t(e, t, n, r) {
7
+ for (let i of e) if (i.parseLine) {
8
+ let e = i.parseLine(t, n, r);
9
+ if (e) return e;
10
+ }
11
+ return null;
12
+ }
13
+ function n(e, t, n, r, i) {
14
+ let a = 0;
15
+ for (let o of e) if (o.collectFollowLines) {
16
+ let e = o.collectFollowLines(t, n + a, r, i);
17
+ a += e;
18
+ }
19
+ return a;
20
+ }
21
+ function r(e, t, n, r) {
22
+ for (let i of e) i.transformNodeData && (t = i.transformNodeData(t, n, r));
23
+ return t;
24
+ }
25
+ function i(e, t, n) {
26
+ for (let r of e) r.postParseTree && (t = r.postParseTree(t, n));
27
+ return t;
28
+ }
29
+ function a(e, t) {
30
+ let n = "";
31
+ for (let r of e) if (r.serializePreamble) {
32
+ let e = r.serializePreamble(t);
33
+ e && (n += e);
34
+ }
35
+ return n;
36
+ }
37
+ function o(e, t, n) {
38
+ let r = n;
39
+ for (let n of e) if (n.serializeListMarker) {
40
+ let e = n.serializeListMarker(t, r);
41
+ if (e !== r) {
42
+ r = e;
43
+ break;
44
+ }
45
+ }
46
+ return r;
47
+ }
48
+ function s(e, t, n) {
49
+ for (let r of e) r.serializeNodeText && (n = r.serializeNodeText(t, n));
50
+ return n;
51
+ }
52
+ function c(e, t, n) {
53
+ let r = [];
54
+ for (let i of e) if (i.serializeFollowLines) {
55
+ let e = i.serializeFollowLines(t, n);
56
+ e && r.push(...e);
57
+ }
58
+ return r;
59
+ }
60
+ function l(e, t, n, r, i) {
61
+ for (let a of e) if (a.adjustNodeSize) {
62
+ let e = a.adjustNodeSize(t, n, r, i);
63
+ n = e.width, r = e.height;
64
+ }
65
+ return {
66
+ width: n,
67
+ height: r
68
+ };
69
+ }
70
+ function u(e, t, n, r) {
71
+ for (let i of e) i.filterChildren && (n = i.filterChildren(t, n, r));
72
+ return n;
73
+ }
74
+ function d(e, t, n, r) {
75
+ for (let i of e) i.transformEdge && (t = i.transformEdge(t, n, r));
76
+ return t;
77
+ }
78
+ function f(e, t, n, r) {
79
+ let i = [];
80
+ for (let a of e) a.generateExtraEdges && i.push(...a.generateExtraEdges(t, n, r));
81
+ return i;
82
+ }
83
+ function p(e, t, n, r) {
84
+ let i = {};
85
+ for (let a of e) if (a.transformNodeColor) {
86
+ let e = a.transformNodeColor(t, n, r);
87
+ i = {
88
+ ...i,
89
+ ...e
90
+ };
91
+ }
92
+ return i;
93
+ }
94
+ function m(e, t, n) {
95
+ let r = [];
96
+ for (let i of e) if (i.renderNodeDecoration) {
97
+ let e = i.renderNodeDecoration(t, n);
98
+ e && r.push(e);
99
+ }
100
+ return r;
101
+ }
102
+ function h(e, t, n) {
103
+ for (let r of e) if (r.renderInlineToken) {
104
+ let e = r.renderInlineToken(t, n);
105
+ if (e) return e;
106
+ }
107
+ return null;
108
+ }
109
+ function g(e, t, n, r) {
110
+ let i = [];
111
+ for (let a of e) if (a.renderOverlay) {
112
+ let e = a.renderOverlay(t, n, r);
113
+ e && i.push(e);
114
+ }
115
+ return i;
116
+ }
117
+ function _(e, t, n, r, i) {
118
+ let a = "";
119
+ for (let o of e) o.exportNodeDecoration && (a += o.exportNodeDecoration(t, n, r, i));
120
+ return a;
121
+ }
122
+ function v(e, t, n, r) {
123
+ let i = "";
124
+ for (let a of e) a.exportOverlay && (i += a.exportOverlay(t, n, r));
125
+ return i;
126
+ }
127
+ //#endregion
128
+ export { l as runAdjustNodeSize, n as runCollectFollowLines, _ as runExportNodeDecoration, v as runExportOverlay, u as runFilterChildren, f as runGenerateExtraEdges, t as runParseLine, i as runPostParseTree, e as runPreParseMarkdown, h as runRenderInlineToken, m as runRenderNodeDecoration, g as runRenderOverlay, c as runSerializeFollowLines, o as runSerializeListMarker, s as runSerializeNodeText, a as runSerializePreamble, d as runTransformEdge, p as runTransformNodeColor, r as runTransformNodeData };
@@ -0,0 +1,55 @@
1
+ import { escapeXml as e } from "../utils/inline-markdown.js";
2
+ //#region src/components/MindMap/plugins/tags.ts
3
+ var t = /((?:\s+#[\w-]+)+)$/, n = [
4
+ "#3B82F6",
5
+ "#8B5CF6",
6
+ "#EC4899",
7
+ "#F59E0B",
8
+ "#10B981",
9
+ "#6366F1"
10
+ ], r = {
11
+ name: "tags",
12
+ transformNodeData(e, n) {
13
+ let r = e.text.match(t);
14
+ if (!r) return e;
15
+ let i = r[1], a = e.text.slice(0, e.text.length - i.length).trim(), o = [], s = /#([\w-]+)/g, c;
16
+ for (; (c = s.exec(i)) !== null;) o.push(c[1]);
17
+ return o.length > 0 ? {
18
+ ...e,
19
+ text: a,
20
+ tags: o
21
+ } : e;
22
+ },
23
+ serializeNodeText(e, t) {
24
+ return !e.tags || e.tags.length === 0 ? t : t + " " + e.tags.map((e) => "#" + e).join(" ");
25
+ },
26
+ adjustNodeSize(e, t, n, r) {
27
+ if (!e.tags || e.tags.length === 0) return {
28
+ width: t,
29
+ height: n
30
+ };
31
+ let i = r * .65, a = 0;
32
+ for (let t of e.tags) a += t.length * i * .65 + 10 + 4;
33
+ return {
34
+ width: Math.max(t, a + 16),
35
+ height: n + (i + 10)
36
+ };
37
+ },
38
+ exportNodeDecoration(t, r) {
39
+ if (!t.tags || t.tags.length === 0) return "";
40
+ let i = t.depth === 0 ? r.root.fontSize : t.depth === 1 ? r.level1.fontSize : r.node.fontSize, a = t.depth === 0 ? r.root.fontFamily : r.node.fontFamily, o = i * .65, s = i * 1.4, c = t.multiLineContent ? t.multiLineContent.length * s : 0, l = i / 2 + 6 + c, u = o + 6, d = 0, f = [];
41
+ for (let e of t.tags) {
42
+ let t = e.length * o * .65 + 10;
43
+ f.push(t), d += t;
44
+ }
45
+ d += (t.tags.length - 1) * 4;
46
+ let p = -d / 2, m = [];
47
+ for (let r = 0; r < t.tags.length; r++) {
48
+ let i = t.tags[r], s = f[r], c = n[r % n.length];
49
+ m.push(`<rect x="${p}" y="${l}" width="${s}" height="${u}" rx="3" fill="${c}" opacity="0.15"/>`), m.push(`<text x="${p + s / 2}" y="${l + u / 2}" text-anchor="middle" dominant-baseline="central" font-size="${o}" fill="${c}" font-family="${a}">${e(i)}</text>`), p += s + 4;
50
+ }
51
+ return m.join("");
52
+ }
53
+ };
54
+ //#endregion
55
+ export { r as tagsPlugin };
@@ -0,0 +1,2 @@
1
+ .mindmap-container{width:100%;height:100%;position:relative;overflow:hidden}.mindmap-svg{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none;width:100%;height:100%;display:block}.mindmap-svg:focus{outline:none}.mindmap-svg.dragging-canvas,.mindmap-svg.dragging-node{cursor:grabbing}.mindmap-node-animated{transition:transform .3s ease-out}.mindmap-edge-animated{transition:d .3s ease-out}@keyframes mindmap-node-appear{0%{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}}.mindmap-node-new{animation:.3s ease-out mindmap-node-appear}@keyframes mindmap-expand-appear{0%{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}.mindmap-node-expanding{animation:.3s ease-out both mindmap-expand-appear}@keyframes mindmap-edge-draw{0%{stroke-dashoffset:300px}to{stroke-dashoffset:0}}.mindmap-edge-expanding{stroke-dasharray:300;animation:.3s ease-out both mindmap-edge-draw}.mindmap-edit-input{text-align:center;box-sizing:border-box;background:0 0;border:none;outline:none;width:100%;height:100%;margin:0;padding:0}.mindmap-edit-root{color:#fff;background:0 0}.mindmap-edit-child{color:inherit;background:0 0;border-radius:4px}.mindmap-zoom-controls{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:8px;align-items:center;gap:2px;padding:4px;display:flex;position:absolute;bottom:16px;left:16px;box-shadow:0 2px 8px #0000001a}.mindmap-ctrl-btn{cursor:pointer;width:32px;height:32px;color:inherit;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;transition:background .15s,color .15s;display:flex}.mindmap-ctrl-btn:hover{background:#80808033}.mindmap-ctrl-pct{cursor:pointer;min-width:48px;height:32px;color:inherit;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;font-family:system-ui,sans-serif;font-size:13px;font-weight:500;transition:background .15s;display:flex}.mindmap-ctrl-pct:hover{background:#80808033}.mindmap-extra-controls{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:20;border-radius:8px;align-items:center;gap:2px;padding:4px;display:flex;position:absolute;bottom:16px;right:16px;box-shadow:0 2px 8px #0000001a}.mindmap-text-editor{resize:none;box-sizing:border-box;z-index:10;border:none;outline:none;width:100%;height:100%;padding:24px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:15px;line-height:1.7;position:absolute;inset:0}.mindmap-add-btn{opacity:0;cursor:pointer;transition:opacity .2s}.mindmap-node-g:hover .mindmap-add-btn{opacity:1}.mindmap-context-menu{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:1000;border:1px solid;border-radius:8px;min-width:150px;padding:4px 0;font-family:system-ui,-apple-system,sans-serif;position:absolute}.mindmap-ctx-item{cursor:pointer;white-space:nowrap;justify-content:space-between;align-items:center;padding:8px 16px;font-size:14px;display:flex;position:relative}.mindmap-ctx-item:hover{filter:brightness(.92);background:#8080801a}.mindmap-ctx-arrow{opacity:.5;margin-left:12px;font-size:8px}.mindmap-ctx-divider{opacity:.3;border-top:1px solid;height:0;margin:4px 8px}.mindmap-ctx-submenu{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid;border-radius:8px;min-width:140px;padding:4px 0;position:absolute;top:-4px;left:100%}.mindmap-ctx-has-sub{position:relative}.mindmap-dialog-backdrop{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:2000;background:#0003;justify-content:center;align-items:center;font-family:system-ui,-apple-system,sans-serif;animation:.15s ease-out mindmap-fade-in;display:flex;position:absolute;inset:0}@keyframes mindmap-fade-in{0%{opacity:0}to{opacity:1}}.mindmap-dialog-modal{border:1px solid;border-radius:12px;width:calc(100% - 32px);max-width:480px;max-height:80%;padding:24px;animation:.2s ease-out mindmap-dialog-enter;position:relative;overflow-y:auto;box-shadow:0 8px 32px #0003}@keyframes mindmap-dialog-enter{0%{opacity:0;transform:scale(.95)translateY(8px)}to{opacity:1;transform:scale(1)translateY(0)}}.mindmap-dialog-header{justify-content:space-between;align-items:center;margin-bottom:16px;display:flex}.mindmap-dialog-title{margin:0;font-size:16px;font-weight:600}.mindmap-dialog-close{cursor:pointer;width:28px;height:28px;color:inherit;opacity:.5;background:0 0;border:none;border-radius:6px;flex-shrink:0;justify-content:center;align-items:center;transition:opacity .15s,background .15s;display:flex}.mindmap-dialog-close:hover{opacity:1;background:#80808033}@media (width<=500px){.mindmap-dialog-modal{max-height:90%;padding:16px}}@media (width<=768px){.mindmap-ctrl-btn{width:28px;height:28px}.mindmap-ctrl-btn svg{width:14px;height:14px}.mindmap-ctrl-pct{min-width:40px;height:28px;font-size:12px}.mindmap-zoom-controls,.mindmap-extra-controls{gap:1px;padding:3px;bottom:12px}.mindmap-zoom-controls{left:12px}.mindmap-extra-controls{right:12px}}.mindmap-node-content{white-space:nowrap;box-sizing:border-box;justify-content:center;align-items:center;gap:4px;line-height:1;display:flex;overflow:hidden}.mindmap-node-root-content{line-height:1}.mindmap-node-content strong{font-weight:700}.mindmap-node-content em{font-style:italic}.mindmap-node-content del{opacity:.6;text-decoration:line-through}.mindmap-node-content .mindmap-inline-code{background:#8080801f;border-radius:3px;padding:1px 4px;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:.88em}.mindmap-node-content .mindmap-highlight{color:#fac800;background:#fcd34d33;border-radius:2px;padding:1px 2px}.mindmap-node-content .mindmap-link{color:#2563eb;cursor:pointer;text-decoration:none}.mindmap-node-content .mindmap-link:hover{text-decoration:underline}.mindmap-node-content .mindmap-inline-image{vertical-align:middle;border-radius:2px;max-width:80px;max-height:1.2em}.mindmap-node-root-content .mindmap-inline-code{background:#ffffff26}.mindmap-node-root-content .mindmap-highlight{color:#fcd34d;background:#fbbf2433}.mindmap-node-root-content .mindmap-link{color:#93c5fd}.mindmap-task-icon{vertical-align:middle;flex-shrink:0}.mindmap-remark-indicator{opacity:.5;cursor:help;flex-shrink:0;font-size:.7em;line-height:1;transition:opacity .15s}.mindmap-remark-indicator:hover{opacity:1}.mindmap-remark-tooltip{white-space:pre-wrap;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:1000;pointer-events:none;border-radius:8px;max-width:280px;padding:8px 12px;font-family:system-ui,-apple-system,sans-serif;font-size:13px;line-height:1.5;animation:.15s ease-out mindmap-fade-in;position:absolute;box-shadow:0 4px 16px #00000026}
2
+ /*$vite$:1*/
@@ -0,0 +1,50 @@
1
+ import { THEME as e } from "./theme.js";
2
+ import { buildSvgNodeTextString as t } from "./inline-markdown.js";
3
+ import { runExportNodeDecoration as n, runExportOverlay as r } from "../plugins/runner.js";
4
+ //#region src/components/MindMap/utils/export.ts
5
+ function i(i, a, o = {}, s = e, c) {
6
+ let { padding: l = 40, background: u = s.canvas.bgColor, pngSafe: d = !1 } = o, f = Infinity, p = -Infinity, m = Infinity, h = -Infinity;
7
+ for (let e of i) f = Math.min(f, e.x - e.width / 2), p = Math.max(p, e.x + e.width / 2), m = Math.min(m, e.y - e.height / 2), h = Math.max(h, e.y + e.height / 2);
8
+ let g = p - f + l * 2, _ = h - m + l * 2, v = -f + l, y = -m + l, b = [];
9
+ b.push(`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${g}" height="${_}" viewBox="0 0 ${g} ${_}">`), a.some((e) => e.isCrossLink) && (b.push("<defs>"), b.push("<marker id=\"arrowhead\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\">"), b.push("<path d=\"M0,0 L8,3 L0,6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/>"), b.push("</marker>"), b.push("</defs>")), b.push(`<rect width="100%" height="100%" fill="${u}"/>`), b.push(`<g transform="translate(${v}, ${y})">`);
10
+ for (let e of a) {
11
+ let t = `d="${e.path}" stroke="${e.color}" stroke-width="${s.connection.strokeWidth}" stroke-linecap="round" fill="none"`;
12
+ if (e.strokeDasharray && (t += ` stroke-dasharray="${e.strokeDasharray}"`), e.isCrossLink && (t += " marker-end=\"url(#arrowhead)\" opacity=\"0.7\""), b.push(`<path ${t}/>`), e.label) {
13
+ let t = i.find((t) => t.id === e.fromId), n = i.find((t) => t.id === e.toId);
14
+ if (t && n) {
15
+ let r = (t.x + n.x) / 2, i = (t.y + n.y) / 2;
16
+ b.push(`<text x="${r}" y="${i - 6}" text-anchor="middle" font-size="11" fill="${e.color}" opacity="0.8" font-family="${s.node.fontFamily}">${e.label}</text>`);
17
+ }
18
+ }
19
+ }
20
+ for (let e of i) {
21
+ let r = e.x, i = e.y;
22
+ if (e.depth === 0) {
23
+ let { fontSize: a, fontWeight: o, fontFamily: l, textColor: u } = s.root, f = s.root.bgColor;
24
+ b.push(`<g transform="translate(${r}, ${i})">`), b.push(`<rect x="${-e.width / 2}" y="${-e.height / 2}" width="${e.width}" height="${e.height}" rx="${e.height / 2}" ry="${e.height / 2}" fill="${f}"/>`), b.push(t(e.text, a, o, l, u, e.taskStatus, e.remark, c, s.highlight.textColor, s.highlight.bgColor, d)), c && c.length > 0 && b.push(n(c, e, s, c, d)), b.push("</g>");
25
+ } else {
26
+ let a = e.depth === 1 ? s.level1.fontSize : s.node.fontSize, o = e.depth === 1 ? s.level1.fontWeight : s.node.fontWeight, l = e.width - s.node.paddingH * 2, u = a / 2 + 4;
27
+ b.push(`<g transform="translate(${r}, ${i})">`), b.push(t(e.text, a, o, s.node.fontFamily, s.node.textColor, e.taskStatus, e.remark, c, s.highlight.textColor, s.highlight.bgColor, d)), b.push(`<line x1="${-l / 2}" y1="${u}" x2="${l / 2}" y2="${u}" stroke="${e.color}" stroke-width="2.5" stroke-linecap="round"/>`), c && c.length > 0 && b.push(n(c, e, s, c, d)), b.push("</g>");
28
+ }
29
+ }
30
+ return c && c.length > 0 && b.push(r(c, i, a, s)), b.push("</g>"), b.push("</svg>"), b.join("\n");
31
+ }
32
+ var a = i;
33
+ function o(e, t = {}) {
34
+ let n = typeof window < "u" ? Math.max(window.devicePixelRatio ?? 1, 2) : 2, { scale: r = n } = t;
35
+ return new Promise((t, n) => {
36
+ let i = new DOMParser().parseFromString(e, "image/svg+xml").documentElement, a = parseFloat(i.getAttribute("width") || "800"), o = parseFloat(i.getAttribute("height") || "600"), s = new Blob([e], { type: "image/svg+xml;charset=utf-8" }), c = URL.createObjectURL(s), l = new Image();
37
+ l.onload = () => {
38
+ let e = document.createElement("canvas");
39
+ e.width = a * r, e.height = o * r;
40
+ let i = e.getContext("2d");
41
+ i.scale(r, r), i.drawImage(l, 0, 0, a, o), URL.revokeObjectURL(c), e.toBlob((e) => {
42
+ e ? t(e) : n(/* @__PURE__ */ Error("Failed to create PNG blob"));
43
+ }, "image/png");
44
+ }, l.onerror = () => {
45
+ URL.revokeObjectURL(c), n(/* @__PURE__ */ Error("Failed to load SVG image"));
46
+ }, l.src = c;
47
+ });
48
+ }
49
+ //#endregion
50
+ export { i as buildExportSVG, a as buildExportSVGForPNG, o as exportToPNG };
@@ -0,0 +1,61 @@
1
+ //#region src/components/MindMap/utils/i18n.ts
2
+ var e = {
3
+ newNode: "新节点",
4
+ zoomIn: "放大",
5
+ zoomOut: "缩小",
6
+ resetView: "重置视图",
7
+ layoutLeft: "向左排版",
8
+ layoutBoth: "左右排版",
9
+ layoutRight: "向右排版",
10
+ textMode: "文本模式",
11
+ viewMode: "视图模式",
12
+ fullscreen: "全屏",
13
+ exitFullscreen: "退出全屏",
14
+ newRootNode: "新建主节点",
15
+ export: "导出",
16
+ exportSVG: "导出为 SVG",
17
+ exportPNG: "导出为 PNG",
18
+ exportMarkdown: "导出为 Markdown",
19
+ layout: "布局",
20
+ close: "关闭"
21
+ }, t = {
22
+ newNode: "New Node",
23
+ zoomIn: "Zoom In",
24
+ zoomOut: "Zoom Out",
25
+ resetView: "Reset View",
26
+ layoutLeft: "Left Layout",
27
+ layoutBoth: "Both Layout",
28
+ layoutRight: "Right Layout",
29
+ textMode: "Text Mode",
30
+ viewMode: "View Mode",
31
+ fullscreen: "Fullscreen",
32
+ exitFullscreen: "Exit Fullscreen",
33
+ newRootNode: "New Root Node",
34
+ export: "Export",
35
+ exportSVG: "Export as SVG",
36
+ exportPNG: "Export as PNG",
37
+ exportMarkdown: "Export as Markdown",
38
+ layout: "Layout",
39
+ close: "Close"
40
+ }, n = {
41
+ "zh-CN": e,
42
+ "en-US": t
43
+ };
44
+ function r() {
45
+ if (typeof navigator > "u") return "en-US";
46
+ let e = navigator.language || "";
47
+ if (n[e]) return e;
48
+ if (e.startsWith("zh")) return "zh-CN";
49
+ let t = e.split("-")[0];
50
+ for (let e of Object.keys(n)) if (e.startsWith(t)) return e;
51
+ return "en-US";
52
+ }
53
+ function i(t = "zh-CN", r) {
54
+ let i = n[t] ?? e;
55
+ return r ? {
56
+ ...i,
57
+ ...r
58
+ } : i;
59
+ }
60
+ //#endregion
61
+ export { r as detectLocale, i as resolveMessages };