@visualli/core 0.1.7 → 0.2.1
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.
- package/README.md +37 -105
- package/dist/chunk-25AJTPMS.js +68 -0
- package/dist/chunk-25AJTPMS.js.map +1 -0
- package/dist/chunk-64PUANNH.js +151 -0
- package/dist/chunk-64PUANNH.js.map +1 -0
- package/dist/chunk-ITDZ72JE.js +96 -0
- package/dist/chunk-ITDZ72JE.js.map +1 -0
- package/dist/{chunk-PDP5CVUL.js → chunk-LOQLNYB3.js} +2 -2
- package/dist/chunk-N7HCYULH.js +12 -0
- package/dist/chunk-N7HCYULH.js.map +1 -0
- package/dist/{chunk-I75TMOE4.js → chunk-P6PKWVYF.js} +2 -2
- package/dist/chunk-RFMUATWB.js +753 -0
- package/dist/chunk-RFMUATWB.js.map +1 -0
- package/dist/chunk-UAMEJG2C.js +267 -0
- package/dist/chunk-UAMEJG2C.js.map +1 -0
- package/dist/{chunk-LJYSKSCE.js → chunk-W2CAOOJJ.js} +6 -6
- package/dist/chunk-W2CAOOJJ.js.map +1 -0
- package/dist/{chunk-6NXADJK2.js → chunk-WO4JAAKP.js} +84 -117
- package/dist/chunk-WO4JAAKP.js.map +1 -0
- package/dist/config/index.cjs +250 -349
- package/dist/config/index.cjs.map +1 -1
- package/dist/config/index.d.cts +107 -66
- package/dist/config/index.d.ts +107 -66
- package/dist/config/index.js +52 -34
- package/dist/constants/index.cjs +14 -333
- package/dist/constants/index.cjs.map +1 -1
- package/dist/constants/index.d.cts +5 -243
- package/dist/constants/index.d.ts +5 -243
- package/dist/constants/index.js +5 -75
- package/dist/designSystem-D49xVfr8.d.cts +150 -0
- package/dist/designSystem-D49xVfr8.d.ts +150 -0
- package/dist/document-BFBwn93X.d.ts +26 -0
- package/dist/document-MEJEfxl3.d.cts +26 -0
- package/dist/ideaSize-BTJu6thN.d.cts +11 -0
- package/dist/ideaSize-RKbms8K6.d.ts +11 -0
- package/dist/index-CcF0Jvmb.d.ts +99 -0
- package/dist/index-Dt--T2l8.d.cts +99 -0
- package/dist/index.cjs +1636 -961
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +350 -27
- package/dist/index.d.ts +350 -27
- package/dist/index.js +434 -179
- package/dist/index.js.map +1 -1
- package/dist/{document-B3hnNr-F.d.cts → layer-B2A3Ki48.d.cts} +2 -16
- package/dist/{document-B3hnNr-F.d.ts → layer-B2A3Ki48.d.ts} +2 -16
- package/dist/layout/index.d.cts +2 -1
- package/dist/layout/index.d.ts +2 -1
- package/dist/mindmap-BO3YD5qu.d.cts +182 -0
- package/dist/mindmap-D0Of0jaZ.d.ts +182 -0
- package/dist/parser/index.cjs +745 -179
- package/dist/parser/index.cjs.map +1 -1
- package/dist/parser/index.d.cts +23 -8
- package/dist/parser/index.d.ts +23 -8
- package/dist/parser/index.js +7 -2
- package/dist/performance/index.cjs +13 -0
- package/dist/performance/index.cjs.map +1 -1
- package/dist/performance/index.js +2 -2
- package/dist/theme/index.cjs +884 -0
- package/dist/theme/index.cjs.map +1 -0
- package/dist/theme/index.d.cts +2 -0
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.js +53 -0
- package/dist/types/index.d.cts +4 -2
- package/dist/types/index.d.ts +4 -2
- package/dist/viewport/index.cjs +17 -6
- package/dist/viewport/index.cjs.map +1 -1
- package/dist/viewport/index.d.cts +6 -4
- package/dist/viewport/index.d.ts +6 -4
- package/dist/viewport/index.js +2 -2
- package/licenses/visualli-design-system/LICENSE +9 -0
- package/licenses/visualli-design-system/NOTICE.md +6 -0
- package/package.json +12 -4
- package/src/config/README.md +2 -4
- package/src/config/USAGE_EXAMPLES.md +0 -4
- package/src/config/index.ts +3 -4
- package/src/constants/index.ts +1 -1
- package/src/constants/layout.ts +11 -0
- package/src/constants/performanceConstants.ts +8 -27
- package/src/generated/README.md +12 -0
- package/src/generated/designSystem.ts +758 -0
- package/src/generated/geometry/blob.ts +99 -0
- package/src/generated/geometry/blobShapes.ts +4 -0
- package/src/generated/geometry/color.ts +37 -0
- package/src/generated/geometry/container.ts +84 -0
- package/src/generated/geometry/detail.ts +22 -0
- package/src/generated/geometry/idea.ts +56 -0
- package/src/generated/geometry/interaction.ts +122 -0
- package/src/generated/geometry/motion.ts +140 -0
- package/src/index.ts +18 -1
- package/src/parser/configUtils.ts +12 -19
- package/src/parser/visualliConverter.ts +71 -112
- package/src/parser/visualliParser.ts +16 -1
- package/src/rendering/culling.ts +16 -12
- package/src/rendering/ideaSize.ts +21 -0
- package/src/rendering/nodeGeometry.ts +97 -0
- package/src/theme/index.ts +136 -0
- package/src/types/document.ts +9 -0
- package/src/types/layer.ts +1 -1
- package/src/types/mindmap.ts +13 -0
- package/src/utils/navigation.ts +33 -63
- package/src/viewport/viewportUtils.ts +6 -4
- package/dist/animations/index.cjs +0 -146
- package/dist/animations/index.cjs.map +0 -1
- package/dist/animations/index.d.cts +0 -81
- package/dist/animations/index.d.ts +0 -81
- package/dist/animations/index.js +0 -35
- package/dist/chunk-6NXADJK2.js.map +0 -1
- package/dist/chunk-F36SMC3K.js +0 -106
- package/dist/chunk-F36SMC3K.js.map +0 -1
- package/dist/chunk-G5H3P4YZ.js +0 -273
- package/dist/chunk-G5H3P4YZ.js.map +0 -1
- package/dist/chunk-LDJRGT2Q.js +0 -163
- package/dist/chunk-LDJRGT2Q.js.map +0 -1
- package/dist/chunk-LJYSKSCE.js.map +0 -1
- package/dist/chunk-LNTJTDB2.js +0 -349
- package/dist/chunk-LNTJTDB2.js.map +0 -1
- package/dist/mindmap-DWS0WZT_.d.cts +0 -118
- package/dist/mindmap-DWS0WZT_.d.ts +0 -118
- package/src/animations/constants.ts +0 -72
- package/src/animations/easing.ts +0 -70
- package/src/animations/index.ts +0 -2
- package/src/config/blobShapes.ts +0 -146
- package/src/config/textScaling.ts +0 -54
- package/src/constants/design.ts +0 -281
- /package/dist/{chunk-PDP5CVUL.js.map → chunk-LOQLNYB3.js.map} +0 -0
- /package/dist/{chunk-I75TMOE4.js.map → chunk-P6PKWVYF.js.map} +0 -0
- /package/dist/{animations → theme}/index.js.map +0 -0
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "./chunk-
|
|
2
|
+
approximateMeasure,
|
|
3
|
+
ideaKindOf,
|
|
4
|
+
ideaSize
|
|
5
|
+
} from "./chunk-25AJTPMS.js";
|
|
6
|
+
import {
|
|
7
|
+
LAYOUT_SPACING
|
|
8
|
+
} from "./chunk-N7HCYULH.js";
|
|
6
9
|
import {
|
|
7
10
|
applyCircularLayout,
|
|
8
11
|
applyLinearHorizontalLayout,
|
|
9
12
|
applyLinearVerticalLayout,
|
|
10
13
|
calculateOptimalRadiusPercentage
|
|
11
14
|
} from "./chunk-GQMFBYLK.js";
|
|
15
|
+
import {
|
|
16
|
+
ideaColor
|
|
17
|
+
} from "./chunk-ITDZ72JE.js";
|
|
18
|
+
import {
|
|
19
|
+
TOKENS,
|
|
20
|
+
TOPICS
|
|
21
|
+
} from "./chunk-RFMUATWB.js";
|
|
12
22
|
|
|
13
23
|
// src/parser/visualliParser.ts
|
|
14
24
|
function toVisualliLayer(schemaLayer) {
|
|
@@ -75,6 +85,13 @@ function parseVisualliFile(content) {
|
|
|
75
85
|
}
|
|
76
86
|
break;
|
|
77
87
|
}
|
|
88
|
+
case "extension": {
|
|
89
|
+
const id = obj["id"];
|
|
90
|
+
if (typeof id === "string") {
|
|
91
|
+
(doc.extensions ?? (doc.extensions = {}))[id] = Array.isArray(obj["data"]) ? obj["data"] : [];
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
78
95
|
default:
|
|
79
96
|
break;
|
|
80
97
|
}
|
|
@@ -112,6 +129,11 @@ function loadVisualliFileFromFile(file) {
|
|
|
112
129
|
reader.readAsText(file);
|
|
113
130
|
});
|
|
114
131
|
}
|
|
132
|
+
function getSemanticAnchors(doc) {
|
|
133
|
+
const raw = doc.extensions?.["semantic-anchors"];
|
|
134
|
+
if (!Array.isArray(raw)) return [];
|
|
135
|
+
return raw.filter((a) => !!a && typeof a.word === "string" && typeof a.description === "string");
|
|
136
|
+
}
|
|
115
137
|
function getChildLayers(doc, nodeId) {
|
|
116
138
|
const result = [];
|
|
117
139
|
for (const layer of doc.layers.values()) {
|
|
@@ -169,26 +191,10 @@ function resolveNodeOverlaps(nodes, maxIterations = 10) {
|
|
|
169
191
|
if (!any) break;
|
|
170
192
|
}
|
|
171
193
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"#F54A57",
|
|
177
|
-
"#FF6C4D",
|
|
178
|
-
"#F28C16",
|
|
179
|
-
"#FFD347",
|
|
180
|
-
"#12C7D3",
|
|
181
|
-
"#7F7F7F",
|
|
182
|
-
"#8D8D8D",
|
|
183
|
-
"#12C7D3"
|
|
184
|
-
];
|
|
185
|
-
function getRandomColorForNode(nodeId) {
|
|
186
|
-
let hash = 0;
|
|
187
|
-
for (let i = 0; i < nodeId.length; i++) {
|
|
188
|
-
hash = nodeId.charCodeAt(i) + ((hash << 5) - hash);
|
|
189
|
-
}
|
|
190
|
-
const index = Math.abs(hash) % COLOR_PALETTE.length;
|
|
191
|
-
return COLOR_PALETTE[index];
|
|
194
|
+
function hasFilePositions(layer) {
|
|
195
|
+
const ps = layer.nodes.map((n) => n.position);
|
|
196
|
+
if (!ps.length || !ps.every((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))) return false;
|
|
197
|
+
return ps.length === 1 || ps.some((p) => p.x !== ps[0].x || p.y !== ps[0].y);
|
|
192
198
|
}
|
|
193
199
|
function applyFormation(nodes, formation) {
|
|
194
200
|
if (nodes.length === 0) return;
|
|
@@ -252,44 +258,34 @@ function proxyRadial(proxies, radius = 500) {
|
|
|
252
258
|
proxies[i].y = radius * Math.sin(angle);
|
|
253
259
|
}
|
|
254
260
|
}
|
|
255
|
-
function
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
261
|
+
function makeFlatNode(node, layer, doc, siblingIndex, opts) {
|
|
262
|
+
const label = Array.isArray(node.data.label) ? node.data.label.join(" ") : node.data.label || "Untitled";
|
|
263
|
+
const branchCount = countLayersBeneath(doc, node.id);
|
|
264
|
+
const kind = ideaKindOf(layer, siblingIndex);
|
|
265
|
+
const size = ideaSize(kind, label, opts.measure ?? approximateMeasure, opts.labelScale ?? 1);
|
|
266
|
+
const { topic, custom } = ideaColor(node.data.color, siblingIndex);
|
|
259
267
|
return {
|
|
260
|
-
id:
|
|
268
|
+
id: node.id,
|
|
261
269
|
parentId: layer.parentNodeId ?? null,
|
|
262
|
-
x,
|
|
263
|
-
y,
|
|
270
|
+
x: node.position?.x ?? 0,
|
|
271
|
+
y: node.position?.y ?? 0,
|
|
264
272
|
level: layer.level,
|
|
265
273
|
title: label,
|
|
266
|
-
description: summary,
|
|
267
|
-
color,
|
|
268
|
-
|
|
269
|
-
|
|
274
|
+
description: node.data.summary || "",
|
|
275
|
+
color: node.data.color ?? "",
|
|
276
|
+
...topic ? { topic } : {},
|
|
277
|
+
...custom ? { custom } : {},
|
|
278
|
+
kind,
|
|
279
|
+
width: size.width,
|
|
280
|
+
height: size.height,
|
|
270
281
|
isExpanded: branchCount > 0,
|
|
271
282
|
branchCount,
|
|
272
283
|
createdAt: /* @__PURE__ */ new Date(),
|
|
273
284
|
updatedAt: /* @__PURE__ */ new Date()
|
|
274
285
|
};
|
|
275
286
|
}
|
|
276
|
-
function
|
|
287
|
+
function layoutLayerWithContainers(layer, flatNodes) {
|
|
277
288
|
const PADDING = 80;
|
|
278
|
-
const flatNodes = [];
|
|
279
|
-
for (const node of layer.nodes) {
|
|
280
|
-
const label = Array.isArray(node.data.label) ? node.data.label.join(" ") : node.data.label || "Untitled";
|
|
281
|
-
const branchCount = countLayersBeneath(doc, node.id);
|
|
282
|
-
flatNodes.push(
|
|
283
|
-
makeFlatNode(
|
|
284
|
-
node.id,
|
|
285
|
-
label,
|
|
286
|
-
node.data.summary || "",
|
|
287
|
-
layer,
|
|
288
|
-
node.data.color || getRandomColorForNode(node.id),
|
|
289
|
-
branchCount
|
|
290
|
-
)
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
289
|
const byId = new Map(flatNodes.map((n) => [n.id, n]));
|
|
294
290
|
const containerNodeIds = /* @__PURE__ */ new Set();
|
|
295
291
|
const containerGroups = /* @__PURE__ */ new Map();
|
|
@@ -302,11 +298,8 @@ function convertLayerWithContainers(layer, doc) {
|
|
|
302
298
|
containerGroups.set(container.id, group);
|
|
303
299
|
}
|
|
304
300
|
const proxies = [];
|
|
305
|
-
for (const
|
|
306
|
-
if (!containerNodeIds.has(
|
|
307
|
-
const nodeWidth = calculateNodeWidth(node.data.label);
|
|
308
|
-
proxies.push({ id: node.id, x: 0, y: 0, width: nodeWidth, height: 80 });
|
|
309
|
-
}
|
|
301
|
+
for (const n of flatNodes) {
|
|
302
|
+
if (!containerNodeIds.has(n.id)) proxies.push({ id: n.id, x: 0, y: 0, width: n.width, height: n.height });
|
|
310
303
|
}
|
|
311
304
|
for (const container of layer.containers) {
|
|
312
305
|
const group = containerGroups.get(container.id);
|
|
@@ -333,54 +326,40 @@ function convertLayerWithContainers(layer, doc) {
|
|
|
333
326
|
}
|
|
334
327
|
}
|
|
335
328
|
}
|
|
336
|
-
resolveNodeOverlaps(flatNodes);
|
|
337
|
-
return flatNodes;
|
|
338
329
|
}
|
|
339
|
-
function
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
const
|
|
347
|
-
flatNodes
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
branchCount,
|
|
355
|
-
0,
|
|
356
|
-
0
|
|
357
|
-
)
|
|
358
|
-
);
|
|
330
|
+
function layoutLayer(layer, flatNodes) {
|
|
331
|
+
const layout = layer.layout || "radial";
|
|
332
|
+
if (layout === "linear-horizontal") {
|
|
333
|
+
applyLinearHorizontalLayout(flatNodes, { centerX: 0, centerY: 0 });
|
|
334
|
+
} else if (layout === "linear-vertical") {
|
|
335
|
+
applyLinearVerticalLayout(flatNodes, { centerX: 0, centerY: 0 });
|
|
336
|
+
} else {
|
|
337
|
+
const pct = calculateOptimalRadiusPercentage(flatNodes.length, 2e3, 2e3, 200, 30);
|
|
338
|
+
applyCircularLayout(flatNodes, {
|
|
339
|
+
radiusPercentage: pct,
|
|
340
|
+
containerWidth: 2e3,
|
|
341
|
+
containerHeight: 2e3,
|
|
342
|
+
centerX: 0,
|
|
343
|
+
centerY: 0
|
|
344
|
+
});
|
|
359
345
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const pct = calculateOptimalRadiusPercentage(flatNodes.length, 2e3, 2e3, 200, 30);
|
|
368
|
-
applyCircularLayout(flatNodes, {
|
|
369
|
-
radiusPercentage: pct,
|
|
370
|
-
containerWidth: 2e3,
|
|
371
|
-
containerHeight: 2e3,
|
|
372
|
-
centerX: 0,
|
|
373
|
-
centerY: 0
|
|
374
|
-
});
|
|
375
|
-
}
|
|
346
|
+
}
|
|
347
|
+
function convertLayerToFlatNodes(layer, doc, opts = {}) {
|
|
348
|
+
const flatNodes = layer.nodes.map((node, i) => makeFlatNode(node, layer, doc, i, opts));
|
|
349
|
+
if (flatNodes.length === 0 || hasFilePositions(layer)) return flatNodes;
|
|
350
|
+
for (const n of flatNodes) {
|
|
351
|
+
n.x = 0;
|
|
352
|
+
n.y = 0;
|
|
376
353
|
}
|
|
354
|
+
if ((layer.containers ?? []).length > 0) layoutLayerWithContainers(layer, flatNodes);
|
|
355
|
+
else layoutLayer(layer, flatNodes);
|
|
377
356
|
resolveNodeOverlaps(flatNodes);
|
|
378
357
|
return flatNodes;
|
|
379
358
|
}
|
|
380
|
-
function convertVisualliToFlatNodes(doc) {
|
|
359
|
+
function convertVisualliToFlatNodes(doc, opts = {}) {
|
|
381
360
|
const map = /* @__PURE__ */ new Map();
|
|
382
361
|
for (const layer of doc.layers.values()) {
|
|
383
|
-
for (const node of convertLayerToFlatNodes(layer, doc)) {
|
|
362
|
+
for (const node of convertLayerToFlatNodes(layer, doc, opts)) {
|
|
384
363
|
map.set(node.id, node);
|
|
385
364
|
}
|
|
386
365
|
}
|
|
@@ -392,9 +371,9 @@ function convertVisualliToFlatNodes(doc) {
|
|
|
392
371
|
}
|
|
393
372
|
return map;
|
|
394
373
|
}
|
|
395
|
-
function getNodesForLayer(doc, layerId) {
|
|
374
|
+
function getNodesForLayer(doc, layerId, opts = {}) {
|
|
396
375
|
const layer = doc.layers.get(layerId);
|
|
397
|
-
return layer ? convertLayerToFlatNodes(layer, doc) : [];
|
|
376
|
+
return layer ? convertLayerToFlatNodes(layer, doc, opts) : [];
|
|
398
377
|
}
|
|
399
378
|
|
|
400
379
|
// src/parser/mindmapUtils.ts
|
|
@@ -446,6 +425,8 @@ function calculateDistance(x1, y1, x2, y2) {
|
|
|
446
425
|
}
|
|
447
426
|
|
|
448
427
|
// src/parser/configUtils.ts
|
|
428
|
+
var levelColor = (level) => TOKENS.light[`topic-${TOPICS[level % TOPICS.length]}`];
|
|
429
|
+
var levelColors = (count) => Object.fromEntries(Array.from({ length: count }, (_, i) => [`level${i}`, levelColor(i)]));
|
|
449
430
|
function createMindMapConfig(nodes, topLevelConnections, title = "Untitled Mindmap") {
|
|
450
431
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
451
432
|
return {
|
|
@@ -459,12 +440,7 @@ function createMindMapConfig(nodes, topLevelConnections, title = "Untitled Mindm
|
|
|
459
440
|
nodes,
|
|
460
441
|
topLevelConnections,
|
|
461
442
|
settings: {
|
|
462
|
-
defaultColors:
|
|
463
|
-
level0: LEVEL_COLORS.level0,
|
|
464
|
-
level1: LEVEL_COLORS.level1,
|
|
465
|
-
level2: LEVEL_COLORS.level2,
|
|
466
|
-
level3: LEVEL_COLORS.level3
|
|
467
|
-
},
|
|
443
|
+
defaultColors: levelColors(4),
|
|
468
444
|
layout: {
|
|
469
445
|
nodeSpacing: LAYOUT_SPACING.nodeSpacing,
|
|
470
446
|
levelSpacing: LAYOUT_SPACING.levelSpacing
|
|
@@ -491,7 +467,7 @@ function generateLevelNodes(parentId, level, maxLevels, xOffset = 0, yOffset = 0
|
|
|
491
467
|
level,
|
|
492
468
|
x,
|
|
493
469
|
y,
|
|
494
|
-
color:
|
|
470
|
+
color: levelColor(level),
|
|
495
471
|
relationshipLabel: level > 0 ? "child" : void 0,
|
|
496
472
|
parent: parentId ?? void 0
|
|
497
473
|
};
|
|
@@ -520,17 +496,7 @@ function generateSampleConfig(maxLevels = 9) {
|
|
|
520
496
|
nodes,
|
|
521
497
|
topLevelConnections,
|
|
522
498
|
settings: {
|
|
523
|
-
defaultColors:
|
|
524
|
-
level0: LEVEL_COLORS.level0,
|
|
525
|
-
level1: LEVEL_COLORS.level1,
|
|
526
|
-
level2: LEVEL_COLORS.level2,
|
|
527
|
-
level3: LEVEL_COLORS.level3,
|
|
528
|
-
level4: LEVEL_COLORS.level4,
|
|
529
|
-
level5: LEVEL_COLORS.level5,
|
|
530
|
-
level6: LEVEL_COLORS.level6,
|
|
531
|
-
level7: LEVEL_COLORS.level7,
|
|
532
|
-
level8: LEVEL_COLORS.level8
|
|
533
|
-
},
|
|
499
|
+
defaultColors: levelColors(9),
|
|
534
500
|
layout: {
|
|
535
501
|
nodeSpacing: LAYOUT_SPACING.nodeSpacing,
|
|
536
502
|
levelSpacing: LAYOUT_SPACING.levelSpacing
|
|
@@ -545,6 +511,7 @@ export {
|
|
|
545
511
|
fetchAndParseVisualli,
|
|
546
512
|
parseVisualliFromMongoDB,
|
|
547
513
|
loadVisualliFileFromFile,
|
|
514
|
+
getSemanticAnchors,
|
|
548
515
|
getChildLayers,
|
|
549
516
|
countLayersBeneath,
|
|
550
517
|
resolveNodeOverlaps,
|
|
@@ -559,4 +526,4 @@ export {
|
|
|
559
526
|
createMindMapConfig,
|
|
560
527
|
generateSampleConfig
|
|
561
528
|
};
|
|
562
|
-
//# sourceMappingURL=chunk-
|
|
529
|
+
//# sourceMappingURL=chunk-WO4JAAKP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parser/visualliParser.ts","../src/parser/visualliConverter.ts","../src/parser/mindmapUtils.ts","../src/parser/configUtils.ts"],"sourcesContent":["// ─── .visualli File Parser ────────────────────────────────────────────────────\n//\n// Reads JSONL (JSON Lines) format and parses into a structured VisualliDocument.\n\nimport type { VisualliDocument, SemanticAnchor } from '../types/document.js';\nimport type { VisualliMeta } from '../types/meta.js';\nimport type { VisualliLayer } from '../types/layer.js';\nimport type { Layer } from '../types/schema.js';\n\n/**\n * Convert schema Layer to VisualliLayer by ensuring required arrays exist.\n */\nfunction toVisualliLayer(schemaLayer: Layer): VisualliLayer {\n return {\n type: 'layer',\n id: schemaLayer.id,\n level: schemaLayer.level,\n parentLayerId: schemaLayer.parentLayerId,\n parentNodeId: schemaLayer.parentNodeId,\n layout: schemaLayer.layout,\n nodes: schemaLayer.nodes ?? [],\n connections: schemaLayer.connections ?? [],\n containers: schemaLayer.containers ?? [],\n };\n}\n\nexport class VisualliParseError extends Error {\n constructor(message: string, public readonly lineNumber?: number) {\n super(message);\n this.name = 'VisualliParseError';\n }\n}\n\n/**\n * Parse a .visualli file content (JSONL format) into a VisualliDocument.\n *\n * @throws VisualliParseError on malformed input\n */\nexport function parseVisualliFile(content: string): VisualliDocument {\n const lines = content.trim().split('\\n');\n\n const doc: VisualliDocument = {\n meta: null as unknown as VisualliMeta,\n layers: new Map(),\n layersByLevel: new Map(),\n rootLayer: null,\n };\n\n let lineNumber = 0;\n\n for (const line of lines) {\n lineNumber++;\n if (!line.trim()) continue;\n\n let obj: Record<string, unknown>;\n try {\n obj = JSON.parse(line) as Record<string, unknown>;\n } catch (err) {\n throw new VisualliParseError(\n `Failed to parse JSON at line ${lineNumber}: ${err}`,\n lineNumber,\n );\n }\n\n if (!obj['type']) {\n throw new VisualliParseError(\n `Missing 'type' field at line ${lineNumber}`,\n lineNumber,\n );\n }\n\n switch (obj['type']) {\n case 'meta':\n doc.meta = obj as unknown as VisualliMeta;\n break;\n\n case 'layer': {\n // Convert schema Layer to VisualliLayer\n const schemaLayer = obj as unknown as Layer;\n const layer = toVisualliLayer(schemaLayer);\n \n doc.layers.set(layer.id, layer);\n\n if (!doc.layersByLevel.has(layer.level)) {\n doc.layersByLevel.set(layer.level, []);\n }\n doc.layersByLevel.get(layer.level)!.push(layer);\n\n if (layer.level === 0) {\n doc.rootLayer = layer;\n }\n break;\n }\n\n case 'extension': {\n const id = obj['id'];\n if (typeof id === 'string') {\n (doc.extensions ??= {})[id] = Array.isArray(obj['data']) ? (obj['data'] as unknown[]) : [];\n }\n break;\n }\n\n default:\n // Unknown type — silently skip\n break;\n }\n }\n\n if (!doc.meta) throw new VisualliParseError('Missing required meta section');\n if (!doc.rootLayer) throw new VisualliParseError('Missing root layer (level 0)');\n\n return doc;\n}\n\nexport async function fetchAndParseVisualli(url: string): Promise<VisualliDocument> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n return parseVisualliFile(await response.text());\n}\n\n/**\n * Parse .visualli JSONL data as returned from the MongoDB `visualli` field.\n *\n * @throws VisualliParseError\n */\nexport function parseVisualliFromMongoDB(visualliJsonl: string): VisualliDocument {\n if (!visualliJsonl || typeof visualliJsonl !== 'string') {\n throw new VisualliParseError('Invalid visualli data: expected a JSONL string');\n }\n const trimmed = visualliJsonl.trim();\n if (!trimmed) throw new VisualliParseError('Empty visualli data from MongoDB');\n return parseVisualliFile(trimmed);\n}\n\n/**\n * Parse a .visualli file from a browser `File` object.\n * (Browser-only – requires `FileReader`.)\n */\nexport function loadVisualliFileFromFile(file: File): Promise<VisualliDocument> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = e => {\n try {\n resolve(parseVisualliFile(e.target?.result as string));\n } catch (err) {\n reject(err);\n }\n };\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n}\n\n// ── Tree Helpers ──────────────────────────────────────────────────────────────\n\n/** Return all layers whose `parentNodeId` matches the given node ID. */\n/** Terms defined by the document's `semantic-anchors` extension (empty when absent). */\nexport function getSemanticAnchors(doc: VisualliDocument): SemanticAnchor[] {\n const raw = doc.extensions?.['semantic-anchors'];\n if (!Array.isArray(raw)) return [];\n return raw.filter((a): a is SemanticAnchor => !!a && typeof (a as SemanticAnchor).word === 'string' && typeof (a as SemanticAnchor).description === 'string');\n}\n\nexport function getChildLayers(\n doc: VisualliDocument,\n nodeId: string,\n): VisualliLayer[] {\n const result: VisualliLayer[] = [];\n for (const layer of doc.layers.values()) {\n if (layer.parentNodeId === nodeId) result.push(layer);\n }\n return result;\n}\n\n/**\n * Count the maximum depth of layers beneath a node (its \"magnitude\").\n * Returns 0 when the node has no child layers.\n */\nexport function countLayersBeneath(\n doc: VisualliDocument,\n nodeId: string,\n visited = new Set<string>(),\n): number {\n if (visited.has(nodeId)) return 0;\n visited.add(nodeId);\n\n const children = getChildLayers(doc, nodeId);\n if (children.length === 0) return 0;\n\n let maxDepth = 0;\n for (const layer of children) {\n let depth = 1;\n for (const node of layer.nodes) {\n depth = Math.max(depth, 1 + countLayersBeneath(doc, node.id, visited));\n }\n maxDepth = Math.max(maxDepth, depth);\n }\n return maxDepth;\n}\n","// ─── .visualli → FlatNode Converter ──────────────────────────────────────────\n//\n// Transforms the layer-based .visualli format into the flat Map<id, FlatNode>\n// structure consumed by the canvas renderer.\n\nimport type { VisualliDocument } from '../types/document.js';\nimport type { VisualliLayer } from '../types/layer.js';\nimport type { FlatNode, NodeMap } from '../types/mindmap.js';\nimport { countLayersBeneath } from './visualliParser.js';\nimport { ideaColor } from '../theme/index.js';\nimport { approximateMeasure, ideaKindOf, ideaSize, type IdeaMeasure } from '../rendering/ideaSize.js';\nimport { applyCircularLayout, calculateOptimalRadiusPercentage } from '../layout/circularLayout.js';\nimport { applyLinearHorizontalLayout, applyLinearVerticalLayout } from '../layout/linearLayout.js';\n\n// ── Overlap Resolution ────────────────────────────────────────────────────────\n\nfunction doNodesOverlap(n1: FlatNode, n2: FlatNode, padding = 20): boolean {\n return !(\n n1.x + n1.width / 2 + padding < n2.x - n2.width / 2 - padding ||\n n1.x - n1.width / 2 - padding > n2.x + n2.width / 2 + padding ||\n n1.y + n1.height / 2 + padding < n2.y - n2.height / 2 - padding ||\n n1.y - n1.height / 2 - padding > n2.y + n2.height / 2 + padding\n );\n}\n\n/** Iteratively push overlapping nodes apart using symmetric force separation. */\nexport function resolveNodeOverlaps(nodes: FlatNode[], maxIterations = 10): void {\n const padding = 150;\n\n for (let iter = 0; iter < maxIterations; iter++) {\n let any = false;\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const n1 = nodes[i];\n const n2 = nodes[j];\n if (!doNodesOverlap(n1, n2, padding)) continue;\n\n any = true;\n const dx = n2.x - n1.x;\n const dy = n2.y - n1.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < 1) {\n n2.x += n2.width / 2 + padding;\n continue;\n }\n\n const minDist = (n1.width + n2.width) / 2 + padding;\n if (dist < minDist) {\n const push = (minDist - dist) / 2;\n n1.x -= (dx / dist) * push;\n n1.y -= (dy / dist) * push;\n n2.x += (dx / dist) * push;\n n2.y += (dy / dist) * push;\n }\n }\n }\n if (!any) break;\n }\n}\n\n// ── Options ───────────────────────────────────────────────────────────────────\n\nexport interface ConvertOptions {\n /** Measures label text in the idea face (the renderer's font engine); ideas are sized with the design system's\n * ideaSize. Defaults to an approximation (half an em per character) where no font engine exists. */\n measure?: IdeaMeasure;\n /** Label scale (comfort: larger text is 1.15); ideas grow to fit the larger label. */\n labelScale?: number;\n}\n\n/** Whether a layer's ideas carry their own positions: every idea has one, and (with more than one idea) they aren't\n * all on the same spot (a placeholder). Then the file's positions are used as they are. */\nfunction hasFilePositions(layer: VisualliLayer): boolean {\n const ps = layer.nodes.map((n) => n.position);\n if (!ps.length || !ps.every((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))) return false;\n return ps.length === 1 || ps.some((p) => p!.x !== ps[0]!.x || p!.y !== ps[0]!.y);\n}\n\n// ── Container-formation Layout ────────────────────────────────────────────────\n\ninterface Proxy { id: string; x: number; y: number; width: number; height: number }\n\nfunction applyFormation(nodes: FlatNode[], formation: string): void {\n if (nodes.length === 0) return;\n if (nodes.length === 1) { nodes[0].x = 0; nodes[0].y = 0; return; }\n if (formation === 'linear-horizontal' || formation === 'linear') {\n applyLinearHorizontalLayout(nodes, { centerX: 0, centerY: 0 });\n } else if (formation === 'linear-vertical') {\n applyLinearVerticalLayout(nodes, { centerX: 0, centerY: 0 });\n } else {\n const r = Math.max(250, nodes.length * 70);\n const step = (2 * Math.PI) / nodes.length;\n for (let i = 0; i < nodes.length; i++) {\n nodes[i].x = r * Math.cos(i * step);\n nodes[i].y = r * Math.sin(i * step);\n }\n }\n}\n\nfunction containerBBox(nodes: FlatNode[], padding: number): { width: number; height: number } {\n let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;\n for (const n of nodes) {\n minX = Math.min(minX, n.x - n.width / 2);\n maxX = Math.max(maxX, n.x + n.width / 2);\n minY = Math.min(minY, n.y - n.height / 2);\n maxY = Math.max(maxY, n.y + n.height / 2);\n }\n return { width: maxX - minX + padding * 2, height: maxY - minY + padding * 2 };\n}\n\nfunction proxyLinearH(proxies: Proxy[], gap = 180): void {\n const total = proxies.reduce((s, p) => s + p.width, 0) + gap * (proxies.length - 1);\n let x = -total / 2;\n for (const p of proxies) { p.x = x + p.width / 2; p.y = 0; x += p.width + gap; }\n}\n\nfunction proxyLinearV(proxies: Proxy[], gap = 180): void {\n const total = proxies.reduce((s, p) => s + p.height, 0) + gap * (proxies.length - 1);\n let y = -total / 2;\n for (const p of proxies) { p.x = 0; p.y = y + p.height / 2; y += p.height + gap; }\n}\n\nfunction proxyRadial(proxies: Proxy[], radius = 500): void {\n if (proxies.length === 1) { proxies[0].x = 0; proxies[0].y = 0; return; }\n // Start at top (12 o'clock) for n>=3, horizontal for n=2 (matches circular layout)\n const startAngle = proxies.length === 2 ? 0 : -Math.PI / 2;\n const step = (2 * Math.PI) / proxies.length;\n for (let i = 0; i < proxies.length; i++) {\n const angle = startAngle + i * step;\n proxies[i].x = radius * Math.cos(angle);\n proxies[i].y = radius * Math.sin(angle);\n }\n}\n\n// ── Layer Conversion ──────────────────────────────────────────────────────────\n\nfunction makeFlatNode(\n node: VisualliLayer['nodes'][number],\n layer: VisualliLayer,\n doc: VisualliDocument,\n /** Position among the layer's ideas (file order): missing colours cycle the topics by it, and the first idea of the root radial layer is the root. */\n siblingIndex: number,\n opts: ConvertOptions,\n): FlatNode {\n const label = Array.isArray(node.data.label) ? (node.data.label as string[]).join(' ') : (node.data.label || 'Untitled');\n const branchCount = countLayersBeneath(doc, node.id);\n const kind = ideaKindOf(layer, siblingIndex);\n const size = ideaSize(kind, label, opts.measure ?? approximateMeasure, opts.labelScale ?? 1);\n const { topic, custom } = ideaColor(node.data.color, siblingIndex);\n return {\n id: node.id,\n parentId: layer.parentNodeId ?? null,\n x: node.position?.x ?? 0,\n y: node.position?.y ?? 0,\n level: layer.level,\n title: label,\n description: node.data.summary || '',\n color: node.data.color ?? '',\n ...(topic ? { topic } : {}),\n ...(custom ? { custom } : {}),\n kind,\n width: size.width,\n height: size.height,\n isExpanded: branchCount > 0,\n branchCount,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n}\n\nfunction layoutLayerWithContainers(layer: VisualliLayer, flatNodes: FlatNode[]): void {\n const PADDING = 80;\n const byId = new Map(flatNodes.map((n: FlatNode) => [n.id, n]));\n const containerNodeIds = new Set<string>();\n const containerGroups = new Map<string, FlatNode[]>();\n\n for (const container of layer.containers) {\n const group = container.nodes.map((id: string) => byId.get(id)).filter((n: FlatNode | undefined): n is FlatNode => !!n);\n if (!group.length) continue;\n container.nodes.forEach((id: string) => containerNodeIds.add(id));\n const formation = ((container.data as unknown as Record<string, unknown> | undefined)?.['formation'] as string | undefined) ?? 'radial';\n applyFormation(group, formation);\n containerGroups.set(container.id, group);\n }\n\n const proxies: Proxy[] = [];\n for (const n of flatNodes) {\n if (!containerNodeIds.has(n.id)) proxies.push({ id: n.id, x: 0, y: 0, width: n.width, height: n.height });\n }\n for (const container of layer.containers) {\n const group = containerGroups.get(container.id);\n if (!group?.length) continue;\n const bbox = containerBBox(group, PADDING);\n proxies.push({ id: `__c__${container.id}`, x: 0, y: 0, width: bbox.width, height: bbox.height });\n }\n\n const layout = layer.layout || 'radial';\n if (layout === 'linear-horizontal') proxyLinearH(proxies, 180);\n else if (layout === 'linear-vertical') proxyLinearV(proxies, 180);\n else proxyRadial(proxies, 500);\n\n for (const proxy of proxies) {\n if (proxy.id.startsWith('__c__')) {\n const group = containerGroups.get(proxy.id.slice(5));\n group?.forEach(n => { n.x += proxy.x; n.y += proxy.y; });\n } else {\n const fn = byId.get(proxy.id);\n if (fn) { fn.x = proxy.x; fn.y = proxy.y; }\n }\n }\n}\n\nfunction layoutLayer(layer: VisualliLayer, flatNodes: FlatNode[]): void {\n const layout = layer.layout || 'radial';\n if (layout === 'linear-horizontal') {\n applyLinearHorizontalLayout(flatNodes, { centerX: 0, centerY: 0 });\n } else if (layout === 'linear-vertical') {\n applyLinearVerticalLayout(flatNodes, { centerX: 0, centerY: 0 });\n } else {\n const pct = calculateOptimalRadiusPercentage(flatNodes.length, 2000, 2000, 200, 30);\n applyCircularLayout(flatNodes, {\n radiusPercentage: pct,\n containerWidth: 2000,\n containerHeight: 2000,\n centerX: 0,\n centerY: 0,\n });\n }\n}\n\n/**\n * Convert a single layer to an array of FlatNode objects, each sized for its label\n * (the design system's idea.ts) and coloured by its colour rule (color.ts).\n * Positions: the file's own when its ideas carry them; otherwise the SDK lays the\n * layer out by `layer.layout` (default radial) and container formations.\n */\nexport function convertLayerToFlatNodes(\n layer: VisualliLayer,\n doc: VisualliDocument,\n opts: ConvertOptions = {},\n): FlatNode[] {\n const flatNodes = layer.nodes.map((node, i) => makeFlatNode(node, layer, doc, i, opts));\n if (flatNodes.length === 0 || hasFilePositions(layer)) return flatNodes;\n for (const n of flatNodes) { n.x = 0; n.y = 0; }\n if ((layer.containers ?? []).length > 0) layoutLayerWithContainers(layer, flatNodes);\n else layoutLayer(layer, flatNodes);\n resolveNodeOverlaps(flatNodes);\n return flatNodes;\n}\n\n/**\n * Convert an entire .visualli document to a flat NodeMap.\n * All layers are converted and a children-index is built for O(1) tree traversal.\n */\nexport function convertVisualliToFlatNodes(doc: VisualliDocument, opts: ConvertOptions = {}): NodeMap {\n const map: NodeMap = new Map();\n\n for (const layer of doc.layers.values()) {\n for (const node of convertLayerToFlatNodes(layer, doc, opts)) {\n map.set(node.id, node);\n }\n }\n\n // Build children index\n for (const node of map.values()) {\n node.childrenIds = [];\n for (const candidate of map.values()) {\n if (candidate.parentId === node.id) node.childrenIds.push(candidate.id);\n }\n }\n\n return map;\n}\n\n/**\n * Get flat nodes for a specific layer only.\n *\n * @param doc - Parsed .visualli document\n * @param layerId - Layer ID to extract\n * @param opts - Text measurement and label scale for sizing ideas\n * @returns FlatNode array, or empty array if layer not found\n */\nexport function getNodesForLayer(doc: VisualliDocument, layerId: string, opts: ConvertOptions = {}): FlatNode[] {\n const layer = doc.layers.get(layerId);\n return layer ? convertLayerToFlatNodes(layer, doc, opts) : [];\n}\n","// ─── Mindmap Tree Utilities ───────────────────────────────────────────────────\n\nimport type { MindMapNode, TopLevelConnection } from '../types/mindmap.js';\n\n/** Flatten a nested MindMapNode tree into a depth-first array. */\nexport function flattenNodes(nodes: MindMapNode[]): MindMapNode[] {\n const result: MindMapNode[] = [];\n const traverse = (list: MindMapNode[]) => {\n for (const n of list) {\n result.push(n);\n if (n.children) traverse(n.children);\n }\n };\n traverse(nodes);\n return result;\n}\n\n/**\n * Return nodes visible at the given zoom level.\n *\n * At lower zoom values only top-level nodes are shown; each 5% zoom increment\n * reveals one additional hierarchy level.\n */\nexport function getVisibleNodes(\n nodes: MindMapNode[],\n zoom: number,\n focusedNode?: string,\n): MindMapNode[] {\n const flat = flattenNodes(nodes);\n\n if (focusedNode) {\n const focused = flat.find(n => n.id === focusedNode);\n if (focused) {\n return focused.children ? [focused, ...focused.children] : [focused];\n }\n }\n\n // Map zoom to max visible level (level 0 at ≤70%, +1 level per 5% increment)\n if (zoom <= 0.70) return flat.filter(n => n.level === 0);\n const maxLevel = Math.floor((zoom - 0.70) / 0.05);\n return flat.filter(n => n.level <= maxLevel);\n}\n\n/** Build parent→child connection pairs from the node tree. */\nexport function getNodeConnections(\n nodes: MindMapNode[],\n): Array<{ from: MindMapNode; to: MindMapNode; label?: string }> {\n const flat = flattenNodes(nodes);\n const result: Array<{ from: MindMapNode; to: MindMapNode; label?: string }> = [];\n for (const n of flat) {\n if (!n.parent) continue;\n const parent = flat.find(p => p.id === n.parent);\n if (parent) result.push({ from: parent, to: n, label: n.relationshipLabel });\n }\n return result;\n}\n\n/** Resolve top-level cross-connections to node pairs. */\nexport function getTopLevelConnections(\n nodes: MindMapNode[],\n topLevelConnections: TopLevelConnection[],\n): Array<{ from: MindMapNode; to: MindMapNode; label: string }> {\n const flat = flattenNodes(nodes);\n const result: Array<{ from: MindMapNode; to: MindMapNode; label: string }> = [];\n for (const conn of topLevelConnections) {\n const from = flat.find(n => n.id === conn.from);\n const to = flat.find(n => n.id === conn.to);\n if (from && to) result.push({ from, to, label: conn.label ?? '' });\n }\n return result;\n}\n\n/** Euclidean distance between two world-space points. */\nexport function calculateDistance(x1: number, y1: number, x2: number, y2: number): number {\n return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);\n}\n","// ─── MindMapConfig Utilities ──────────────────────────────────────────────────\n//\n// Helpers for creating and generating MindMapConfig objects (pure data, no UI).\n\nimport type { MindMapNode, MindMapConfig, TopLevelConnection } from '../types/mindmap.js';\nimport { LAYOUT_SPACING } from '../constants/layout.js';\nimport { TOKENS, TOPICS } from '../theme/index.js';\n\n/** Light-theme fill of the topic used for a level (cycles through the design-system topics). */\nconst levelColor = (level: number): string => TOKENS.light[`topic-${TOPICS[level % TOPICS.length]}`]!;\n\ntype LevelColors = { level0: string; level1: string; level2: string; level3: string; [key: `level${number}`]: string };\nconst levelColors = (count: number): LevelColors =>\n Object.fromEntries(Array.from({ length: count }, (_, i) => [`level${i}`, levelColor(i)])) as LevelColors;\n\nexport function createMindMapConfig(\n nodes: MindMapNode[],\n topLevelConnections: TopLevelConnection[],\n title = 'Untitled Mindmap',\n): MindMapConfig {\n const now = new Date().toISOString();\n return {\n metadata: {\n title,\n description: `Interactive mindmap with ${nodes.length} nodes`,\n version: '1.0.0',\n created: now,\n lastModified: now,\n },\n nodes,\n topLevelConnections,\n settings: {\n defaultColors: levelColors(4),\n layout: {\n nodeSpacing: LAYOUT_SPACING.nodeSpacing,\n levelSpacing: LAYOUT_SPACING.levelSpacing,\n },\n },\n };\n}\n\n// ── Sample Data Generator ─────────────────────────────────────────────────────\n\nfunction generateId(prefix: string, level: number, index: number): string {\n return `${prefix}-l${level}-${index}`;\n}\n\nfunction generateLevelNodes(\n parentId: string | null,\n level: number,\n maxLevels: number,\n xOffset = 0,\n yOffset = 0,\n): MindMapNode[] {\n if (level >= maxLevels) return [];\n\n const count = 5;\n const levelSpacing = 200;\n const nodeSpacing = 300;\n const nodes: MindMapNode[] = [];\n\n for (let i = 0; i < count; i++) {\n const nodeId = parentId\n ? generateId(`${parentId}-${i}`, level, i)\n : generateId('root', level, i);\n\n const x = xOffset + (i - (count - 1) / 2) * nodeSpacing;\n const y = yOffset + level * levelSpacing;\n\n const node: MindMapNode = {\n id: nodeId,\n title: `Level ${level} Node ${i + 1}`,\n level,\n x,\n y,\n color: levelColor(level),\n relationshipLabel: level > 0 ? 'child' : undefined,\n parent: parentId ?? undefined,\n };\n\n const children = generateLevelNodes(nodeId, level + 1, maxLevels, x, y + levelSpacing);\n if (children.length > 0) node.children = children;\n\n nodes.push(node);\n }\n\n return nodes;\n}\n\n/**\n * Generate a sample MindMapConfig with `maxLevels` of hierarchy.\n * Useful for testing and demos.\n */\nexport function generateSampleConfig(maxLevels = 9): MindMapConfig {\n const nodes = generateLevelNodes(null, 0, maxLevels, 0, 0);\n\n const topLevelConnections: TopLevelConnection[] = nodes.slice(0, -1).map((n, i) => ({\n from: n.id,\n to: nodes[i + 1].id,\n label: 'related to',\n }));\n\n return {\n metadata: {\n id: `mindmap-${Date.now()}`,\n title: 'Sample Mind Map',\n description: 'A sample mind map',\n version: '1.0.0',\n created: new Date().toISOString(),\n lastModified: new Date().toISOString(),\n },\n nodes,\n topLevelConnections,\n settings: {\n defaultColors: levelColors(9),\n layout: {\n nodeSpacing: LAYOUT_SPACING.nodeSpacing,\n levelSpacing: LAYOUT_SPACING.levelSpacing,\n },\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAYA,SAAS,gBAAgB,aAAmC;AAC1D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,IAAI,YAAY;AAAA,IAChB,OAAO,YAAY;AAAA,IACnB,eAAe,YAAY;AAAA,IAC3B,cAAc,YAAY;AAAA,IAC1B,QAAQ,YAAY;AAAA,IACpB,OAAO,YAAY,SAAS,CAAC;AAAA,IAC7B,aAAa,YAAY,eAAe,CAAC;AAAA,IACzC,YAAY,YAAY,cAAc,CAAC;AAAA,EACzC;AACF;AAEO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,SAAiC,YAAqB;AAChE,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAOO,SAAS,kBAAkB,SAAmC;AACnE,QAAM,QAAQ,QAAQ,KAAK,EAAE,MAAM,IAAI;AAEvC,QAAM,MAAwB;AAAA,IAC5B,MAAM;AAAA,IACN,QAAQ,oBAAI,IAAI;AAAA,IAChB,eAAe,oBAAI,IAAI;AAAA,IACvB,WAAW;AAAA,EACb;AAEA,MAAI,aAAa;AAEjB,aAAW,QAAQ,OAAO;AACxB;AACA,QAAI,CAAC,KAAK,KAAK,EAAG;AAElB,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAM,IAAI;AAAA,IACvB,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,gCAAgC,UAAU,KAAK,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,IAAI,MAAM,GAAG;AAChB,YAAM,IAAI;AAAA,QACR,gCAAgC,UAAU;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,IAAI,MAAM,GAAG;AAAA,MACnB,KAAK;AACH,YAAI,OAAO;AACX;AAAA,MAEF,KAAK,SAAS;AAEZ,cAAM,cAAc;AACpB,cAAM,QAAQ,gBAAgB,WAAW;AAEzC,YAAI,OAAO,IAAI,MAAM,IAAI,KAAK;AAE9B,YAAI,CAAC,IAAI,cAAc,IAAI,MAAM,KAAK,GAAG;AACvC,cAAI,cAAc,IAAI,MAAM,OAAO,CAAC,CAAC;AAAA,QACvC;AACA,YAAI,cAAc,IAAI,MAAM,KAAK,EAAG,KAAK,KAAK;AAE9C,YAAI,MAAM,UAAU,GAAG;AACrB,cAAI,YAAY;AAAA,QAClB;AACA;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAChB,cAAM,KAAK,IAAI,IAAI;AACnB,YAAI,OAAO,OAAO,UAAU;AAC1B,WAAC,IAAI,eAAJ,IAAI,aAAe,CAAC,IAAG,EAAE,IAAI,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAK,IAAI,MAAM,IAAkB,CAAC;AAAA,QAC3F;AACA;AAAA,MACF;AAAA,MAEA;AAEE;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,CAAC,IAAI,KAAM,OAAM,IAAI,mBAAmB,+BAA+B;AAC3E,MAAI,CAAC,IAAI,UAAW,OAAM,IAAI,mBAAmB,8BAA8B;AAE/E,SAAO;AACT;AAEA,eAAsB,sBAAsB,KAAwC;AAClF,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,EACnE;AACA,SAAO,kBAAkB,MAAM,SAAS,KAAK,CAAC;AAChD;AAOO,SAAS,yBAAyB,eAAyC;AAChF,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,UAAM,IAAI,mBAAmB,gDAAgD;AAAA,EAC/E;AACA,QAAM,UAAU,cAAc,KAAK;AACnC,MAAI,CAAC,QAAS,OAAM,IAAI,mBAAmB,kCAAkC;AAC7E,SAAO,kBAAkB,OAAO;AAClC;AAMO,SAAS,yBAAyB,MAAuC;AAC9E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,SAAS,OAAK;AACnB,UAAI;AACF,gBAAQ,kBAAkB,EAAE,QAAQ,MAAgB,CAAC;AAAA,MACvD,SAAS,KAAK;AACZ,eAAO,GAAG;AAAA,MACZ;AAAA,IACF;AACA,WAAO,UAAU,MAAM,OAAO,IAAI,MAAM,qBAAqB,CAAC;AAC9D,WAAO,WAAW,IAAI;AAAA,EACxB,CAAC;AACH;AAMO,SAAS,mBAAmB,KAAyC;AAC1E,QAAM,MAAM,IAAI,aAAa,kBAAkB;AAC/C,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AACjC,SAAO,IAAI,OAAO,CAAC,MAA2B,CAAC,CAAC,KAAK,OAAQ,EAAqB,SAAS,YAAY,OAAQ,EAAqB,gBAAgB,QAAQ;AAC9J;AAEO,SAAS,eACd,KACA,QACiB;AACjB,QAAM,SAA0B,CAAC;AACjC,aAAW,SAAS,IAAI,OAAO,OAAO,GAAG;AACvC,QAAI,MAAM,iBAAiB,OAAQ,QAAO,KAAK,KAAK;AAAA,EACtD;AACA,SAAO;AACT;AAMO,SAAS,mBACd,KACA,QACA,UAAU,oBAAI,IAAY,GAClB;AACR,MAAI,QAAQ,IAAI,MAAM,EAAG,QAAO;AAChC,UAAQ,IAAI,MAAM;AAElB,QAAM,WAAW,eAAe,KAAK,MAAM;AAC3C,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,MAAI,WAAW;AACf,aAAW,SAAS,UAAU;AAC5B,QAAI,QAAQ;AACZ,eAAW,QAAQ,MAAM,OAAO;AAC9B,cAAQ,KAAK,IAAI,OAAO,IAAI,mBAAmB,KAAK,KAAK,IAAI,OAAO,CAAC;AAAA,IACvE;AACA,eAAW,KAAK,IAAI,UAAU,KAAK;AAAA,EACrC;AACA,SAAO;AACT;;;ACxLA,SAAS,eAAe,IAAc,IAAc,UAAU,IAAa;AACzE,SAAO,EACL,GAAG,IAAI,GAAG,QAAQ,IAAI,UAAU,GAAG,IAAI,GAAG,QAAQ,IAAI,WACtD,GAAG,IAAI,GAAG,QAAQ,IAAI,UAAU,GAAG,IAAI,GAAG,QAAQ,IAAI,WACtD,GAAG,IAAI,GAAG,SAAS,IAAI,UAAU,GAAG,IAAI,GAAG,SAAS,IAAI,WACxD,GAAG,IAAI,GAAG,SAAS,IAAI,UAAU,GAAG,IAAI,GAAG,SAAS,IAAI;AAE5D;AAGO,SAAS,oBAAoB,OAAmB,gBAAgB,IAAU;AAC/E,QAAM,UAAU;AAEhB,WAAS,OAAO,GAAG,OAAO,eAAe,QAAQ;AAC/C,QAAI,MAAM;AACV,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,eAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,cAAM,KAAK,MAAM,CAAC;AAClB,cAAM,KAAK,MAAM,CAAC;AAClB,YAAI,CAAC,eAAe,IAAI,IAAI,OAAO,EAAG;AAEtC,cAAM;AACN,cAAM,KAAK,GAAG,IAAI,GAAG;AACrB,cAAM,KAAK,GAAG,IAAI,GAAG;AACrB,cAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAExC,YAAI,OAAO,GAAG;AACZ,aAAG,KAAK,GAAG,QAAQ,IAAI;AACvB;AAAA,QACF;AAEA,cAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,IAAI;AAC5C,YAAI,OAAO,SAAS;AAClB,gBAAM,QAAQ,UAAU,QAAQ;AAChC,aAAG,KAAM,KAAK,OAAQ;AACtB,aAAG,KAAM,KAAK,OAAQ;AACtB,aAAG,KAAM,KAAK,OAAQ;AACtB,aAAG,KAAM,KAAK,OAAQ;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,IAAK;AAAA,EACZ;AACF;AAcA,SAAS,iBAAiB,OAA+B;AACvD,QAAM,KAAK,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,QAAQ;AAC5C,MAAI,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,OAAO,SAAS,EAAE,CAAC,KAAK,OAAO,SAAS,EAAE,CAAC,CAAC,EAAG,QAAO;AAC9F,SAAO,GAAG,WAAW,KAAK,GAAG,KAAK,CAAC,MAAM,EAAG,MAAM,GAAG,CAAC,EAAG,KAAK,EAAG,MAAM,GAAG,CAAC,EAAG,CAAC;AACjF;AAMA,SAAS,eAAe,OAAmB,WAAyB;AAClE,MAAI,MAAM,WAAW,EAAG;AACxB,MAAI,MAAM,WAAW,GAAG;AAAE,UAAM,CAAC,EAAE,IAAI;AAAG,UAAM,CAAC,EAAE,IAAI;AAAG;AAAA,EAAQ;AAClE,MAAI,cAAc,uBAAuB,cAAc,UAAU;AAC/D,gCAA4B,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;AAAA,EAC/D,WAAW,cAAc,mBAAmB;AAC1C,8BAA0B,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;AAAA,EAC7D,OAAO;AACL,UAAM,IAAI,KAAK,IAAI,KAAK,MAAM,SAAS,EAAE;AACzC,UAAM,OAAQ,IAAI,KAAK,KAAM,MAAM;AACnC,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,CAAC,EAAE,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAClC,YAAM,CAAC,EAAE,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,IACpC;AAAA,EACF;AACF;AAEA,SAAS,cAAc,OAAmB,SAAoD;AAC5F,MAAI,OAAO,UAAU,OAAO,WAAW,OAAO,UAAU,OAAO;AAC/D,aAAW,KAAK,OAAO;AACrB,WAAO,KAAK,IAAI,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;AACvC,WAAO,KAAK,IAAI,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;AACvC,WAAO,KAAK,IAAI,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC;AACxC,WAAO,KAAK,IAAI,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC;AAAA,EAC1C;AACA,SAAO,EAAE,OAAO,OAAO,OAAO,UAAU,GAAG,QAAQ,OAAO,OAAO,UAAU,EAAE;AAC/E;AAEA,SAAS,aAAa,SAAkB,MAAM,KAAW;AACvD,QAAM,QAAQ,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC,IAAI,OAAO,QAAQ,SAAS;AACjF,MAAI,IAAI,CAAC,QAAQ;AACjB,aAAW,KAAK,SAAS;AAAE,MAAE,IAAI,IAAI,EAAE,QAAQ;AAAG,MAAE,IAAI;AAAG,SAAK,EAAE,QAAQ;AAAA,EAAK;AACjF;AAEA,SAAS,aAAa,SAAkB,MAAM,KAAW;AACvD,QAAM,QAAQ,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC,IAAI,OAAO,QAAQ,SAAS;AAClF,MAAI,IAAI,CAAC,QAAQ;AACjB,aAAW,KAAK,SAAS;AAAE,MAAE,IAAI;AAAG,MAAE,IAAI,IAAI,EAAE,SAAS;AAAG,SAAK,EAAE,SAAS;AAAA,EAAK;AACnF;AAEA,SAAS,YAAY,SAAkB,SAAS,KAAW;AACzD,MAAI,QAAQ,WAAW,GAAG;AAAE,YAAQ,CAAC,EAAE,IAAI;AAAG,YAAQ,CAAC,EAAE,IAAI;AAAG;AAAA,EAAQ;AAExE,QAAM,aAAa,QAAQ,WAAW,IAAI,IAAI,CAAC,KAAK,KAAK;AACzD,QAAM,OAAQ,IAAI,KAAK,KAAM,QAAQ;AACrC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,QAAQ,aAAa,IAAI;AAC/B,YAAQ,CAAC,EAAE,IAAI,SAAS,KAAK,IAAI,KAAK;AACtC,YAAQ,CAAC,EAAE,IAAI,SAAS,KAAK,IAAI,KAAK;AAAA,EACxC;AACF;AAIA,SAAS,aACP,MACA,OACA,KAEA,cACA,MACU;AACV,QAAM,QAAQ,MAAM,QAAQ,KAAK,KAAK,KAAK,IAAK,KAAK,KAAK,MAAmB,KAAK,GAAG,IAAK,KAAK,KAAK,SAAS;AAC7G,QAAM,cAAc,mBAAmB,KAAK,KAAK,EAAE;AACnD,QAAM,OAAO,WAAW,OAAO,YAAY;AAC3C,QAAM,OAAO,SAAS,MAAM,OAAO,KAAK,WAAW,oBAAoB,KAAK,cAAc,CAAC;AAC3F,QAAM,EAAE,OAAO,OAAO,IAAI,UAAU,KAAK,KAAK,OAAO,YAAY;AACjE,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,UAAU,MAAM,gBAAgB;AAAA,IAChC,GAAG,KAAK,UAAU,KAAK;AAAA,IACvB,GAAG,KAAK,UAAU,KAAK;AAAA,IACvB,OAAO,MAAM;AAAA,IACb,OAAO;AAAA,IACP,aAAa,KAAK,KAAK,WAAW;AAAA,IAClC,OAAO,KAAK,KAAK,SAAS;AAAA,IAC1B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B;AAAA,IACA,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,YAAY,cAAc;AAAA,IAC1B;AAAA,IACA,WAAW,oBAAI,KAAK;AAAA,IACpB,WAAW,oBAAI,KAAK;AAAA,EACtB;AACF;AAEA,SAAS,0BAA0B,OAAsB,WAA6B;AACpF,QAAM,UAAU;AAChB,QAAM,OAAO,IAAI,IAAI,UAAU,IAAI,CAAC,MAAgB,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAC9D,QAAM,mBAAmB,oBAAI,IAAY;AACzC,QAAM,kBAAkB,oBAAI,IAAwB;AAEpD,aAAW,aAAa,MAAM,YAAY;AACxC,UAAM,QAAQ,UAAU,MAAM,IAAI,CAAC,OAAe,KAAK,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,MAA2C,CAAC,CAAC,CAAC;AACtH,QAAI,CAAC,MAAM,OAAQ;AACnB,cAAU,MAAM,QAAQ,CAAC,OAAe,iBAAiB,IAAI,EAAE,CAAC;AAChE,UAAM,YAAc,UAAU,OAA0D,WAAW,KAA4B;AAC/H,mBAAe,OAAO,SAAS;AAC/B,oBAAgB,IAAI,UAAU,IAAI,KAAK;AAAA,EACzC;AAEA,QAAM,UAAmB,CAAC;AAC1B,aAAW,KAAK,WAAW;AACzB,QAAI,CAAC,iBAAiB,IAAI,EAAE,EAAE,EAAG,SAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,GAAG,GAAG,GAAG,OAAO,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;AAAA,EAC1G;AACA,aAAW,aAAa,MAAM,YAAY;AACxC,UAAM,QAAQ,gBAAgB,IAAI,UAAU,EAAE;AAC9C,QAAI,CAAC,OAAO,OAAQ;AACpB,UAAM,OAAO,cAAc,OAAO,OAAO;AACzC,YAAQ,KAAK,EAAE,IAAI,QAAQ,UAAU,EAAE,IAAI,GAAG,GAAG,GAAG,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AAAA,EACjG;AAEA,QAAM,SAAS,MAAM,UAAU;AAC/B,MAAI,WAAW,oBAAqB,cAAa,SAAS,GAAG;AAAA,WACpD,WAAW,kBAAmB,cAAa,SAAS,GAAG;AAAA,MAC3D,aAAY,SAAS,GAAG;AAE7B,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,GAAG,WAAW,OAAO,GAAG;AAChC,YAAM,QAAQ,gBAAgB,IAAI,MAAM,GAAG,MAAM,CAAC,CAAC;AACnD,aAAO,QAAQ,OAAK;AAAE,UAAE,KAAK,MAAM;AAAG,UAAE,KAAK,MAAM;AAAA,MAAG,CAAC;AAAA,IACzD,OAAO;AACL,YAAM,KAAK,KAAK,IAAI,MAAM,EAAE;AAC5B,UAAI,IAAI;AAAE,WAAG,IAAI,MAAM;AAAG,WAAG,IAAI,MAAM;AAAA,MAAG;AAAA,IAC5C;AAAA,EACF;AACF;AAEA,SAAS,YAAY,OAAsB,WAA6B;AACtE,QAAM,SAAS,MAAM,UAAU;AAC/B,MAAI,WAAW,qBAAqB;AAClC,gCAA4B,WAAW,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;AAAA,EACnE,WAAW,WAAW,mBAAmB;AACvC,8BAA0B,WAAW,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;AAAA,EACjE,OAAO;AACL,UAAM,MAAM,iCAAiC,UAAU,QAAQ,KAAM,KAAM,KAAK,EAAE;AAClF,wBAAoB,WAAW;AAAA,MAC7B,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAQO,SAAS,wBACd,OACA,KACA,OAAuB,CAAC,GACZ;AACZ,QAAM,YAAY,MAAM,MAAM,IAAI,CAAC,MAAM,MAAM,aAAa,MAAM,OAAO,KAAK,GAAG,IAAI,CAAC;AACtF,MAAI,UAAU,WAAW,KAAK,iBAAiB,KAAK,EAAG,QAAO;AAC9D,aAAW,KAAK,WAAW;AAAE,MAAE,IAAI;AAAG,MAAE,IAAI;AAAA,EAAG;AAC/C,OAAK,MAAM,cAAc,CAAC,GAAG,SAAS,EAAG,2BAA0B,OAAO,SAAS;AAAA,MAC9E,aAAY,OAAO,SAAS;AACjC,sBAAoB,SAAS;AAC7B,SAAO;AACT;AAMO,SAAS,2BAA2B,KAAuB,OAAuB,CAAC,GAAY;AACpG,QAAM,MAAe,oBAAI,IAAI;AAE7B,aAAW,SAAS,IAAI,OAAO,OAAO,GAAG;AACvC,eAAW,QAAQ,wBAAwB,OAAO,KAAK,IAAI,GAAG;AAC5D,UAAI,IAAI,KAAK,IAAI,IAAI;AAAA,IACvB;AAAA,EACF;AAGA,aAAW,QAAQ,IAAI,OAAO,GAAG;AAC/B,SAAK,cAAc,CAAC;AACpB,eAAW,aAAa,IAAI,OAAO,GAAG;AACpC,UAAI,UAAU,aAAa,KAAK,GAAI,MAAK,YAAY,KAAK,UAAU,EAAE;AAAA,IACxE;AAAA,EACF;AAEA,SAAO;AACT;AAUO,SAAS,iBAAiB,KAAuB,SAAiB,OAAuB,CAAC,GAAe;AAC9G,QAAM,QAAQ,IAAI,OAAO,IAAI,OAAO;AACpC,SAAO,QAAQ,wBAAwB,OAAO,KAAK,IAAI,IAAI,CAAC;AAC9D;;;ACzRO,SAAS,aAAa,OAAqC;AAChE,QAAM,SAAwB,CAAC;AAC/B,QAAM,WAAW,CAAC,SAAwB;AACxC,eAAW,KAAK,MAAM;AACpB,aAAO,KAAK,CAAC;AACb,UAAI,EAAE,SAAU,UAAS,EAAE,QAAQ;AAAA,IACrC;AAAA,EACF;AACA,WAAS,KAAK;AACd,SAAO;AACT;AAQO,SAAS,gBACd,OACA,MACA,aACe;AACf,QAAM,OAAO,aAAa,KAAK;AAE/B,MAAI,aAAa;AACf,UAAM,UAAU,KAAK,KAAK,OAAK,EAAE,OAAO,WAAW;AACnD,QAAI,SAAS;AACX,aAAO,QAAQ,WAAW,CAAC,SAAS,GAAG,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,IACrE;AAAA,EACF;AAGA,MAAI,QAAQ,IAAM,QAAO,KAAK,OAAO,OAAK,EAAE,UAAU,CAAC;AACvD,QAAM,WAAW,KAAK,OAAO,OAAO,OAAQ,IAAI;AAChD,SAAO,KAAK,OAAO,OAAK,EAAE,SAAS,QAAQ;AAC7C;AAGO,SAAS,mBACd,OAC+D;AAC/D,QAAM,OAAO,aAAa,KAAK;AAC/B,QAAM,SAAwE,CAAC;AAC/E,aAAW,KAAK,MAAM;AACpB,QAAI,CAAC,EAAE,OAAQ;AACf,UAAM,SAAS,KAAK,KAAK,OAAK,EAAE,OAAO,EAAE,MAAM;AAC/C,QAAI,OAAQ,QAAO,KAAK,EAAE,MAAM,QAAQ,IAAI,GAAG,OAAO,EAAE,kBAAkB,CAAC;AAAA,EAC7E;AACA,SAAO;AACT;AAGO,SAAS,uBACd,OACA,qBAC8D;AAC9D,QAAM,OAAO,aAAa,KAAK;AAC/B,QAAM,SAAuE,CAAC;AAC9E,aAAW,QAAQ,qBAAqB;AACtC,UAAM,OAAO,KAAK,KAAK,OAAK,EAAE,OAAO,KAAK,IAAI;AAC9C,UAAM,KAAO,KAAK,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE;AAC5C,QAAI,QAAQ,GAAI,QAAO,KAAK,EAAE,MAAM,IAAI,OAAO,KAAK,SAAS,GAAG,CAAC;AAAA,EACnE;AACA,SAAO;AACT;AAGO,SAAS,kBAAkB,IAAY,IAAY,IAAY,IAAoB;AACxF,SAAO,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,OAAO,CAAC;AAClD;;;AClEA,IAAM,aAAa,CAAC,UAA0B,OAAO,MAAM,SAAS,OAAO,QAAQ,OAAO,MAAM,CAAC,EAAE;AAGnG,IAAM,cAAc,CAAC,UACnB,OAAO,YAAY,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;AAEnF,SAAS,oBACd,OACA,qBACA,QAAQ,oBACO;AACf,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,SAAO;AAAA,IACL,UAAU;AAAA,MACR;AAAA,MACA,aAAa,4BAA4B,MAAM,MAAM;AAAA,MACrD,SAAS;AAAA,MACT,SAAS;AAAA,MACT,cAAc;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,MACR,eAAe,YAAY,CAAC;AAAA,MAC5B,QAAQ;AAAA,QACN,aAAa,eAAe;AAAA,QAC5B,cAAc,eAAe;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAIA,SAAS,WAAW,QAAgB,OAAe,OAAuB;AACxE,SAAO,GAAG,MAAM,KAAK,KAAK,IAAI,KAAK;AACrC;AAEA,SAAS,mBACP,UACA,OACA,WACA,UAAU,GACV,UAAU,GACK;AACf,MAAI,SAAS,UAAW,QAAO,CAAC;AAEhC,QAAM,QAAQ;AACd,QAAM,eAAe;AACrB,QAAM,cAAc;AACpB,QAAM,QAAuB,CAAC;AAE9B,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,UAAM,SAAS,WACX,WAAW,GAAG,QAAQ,IAAI,CAAC,IAAI,OAAO,CAAC,IACvC,WAAW,QAAQ,OAAO,CAAC;AAE/B,UAAM,IAAI,WAAW,KAAK,QAAQ,KAAK,KAAK;AAC5C,UAAM,IAAI,UAAU,QAAQ;AAE5B,UAAM,OAAoB;AAAA,MACxB,IAAI;AAAA,MACJ,OAAO,SAAS,KAAK,SAAS,IAAI,CAAC;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,WAAW,KAAK;AAAA,MACvB,mBAAmB,QAAQ,IAAI,UAAU;AAAA,MACzC,QAAQ,YAAY;AAAA,IACtB;AAEA,UAAM,WAAW,mBAAmB,QAAQ,QAAQ,GAAG,WAAW,GAAG,IAAI,YAAY;AACrF,QAAI,SAAS,SAAS,EAAG,MAAK,WAAW;AAEzC,UAAM,KAAK,IAAI;AAAA,EACjB;AAEA,SAAO;AACT;AAMO,SAAS,qBAAqB,YAAY,GAAkB;AACjE,QAAM,QAAQ,mBAAmB,MAAM,GAAG,WAAW,GAAG,CAAC;AAEzD,QAAM,sBAA4C,MAAM,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,OAAO;AAAA,IAClF,MAAM,EAAE;AAAA,IACR,IAAI,MAAM,IAAI,CAAC,EAAE;AAAA,IACjB,OAAO;AAAA,EACT,EAAE;AAEF,SAAO;AAAA,IACL,UAAU;AAAA,MACR,IAAI,WAAW,KAAK,IAAI,CAAC;AAAA,MACzB,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,MACT,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,MAChC,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,MACR,eAAe,YAAY,CAAC;AAAA,MAC5B,QAAQ;AAAA,QACN,aAAa,eAAe;AAAA,QAC5B,cAAc,eAAe;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|