@visualli/core 0.1.5 → 0.1.6

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 (85) hide show
  1. package/dist/animations/index.cjs +146 -0
  2. package/dist/animations/index.cjs.map +1 -0
  3. package/dist/animations/index.d.cts +81 -0
  4. package/dist/animations/index.d.ts +81 -0
  5. package/dist/animations/index.js +35 -0
  6. package/dist/animations/index.js.map +1 -0
  7. package/dist/chunk-6NXADJK2.js +562 -0
  8. package/dist/chunk-6NXADJK2.js.map +1 -0
  9. package/dist/chunk-F36SMC3K.js +106 -0
  10. package/dist/chunk-F36SMC3K.js.map +1 -0
  11. package/dist/chunk-G5H3P4YZ.js +273 -0
  12. package/dist/chunk-G5H3P4YZ.js.map +1 -0
  13. package/dist/chunk-GQMFBYLK.js +81 -0
  14. package/dist/chunk-GQMFBYLK.js.map +1 -0
  15. package/dist/chunk-I75TMOE4.js +108 -0
  16. package/dist/chunk-I75TMOE4.js.map +1 -0
  17. package/dist/chunk-LDJRGT2Q.js +163 -0
  18. package/dist/chunk-LDJRGT2Q.js.map +1 -0
  19. package/dist/chunk-LI3BVD6H.js +98 -0
  20. package/dist/chunk-LI3BVD6H.js.map +1 -0
  21. package/dist/chunk-LJYSKSCE.js +95 -0
  22. package/dist/chunk-LJYSKSCE.js.map +1 -0
  23. package/dist/chunk-LNTJTDB2.js +349 -0
  24. package/dist/chunk-LNTJTDB2.js.map +1 -0
  25. package/dist/chunk-PDP5CVUL.js +139 -0
  26. package/dist/chunk-PDP5CVUL.js.map +1 -0
  27. package/dist/chunk-VLGR5PZX.js +1 -0
  28. package/dist/chunk-VLGR5PZX.js.map +1 -0
  29. package/dist/config/index.cjs +391 -0
  30. package/dist/config/index.cjs.map +1 -0
  31. package/dist/config/index.d.cts +77 -0
  32. package/dist/config/index.d.ts +77 -0
  33. package/dist/config/index.js +38 -0
  34. package/dist/config/index.js.map +1 -0
  35. package/dist/constants/index.cjs +642 -0
  36. package/dist/constants/index.cjs.map +1 -0
  37. package/dist/constants/index.d.cts +448 -0
  38. package/dist/constants/index.d.ts +448 -0
  39. package/dist/constants/index.js +183 -0
  40. package/dist/constants/index.js.map +1 -0
  41. package/dist/document-B3hnNr-F.d.cts +73 -0
  42. package/dist/document-B3hnNr-F.d.ts +73 -0
  43. package/dist/index.cjs +32 -32
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.cts +15 -1044
  46. package/dist/index.d.ts +15 -1044
  47. package/dist/index.js +179 -1747
  48. package/dist/index.js.map +1 -1
  49. package/dist/layout/index.cjs +210 -0
  50. package/dist/layout/index.cjs.map +1 -0
  51. package/dist/layout/index.d.cts +80 -0
  52. package/dist/layout/index.d.ts +80 -0
  53. package/dist/layout/index.js +25 -0
  54. package/dist/layout/index.js.map +1 -0
  55. package/dist/mindmap-DWS0WZT_.d.cts +118 -0
  56. package/dist/mindmap-DWS0WZT_.d.ts +118 -0
  57. package/dist/parser/index.cjs +739 -0
  58. package/dist/parser/index.cjs.map +1 -0
  59. package/dist/parser/index.d.cts +87 -0
  60. package/dist/parser/index.d.ts +87 -0
  61. package/dist/parser/index.js +43 -0
  62. package/dist/parser/index.js.map +1 -0
  63. package/dist/performance/index.cjs +167 -0
  64. package/dist/performance/index.cjs.map +1 -0
  65. package/dist/performance/index.d.cts +40 -0
  66. package/dist/performance/index.d.ts +40 -0
  67. package/dist/performance/index.js +12 -0
  68. package/dist/performance/index.js.map +1 -0
  69. package/dist/types/index.cjs +19 -0
  70. package/dist/types/index.cjs.map +1 -0
  71. package/dist/types/index.d.cts +8 -0
  72. package/dist/types/index.d.ts +8 -0
  73. package/dist/types/index.js +2 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/dist/viewport/index.cjs +131 -0
  76. package/dist/viewport/index.cjs.map +1 -0
  77. package/dist/viewport/index.d.cts +56 -0
  78. package/dist/viewport/index.d.ts +56 -0
  79. package/dist/viewport/index.js +26 -0
  80. package/dist/viewport/index.js.map +1 -0
  81. package/package.json +6 -1
  82. package/src/config/README.md +59 -0
  83. package/src/config/USAGE_EXAMPLES.md +285 -0
  84. package/src/config/index.ts +7 -0
  85. package/src/index.ts +1 -2
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/layout/index.ts","../../src/layout/circularLayout.ts","../../src/layout/linearLayout.ts","../../src/layout/layoutUtils.ts"],"sourcesContent":["export * from './circularLayout.js';\nexport * from './linearLayout.js';\nexport * from './layoutUtils.js';\n","// ─── Circular Layout Algorithm ────────────────────────────────────────────────\n//\n// Positions nodes in a uniform circle with equal angular spacing.\n// PATTERN : Uniform circular distribution (polar coordinates)\n// SPACING : Equal angular intervals (2π/n)\n// ORIGIN : Configurable center (default 0, 0)\n// RADIUS : Configurable percentage of container (default 13.5%)\n\nimport type { FlatNode } from '../types/mindmap.js';\n\nexport interface CircularLayoutOptions {\n /** Radius as a fraction of the container's minimum dimension (0–1). Default: 0.135 */\n radiusPercentage?: number;\n /** Container width used to calculate absolute radius. Default: 2000 */\n containerWidth?: number;\n /** Container height used to calculate absolute radius. Default: 2000 */\n containerHeight?: number;\n /** World-space X of the circle centre. Default: 0 */\n centerX?: number;\n /** World-space Y of the circle centre. Default: 0 */\n centerY?: number;\n}\n\n/**\n * Apply circular layout to a set of nodes.\n * Mutates the `x` / `y` properties of each node and returns the same array.\n */\nexport function applyCircularLayout(\n nodes: FlatNode[],\n options: CircularLayoutOptions = {},\n): FlatNode[] {\n const {\n radiusPercentage = 0.135,\n containerWidth = 2000,\n containerHeight = 2000,\n centerX = 0,\n centerY = 0,\n } = options;\n\n if (nodes.length === 0) return nodes;\n\n if (nodes.length === 1) {\n nodes[0].x = centerX;\n nodes[0].y = centerY;\n return nodes;\n }\n\n const radius = Math.min(containerWidth, containerHeight) * radiusPercentage;\n\n // n=2 → horizontal; n≥3 → start at 12 o'clock\n const startAngle = nodes.length === 2 ? 0 : -Math.PI / 2;\n const angleStep = (2 * Math.PI) / nodes.length;\n\n for (let i = 0; i < nodes.length; i++) {\n const angle = startAngle + i * angleStep;\n nodes[i].x = centerX + radius * Math.cos(angle);\n nodes[i].y = centerY + radius * Math.sin(angle);\n }\n\n return nodes;\n}\n\n/**\n * Calculate the minimum radius needed to prevent node boxes from overlapping.\n *\n * Uses the chord-length formula: `chord = 2r · sin(θ/2)`, solved for `r`.\n */\nexport function calculateMinimumRadius(\n nodeCount: number,\n nodeWidth = 200,\n nodePadding = 150,\n): number {\n if (nodeCount <= 1) return 0;\n const angleStep = (2 * Math.PI) / nodeCount;\n const minChordLength = nodeWidth + nodePadding;\n return minChordLength / (2 * Math.sin(angleStep / 2));\n}\n\n/**\n * Calculate the optimal radius percentage for a given node count,\n * ensuring sufficient spacing for edge labels.\n *\n * @returns A value in [0.135, 0.45]\n */\nexport function calculateOptimalRadiusPercentage(\n nodeCount: number,\n containerWidth = 2000,\n containerHeight = 2000,\n nodeWidth = 200,\n nodePadding = 120,\n): number {\n const minRadius = calculateMinimumRadius(nodeCount, nodeWidth, nodePadding);\n const minDimension = Math.min(containerWidth, containerHeight);\n return Math.min(0.45, Math.max(0.135, minRadius / minDimension));\n}\n","// ─── Linear Layout Algorithms ─────────────────────────────────────────────────\n//\n// Positions nodes in a straight line without overlap, with enough gap between\n// node edges for edge-label text to render cleanly.\n//\n// linear-horizontal → left-to-right along X-axis\n// linear-vertical → top-to-bottom along Y-axis\n\nimport type { FlatNode } from '../types/mindmap.js';\n\nexport interface LinearLayoutOptions {\n /** Logical node width (px). Default: 200 */\n nodeWidth?: number;\n /** Logical node height (px). Default: 80 */\n nodeHeight?: number;\n /** Gap between node edges for horizontal layout (px). Default: 180 */\n hGap?: number;\n /** Gap between node edges for vertical layout (px). Default: 220 */\n vGap?: number;\n /** World X of the layout midpoint. Default: 0 */\n centerX?: number;\n /** World Y of the layout midpoint. Default: 0 */\n centerY?: number;\n}\n\n/**\n * Arrange nodes in a horizontal row (shared Y, varying X).\n * Row is centred on (`centerX`, `centerY`).\n */\nexport function applyLinearHorizontalLayout(\n nodes: FlatNode[],\n options: LinearLayoutOptions = {},\n): FlatNode[] {\n const { nodeWidth = 200, hGap = 180, centerX = 0, centerY = 0 } = options;\n\n if (nodes.length === 0) return nodes;\n\n if (nodes.length === 1) {\n nodes[0].x = centerX;\n nodes[0].y = centerY;\n return nodes;\n }\n\n const spacing = nodeWidth + hGap;\n const totalWidth = (nodes.length - 1) * spacing;\n const startX = centerX - totalWidth / 2;\n\n for (let i = 0; i < nodes.length; i++) {\n nodes[i].x = startX + i * spacing;\n nodes[i].y = centerY;\n }\n\n return nodes;\n}\n\n/**\n * Arrange nodes in a vertical column (shared X, varying Y).\n * Column is centred on (`centerX`, `centerY`).\n */\nexport function applyLinearVerticalLayout(\n nodes: FlatNode[],\n options: LinearLayoutOptions = {},\n): FlatNode[] {\n const { nodeHeight = 80, vGap = 220, centerX = 0, centerY = 0 } = options;\n\n if (nodes.length === 0) return nodes;\n\n if (nodes.length === 1) {\n nodes[0].x = centerX;\n nodes[0].y = centerY;\n return nodes;\n }\n\n const spacing = nodeHeight + vGap;\n const totalHeight = (nodes.length - 1) * spacing;\n const startY = centerY - totalHeight / 2;\n\n for (let i = 0; i < nodes.length; i++) {\n nodes[i].x = centerX;\n nodes[i].y = startY + i * spacing;\n }\n\n return nodes;\n}\n","// ─── Layout Utilities ─────────────────────────────────────────────────────────\n//\n// Collision detection and force-based positioning for MindMapNode trees.\n\nimport type { MindMapNode } from '../types/mindmap.js';\n\nexport interface CollisionBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Axis-aligned bounding box for a node, expanded by a fixed padding. */\nexport function getNodeBounds(node: MindMapNode): CollisionBox {\n const baseWidth = Math.max(120, node.title.length * 8 + 40);\n const baseHeight = Math.max(40, 32 + 16);\n const padding = 20;\n return {\n x: node.x - baseWidth / 2 - padding,\n y: node.y - baseHeight / 2 - padding,\n width: baseWidth + padding * 2,\n height: baseHeight + padding * 2,\n };\n}\n\nexport function checkCollision(box1: CollisionBox, box2: CollisionBox): boolean {\n return !(\n box1.x + box1.width < box2.x ||\n box2.x + box2.width < box1.x ||\n box1.y + box1.height < box2.y ||\n box2.y + box2.height < box1.y\n );\n}\n\n/**\n * Iteratively resolve bounding-box collisions within each level.\n * Nodes are pushed apart symmetrically until no overlaps remain\n * or `maxIterations` is reached.\n */\nexport function resolveCollisions(nodes: MindMapNode[], maxIterations = 10): MindMapNode[] {\n const result = [...nodes];\n\n for (let iter = 0; iter < maxIterations; iter++) {\n let hasCollisions = false;\n\n const byLevel = result.reduce<Record<number, MindMapNode[]>>((acc, n) => {\n (acc[n.level] ??= []).push(n);\n return acc;\n }, {});\n\n for (const levelNodes of Object.values(byLevel)) {\n for (let i = 0; i < levelNodes.length; i++) {\n for (let j = i + 1; j < levelNodes.length; j++) {\n const n1 = levelNodes[i];\n const n2 = levelNodes[j];\n if (!checkCollision(getNodeBounds(n1), getNodeBounds(n2))) continue;\n\n hasCollisions = 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 += 100;\n } else {\n const b1 = getNodeBounds(n1);\n const b2 = getNodeBounds(n2);\n const minSep = (b1.width + b2.width) / 2;\n const overlap = minSep - dist + 20;\n if (overlap > 0) {\n const move = overlap / 2;\n n1.x -= (dx / dist) * move;\n n1.y -= (dy / dist) * move;\n n2.x += (dx / dist) * move;\n n2.y += (dy / dist) * move;\n }\n }\n }\n }\n }\n\n if (!hasCollisions) break;\n }\n\n return result;\n}\n\n/**\n * Apply a lightweight repulsive force between same-level nodes that are\n * closer than 300 px, then resolve remaining collisions.\n */\nexport function optimizeLayout(nodes: MindMapNode[]): MindMapNode[] {\n const result = [...nodes];\n const iterations = 5;\n const repulsion = 1000;\n const damp = 0.8;\n\n for (let iter = 0; iter < iterations; iter++) {\n const forces = new Map<string, { x: number; y: number }>();\n result.forEach(n => forces.set(n.id, { x: 0, y: 0 }));\n\n for (let i = 0; i < result.length; i++) {\n for (let j = i + 1; j < result.length; j++) {\n const n1 = result[i];\n const n2 = result[j];\n if (n1.level !== n2.level) continue;\n\n const dx = n2.x - n1.x;\n const dy = n2.y - n1.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n if (dist <= 0 || dist >= 300) continue;\n\n const force = repulsion / (dist * dist);\n const f1 = forces.get(n1.id)!;\n const f2 = forces.get(n2.id)!;\n f1.x -= (dx / dist) * force;\n f1.y -= (dy / dist) * force;\n f2.x += (dx / dist) * force;\n f2.y += (dy / dist) * force;\n }\n }\n\n result.forEach(n => {\n const f = forces.get(n.id)!;\n n.x += f.x * damp;\n n.y += f.y * damp;\n });\n }\n\n return resolveCollisions(result);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,80 @@
1
+ import { F as FlatNode, c as MindMapNode } from '../mindmap-DWS0WZT_.cjs';
2
+
3
+ interface CircularLayoutOptions {
4
+ /** Radius as a fraction of the container's minimum dimension (0–1). Default: 0.135 */
5
+ radiusPercentage?: number;
6
+ /** Container width used to calculate absolute radius. Default: 2000 */
7
+ containerWidth?: number;
8
+ /** Container height used to calculate absolute radius. Default: 2000 */
9
+ containerHeight?: number;
10
+ /** World-space X of the circle centre. Default: 0 */
11
+ centerX?: number;
12
+ /** World-space Y of the circle centre. Default: 0 */
13
+ centerY?: number;
14
+ }
15
+ /**
16
+ * Apply circular layout to a set of nodes.
17
+ * Mutates the `x` / `y` properties of each node and returns the same array.
18
+ */
19
+ declare function applyCircularLayout(nodes: FlatNode[], options?: CircularLayoutOptions): FlatNode[];
20
+ /**
21
+ * Calculate the minimum radius needed to prevent node boxes from overlapping.
22
+ *
23
+ * Uses the chord-length formula: `chord = 2r · sin(θ/2)`, solved for `r`.
24
+ */
25
+ declare function calculateMinimumRadius(nodeCount: number, nodeWidth?: number, nodePadding?: number): number;
26
+ /**
27
+ * Calculate the optimal radius percentage for a given node count,
28
+ * ensuring sufficient spacing for edge labels.
29
+ *
30
+ * @returns A value in [0.135, 0.45]
31
+ */
32
+ declare function calculateOptimalRadiusPercentage(nodeCount: number, containerWidth?: number, containerHeight?: number, nodeWidth?: number, nodePadding?: number): number;
33
+
34
+ interface LinearLayoutOptions {
35
+ /** Logical node width (px). Default: 200 */
36
+ nodeWidth?: number;
37
+ /** Logical node height (px). Default: 80 */
38
+ nodeHeight?: number;
39
+ /** Gap between node edges for horizontal layout (px). Default: 180 */
40
+ hGap?: number;
41
+ /** Gap between node edges for vertical layout (px). Default: 220 */
42
+ vGap?: number;
43
+ /** World X of the layout midpoint. Default: 0 */
44
+ centerX?: number;
45
+ /** World Y of the layout midpoint. Default: 0 */
46
+ centerY?: number;
47
+ }
48
+ /**
49
+ * Arrange nodes in a horizontal row (shared Y, varying X).
50
+ * Row is centred on (`centerX`, `centerY`).
51
+ */
52
+ declare function applyLinearHorizontalLayout(nodes: FlatNode[], options?: LinearLayoutOptions): FlatNode[];
53
+ /**
54
+ * Arrange nodes in a vertical column (shared X, varying Y).
55
+ * Column is centred on (`centerX`, `centerY`).
56
+ */
57
+ declare function applyLinearVerticalLayout(nodes: FlatNode[], options?: LinearLayoutOptions): FlatNode[];
58
+
59
+ interface CollisionBox {
60
+ x: number;
61
+ y: number;
62
+ width: number;
63
+ height: number;
64
+ }
65
+ /** Axis-aligned bounding box for a node, expanded by a fixed padding. */
66
+ declare function getNodeBounds(node: MindMapNode): CollisionBox;
67
+ declare function checkCollision(box1: CollisionBox, box2: CollisionBox): boolean;
68
+ /**
69
+ * Iteratively resolve bounding-box collisions within each level.
70
+ * Nodes are pushed apart symmetrically until no overlaps remain
71
+ * or `maxIterations` is reached.
72
+ */
73
+ declare function resolveCollisions(nodes: MindMapNode[], maxIterations?: number): MindMapNode[];
74
+ /**
75
+ * Apply a lightweight repulsive force between same-level nodes that are
76
+ * closer than 300 px, then resolve remaining collisions.
77
+ */
78
+ declare function optimizeLayout(nodes: MindMapNode[]): MindMapNode[];
79
+
80
+ export { type CircularLayoutOptions, type CollisionBox, type LinearLayoutOptions, applyCircularLayout, applyLinearHorizontalLayout, applyLinearVerticalLayout, calculateMinimumRadius, calculateOptimalRadiusPercentage, checkCollision, getNodeBounds, optimizeLayout, resolveCollisions };
@@ -0,0 +1,80 @@
1
+ import { F as FlatNode, c as MindMapNode } from '../mindmap-DWS0WZT_.js';
2
+
3
+ interface CircularLayoutOptions {
4
+ /** Radius as a fraction of the container's minimum dimension (0–1). Default: 0.135 */
5
+ radiusPercentage?: number;
6
+ /** Container width used to calculate absolute radius. Default: 2000 */
7
+ containerWidth?: number;
8
+ /** Container height used to calculate absolute radius. Default: 2000 */
9
+ containerHeight?: number;
10
+ /** World-space X of the circle centre. Default: 0 */
11
+ centerX?: number;
12
+ /** World-space Y of the circle centre. Default: 0 */
13
+ centerY?: number;
14
+ }
15
+ /**
16
+ * Apply circular layout to a set of nodes.
17
+ * Mutates the `x` / `y` properties of each node and returns the same array.
18
+ */
19
+ declare function applyCircularLayout(nodes: FlatNode[], options?: CircularLayoutOptions): FlatNode[];
20
+ /**
21
+ * Calculate the minimum radius needed to prevent node boxes from overlapping.
22
+ *
23
+ * Uses the chord-length formula: `chord = 2r · sin(θ/2)`, solved for `r`.
24
+ */
25
+ declare function calculateMinimumRadius(nodeCount: number, nodeWidth?: number, nodePadding?: number): number;
26
+ /**
27
+ * Calculate the optimal radius percentage for a given node count,
28
+ * ensuring sufficient spacing for edge labels.
29
+ *
30
+ * @returns A value in [0.135, 0.45]
31
+ */
32
+ declare function calculateOptimalRadiusPercentage(nodeCount: number, containerWidth?: number, containerHeight?: number, nodeWidth?: number, nodePadding?: number): number;
33
+
34
+ interface LinearLayoutOptions {
35
+ /** Logical node width (px). Default: 200 */
36
+ nodeWidth?: number;
37
+ /** Logical node height (px). Default: 80 */
38
+ nodeHeight?: number;
39
+ /** Gap between node edges for horizontal layout (px). Default: 180 */
40
+ hGap?: number;
41
+ /** Gap between node edges for vertical layout (px). Default: 220 */
42
+ vGap?: number;
43
+ /** World X of the layout midpoint. Default: 0 */
44
+ centerX?: number;
45
+ /** World Y of the layout midpoint. Default: 0 */
46
+ centerY?: number;
47
+ }
48
+ /**
49
+ * Arrange nodes in a horizontal row (shared Y, varying X).
50
+ * Row is centred on (`centerX`, `centerY`).
51
+ */
52
+ declare function applyLinearHorizontalLayout(nodes: FlatNode[], options?: LinearLayoutOptions): FlatNode[];
53
+ /**
54
+ * Arrange nodes in a vertical column (shared X, varying Y).
55
+ * Column is centred on (`centerX`, `centerY`).
56
+ */
57
+ declare function applyLinearVerticalLayout(nodes: FlatNode[], options?: LinearLayoutOptions): FlatNode[];
58
+
59
+ interface CollisionBox {
60
+ x: number;
61
+ y: number;
62
+ width: number;
63
+ height: number;
64
+ }
65
+ /** Axis-aligned bounding box for a node, expanded by a fixed padding. */
66
+ declare function getNodeBounds(node: MindMapNode): CollisionBox;
67
+ declare function checkCollision(box1: CollisionBox, box2: CollisionBox): boolean;
68
+ /**
69
+ * Iteratively resolve bounding-box collisions within each level.
70
+ * Nodes are pushed apart symmetrically until no overlaps remain
71
+ * or `maxIterations` is reached.
72
+ */
73
+ declare function resolveCollisions(nodes: MindMapNode[], maxIterations?: number): MindMapNode[];
74
+ /**
75
+ * Apply a lightweight repulsive force between same-level nodes that are
76
+ * closer than 300 px, then resolve remaining collisions.
77
+ */
78
+ declare function optimizeLayout(nodes: MindMapNode[]): MindMapNode[];
79
+
80
+ export { type CircularLayoutOptions, type CollisionBox, type LinearLayoutOptions, applyCircularLayout, applyLinearHorizontalLayout, applyLinearVerticalLayout, calculateMinimumRadius, calculateOptimalRadiusPercentage, checkCollision, getNodeBounds, optimizeLayout, resolveCollisions };
@@ -0,0 +1,25 @@
1
+ import {
2
+ checkCollision,
3
+ getNodeBounds,
4
+ optimizeLayout,
5
+ resolveCollisions
6
+ } from "../chunk-LI3BVD6H.js";
7
+ import {
8
+ applyCircularLayout,
9
+ applyLinearHorizontalLayout,
10
+ applyLinearVerticalLayout,
11
+ calculateMinimumRadius,
12
+ calculateOptimalRadiusPercentage
13
+ } from "../chunk-GQMFBYLK.js";
14
+ export {
15
+ applyCircularLayout,
16
+ applyLinearHorizontalLayout,
17
+ applyLinearVerticalLayout,
18
+ calculateMinimumRadius,
19
+ calculateOptimalRadiusPercentage,
20
+ checkCollision,
21
+ getNodeBounds,
22
+ optimizeLayout,
23
+ resolveCollisions
24
+ };
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,118 @@
1
+ interface MindMapNode {
2
+ id: string;
3
+ title: string;
4
+ level: number;
5
+ x: number;
6
+ y: number;
7
+ children?: MindMapNode[];
8
+ parent?: string;
9
+ color?: string;
10
+ relationshipLabel?: string;
11
+ }
12
+ /** Flat structure for performance-optimised storage (10K+ nodes). */
13
+ interface FlatNode {
14
+ id: string;
15
+ parentId: string | null;
16
+ /** IDs of child nodes for quick tree traversal */
17
+ childrenIds?: string[];
18
+ x: number;
19
+ y: number;
20
+ /** Alternative position format for compatibility */
21
+ position?: {
22
+ x: number;
23
+ y: number;
24
+ };
25
+ /** Depth in tree hierarchy */
26
+ level: number;
27
+ title: string;
28
+ description?: string;
29
+ /** Label describing relationship to parent */
30
+ relationshipLabel?: string;
31
+ color: string;
32
+ width: number;
33
+ height: number;
34
+ /** Whether this node's children are visible */
35
+ isExpanded?: boolean;
36
+ branchCount?: number;
37
+ createdAt: Date;
38
+ updatedAt: Date;
39
+ }
40
+ /** Map-based node storage for O(1) lookups. */
41
+ type NodeMap = Map<string, FlatNode>;
42
+ /** Spatial bounds for RBush indexing. */
43
+ interface SpatialBounds {
44
+ minX: number;
45
+ minY: number;
46
+ maxX: number;
47
+ maxY: number;
48
+ nodeId: string;
49
+ }
50
+ /** Viewport state for camera position and zoom. */
51
+ interface ViewportState {
52
+ centerX: number;
53
+ centerY: number;
54
+ zoomLevel: number;
55
+ rotation: number;
56
+ visibleBounds: {
57
+ minX: number;
58
+ minY: number;
59
+ maxX: number;
60
+ maxY: number;
61
+ };
62
+ }
63
+ /** Single-selection node state. */
64
+ interface NodeSelection {
65
+ selectedId: string | null;
66
+ }
67
+ /** Render configuration flags. */
68
+ interface RenderConfig {
69
+ renderMode: 'canvas' | 'simplified';
70
+ qualityLevel: 'high' | 'medium' | 'low';
71
+ cullingEnabled: boolean;
72
+ fpsTarget: number;
73
+ memoryLimit: number;
74
+ }
75
+ interface MindMapData {
76
+ nodes: MindMapNode[];
77
+ connections: MindMapConnection[];
78
+ }
79
+ /** Simplified connection type for mindmap rendering (not to be confused with schema Connection) */
80
+ interface MindMapConnection {
81
+ from: string;
82
+ to: string;
83
+ level: number;
84
+ label?: string;
85
+ }
86
+ interface TopLevelConnection {
87
+ from: string;
88
+ to: string;
89
+ label: string;
90
+ }
91
+ /** Complete mindmap configuration schema. */
92
+ interface MindMapConfig {
93
+ metadata: {
94
+ id?: string;
95
+ title: string;
96
+ description?: string;
97
+ version: string;
98
+ created: string;
99
+ lastModified: string;
100
+ };
101
+ nodes: MindMapNode[];
102
+ topLevelConnections: TopLevelConnection[];
103
+ settings?: {
104
+ defaultColors?: {
105
+ level0: string;
106
+ level1: string;
107
+ level2: string;
108
+ level3: string;
109
+ [key: `level${number}`]: string;
110
+ };
111
+ layout?: {
112
+ nodeSpacing: number;
113
+ levelSpacing: number;
114
+ };
115
+ };
116
+ }
117
+
118
+ export type { FlatNode as F, MindMapConnection as M, NodeSelection as N, RenderConfig as R, SpatialBounds as S, TopLevelConnection as T, ViewportState as V, MindMapConfig as a, MindMapData as b, MindMapNode as c, NodeMap as d };
@@ -0,0 +1,118 @@
1
+ interface MindMapNode {
2
+ id: string;
3
+ title: string;
4
+ level: number;
5
+ x: number;
6
+ y: number;
7
+ children?: MindMapNode[];
8
+ parent?: string;
9
+ color?: string;
10
+ relationshipLabel?: string;
11
+ }
12
+ /** Flat structure for performance-optimised storage (10K+ nodes). */
13
+ interface FlatNode {
14
+ id: string;
15
+ parentId: string | null;
16
+ /** IDs of child nodes for quick tree traversal */
17
+ childrenIds?: string[];
18
+ x: number;
19
+ y: number;
20
+ /** Alternative position format for compatibility */
21
+ position?: {
22
+ x: number;
23
+ y: number;
24
+ };
25
+ /** Depth in tree hierarchy */
26
+ level: number;
27
+ title: string;
28
+ description?: string;
29
+ /** Label describing relationship to parent */
30
+ relationshipLabel?: string;
31
+ color: string;
32
+ width: number;
33
+ height: number;
34
+ /** Whether this node's children are visible */
35
+ isExpanded?: boolean;
36
+ branchCount?: number;
37
+ createdAt: Date;
38
+ updatedAt: Date;
39
+ }
40
+ /** Map-based node storage for O(1) lookups. */
41
+ type NodeMap = Map<string, FlatNode>;
42
+ /** Spatial bounds for RBush indexing. */
43
+ interface SpatialBounds {
44
+ minX: number;
45
+ minY: number;
46
+ maxX: number;
47
+ maxY: number;
48
+ nodeId: string;
49
+ }
50
+ /** Viewport state for camera position and zoom. */
51
+ interface ViewportState {
52
+ centerX: number;
53
+ centerY: number;
54
+ zoomLevel: number;
55
+ rotation: number;
56
+ visibleBounds: {
57
+ minX: number;
58
+ minY: number;
59
+ maxX: number;
60
+ maxY: number;
61
+ };
62
+ }
63
+ /** Single-selection node state. */
64
+ interface NodeSelection {
65
+ selectedId: string | null;
66
+ }
67
+ /** Render configuration flags. */
68
+ interface RenderConfig {
69
+ renderMode: 'canvas' | 'simplified';
70
+ qualityLevel: 'high' | 'medium' | 'low';
71
+ cullingEnabled: boolean;
72
+ fpsTarget: number;
73
+ memoryLimit: number;
74
+ }
75
+ interface MindMapData {
76
+ nodes: MindMapNode[];
77
+ connections: MindMapConnection[];
78
+ }
79
+ /** Simplified connection type for mindmap rendering (not to be confused with schema Connection) */
80
+ interface MindMapConnection {
81
+ from: string;
82
+ to: string;
83
+ level: number;
84
+ label?: string;
85
+ }
86
+ interface TopLevelConnection {
87
+ from: string;
88
+ to: string;
89
+ label: string;
90
+ }
91
+ /** Complete mindmap configuration schema. */
92
+ interface MindMapConfig {
93
+ metadata: {
94
+ id?: string;
95
+ title: string;
96
+ description?: string;
97
+ version: string;
98
+ created: string;
99
+ lastModified: string;
100
+ };
101
+ nodes: MindMapNode[];
102
+ topLevelConnections: TopLevelConnection[];
103
+ settings?: {
104
+ defaultColors?: {
105
+ level0: string;
106
+ level1: string;
107
+ level2: string;
108
+ level3: string;
109
+ [key: `level${number}`]: string;
110
+ };
111
+ layout?: {
112
+ nodeSpacing: number;
113
+ levelSpacing: number;
114
+ };
115
+ };
116
+ }
117
+
118
+ export type { FlatNode as F, MindMapConnection as M, NodeSelection as N, RenderConfig as R, SpatialBounds as S, TopLevelConnection as T, ViewportState as V, MindMapConfig as a, MindMapData as b, MindMapNode as c, NodeMap as d };