@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.
Files changed (127) hide show
  1. package/README.md +37 -105
  2. package/dist/chunk-25AJTPMS.js +68 -0
  3. package/dist/chunk-25AJTPMS.js.map +1 -0
  4. package/dist/chunk-64PUANNH.js +151 -0
  5. package/dist/chunk-64PUANNH.js.map +1 -0
  6. package/dist/chunk-ITDZ72JE.js +96 -0
  7. package/dist/chunk-ITDZ72JE.js.map +1 -0
  8. package/dist/{chunk-PDP5CVUL.js → chunk-LOQLNYB3.js} +2 -2
  9. package/dist/chunk-N7HCYULH.js +12 -0
  10. package/dist/chunk-N7HCYULH.js.map +1 -0
  11. package/dist/{chunk-I75TMOE4.js → chunk-P6PKWVYF.js} +2 -2
  12. package/dist/chunk-RFMUATWB.js +753 -0
  13. package/dist/chunk-RFMUATWB.js.map +1 -0
  14. package/dist/chunk-UAMEJG2C.js +267 -0
  15. package/dist/chunk-UAMEJG2C.js.map +1 -0
  16. package/dist/{chunk-LJYSKSCE.js → chunk-W2CAOOJJ.js} +6 -6
  17. package/dist/chunk-W2CAOOJJ.js.map +1 -0
  18. package/dist/{chunk-6NXADJK2.js → chunk-WO4JAAKP.js} +84 -117
  19. package/dist/chunk-WO4JAAKP.js.map +1 -0
  20. package/dist/config/index.cjs +250 -349
  21. package/dist/config/index.cjs.map +1 -1
  22. package/dist/config/index.d.cts +107 -66
  23. package/dist/config/index.d.ts +107 -66
  24. package/dist/config/index.js +52 -34
  25. package/dist/constants/index.cjs +14 -333
  26. package/dist/constants/index.cjs.map +1 -1
  27. package/dist/constants/index.d.cts +5 -243
  28. package/dist/constants/index.d.ts +5 -243
  29. package/dist/constants/index.js +5 -75
  30. package/dist/designSystem-D49xVfr8.d.cts +150 -0
  31. package/dist/designSystem-D49xVfr8.d.ts +150 -0
  32. package/dist/document-BFBwn93X.d.ts +26 -0
  33. package/dist/document-MEJEfxl3.d.cts +26 -0
  34. package/dist/ideaSize-BTJu6thN.d.cts +11 -0
  35. package/dist/ideaSize-RKbms8K6.d.ts +11 -0
  36. package/dist/index-CcF0Jvmb.d.ts +99 -0
  37. package/dist/index-Dt--T2l8.d.cts +99 -0
  38. package/dist/index.cjs +1636 -961
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +350 -27
  41. package/dist/index.d.ts +350 -27
  42. package/dist/index.js +434 -179
  43. package/dist/index.js.map +1 -1
  44. package/dist/{document-B3hnNr-F.d.cts → layer-B2A3Ki48.d.cts} +2 -16
  45. package/dist/{document-B3hnNr-F.d.ts → layer-B2A3Ki48.d.ts} +2 -16
  46. package/dist/layout/index.d.cts +2 -1
  47. package/dist/layout/index.d.ts +2 -1
  48. package/dist/mindmap-BO3YD5qu.d.cts +182 -0
  49. package/dist/mindmap-D0Of0jaZ.d.ts +182 -0
  50. package/dist/parser/index.cjs +745 -179
  51. package/dist/parser/index.cjs.map +1 -1
  52. package/dist/parser/index.d.cts +23 -8
  53. package/dist/parser/index.d.ts +23 -8
  54. package/dist/parser/index.js +7 -2
  55. package/dist/performance/index.cjs +13 -0
  56. package/dist/performance/index.cjs.map +1 -1
  57. package/dist/performance/index.js +2 -2
  58. package/dist/theme/index.cjs +884 -0
  59. package/dist/theme/index.cjs.map +1 -0
  60. package/dist/theme/index.d.cts +2 -0
  61. package/dist/theme/index.d.ts +2 -0
  62. package/dist/theme/index.js +53 -0
  63. package/dist/types/index.d.cts +4 -2
  64. package/dist/types/index.d.ts +4 -2
  65. package/dist/viewport/index.cjs +17 -6
  66. package/dist/viewport/index.cjs.map +1 -1
  67. package/dist/viewport/index.d.cts +6 -4
  68. package/dist/viewport/index.d.ts +6 -4
  69. package/dist/viewport/index.js +2 -2
  70. package/licenses/visualli-design-system/LICENSE +9 -0
  71. package/licenses/visualli-design-system/NOTICE.md +6 -0
  72. package/package.json +12 -4
  73. package/src/config/README.md +2 -4
  74. package/src/config/USAGE_EXAMPLES.md +0 -4
  75. package/src/config/index.ts +3 -4
  76. package/src/constants/index.ts +1 -1
  77. package/src/constants/layout.ts +11 -0
  78. package/src/constants/performanceConstants.ts +8 -27
  79. package/src/generated/README.md +12 -0
  80. package/src/generated/designSystem.ts +758 -0
  81. package/src/generated/geometry/blob.ts +99 -0
  82. package/src/generated/geometry/blobShapes.ts +4 -0
  83. package/src/generated/geometry/color.ts +37 -0
  84. package/src/generated/geometry/container.ts +84 -0
  85. package/src/generated/geometry/detail.ts +22 -0
  86. package/src/generated/geometry/idea.ts +56 -0
  87. package/src/generated/geometry/interaction.ts +122 -0
  88. package/src/generated/geometry/motion.ts +140 -0
  89. package/src/index.ts +18 -1
  90. package/src/parser/configUtils.ts +12 -19
  91. package/src/parser/visualliConverter.ts +71 -112
  92. package/src/parser/visualliParser.ts +16 -1
  93. package/src/rendering/culling.ts +16 -12
  94. package/src/rendering/ideaSize.ts +21 -0
  95. package/src/rendering/nodeGeometry.ts +97 -0
  96. package/src/theme/index.ts +136 -0
  97. package/src/types/document.ts +9 -0
  98. package/src/types/layer.ts +1 -1
  99. package/src/types/mindmap.ts +13 -0
  100. package/src/utils/navigation.ts +33 -63
  101. package/src/viewport/viewportUtils.ts +6 -4
  102. package/dist/animations/index.cjs +0 -146
  103. package/dist/animations/index.cjs.map +0 -1
  104. package/dist/animations/index.d.cts +0 -81
  105. package/dist/animations/index.d.ts +0 -81
  106. package/dist/animations/index.js +0 -35
  107. package/dist/chunk-6NXADJK2.js.map +0 -1
  108. package/dist/chunk-F36SMC3K.js +0 -106
  109. package/dist/chunk-F36SMC3K.js.map +0 -1
  110. package/dist/chunk-G5H3P4YZ.js +0 -273
  111. package/dist/chunk-G5H3P4YZ.js.map +0 -1
  112. package/dist/chunk-LDJRGT2Q.js +0 -163
  113. package/dist/chunk-LDJRGT2Q.js.map +0 -1
  114. package/dist/chunk-LJYSKSCE.js.map +0 -1
  115. package/dist/chunk-LNTJTDB2.js +0 -349
  116. package/dist/chunk-LNTJTDB2.js.map +0 -1
  117. package/dist/mindmap-DWS0WZT_.d.cts +0 -118
  118. package/dist/mindmap-DWS0WZT_.d.ts +0 -118
  119. package/src/animations/constants.ts +0 -72
  120. package/src/animations/easing.ts +0 -70
  121. package/src/animations/index.ts +0 -2
  122. package/src/config/blobShapes.ts +0 -146
  123. package/src/config/textScaling.ts +0 -54
  124. package/src/constants/design.ts +0 -281
  125. /package/dist/{chunk-PDP5CVUL.js.map → chunk-LOQLNYB3.js.map} +0 -0
  126. /package/dist/{chunk-I75TMOE4.js.map → chunk-P6PKWVYF.js.map} +0 -0
  127. /package/dist/{animations → theme}/index.js.map +0 -0
@@ -32,6 +32,7 @@ __export(parser_exports, {
32
32
  getChildLayers: () => getChildLayers,
33
33
  getNodeConnections: () => getNodeConnections,
34
34
  getNodesForLayer: () => getNodesForLayer,
35
+ getSemanticAnchors: () => getSemanticAnchors,
35
36
  getTopLevelConnections: () => getTopLevelConnections,
36
37
  getVisibleNodes: () => getVisibleNodes,
37
38
  loadVisualliFileFromFile: () => loadVisualliFileFromFile,
@@ -106,6 +107,13 @@ function parseVisualliFile(content) {
106
107
  }
107
108
  break;
108
109
  }
110
+ case "extension": {
111
+ const id = obj["id"];
112
+ if (typeof id === "string") {
113
+ (doc.extensions ?? (doc.extensions = {}))[id] = Array.isArray(obj["data"]) ? obj["data"] : [];
114
+ }
115
+ break;
116
+ }
109
117
  default:
110
118
  break;
111
119
  }
@@ -143,6 +151,11 @@ function loadVisualliFileFromFile(file) {
143
151
  reader.readAsText(file);
144
152
  });
145
153
  }
154
+ function getSemanticAnchors(doc) {
155
+ const raw = doc.extensions?.["semantic-anchors"];
156
+ if (!Array.isArray(raw)) return [];
157
+ return raw.filter((a) => !!a && typeof a.word === "string" && typeof a.description === "string");
158
+ }
146
159
  function getChildLayers(doc, nodeId) {
147
160
  const result = [];
148
161
  for (const layer of doc.layers.values()) {
@@ -166,6 +179,679 @@ function countLayersBeneath(doc, nodeId, visited = /* @__PURE__ */ new Set()) {
166
179
  return maxDepth;
167
180
  }
168
181
 
182
+ // src/generated/designSystem.ts
183
+ var TOKENS = {
184
+ "light": {
185
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
186
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
187
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
188
+ "font-note": "Caveat, Kalam, cursive",
189
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
190
+ "canvas": "#f6f3ee",
191
+ "surface": "#ffffff",
192
+ "surface-sunken": "#f0ece5",
193
+ "surface-overlay": "#ffffff",
194
+ "line": "#e4dfd6",
195
+ "line-strong": "#7a7f94",
196
+ "ink": "#182140",
197
+ "ink-muted": "#4f5671",
198
+ "ink-subtle": "#5f647c",
199
+ "action": "#182140",
200
+ "on-action": "#ffffff",
201
+ "focus": "#325e8c",
202
+ "link": "#2f5a87",
203
+ "selection": "rgba(18, 199, 211, 0.28)",
204
+ "node-ink": "#182140",
205
+ "edge": "#2a3048",
206
+ "edge-label": "#4f5671",
207
+ "topic-teal": "#87f2f8",
208
+ "topic-teal-ring": "#00cdd5",
209
+ "topic-harbor": "#bcdbff",
210
+ "topic-harbor-ring": "#76b2f5",
211
+ "topic-iris": "#e0c8fe",
212
+ "topic-iris-ring": "#bd96ea",
213
+ "topic-berry": "#ffbdc4",
214
+ "topic-berry-ring": "#f47e8f",
215
+ "topic-coral": "#ffc7b2",
216
+ "topic-coral-ring": "#f38e65",
217
+ "topic-amber": "#ffcf9d",
218
+ "topic-amber-ring": "#eb9c38",
219
+ "topic-sun": "#ffea94",
220
+ "topic-sun-ring": "#dfbd04",
221
+ "topic-stone": "#e0dacf",
222
+ "topic-stone-ring": "#bab09f",
223
+ "space-1": "4px",
224
+ "space-2": "8px",
225
+ "space-3": "12px",
226
+ "space-4": "16px",
227
+ "space-7": "48px",
228
+ "radius-sm": "10px",
229
+ "radius-md": "16px",
230
+ "radius-lg": "24px",
231
+ "radius-pill": "999px",
232
+ "shadow-float": "0 1px 2px rgba(24, 33, 64, 0.06), 0 8px 24px rgba(24, 33, 64, 0.08)",
233
+ "shadow-pop": "0 2px 4px rgba(24, 33, 64, 0.08), 0 16px 40px rgba(24, 33, 64, 0.14)",
234
+ "node-width": "200px",
235
+ "node-height": "148px",
236
+ "node-stroke": "3px",
237
+ "edge-width": "2.5px",
238
+ "edge-gap": "15px",
239
+ "edge-arc-max": "45px",
240
+ "immersion-alpha": "0.15",
241
+ "zoom-min": "0.3",
242
+ "zoom-max": "5",
243
+ "duration-instant": "100ms",
244
+ "duration-quick": "160ms",
245
+ "duration-base": "240ms",
246
+ "duration-zoom": "500ms",
247
+ "duration-reveal": "420ms",
248
+ "stagger-reveal": "70ms",
249
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
250
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
251
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
252
+ "z-chrome": "10",
253
+ "z-card": "20",
254
+ "z-menu": "40"
255
+ },
256
+ "dark": {
257
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
258
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
259
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
260
+ "font-note": "Caveat, Kalam, cursive",
261
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
262
+ "canvas": "#0f1220",
263
+ "surface": "#171b2b",
264
+ "surface-sunken": "#0f1220",
265
+ "surface-overlay": "#212639",
266
+ "line": "#2b3148",
267
+ "line-strong": "#6c7392",
268
+ "ink": "#eef0f7",
269
+ "ink-muted": "#b3b8cc",
270
+ "ink-subtle": "#8f95ae",
271
+ "action": "#f6f3ee",
272
+ "on-action": "#182140",
273
+ "focus": "#12c7d3",
274
+ "link": "#5fd8e1",
275
+ "selection": "rgba(18, 199, 211, 0.32)",
276
+ "node-ink": "#182140",
277
+ "edge": "#c9cddc",
278
+ "edge-label": "#b3b8cc",
279
+ "topic-teal": "#87f2f8",
280
+ "topic-teal-ring": "#0fc5cd",
281
+ "topic-harbor": "#bcdbff",
282
+ "topic-harbor-ring": "#73aceb",
283
+ "topic-iris": "#e0c8fe",
284
+ "topic-iris-ring": "#b691e1",
285
+ "topic-berry": "#ffbdc4",
286
+ "topic-berry-ring": "#eb798a",
287
+ "topic-coral": "#ffc7b2",
288
+ "topic-coral-ring": "#ea8962",
289
+ "topic-amber": "#ffcf9d",
290
+ "topic-amber-ring": "#e29737",
291
+ "topic-sun": "#ffea94",
292
+ "topic-sun-ring": "#d8b70a",
293
+ "topic-stone": "#e0dacf",
294
+ "topic-stone-ring": "#b4a999",
295
+ "space-1": "4px",
296
+ "space-2": "8px",
297
+ "space-3": "12px",
298
+ "space-4": "16px",
299
+ "space-7": "48px",
300
+ "radius-sm": "10px",
301
+ "radius-md": "16px",
302
+ "radius-lg": "24px",
303
+ "radius-pill": "999px",
304
+ "shadow-float": "0 1px 2px rgba(0, 0, 0, 0.40), 0 8px 24px rgba(0, 0, 0, 0.35)",
305
+ "shadow-pop": "0 2px 4px rgba(0, 0, 0, 0.50), 0 16px 40px rgba(0, 0, 0, 0.50)",
306
+ "node-width": "200px",
307
+ "node-height": "148px",
308
+ "node-stroke": "3px",
309
+ "edge-width": "2.5px",
310
+ "edge-gap": "15px",
311
+ "edge-arc-max": "45px",
312
+ "immersion-alpha": "0.15",
313
+ "zoom-min": "0.3",
314
+ "zoom-max": "5",
315
+ "duration-instant": "100ms",
316
+ "duration-quick": "160ms",
317
+ "duration-base": "240ms",
318
+ "duration-zoom": "500ms",
319
+ "duration-reveal": "420ms",
320
+ "stagger-reveal": "70ms",
321
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
322
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
323
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
324
+ "z-chrome": "10",
325
+ "z-card": "20",
326
+ "z-menu": "40"
327
+ },
328
+ "focus-light": {
329
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
330
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
331
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
332
+ "font-note": "Caveat, Kalam, cursive",
333
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
334
+ "canvas": "#f4f2ee",
335
+ "surface": "#ffffff",
336
+ "surface-sunken": "#f0ece5",
337
+ "surface-overlay": "#ffffff",
338
+ "line": "#e4dfd6",
339
+ "line-strong": "#7a7f94",
340
+ "ink": "#182140",
341
+ "ink-muted": "#4f5671",
342
+ "ink-subtle": "#5f647c",
343
+ "action": "#182140",
344
+ "on-action": "#ffffff",
345
+ "focus": "#325e8c",
346
+ "link": "#2f5a87",
347
+ "selection": "rgba(18, 199, 211, 0.28)",
348
+ "node-ink": "#182140",
349
+ "edge": "#5a6079",
350
+ "edge-label": "#5a6079",
351
+ "topic-teal": "#bce8ea",
352
+ "topic-teal-ring": "#67c6cb",
353
+ "topic-harbor": "#c9d9ec",
354
+ "topic-harbor-ring": "#8bb2de",
355
+ "topic-iris": "#d9cfe8",
356
+ "topic-iris-ring": "#b79ed4",
357
+ "topic-berry": "#edc6c9",
358
+ "topic-berry-ring": "#da9099",
359
+ "topic-coral": "#eecec1",
360
+ "topic-coral-ring": "#db9b82",
361
+ "topic-amber": "#eed4ba",
362
+ "topic-amber-ring": "#d6a570",
363
+ "topic-sun": "#f4eac1",
364
+ "topic-sun-ring": "#d2bf73",
365
+ "topic-stone": "#dddad5",
366
+ "topic-stone-ring": "#bab09f",
367
+ "space-1": "4px",
368
+ "space-2": "8px",
369
+ "space-3": "12px",
370
+ "space-4": "16px",
371
+ "space-7": "48px",
372
+ "radius-sm": "10px",
373
+ "radius-md": "16px",
374
+ "radius-lg": "24px",
375
+ "radius-pill": "999px",
376
+ "shadow-float": "0 1px 2px rgba(24, 33, 64, 0.06), 0 8px 24px rgba(24, 33, 64, 0.08)",
377
+ "shadow-pop": "0 2px 4px rgba(24, 33, 64, 0.08), 0 16px 40px rgba(24, 33, 64, 0.14)",
378
+ "node-width": "200px",
379
+ "node-height": "148px",
380
+ "node-stroke": "3px",
381
+ "edge-width": "2.5px",
382
+ "edge-gap": "15px",
383
+ "edge-arc-max": "45px",
384
+ "immersion-alpha": "0.15",
385
+ "zoom-min": "0.3",
386
+ "zoom-max": "5",
387
+ "duration-instant": "100ms",
388
+ "duration-quick": "160ms",
389
+ "duration-base": "240ms",
390
+ "duration-zoom": "500ms",
391
+ "duration-reveal": "420ms",
392
+ "stagger-reveal": "70ms",
393
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
394
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
395
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
396
+ "z-chrome": "10",
397
+ "z-card": "20",
398
+ "z-menu": "40"
399
+ },
400
+ "focus-dark": {
401
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
402
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
403
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
404
+ "font-note": "Caveat, Kalam, cursive",
405
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
406
+ "canvas": "#12141c",
407
+ "surface": "#171b2b",
408
+ "surface-sunken": "#0f1220",
409
+ "surface-overlay": "#212639",
410
+ "line": "#2b3148",
411
+ "line-strong": "#6c7392",
412
+ "ink": "#eef0f7",
413
+ "ink-muted": "#b3b8cc",
414
+ "ink-subtle": "#8f95ae",
415
+ "action": "#f6f3ee",
416
+ "on-action": "#182140",
417
+ "focus": "#12c7d3",
418
+ "link": "#5fd8e1",
419
+ "selection": "rgba(18, 199, 211, 0.32)",
420
+ "node-ink": "#182140",
421
+ "edge": "#a9aec0",
422
+ "edge-label": "#b3b8cc",
423
+ "topic-teal": "#bce8ea",
424
+ "topic-teal-ring": "#71bdc1",
425
+ "topic-harbor": "#c9d9ec",
426
+ "topic-harbor-ring": "#8cabce",
427
+ "topic-iris": "#d9cfe8",
428
+ "topic-iris-ring": "#ae9bc6",
429
+ "topic-berry": "#edc6c9",
430
+ "topic-berry-ring": "#cc8e95",
431
+ "topic-coral": "#eecec1",
432
+ "topic-coral-ring": "#cd9884",
433
+ "topic-amber": "#eed4ba",
434
+ "topic-amber-ring": "#c9a176",
435
+ "topic-sun": "#f4eac1",
436
+ "topic-sun-ring": "#c9b97a",
437
+ "topic-stone": "#dddad5",
438
+ "topic-stone-ring": "#b4a999",
439
+ "space-1": "4px",
440
+ "space-2": "8px",
441
+ "space-3": "12px",
442
+ "space-4": "16px",
443
+ "space-7": "48px",
444
+ "radius-sm": "10px",
445
+ "radius-md": "16px",
446
+ "radius-lg": "24px",
447
+ "radius-pill": "999px",
448
+ "shadow-float": "0 1px 2px rgba(24, 33, 64, 0.06), 0 8px 24px rgba(24, 33, 64, 0.08)",
449
+ "shadow-pop": "0 2px 4px rgba(24, 33, 64, 0.08), 0 16px 40px rgba(24, 33, 64, 0.14)",
450
+ "node-width": "200px",
451
+ "node-height": "148px",
452
+ "node-stroke": "3px",
453
+ "edge-width": "2.5px",
454
+ "edge-gap": "15px",
455
+ "edge-arc-max": "45px",
456
+ "immersion-alpha": "0.15",
457
+ "zoom-min": "0.3",
458
+ "zoom-max": "5",
459
+ "duration-instant": "100ms",
460
+ "duration-quick": "160ms",
461
+ "duration-base": "240ms",
462
+ "duration-zoom": "500ms",
463
+ "duration-reveal": "420ms",
464
+ "stagger-reveal": "70ms",
465
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
466
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
467
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
468
+ "z-chrome": "10",
469
+ "z-card": "20",
470
+ "z-menu": "40"
471
+ },
472
+ "colorsafe-light": {
473
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
474
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
475
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
476
+ "font-note": "Caveat, Kalam, cursive",
477
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
478
+ "canvas": "#f6f3ee",
479
+ "surface": "#ffffff",
480
+ "surface-sunken": "#f0ece5",
481
+ "surface-overlay": "#ffffff",
482
+ "line": "#e4dfd6",
483
+ "line-strong": "#7a7f94",
484
+ "ink": "#182140",
485
+ "ink-muted": "#4f5671",
486
+ "ink-subtle": "#5f647c",
487
+ "action": "#182140",
488
+ "on-action": "#ffffff",
489
+ "focus": "#325e8c",
490
+ "link": "#2f5a87",
491
+ "selection": "rgba(18, 199, 211, 0.28)",
492
+ "node-ink": "#182140",
493
+ "edge": "#2a3048",
494
+ "edge-label": "#4f5671",
495
+ "topic-teal": "#b0ecbc",
496
+ "topic-teal-ring": "#6cc982",
497
+ "topic-harbor": "#abdbfe",
498
+ "topic-harbor-ring": "#60b4ec",
499
+ "topic-iris": "#f6bde2",
500
+ "topic-iris-ring": "#dc87c0",
501
+ "topic-berry": "#feb79e",
502
+ "topic-berry-ring": "#ec7f58",
503
+ "topic-coral": "#fece96",
504
+ "topic-coral-ring": "#e49d41",
505
+ "topic-amber": "#b2e8fa",
506
+ "topic-amber-ring": "#5cc4e2",
507
+ "topic-sun": "#f6f097",
508
+ "topic-sun-ring": "#d0c637",
509
+ "topic-stone": "#dbdbdb",
510
+ "topic-stone-ring": "#b7afb1",
511
+ "space-1": "4px",
512
+ "space-2": "8px",
513
+ "space-3": "12px",
514
+ "space-4": "16px",
515
+ "space-7": "48px",
516
+ "radius-sm": "10px",
517
+ "radius-md": "16px",
518
+ "radius-lg": "24px",
519
+ "radius-pill": "999px",
520
+ "shadow-float": "0 1px 2px rgba(24, 33, 64, 0.06), 0 8px 24px rgba(24, 33, 64, 0.08)",
521
+ "shadow-pop": "0 2px 4px rgba(24, 33, 64, 0.08), 0 16px 40px rgba(24, 33, 64, 0.14)",
522
+ "node-width": "200px",
523
+ "node-height": "148px",
524
+ "node-stroke": "3px",
525
+ "edge-width": "2.5px",
526
+ "edge-gap": "15px",
527
+ "edge-arc-max": "45px",
528
+ "immersion-alpha": "0.15",
529
+ "zoom-min": "0.3",
530
+ "zoom-max": "5",
531
+ "duration-instant": "100ms",
532
+ "duration-quick": "160ms",
533
+ "duration-base": "240ms",
534
+ "duration-zoom": "500ms",
535
+ "duration-reveal": "420ms",
536
+ "stagger-reveal": "70ms",
537
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
538
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
539
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
540
+ "z-chrome": "10",
541
+ "z-card": "20",
542
+ "z-menu": "40"
543
+ },
544
+ "colorsafe-dark": {
545
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
546
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
547
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
548
+ "font-note": "Caveat, Kalam, cursive",
549
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
550
+ "canvas": "#0f1220",
551
+ "surface": "#171b2b",
552
+ "surface-sunken": "#0f1220",
553
+ "surface-overlay": "#212639",
554
+ "line": "#2b3148",
555
+ "line-strong": "#6c7392",
556
+ "ink": "#eef0f7",
557
+ "ink-muted": "#b3b8cc",
558
+ "ink-subtle": "#8f95ae",
559
+ "action": "#f6f3ee",
560
+ "on-action": "#182140",
561
+ "focus": "#12c7d3",
562
+ "link": "#5fd8e1",
563
+ "selection": "rgba(18, 199, 211, 0.32)",
564
+ "node-ink": "#182140",
565
+ "edge": "#c9cddc",
566
+ "edge-label": "#b3b8cc",
567
+ "topic-teal": "#b0ecbc",
568
+ "topic-teal-ring": "#69c27e",
569
+ "topic-harbor": "#abdbfe",
570
+ "topic-harbor-ring": "#5eade2",
571
+ "topic-iris": "#f6bde2",
572
+ "topic-iris-ring": "#d383b9",
573
+ "topic-berry": "#feb79e",
574
+ "topic-berry-ring": "#e37a55",
575
+ "topic-coral": "#fece96",
576
+ "topic-coral-ring": "#db9840",
577
+ "topic-amber": "#b2e8fa",
578
+ "topic-amber-ring": "#5bbdda",
579
+ "topic-sun": "#f6f097",
580
+ "topic-sun-ring": "#c9bf37",
581
+ "topic-stone": "#dbdbdb",
582
+ "topic-stone-ring": "#b1a8aa",
583
+ "space-1": "4px",
584
+ "space-2": "8px",
585
+ "space-3": "12px",
586
+ "space-4": "16px",
587
+ "space-7": "48px",
588
+ "radius-sm": "10px",
589
+ "radius-md": "16px",
590
+ "radius-lg": "24px",
591
+ "radius-pill": "999px",
592
+ "shadow-float": "0 1px 2px rgba(24, 33, 64, 0.06), 0 8px 24px rgba(24, 33, 64, 0.08)",
593
+ "shadow-pop": "0 2px 4px rgba(24, 33, 64, 0.08), 0 16px 40px rgba(24, 33, 64, 0.14)",
594
+ "node-width": "200px",
595
+ "node-height": "148px",
596
+ "node-stroke": "3px",
597
+ "edge-width": "2.5px",
598
+ "edge-gap": "15px",
599
+ "edge-arc-max": "45px",
600
+ "immersion-alpha": "0.15",
601
+ "zoom-min": "0.3",
602
+ "zoom-max": "5",
603
+ "duration-instant": "100ms",
604
+ "duration-quick": "160ms",
605
+ "duration-base": "240ms",
606
+ "duration-zoom": "500ms",
607
+ "duration-reveal": "420ms",
608
+ "stagger-reveal": "70ms",
609
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
610
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
611
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
612
+ "z-chrome": "10",
613
+ "z-card": "20",
614
+ "z-menu": "40"
615
+ },
616
+ "contrast-light": {
617
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
618
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
619
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
620
+ "font-note": "Caveat, Kalam, cursive",
621
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
622
+ "canvas": "#ffffff",
623
+ "surface": "#ffffff",
624
+ "surface-sunken": "#f2f2f2",
625
+ "surface-overlay": "#ffffff",
626
+ "line": "#5c6178",
627
+ "line-strong": "#000000",
628
+ "ink": "#000000",
629
+ "ink-muted": "#1f2433",
630
+ "ink-subtle": "#3a3f52",
631
+ "action": "#000000",
632
+ "on-action": "#ffffff",
633
+ "focus": "#0b4a8f",
634
+ "link": "#0b4a8f",
635
+ "selection": "rgba(18, 199, 211, 0.28)",
636
+ "node-ink": "#000000",
637
+ "edge": "#000000",
638
+ "edge-label": "#1f2433",
639
+ "topic-teal": "#87f2f8",
640
+ "topic-teal-ring": "#006b70",
641
+ "topic-harbor": "#bcdbff",
642
+ "topic-harbor-ring": "#0e599d",
643
+ "topic-iris": "#e0c8fe",
644
+ "topic-iris-ring": "#683b92",
645
+ "topic-berry": "#ffbdc4",
646
+ "topic-berry-ring": "#96173a",
647
+ "topic-coral": "#ffc7b2",
648
+ "topic-coral-ring": "#923400",
649
+ "topic-amber": "#ffcf9d",
650
+ "topic-amber-ring": "#7e4d00",
651
+ "topic-sun": "#ffea94",
652
+ "topic-sun-ring": "#7a6600",
653
+ "topic-stone": "#e0dacf",
654
+ "topic-stone-ring": "#63594b",
655
+ "space-1": "4px",
656
+ "space-2": "8px",
657
+ "space-3": "12px",
658
+ "space-4": "16px",
659
+ "space-7": "48px",
660
+ "radius-sm": "10px",
661
+ "radius-md": "16px",
662
+ "radius-lg": "24px",
663
+ "radius-pill": "999px",
664
+ "shadow-float": "none",
665
+ "shadow-pop": "none",
666
+ "node-width": "200px",
667
+ "node-height": "148px",
668
+ "node-stroke": "3px",
669
+ "edge-width": "2.5px",
670
+ "edge-gap": "15px",
671
+ "edge-arc-max": "45px",
672
+ "immersion-alpha": "0.15",
673
+ "zoom-min": "0.3",
674
+ "zoom-max": "5",
675
+ "duration-instant": "100ms",
676
+ "duration-quick": "160ms",
677
+ "duration-base": "240ms",
678
+ "duration-zoom": "500ms",
679
+ "duration-reveal": "420ms",
680
+ "stagger-reveal": "70ms",
681
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
682
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
683
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
684
+ "z-chrome": "10",
685
+ "z-card": "20",
686
+ "z-menu": "40"
687
+ },
688
+ "contrast-dark": {
689
+ "font-display": '"Atkinson Hyperlegible Next", system-ui, sans-serif',
690
+ "font-ui": '"Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif',
691
+ "font-hand": 'Kalam, "Atkinson Hyperlegible Next", cursive',
692
+ "font-note": "Caveat, Kalam, cursive",
693
+ "font-mono": '"Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace',
694
+ "canvas": "#000000",
695
+ "surface": "#000000",
696
+ "surface-sunken": "#0d0d0d",
697
+ "surface-overlay": "#0d0d0d",
698
+ "line": "#9aa0b8",
699
+ "line-strong": "#ffffff",
700
+ "ink": "#ffffff",
701
+ "ink-muted": "#e6e8f0",
702
+ "ink-subtle": "#c8ccda",
703
+ "action": "#ffffff",
704
+ "on-action": "#000000",
705
+ "focus": "#5fe8f0",
706
+ "link": "#7ff0f5",
707
+ "selection": "rgba(18, 199, 211, 0.32)",
708
+ "node-ink": "#000000",
709
+ "edge": "#ffffff",
710
+ "edge-label": "#e6e8f0",
711
+ "topic-teal": "#87f2f8",
712
+ "topic-teal-ring": "#64eff7",
713
+ "topic-harbor": "#bcdbff",
714
+ "topic-harbor-ring": "#b0d5fe",
715
+ "topic-iris": "#e0c8fe",
716
+ "topic-iris-ring": "#dcbfff",
717
+ "topic-berry": "#ffbdc4",
718
+ "topic-berry-ring": "#feb3bb",
719
+ "topic-coral": "#ffc7b2",
720
+ "topic-coral-ring": "#ffbea5",
721
+ "topic-amber": "#ffcf9d",
722
+ "topic-amber-ring": "#ffc78a",
723
+ "topic-sun": "#ffea94",
724
+ "topic-sun-ring": "#ffe26d",
725
+ "topic-stone": "#e0dacf",
726
+ "topic-stone-ring": "#ddd3c2",
727
+ "space-1": "4px",
728
+ "space-2": "8px",
729
+ "space-3": "12px",
730
+ "space-4": "16px",
731
+ "space-7": "48px",
732
+ "radius-sm": "10px",
733
+ "radius-md": "16px",
734
+ "radius-lg": "24px",
735
+ "radius-pill": "999px",
736
+ "shadow-float": "none",
737
+ "shadow-pop": "none",
738
+ "node-width": "200px",
739
+ "node-height": "148px",
740
+ "node-stroke": "3px",
741
+ "edge-width": "2.5px",
742
+ "edge-gap": "15px",
743
+ "edge-arc-max": "45px",
744
+ "immersion-alpha": "0.15",
745
+ "zoom-min": "0.3",
746
+ "zoom-max": "5",
747
+ "duration-instant": "100ms",
748
+ "duration-quick": "160ms",
749
+ "duration-base": "240ms",
750
+ "duration-zoom": "500ms",
751
+ "duration-reveal": "420ms",
752
+ "stagger-reveal": "70ms",
753
+ "ease-zoom": "cubic-bezier(0.2, 0.8, 0.2, 1)",
754
+ "ease-standard": "cubic-bezier(0.4, 0, 0.2, 1)",
755
+ "ease-bloom": "cubic-bezier(0.34, 1.4, 0.64, 1)",
756
+ "z-chrome": "10",
757
+ "z-card": "20",
758
+ "z-menu": "40"
759
+ }
760
+ };
761
+ var TOPICS = [
762
+ "teal",
763
+ "harbor",
764
+ "iris",
765
+ "berry",
766
+ "coral",
767
+ "amber",
768
+ "sun",
769
+ "stone"
770
+ ];
771
+
772
+ // src/generated/geometry/color.ts
773
+ var TOPIC_ORDER = ["teal", "harbor", "iris", "berry", "coral", "amber", "sun", "stone"];
774
+ function topicFromName(color) {
775
+ if (!color) return null;
776
+ const c = color.trim().toLowerCase();
777
+ return TOPIC_ORDER.includes(c) ? c : null;
778
+ }
779
+ function topicFor(color, siblingIndex) {
780
+ if (!color || !color.trim()) return TOPIC_ORDER[(siblingIndex % TOPIC_ORDER.length + TOPIC_ORDER.length) % TOPIC_ORDER.length];
781
+ return topicFromName(color);
782
+ }
783
+ var CUSTOM = {
784
+ /** The ring is the fill with each RGB channel multiplied by this. */
785
+ ringShade: 0.78
786
+ };
787
+ function customColor(color) {
788
+ const m = /^#?([0-9a-f]{6})$/i.exec((color || "").trim());
789
+ if (!m) return { fill: color, ring: null };
790
+ const n = parseInt(m[1], 16), f = CUSTOM.ringShade;
791
+ const r = Math.round((n >> 16 & 255) * f), g = Math.round((n >> 8 & 255) * f), b = Math.round((n & 255) * f);
792
+ return { fill: color.trim(), ring: "#" + (1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1) };
793
+ }
794
+
795
+ // src/theme/index.ts
796
+ function ideaColor(color, siblingIndex) {
797
+ const topic = topicFor(color, siblingIndex);
798
+ return topic ? { topic, custom: null } : { topic: null, custom: customColor(color) };
799
+ }
800
+
801
+ // src/generated/geometry/idea.ts
802
+ var LABEL_GROWTH = { idea: 1.3, connector: 1.6 };
803
+ var IDEA = {
804
+ /** Width an idea starts at… */
805
+ baseWidth: { root: 240, node: 200, mini: 120 },
806
+ /** …and the widest it gets before it grows taller instead. */
807
+ maxWidth: { root: 400, node: 360, mini: 200 },
808
+ /** Width grows in steps of this. */
809
+ step: 20,
810
+ /** Height = width × aspect (at least `minRy` × 2), more if the label needs it. */
811
+ aspect: 0.74,
812
+ minRy: 64,
813
+ /** The label's box is the idea's width less this (22 each side). */
814
+ labelInset: 44,
815
+ /** The idea widens until its label fits in this many lines. */
816
+ labelLines: 3,
817
+ /** Label size (before the label scale and zoom growth), weight from the canvas type styles. */
818
+ labelSize: { root: 30, node: 22, mini: 15 },
819
+ labelLineHeight: 1.15,
820
+ /** The label may fill at most this share of the idea's height. */
821
+ labelFillHeight: 0.7
822
+ };
823
+ function wrapLines(text, maxWidth, measure) {
824
+ const words = text.split(/\s+/).filter(Boolean);
825
+ const lines = [];
826
+ let cur = "";
827
+ for (const w of words) {
828
+ const next = cur ? `${cur} ${w}` : w;
829
+ if (cur && measure(next) > maxWidth) {
830
+ lines.push(cur);
831
+ cur = w;
832
+ } else cur = next;
833
+ }
834
+ if (cur) lines.push(cur);
835
+ return lines.length ? lines : [""];
836
+ }
837
+ function ideaSize(kind, label, measure, labelScale = 1) {
838
+ const px = IDEA.labelSize[kind] * labelScale * LABEL_GROWTH.idea;
839
+ const fit = (w) => wrapLines(label, w - IDEA.labelInset, (t) => measure(t, px));
840
+ const base = IDEA.baseWidth[kind], max = IDEA.maxWidth[kind];
841
+ let width = base, lines = fit(width);
842
+ while (lines.length > IDEA.labelLines && width < max) {
843
+ width = Math.min(max, width + IDEA.step);
844
+ lines = fit(width);
845
+ }
846
+ const rx = width / 2;
847
+ const ry = Math.max(IDEA.minRy, rx * IDEA.aspect, lines.length * px * IDEA.labelLineHeight / 2 / IDEA.labelFillHeight);
848
+ return { width, height: ry * 2, rx, ry, lines };
849
+ }
850
+
851
+ // src/rendering/ideaSize.ts
852
+ var approximateMeasure = (text, px) => text.length * px * 0.5;
853
+ var ideaKindOf = (layer, index) => layer.level === 0 && (layer.layout ?? "radial") === "radial" && index === 0 ? "root" : "node";
854
+
169
855
  // src/layout/circularLayout.ts
170
856
  function applyCircularLayout(nodes, options = {}) {
171
857
  const {
@@ -273,26 +959,10 @@ function resolveNodeOverlaps(nodes, maxIterations = 10) {
273
959
  if (!any) break;
274
960
  }
275
961
  }
276
- var COLOR_PALETTE = [
277
- "#12C7D3",
278
- "#325E8C",
279
- "#8A70A6",
280
- "#F54A57",
281
- "#FF6C4D",
282
- "#F28C16",
283
- "#FFD347",
284
- "#12C7D3",
285
- "#7F7F7F",
286
- "#8D8D8D",
287
- "#12C7D3"
288
- ];
289
- function getRandomColorForNode(nodeId) {
290
- let hash = 0;
291
- for (let i = 0; i < nodeId.length; i++) {
292
- hash = nodeId.charCodeAt(i) + ((hash << 5) - hash);
293
- }
294
- const index = Math.abs(hash) % COLOR_PALETTE.length;
295
- return COLOR_PALETTE[index];
962
+ function hasFilePositions(layer) {
963
+ const ps = layer.nodes.map((n) => n.position);
964
+ if (!ps.length || !ps.every((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))) return false;
965
+ return ps.length === 1 || ps.some((p) => p.x !== ps[0].x || p.y !== ps[0].y);
296
966
  }
297
967
  function applyFormation(nodes, formation) {
298
968
  if (nodes.length === 0) return;
@@ -356,44 +1026,34 @@ function proxyRadial(proxies, radius = 500) {
356
1026
  proxies[i].y = radius * Math.sin(angle);
357
1027
  }
358
1028
  }
359
- function calculateNodeWidth(title) {
360
- return Math.max(200, title.length * 8 + 40);
361
- }
362
- function makeFlatNode(nodeId, label, summary, layer, color, branchCount, x = 0, y = 0) {
1029
+ function makeFlatNode(node, layer, doc, siblingIndex, opts) {
1030
+ const label = Array.isArray(node.data.label) ? node.data.label.join(" ") : node.data.label || "Untitled";
1031
+ const branchCount = countLayersBeneath(doc, node.id);
1032
+ const kind = ideaKindOf(layer, siblingIndex);
1033
+ const size = ideaSize(kind, label, opts.measure ?? approximateMeasure, opts.labelScale ?? 1);
1034
+ const { topic, custom } = ideaColor(node.data.color, siblingIndex);
363
1035
  return {
364
- id: nodeId,
1036
+ id: node.id,
365
1037
  parentId: layer.parentNodeId ?? null,
366
- x,
367
- y,
1038
+ x: node.position?.x ?? 0,
1039
+ y: node.position?.y ?? 0,
368
1040
  level: layer.level,
369
1041
  title: label,
370
- description: summary,
371
- color,
372
- width: calculateNodeWidth(label),
373
- height: 80,
1042
+ description: node.data.summary || "",
1043
+ color: node.data.color ?? "",
1044
+ ...topic ? { topic } : {},
1045
+ ...custom ? { custom } : {},
1046
+ kind,
1047
+ width: size.width,
1048
+ height: size.height,
374
1049
  isExpanded: branchCount > 0,
375
1050
  branchCount,
376
1051
  createdAt: /* @__PURE__ */ new Date(),
377
1052
  updatedAt: /* @__PURE__ */ new Date()
378
1053
  };
379
1054
  }
380
- function convertLayerWithContainers(layer, doc) {
1055
+ function layoutLayerWithContainers(layer, flatNodes) {
381
1056
  const PADDING = 80;
382
- const flatNodes = [];
383
- for (const node of layer.nodes) {
384
- const label = Array.isArray(node.data.label) ? node.data.label.join(" ") : node.data.label || "Untitled";
385
- const branchCount = countLayersBeneath(doc, node.id);
386
- flatNodes.push(
387
- makeFlatNode(
388
- node.id,
389
- label,
390
- node.data.summary || "",
391
- layer,
392
- node.data.color || getRandomColorForNode(node.id),
393
- branchCount
394
- )
395
- );
396
- }
397
1057
  const byId = new Map(flatNodes.map((n) => [n.id, n]));
398
1058
  const containerNodeIds = /* @__PURE__ */ new Set();
399
1059
  const containerGroups = /* @__PURE__ */ new Map();
@@ -406,11 +1066,8 @@ function convertLayerWithContainers(layer, doc) {
406
1066
  containerGroups.set(container.id, group);
407
1067
  }
408
1068
  const proxies = [];
409
- for (const node of layer.nodes) {
410
- if (!containerNodeIds.has(node.id)) {
411
- const nodeWidth = calculateNodeWidth(node.data.label);
412
- proxies.push({ id: node.id, x: 0, y: 0, width: nodeWidth, height: 80 });
413
- }
1069
+ for (const n of flatNodes) {
1070
+ if (!containerNodeIds.has(n.id)) proxies.push({ id: n.id, x: 0, y: 0, width: n.width, height: n.height });
414
1071
  }
415
1072
  for (const container of layer.containers) {
416
1073
  const group = containerGroups.get(container.id);
@@ -437,54 +1094,40 @@ function convertLayerWithContainers(layer, doc) {
437
1094
  }
438
1095
  }
439
1096
  }
440
- resolveNodeOverlaps(flatNodes);
441
- return flatNodes;
442
1097
  }
443
- function convertLayerToFlatNodes(layer, doc) {
444
- if ((layer.containers ?? []).length > 0) {
445
- return convertLayerWithContainers(layer, doc);
446
- }
447
- const flatNodes = [];
448
- for (const node of layer.nodes) {
449
- const label = Array.isArray(node.data.label) ? node.data.label.join(" ") : node.data.label || "Untitled";
450
- const branchCount = countLayersBeneath(doc, node.id);
451
- flatNodes.push(
452
- makeFlatNode(
453
- node.id,
454
- label,
455
- node.data.summary || "",
456
- layer,
457
- node.data.color || getRandomColorForNode(node.id),
458
- branchCount,
459
- 0,
460
- 0
461
- )
462
- );
463
- }
464
- if (flatNodes.length > 0) {
465
- const layout = layer.layout || "radial";
466
- if (layout === "linear-horizontal") {
467
- applyLinearHorizontalLayout(flatNodes, { centerX: 0, centerY: 0 });
468
- } else if (layout === "linear-vertical") {
469
- applyLinearVerticalLayout(flatNodes, { centerX: 0, centerY: 0 });
470
- } else {
471
- const pct = calculateOptimalRadiusPercentage(flatNodes.length, 2e3, 2e3, 200, 30);
472
- applyCircularLayout(flatNodes, {
473
- radiusPercentage: pct,
474
- containerWidth: 2e3,
475
- containerHeight: 2e3,
476
- centerX: 0,
477
- centerY: 0
478
- });
479
- }
1098
+ function layoutLayer(layer, flatNodes) {
1099
+ const layout = layer.layout || "radial";
1100
+ if (layout === "linear-horizontal") {
1101
+ applyLinearHorizontalLayout(flatNodes, { centerX: 0, centerY: 0 });
1102
+ } else if (layout === "linear-vertical") {
1103
+ applyLinearVerticalLayout(flatNodes, { centerX: 0, centerY: 0 });
1104
+ } else {
1105
+ const pct = calculateOptimalRadiusPercentage(flatNodes.length, 2e3, 2e3, 200, 30);
1106
+ applyCircularLayout(flatNodes, {
1107
+ radiusPercentage: pct,
1108
+ containerWidth: 2e3,
1109
+ containerHeight: 2e3,
1110
+ centerX: 0,
1111
+ centerY: 0
1112
+ });
1113
+ }
1114
+ }
1115
+ function convertLayerToFlatNodes(layer, doc, opts = {}) {
1116
+ const flatNodes = layer.nodes.map((node, i) => makeFlatNode(node, layer, doc, i, opts));
1117
+ if (flatNodes.length === 0 || hasFilePositions(layer)) return flatNodes;
1118
+ for (const n of flatNodes) {
1119
+ n.x = 0;
1120
+ n.y = 0;
480
1121
  }
1122
+ if ((layer.containers ?? []).length > 0) layoutLayerWithContainers(layer, flatNodes);
1123
+ else layoutLayer(layer, flatNodes);
481
1124
  resolveNodeOverlaps(flatNodes);
482
1125
  return flatNodes;
483
1126
  }
484
- function convertVisualliToFlatNodes(doc) {
1127
+ function convertVisualliToFlatNodes(doc, opts = {}) {
485
1128
  const map = /* @__PURE__ */ new Map();
486
1129
  for (const layer of doc.layers.values()) {
487
- for (const node of convertLayerToFlatNodes(layer, doc)) {
1130
+ for (const node of convertLayerToFlatNodes(layer, doc, opts)) {
488
1131
  map.set(node.id, node);
489
1132
  }
490
1133
  }
@@ -496,9 +1139,9 @@ function convertVisualliToFlatNodes(doc) {
496
1139
  }
497
1140
  return map;
498
1141
  }
499
- function getNodesForLayer(doc, layerId) {
1142
+ function getNodesForLayer(doc, layerId, opts = {}) {
500
1143
  const layer = doc.layers.get(layerId);
501
- return layer ? convertLayerToFlatNodes(layer, doc) : [];
1144
+ return layer ? convertLayerToFlatNodes(layer, doc, opts) : [];
502
1145
  }
503
1146
 
504
1147
  // src/parser/mindmapUtils.ts
@@ -549,80 +1192,17 @@ function calculateDistance(x1, y1, x2, y2) {
549
1192
  return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
550
1193
  }
551
1194
 
552
- // src/constants/design.ts
553
- var BRAND_COLORS = {
554
- primary: {
555
- 50: "#EFF6FF",
556
- 100: "#DBEAFE",
557
- 200: "#BFDBFE",
558
- 300: "#93C5FD",
559
- 400: "#60A5FA",
560
- 500: "#3B82F6",
561
- 600: "#2563EB",
562
- 700: "#1D4ED8",
563
- 800: "#1E40AF",
564
- 900: "#1E3A8A"
565
- },
566
- secondary: {
567
- 50: "#F0FDF4",
568
- 100: "#DCFCE7",
569
- 200: "#BBF7D0",
570
- 300: "#86EFAC",
571
- 400: "#4ADE80",
572
- 500: "#10B981",
573
- 600: "#059669",
574
- 700: "#047857",
575
- 800: "#065F46",
576
- 900: "#064E3B"
577
- },
578
- accent: {
579
- purple: "#8B5CF6",
580
- cyan: "#06B6D4",
581
- sky: "#0EA5E9",
582
- lime: "#84CC16",
583
- amber: "#F59E0B",
584
- red: "#EF4444"
585
- }
586
- };
587
- var LEVEL_COLORS = {
588
- level0: BRAND_COLORS.primary[500],
589
- level1: BRAND_COLORS.primary[400],
590
- level2: BRAND_COLORS.primary[300],
591
- level3: BRAND_COLORS.primary[200],
592
- level4: BRAND_COLORS.primary[300],
593
- level5: BRAND_COLORS.primary[400],
594
- level6: BRAND_COLORS.primary[500],
595
- level7: BRAND_COLORS.primary[600],
596
- level8: BRAND_COLORS.primary[700]
597
- };
598
- var LEVEL_COLOR_ARRAY = [
599
- LEVEL_COLORS.level0,
600
- LEVEL_COLORS.level1,
601
- LEVEL_COLORS.level2,
602
- LEVEL_COLORS.level3,
603
- LEVEL_COLORS.level4,
604
- LEVEL_COLORS.level5,
605
- LEVEL_COLORS.level6,
606
- LEVEL_COLORS.level7,
607
- LEVEL_COLORS.level8
608
- ];
609
- var SEMANTIC_COLORS = {
610
- success: BRAND_COLORS.secondary[500],
611
- error: BRAND_COLORS.accent.red,
612
- warning: BRAND_COLORS.accent.amber,
613
- info: BRAND_COLORS.primary[500]
614
- };
1195
+ // src/constants/layout.ts
615
1196
  var LAYOUT_SPACING = {
616
1197
  nodeSpacing: 200,
617
1198
  levelSpacing: 150,
618
1199
  containerPadding: 20,
619
1200
  gridSize: 50
620
1201
  };
621
- function getColorForLevel(level) {
622
- return LEVEL_COLOR_ARRAY[level % LEVEL_COLOR_ARRAY.length];
623
- }
624
1202
 
625
1203
  // src/parser/configUtils.ts
1204
+ var levelColor = (level) => TOKENS.light[`topic-${TOPICS[level % TOPICS.length]}`];
1205
+ var levelColors = (count) => Object.fromEntries(Array.from({ length: count }, (_, i) => [`level${i}`, levelColor(i)]));
626
1206
  function createMindMapConfig(nodes, topLevelConnections, title = "Untitled Mindmap") {
627
1207
  const now = (/* @__PURE__ */ new Date()).toISOString();
628
1208
  return {
@@ -636,12 +1216,7 @@ function createMindMapConfig(nodes, topLevelConnections, title = "Untitled Mindm
636
1216
  nodes,
637
1217
  topLevelConnections,
638
1218
  settings: {
639
- defaultColors: {
640
- level0: LEVEL_COLORS.level0,
641
- level1: LEVEL_COLORS.level1,
642
- level2: LEVEL_COLORS.level2,
643
- level3: LEVEL_COLORS.level3
644
- },
1219
+ defaultColors: levelColors(4),
645
1220
  layout: {
646
1221
  nodeSpacing: LAYOUT_SPACING.nodeSpacing,
647
1222
  levelSpacing: LAYOUT_SPACING.levelSpacing
@@ -668,7 +1243,7 @@ function generateLevelNodes(parentId, level, maxLevels, xOffset = 0, yOffset = 0
668
1243
  level,
669
1244
  x,
670
1245
  y,
671
- color: getColorForLevel(level),
1246
+ color: levelColor(level),
672
1247
  relationshipLabel: level > 0 ? "child" : void 0,
673
1248
  parent: parentId ?? void 0
674
1249
  };
@@ -697,17 +1272,7 @@ function generateSampleConfig(maxLevels = 9) {
697
1272
  nodes,
698
1273
  topLevelConnections,
699
1274
  settings: {
700
- defaultColors: {
701
- level0: LEVEL_COLORS.level0,
702
- level1: LEVEL_COLORS.level1,
703
- level2: LEVEL_COLORS.level2,
704
- level3: LEVEL_COLORS.level3,
705
- level4: LEVEL_COLORS.level4,
706
- level5: LEVEL_COLORS.level5,
707
- level6: LEVEL_COLORS.level6,
708
- level7: LEVEL_COLORS.level7,
709
- level8: LEVEL_COLORS.level8
710
- },
1275
+ defaultColors: levelColors(9),
711
1276
  layout: {
712
1277
  nodeSpacing: LAYOUT_SPACING.nodeSpacing,
713
1278
  levelSpacing: LAYOUT_SPACING.levelSpacing
@@ -729,6 +1294,7 @@ function generateSampleConfig(maxLevels = 9) {
729
1294
  getChildLayers,
730
1295
  getNodeConnections,
731
1296
  getNodesForLayer,
1297
+ getSemanticAnchors,
732
1298
  getTopLevelConnections,
733
1299
  getVisibleNodes,
734
1300
  loadVisualliFileFromFile,