@visualli/core 0.1.2 → 0.1.4

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/layout/circularLayout.ts","../src/layout/linearLayout.ts","../src/layout/layoutUtils.ts","../src/parser/visualliParser.ts","../src/parser/visualliConverter.ts","../src/parser/mindmapUtils.ts","../src/constants/design.ts","../src/parser/configUtils.ts","../src/constants/performanceConstants.ts","../src/constants/renderConfig.ts","../src/viewport/viewportUtils.ts","../src/performance/performanceMonitor.ts","../src/animations/easing.ts","../src/animations/constants.ts","../src/spatial/spatialIndex.ts","../../../node_modules/zustand/esm/vanilla.mjs","../src/stores/index.ts","../src/utils/navigation.ts","../src/rendering/culling.ts","../src/config/textScaling.ts","../src/config/blobShapes.ts"],"sourcesContent":["// ─── 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","// ─── .visualli File Parser ────────────────────────────────────────────────────\n//\n// Reads JSONL (JSON Lines) format and parses into a structured VisualliDocument.\n\nimport type { VisualliDocument } 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 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\n/**\n * Fetch and parse a .visualli file from a URL.\n *\n * @throws VisualliParseError | Error\n */\nexport async function loadVisualliFile(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. */\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 { 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// ── Color Helpers ─────────────────────────────────────────────────────────────\n\nconst COLOR_PALETTE = [\n '#12C7D3', '#325E8C', '#8A70A6', '#F54A57', '#FF6C4D',\n '#F28C16', '#FFD347', '#12C7D3', '#7F7F7F', '#8D8D8D', '#12C7D3',\n];\n\n/**\n * Get a deterministic random color from palette based on node ID\n */\nfunction getRandomColorForNode(nodeId: string): string {\n // Simple hash function to convert string to number\n let hash = 0;\n for (let i = 0; i < nodeId.length; i++) {\n hash = nodeId.charCodeAt(i) + ((hash << 5) - hash);\n }\n \n // Use absolute value and modulo to get palette index\n const index = Math.abs(hash) % COLOR_PALETTE.length;\n return COLOR_PALETTE[index];\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\n/**\n * Calculate dynamic node width based on title length.\n * Formula matches visualli.ai: max(200, title.length * 8 + 40)\n */\nfunction calculateNodeWidth(title: string): number {\n return Math.max(200, title.length * 8 + 40);\n}\n\nfunction makeFlatNode(\n nodeId: string,\n label: string,\n summary: string,\n layer: VisualliLayer,\n color: string,\n branchCount: number,\n x = 0,\n y = 0,\n): FlatNode {\n return {\n id: nodeId,\n parentId: layer.parentNodeId ?? null,\n x,\n y,\n level: layer.level,\n title: label,\n description: summary,\n color,\n width: calculateNodeWidth(label),\n height: 80,\n isExpanded: branchCount > 0,\n branchCount,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n}\n\nfunction convertLayerWithContainers(\n layer: VisualliLayer,\n doc: VisualliDocument,\n): FlatNode[] {\n const PADDING = 80;\n const flatNodes: FlatNode[] = [];\n\n for (const node of layer.nodes) {\n const label = Array.isArray(node.data.label)\n ? (node.data.label as string[]).join(' ')\n : (node.data.label || 'Untitled');\n const branchCount = countLayersBeneath(doc, node.id);\n flatNodes.push(\n makeFlatNode(\n node.id, label, node.data.summary || '', layer,\n node.data.color || getRandomColorForNode(node.id), branchCount,\n ),\n );\n }\n\n const byId = new Map(flatNodes.map(n => [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 => byId.get(id)).filter((n): n is FlatNode => !!n);\n if (!group.length) continue;\n container.nodes.forEach(id => 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 node of layer.nodes) {\n if (!containerNodeIds.has(node.id)) {\n const nodeWidth = calculateNodeWidth(node.data.label);\n proxies.push({ id: node.id, x: 0, y: 0, width: nodeWidth, height: 80 });\n }\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 resolveNodeOverlaps(flatNodes);\n\n return flatNodes;\n}\n\n/**\n * Convert a single layer to an array of FlatNode objects.\n * Layout algorithm is determined by `layer.layout` (default: radial).\n */\nexport function convertLayerToFlatNodes(\n layer: VisualliLayer,\n doc: VisualliDocument,\n): FlatNode[] {\n if ((layer.containers ?? []).length > 0) {\n return convertLayerWithContainers(layer, doc);\n }\n\n const flatNodes: FlatNode[] = [];\n\n for (const node of layer.nodes) {\n const label = Array.isArray(node.data.label)\n ? (node.data.label as string[]).join(' ')\n : (node.data.label || 'Untitled');\n const branchCount = countLayersBeneath(doc, node.id);\n flatNodes.push(\n makeFlatNode(\n node.id, label, node.data.summary || '', layer,\n node.data.color || getRandomColorForNode(node.id), branchCount,\n 0, 0,\n ),\n );\n }\n\n if (flatNodes.length > 0) {\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 resolveNodeOverlaps(flatNodes);\n\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): NodeMap {\n const map: NodeMap = new Map();\n\n for (const layer of doc.layers.values()) {\n for (const node of convertLayerToFlatNodes(layer, doc)) {\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 * @returns FlatNode array, or empty array if layer not found\n */\nexport function getNodesForLayer(doc: VisualliDocument, layerId: string): FlatNode[] {\n const layer = doc.layers.get(layerId);\n return layer ? convertLayerToFlatNodes(layer, doc) : [];\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","// ─── Design System Constants ──────────────────────────────────────────────────\n//\n// Single source of truth for all color tokens, typography, spacing, and\n// visual design constants used across the SDK and consuming apps.\n//\n// ## Color Priority\n// 1. Data file values (node.color, layer.backgroundColor)\n// 2. Fall back to these constants\n\n// ── Visualli Design System v2 ─────────────────────────────────────────────────\n\nexport const DS_COLORS = {\n light: {\n bgApp: '#F0EDE6',\n bgSurface: '#FAF8F4',\n bgInput: '#FFFFFF',\n border: '#DDD9D0',\n borderDivider: '#E8E4DC',\n primary: '#1B2D4F',\n primaryHover: '#243B68',\n textPrimary: '#1A1A18',\n textSecondary: '#6B6860',\n textMuted: '#747270',\n textOnPrimary: '#FAF8F4',\n hoverItem: 'rgba(27,45,79,0.07)',\n focusRing: 'rgba(27,45,79,0.40)',\n btnMuted: '#8E8C88',\n },\n dark: {\n bgApp: '#141412',\n bgSurface: '#1C1C1A',\n bgInput: '#262622',\n border: '#333330',\n borderDivider: '#2A2A28',\n primary: '#BB532D',\n primaryHover: '#CC6440',\n textPrimary: '#F0EDE6',\n textSecondary: '#B0ABA3',\n textMuted: '#8E8C88',\n textOnPrimary: '#FAF8F4',\n hoverItem: 'rgba(198,94,56,0.12)',\n focusRing: 'rgba(198,94,56,0.50)',\n btnMuted: '#4A4845',\n },\n} as const;\n\nexport const DS_TYPOGRAPHY = {\n fontDisplay: \"'Nunito', sans-serif\",\n fontBody: \"'Nunito Sans', sans-serif\",\n logo: { size: '20px', weight: 800, letterSpacing: '0.04em' },\n heading: { size: '16px', weight: 700, letterSpacing: '-0.2px' },\n cta: { size: '11px', weight: 800, letterSpacing: '0.12em', transform: 'uppercase' as const },\n body: { size: '13px', weight: 400 },\n input: { size: '13px', weight: 300, style: 'italic' as const },\n search: { size: '12px', weight: 400 },\n username: { size: '13px', weight: 600 },\n avatar: { size: '11px', weight: 700 },\n footer: { size: '12px', weight: 400 },\n empty: { size: '11px', weight: 300, style: 'italic' as const },\n} as const;\n\nexport const DS_RADII = {\n sidebar: 16,\n input: 8,\n cta: 7,\n item: 6,\n swatch: 10,\n} as const;\n\n// ── Brand Colors ──────────────────────────────────────────────────────────────\n\nexport const BRAND_COLORS = {\n primary: {\n 50: '#EFF6FF',\n 100: '#DBEAFE',\n 200: '#BFDBFE',\n 300: '#93C5FD',\n 400: '#60A5FA',\n 500: '#3B82F6',\n 600: '#2563EB',\n 700: '#1D4ED8',\n 800: '#1E40AF',\n 900: '#1E3A8A',\n },\n secondary: {\n 50: '#F0FDF4',\n 100: '#DCFCE7',\n 200: '#BBF7D0',\n 300: '#86EFAC',\n 400: '#4ADE80',\n 500: '#10B981',\n 600: '#059669',\n 700: '#047857',\n 800: '#065F46',\n 900: '#064E3B',\n },\n accent: {\n purple: '#8B5CF6',\n cyan: '#06B6D4',\n sky: '#0EA5E9',\n lime: '#84CC16',\n amber: '#F59E0B',\n red: '#EF4444',\n },\n} as const;\n\n// ── Level Colors ──────────────────────────────────────────────────────────────\n\nexport const LEVEL_COLORS = {\n level0: BRAND_COLORS.primary[500],\n level1: BRAND_COLORS.primary[400],\n level2: BRAND_COLORS.primary[300],\n level3: BRAND_COLORS.primary[200],\n level4: BRAND_COLORS.primary[300],\n level5: BRAND_COLORS.primary[400],\n level6: BRAND_COLORS.primary[500],\n level7: BRAND_COLORS.primary[600],\n level8: BRAND_COLORS.primary[700],\n} as const;\n\nexport const LEVEL_COLOR_ARRAY = [\n LEVEL_COLORS.level0,\n LEVEL_COLORS.level1,\n LEVEL_COLORS.level2,\n LEVEL_COLORS.level3,\n LEVEL_COLORS.level4,\n LEVEL_COLORS.level5,\n LEVEL_COLORS.level6,\n LEVEL_COLORS.level7,\n LEVEL_COLORS.level8,\n] as const;\n\nexport const PARENT_FALLBACK_COLORS = [\n '#12C7D3', '#325E8C', '#8A70A6', '#F54A57', '#FF6C4D',\n '#F28C16', '#FFD347', '#7F7F7F', '#8D8D8D',\n] as const;\n\nexport const SEMANTIC_COLORS = {\n success: BRAND_COLORS.secondary[500],\n error: BRAND_COLORS.accent.red,\n warning: BRAND_COLORS.accent.amber,\n info: BRAND_COLORS.primary[500],\n} as const;\n\n// ── Theme Colors ──────────────────────────────────────────────────────────────\n\nexport const THEME_COLORS = {\n light: {\n background: { primary: '#FAF8F4', secondary: '#F0EDE6', tertiary: '#FFFFFF' },\n text: { primary: '#1A1A18', secondary: '#6B6860', tertiary: '#747270' },\n border: { primary: '#DDD9D0', secondary: '#E8E4DC' },\n },\n dark: {\n background: { primary: '#1C1C1A', secondary: '#141412', tertiary: '#262622' },\n text: { primary: '#F0EDE6', secondary: '#B0ABA3', tertiary: '#8E8C88' },\n border: { primary: '#333330', secondary: '#2A2A28' },\n },\n} as const;\n\n// ── Canvas Node Colors ────────────────────────────────────────────────────────\n\nexport const CANVAS_COLORS = {\n node: {\n border: '#FFFFFF',\n titleColor: '#1e1b4b',\n badgeBackground: '#FFC107',\n badgeStroke: '#fcd34d',\n },\n} as const;\n\n// ── Spacing ───────────────────────────────────────────────────────────────────\n\nexport const SPACING = {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n '2xl': 48,\n '3xl': 64,\n '4xl': 96,\n} as const;\n\nexport const LAYOUT_SPACING = {\n nodeSpacing: 200,\n levelSpacing: 150,\n containerPadding: 20,\n gridSize: 50,\n} as const;\n\n// ── Typography ────────────────────────────────────────────────────────────────\n\nexport const FONTS = {\n primary: \"'Inter', sans-serif\",\n secondary: \"'Poppins', sans-serif\",\n mono: \"'Roboto Mono', monospace\",\n} as const;\n\nexport const FONT_SIZES = {\n xs: '0.75rem',\n sm: '0.875rem',\n base: '1rem',\n lg: '1.125rem',\n xl: '1.25rem',\n '2xl': '1.5rem',\n '3xl': '1.875rem',\n '4xl': '2.25rem',\n} as const;\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/** Get a level color, cycling back to level 0 for levels > 8. */\nexport function getColorForLevel(level: number): string {\n return LEVEL_COLOR_ARRAY[level % LEVEL_COLOR_ARRAY.length];\n}\n\n/**\n * Darken a hex color by reducing HSL lightness.\n * Returns a monochromatic darker version — used for border/stroke colors.\n * Falls back to the original string if parsing fails.\n */\nexport function darkenHexColor(hex: string, amount: number = 0.22): string {\n if (!hex || !hex.startsWith('#')) return hex;\n let r: number, g: number, b: number;\n if (hex.length === 4) {\n r = parseInt(hex[1] + hex[1], 16);\n g = parseInt(hex[2] + hex[2], 16);\n b = parseInt(hex[3] + hex[3], 16);\n } else if (hex.length === 7) {\n r = parseInt(hex.slice(1, 3), 16);\n g = parseInt(hex.slice(3, 5), 16);\n b = parseInt(hex.slice(5, 7), 16);\n } else {\n return hex;\n }\n if (isNaN(r) || isNaN(g) || isNaN(b)) return hex;\n const rn = r / 255, gn = g / 255, bn = b / 255;\n const cmax = Math.max(rn, gn, bn), cmin = Math.min(rn, gn, bn);\n const d = cmax - cmin;\n const l = (cmax + cmin) / 2;\n const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));\n let h = 0;\n if (d !== 0) {\n const seg = cmax === rn ? (gn - bn) / d : cmax === gn ? (bn - rn) / d + 2 : (rn - gn) / d + 4;\n h = ((seg * 60) + 360) % 360;\n }\n const newL = Math.max(0, l - amount);\n const c2 = (1 - Math.abs(2 * newL - 1)) * s;\n const x2 = c2 * (1 - Math.abs(((h / 60) % 2) - 1));\n const m2 = newL - c2 / 2;\n let r1 = 0, g1 = 0, b1 = 0;\n if (h < 60) { r1 = c2; g1 = x2; b1 = 0; }\n else if (h < 120) { r1 = x2; g1 = c2; b1 = 0; }\n else if (h < 180) { r1 = 0; g1 = c2; b1 = x2; }\n else if (h < 240) { r1 = 0; g1 = x2; b1 = c2; }\n else if (h < 300) { r1 = x2; g1 = 0; b1 = c2; }\n else { r1 = c2; g1 = 0; b1 = x2; }\n const toHex = (v: number) => Math.round((v + m2) * 255).toString(16).padStart(2, '0');\n return `#${toHex(r1)}${toHex(g1)}${toHex(b1)}`;\n}\n\nexport function getThemeBackground(\n isDark: boolean,\n variant: 'primary' | 'secondary' | 'tertiary' = 'primary',\n): string {\n return isDark ? THEME_COLORS.dark.background[variant] : THEME_COLORS.light.background[variant];\n}\n\nexport function getThemeText(\n isDark: boolean,\n variant: 'primary' | 'secondary' | 'tertiary' = 'primary',\n): string {\n return isDark ? THEME_COLORS.dark.text[variant] : THEME_COLORS.light.text[variant];\n}\n\nexport function getThemeBorder(\n isDark: boolean,\n variant: 'primary' | 'secondary' = 'primary',\n): string {\n return isDark ? THEME_COLORS.dark.border[variant] : THEME_COLORS.light.border[variant];\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 { LEVEL_COLORS, LAYOUT_SPACING, getColorForLevel } from '../constants/design.js';\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: {\n level0: LEVEL_COLORS.level0,\n level1: LEVEL_COLORS.level1,\n level2: LEVEL_COLORS.level2,\n level3: LEVEL_COLORS.level3,\n },\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: getColorForLevel(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: {\n level0: LEVEL_COLORS.level0,\n level1: LEVEL_COLORS.level1,\n level2: LEVEL_COLORS.level2,\n level3: LEVEL_COLORS.level3,\n level4: LEVEL_COLORS.level4,\n level5: LEVEL_COLORS.level5,\n level6: LEVEL_COLORS.level6,\n level7: LEVEL_COLORS.level7,\n level8: LEVEL_COLORS.level8,\n },\n layout: {\n nodeSpacing: LAYOUT_SPACING.nodeSpacing,\n levelSpacing: LAYOUT_SPACING.levelSpacing,\n },\n },\n };\n}\n","// ─── Performance & Rendering Constants ───────────────────────────────────────\n\n// ── FPS ───────────────────────────────────────────────────────────────────────\n\nexport const FPS_TARGET = 60;\nexport const FPS_WARNING_THRESHOLD = 45;\nexport const FPS_CRITICAL_THRESHOLD = 30;\nexport const TARGET_FRAME_TIME = 1000 / FPS_TARGET; // ~16.67 ms\nexport const MAX_FRAME_TIME = 18; // p95 threshold\n\n/** Legacy frame-rate targets kept for backward compatibility. */\nexport const FPS_TARGETS = {\n PAN_MIN: 30,\n ZOOM_TARGET: 60,\n WARNING_THRESHOLD: 20,\n} as const;\n\n// ── Timing Thresholds (ms) ────────────────────────────────────────────────────\n\nexport const TIMING_THRESHOLDS = {\n VIEWPORT_QUERY_MAX: 5,\n SPATIAL_UPDATE_MAX: 10,\n DRAG_RESPONSE_MAX: 16,\n LOAD_5K_TARGET: 2000,\n LOAD_10K_TARGET: 3000,\n VIEWPORT_DEBOUNCE: 100,\n SPATIAL_INDEX_BUILD: 50,\n} as const;\n\n// ── Memory Limits (MB) ────────────────────────────────────────────────────────\n\nexport const MEMORY_TARGET_MB = 500;\nexport const MEMORY_WARNING_MB = 600;\nexport const MEMORY_CRITICAL_MB = 800;\n\nexport const MEMORY_LIMITS = {\n MAX_10K_NODES: 500,\n MAX_GROWTH_PERCENT: 20,\n WARNING_THRESHOLD: 400,\n} as const;\n\n// ── Viewport Culling ──────────────────────────────────────────────────────────\n\nexport const VIEWPORT_MARGIN = 0.1;\nexport const MAX_VISIBLE_NODES = 800;\nexport const CULLING_QUERY_TIME_BUDGET = 5;\n\n// ── Spatial Index ─────────────────────────────────────────────────────────────\n\nexport const RBUSH_MAX_ENTRIES = 16;\nexport const SPATIAL_INDEX_BUILD_BUDGET = 50;\n\n// ── Node Dimensions ───────────────────────────────────────────────────────────\n\nexport const NODE_MIN_WIDTH = 200;\nexport const NODE_HEIGHT = 80;\nexport const NODE_PADDING = 40;\nexport const CHAR_WIDTH = 8;\nexport const TITLE_MAX_LENGTH = 150;\n\n// ── Visual Styling ────────────────────────────────────────────────────────────\n\nexport const CORNER_RADIUS = 8;\nexport const BORDER_WIDTH_NORMAL = 2;\nexport const BORDER_WIDTH_SELECTED = 3;\n\nexport const COLOR_SELECTED = '#1B2D4F';\nexport const COLOR_BORDER_LIGHT = '#4A3728';\nexport const COLOR_BORDER_DARK = '#FAF6F1';\nexport const COLOR_DEFAULT_NODE = '#FAF6F1';\n\n// ── Zoom Constraints ──────────────────────────────────────────────────────────\n\nexport const ZOOM_MIN = 0.05;\nexport const ZOOM_MAX = 5.0;\nexport const ZOOM_DEFAULT = 1.0;\nexport const ZOOM_STEP = 0.1;\nexport const ZOOM_WHEEL_SENSITIVITY = 0.001;\n\nexport const ZOOM_NAV_IN_THRESHOLD = 2.7;\nexport const ZOOM_NAV_OUT_THRESHOLD = 0.4;\nexport const TEXT_LABEL_HIDE_BELOW_ZOOM = 0.3;\n\n// ── Quality Level Presets ─────────────────────────────────────────────────────\n\nexport const QUALITY_HIGH = {\n shadows: true,\n bezierCurves: true,\n animations: true,\n textQuality: 'high' as const,\n antialiasing: true,\n};\n\nexport const QUALITY_MEDIUM = {\n shadows: false,\n bezierCurves: true,\n animations: true,\n textQuality: 'medium' as const,\n antialiasing: true,\n};\n\nexport const QUALITY_LOW = {\n shadows: false,\n bezierCurves: false,\n animations: false,\n textQuality: 'low' as const,\n antialiasing: false,\n};\n\n// ── Performance Monitoring ────────────────────────────────────────────────────\n\nexport const FPS_SAMPLE_WINDOW = 60;\nexport const FPS_UPDATE_INTERVAL = 1000;\nexport const MEMORY_CHECK_INTERVAL = 5000;\nexport const PERFORMANCE_TOAST_COOLDOWN = 10000;\n\n// ── Auto-Adjustment ───────────────────────────────────────────────────────────\n\nexport const FPS_DOWNGRADE_THRESHOLD = 45;\nexport const FPS_UPGRADE_THRESHOLD = 58;\nexport const FPS_STABILIZATION_FRAMES = 180;\n\n// ── Canvas Dimensions ─────────────────────────────────────────────────────────\n\nexport const DEFAULT_CANVAS_WIDTH = 1920;\nexport const DEFAULT_CANVAS_HEIGHT = 1080;\n\n// ── Interaction ───────────────────────────────────────────────────────────────\n\nexport const CLICK_THRESHOLD = 5;\nexport const DOUBLE_CLICK_DELAY = 300;\nexport const DRAG_START_DISTANCE = 10;\n\n// ── Data Validation ───────────────────────────────────────────────────────────\n\nexport const MAX_NODES = 20000;\nexport const CIRCULAR_REFERENCE_MAX_DEPTH = 1000;\n\n// ── Debounce / Throttle ───────────────────────────────────────────────────────\n\nexport const RESIZE_DEBOUNCE = 300;\nexport const SCROLL_THROTTLE = 16;\nexport const SEARCH_DEBOUNCE = 500;\n\n/** Node count thresholds that gate optimisation strategies. */\nexport const NODE_COUNT_THRESHOLDS = {\n SPATIAL_INDEX_MIN: 100,\n VIEWPORT_CULLING_MIN: 500,\n CANVAS_RENDERING_MIN: 2000,\n DOM_RENDERING_MAX: 5000,\n} as const;\n\n/** Viewport buffer configuration. */\nexport const VIEWPORT_CONFIG = {\n BUFFER_PERCENT: 0.2,\n MIN_VISIBLE_NODES: 10,\n} as const;\n","// ─── Render Configuration ─────────────────────────────────────────────────────\n\nimport type { RenderConfig } from '../types/mindmap.js';\nimport {\n FPS_TARGET,\n MEMORY_TARGET_MB,\n QUALITY_HIGH,\n QUALITY_MEDIUM,\n QUALITY_LOW,\n NODE_COUNT_THRESHOLDS,\n} from './performanceConstants.js';\n\n// ── Defaults ──────────────────────────────────────────────────────────────────\n\nexport const DEFAULT_RENDER_CONFIG: RenderConfig = {\n renderMode: 'canvas',\n qualityLevel: 'high',\n cullingEnabled: false,\n fpsTarget: FPS_TARGET,\n memoryLimit: MEMORY_TARGET_MB,\n};\n\nexport const SIMPLIFIED_RENDER_CONFIG: RenderConfig = {\n renderMode: 'simplified',\n qualityLevel: 'low',\n cullingEnabled: true,\n fpsTarget: 30,\n memoryLimit: 400,\n};\n\n// ── Quality Map ───────────────────────────────────────────────────────────────\n\nexport const QUALITY_SETTINGS = {\n high: QUALITY_HIGH,\n medium: QUALITY_MEDIUM,\n low: QUALITY_LOW,\n} as const;\n\n// ── Feature Flags ─────────────────────────────────────────────────────────────\n\nexport const FEATURE_FLAGS = {\n viewportCulling: true,\n spatialIndexing: true,\n shadows: true,\n bezierCurves: true,\n animations: true,\n branchBadges: true,\n autoQualityAdjustment: true,\n performanceMonitoring: true,\n performanceToasts: true,\n debugOverlay: false,\n showFPS: false,\n showMemory: false,\n showVisibleCount: false,\n} as const;\n\n// ── Render Modes ──────────────────────────────────────────────────────────────\n\nexport type RenderMode = RenderConfig['renderMode'];\nexport type QualityLevel = RenderConfig['qualityLevel'];\n\nexport const RENDER_MODES = {\n canvas: {\n name: 'Canvas',\n description: 'Full Konva canvas rendering with all features',\n features: { culling: true, shadows: true, bezierCurves: true, animations: true },\n },\n simplified: {\n name: 'Simplified',\n description: 'Reduced feature set for low-end devices',\n features: { culling: true, shadows: false, bezierCurves: false, animations: false },\n },\n} as const;\n\nexport const QUALITY_LEVELS = {\n high: { name: 'High', description: 'All visual features enabled', targetFPS: 60, features: QUALITY_HIGH },\n medium: { name: 'Medium', description: 'Shadows disabled, other features enabled', targetFPS: 60, features: QUALITY_MEDIUM },\n low: { name: 'Low', description: 'Minimal visual features, max performance', targetFPS: 30, features: QUALITY_LOW },\n} as const;\n\n// ── Auto-Adjustment Helpers ───────────────────────────────────────────────────\n\nexport function getOptimalQualityLevel(\n currentFPS: number,\n currentQuality: QualityLevel,\n): QualityLevel {\n if (currentFPS < 45 && currentQuality === 'high') return 'medium';\n if (currentFPS < 30 && currentQuality === 'medium') return 'low';\n if (currentFPS > 58 && currentQuality === 'low') return 'medium';\n if (currentFPS > 58 && currentQuality === 'medium') return 'high';\n return currentQuality;\n}\n\nexport function getRenderConfigForQuality(quality: QualityLevel): Partial<RenderConfig> {\n return { qualityLevel: quality, fpsTarget: QUALITY_LEVELS[quality].targetFPS };\n}\n\nexport function isFeatureEnabled(\n featureName: keyof typeof FEATURE_FLAGS,\n config: RenderConfig,\n): boolean {\n if (!FEATURE_FLAGS[featureName]) return false;\n\n const qs = QUALITY_SETTINGS[config.qualityLevel];\n switch (featureName) {\n case 'shadows': return qs.shadows;\n case 'bezierCurves': return qs.bezierCurves;\n case 'animations': return qs.animations;\n default: return FEATURE_FLAGS[featureName] as boolean;\n }\n}\n\n// ── Device Detection ──────────────────────────────────────────────────────────\n\n/**\n * Recommend a render config based on detected device memory (browser only).\n * Falls back to SIMPLIFIED_RENDER_CONFIG when the Performance Memory API is\n * unavailable or memory is constrained.\n */\nexport function getRecommendedRenderConfig(): RenderConfig {\n if (typeof performance === 'undefined' || !(performance as unknown as Record<string, unknown>)['memory']) {\n return SIMPLIFIED_RENDER_CONFIG;\n }\n\n const memory = (performance as unknown as Record<string, unknown>)['memory'] as Record<string, number>;\n if (memory?.['jsHeapSizeLimit'] && memory['jsHeapSizeLimit'] < 512 * 1024 * 1024) {\n return SIMPLIFIED_RENDER_CONFIG;\n }\n\n return DEFAULT_RENDER_CONFIG;\n}\n\n/** Re-export so consumers need only one import. */\nexport { NODE_COUNT_THRESHOLDS };\n","// ─── Viewport Utilities ───────────────────────────────────────────────────────\n//\n// Pure functions for viewport bounds calculation, coordinate transforms,\n// pan/zoom operations, and node visibility queries.\n\nimport type { ViewportState } from '../types/mindmap.js';\nimport {\n VIEWPORT_MARGIN,\n DEFAULT_CANVAS_WIDTH,\n DEFAULT_CANVAS_HEIGHT,\n ZOOM_MIN,\n ZOOM_MAX,\n} from '../constants/performanceConstants.js';\n\n// ── Viewport Bounds ───────────────────────────────────────────────────────────\n\nexport interface WorldBounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\n/**\n * Calculate the visible world-space bounding box including a margin buffer.\n */\nexport function calculateViewportBounds(\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): WorldBounds {\n const worldW = canvasWidth / viewport.zoomLevel;\n const worldH = canvasHeight / viewport.zoomLevel;\n const mx = worldW * VIEWPORT_MARGIN;\n const my = worldH * VIEWPORT_MARGIN;\n return {\n minX: viewport.centerX - worldW / 2 - mx,\n minY: viewport.centerY - worldH / 2 - my,\n maxX: viewport.centerX + worldW / 2 + mx,\n maxY: viewport.centerY + worldH / 2 + my,\n };\n}\n\n/**\n * Return a new ViewportState with `visibleBounds` recalculated.\n */\nexport function recalculateViewportBounds(\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): ViewportState {\n return {\n ...viewport,\n visibleBounds: calculateViewportBounds(viewport, canvasWidth, canvasHeight),\n };\n}\n\n// ── Coordinate Transforms ─────────────────────────────────────────────────────\n\n/**\n * Convert world-space coordinates to screen-space pixel coordinates.\n */\nexport function worldToScreen(\n worldX: number,\n worldY: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): { x: number; y: number } {\n return {\n x: (worldX - viewport.centerX) * viewport.zoomLevel + canvasWidth / 2,\n y: (worldY - viewport.centerY) * viewport.zoomLevel + canvasHeight / 2,\n };\n}\n\n/**\n * Convert screen-space pixel coordinates to world-space coordinates.\n */\nexport function screenToWorld(\n screenX: number,\n screenY: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): { x: number; y: number } {\n return {\n x: (screenX - canvasWidth / 2) / viewport.zoomLevel + viewport.centerX,\n y: (screenY - canvasHeight / 2) / viewport.zoomLevel + viewport.centerY,\n };\n}\n\n// ── Pan / Zoom ────────────────────────────────────────────────────────────────\n\n/** Clamp zoom to [ZOOM_MIN, ZOOM_MAX]. */\nexport function clampZoom(zoom: number): number {\n return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, zoom));\n}\n\n/**\n * Pan the viewport by a screen-space delta (positive = right/down).\n */\nexport function panViewport(\n deltaX: number,\n deltaY: number,\n viewport: ViewportState,\n): ViewportState {\n return {\n ...viewport,\n centerX: viewport.centerX - deltaX / viewport.zoomLevel,\n centerY: viewport.centerY - deltaY / viewport.zoomLevel,\n };\n}\n\n/** Teleport the viewport centre to the given world coordinates. */\nexport function setViewportCenter(\n x: number,\n y: number,\n viewport: ViewportState,\n): ViewportState {\n return { ...viewport, centerX: x, centerY: y };\n}\n\n/**\n * Zoom the viewport by a multiplicative delta, optionally around a pivot point.\n *\n * @param delta - Multiplier delta, e.g. 0.1 for +10% zoom\n * @param pivotX - Optional screen-space X pivot\n * @param pivotY - Optional screen-space Y pivot\n */\nexport function zoomViewport(\n delta: number,\n viewport: ViewportState,\n pivotX?: number,\n pivotY?: number,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): ViewportState {\n const newZoom = clampZoom(viewport.zoomLevel * (1 + delta));\n\n let cx = viewport.centerX;\n let cy = viewport.centerY;\n\n if (pivotX !== undefined && pivotY !== undefined) {\n const worldPivot = screenToWorld(pivotX, pivotY, viewport, canvasWidth, canvasHeight);\n cx = worldPivot.x - (pivotX - canvasWidth / 2) / newZoom;\n cy = worldPivot.y - (pivotY - canvasHeight / 2) / newZoom;\n }\n\n return { ...viewport, centerX: cx, centerY: cy, zoomLevel: newZoom };\n}\n\n/**\n * Create a viewport centred on a node (world coordinates) at the given zoom level.\n */\nexport function focusOnNode(\n nodeX: number,\n nodeY: number,\n zoom: number,\n): ViewportState {\n const clamped = clampZoom(zoom);\n return {\n centerX: nodeX,\n centerY: nodeY,\n zoomLevel: clamped,\n rotation: 0,\n visibleBounds: calculateViewportBounds(\n { centerX: nodeX, centerY: nodeY, zoomLevel: clamped, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } },\n ),\n };\n}\n\n// ── Visibility ────────────────────────────────────────────────────────────────\n\n/**\n * Test whether a world-space AABB intersects the viewport's visible bounds.\n */\nexport function isNodeInViewport(\n nodeX: number,\n nodeY: number,\n nodeWidth: number,\n nodeHeight: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): boolean {\n const bounds = calculateViewportBounds(viewport, canvasWidth, canvasHeight);\n const hw = nodeWidth / 2;\n const hh = nodeHeight / 2;\n return !(\n nodeX + hw < bounds.minX ||\n nodeX - hw > bounds.maxX ||\n nodeY + hh < bounds.minY ||\n nodeY - hh > bounds.maxY\n );\n}\n","// ─── Performance Monitors ─────────────────────────────────────────────────────\n//\n// FPSMonitor – tracks frame rate via requestAnimationFrame (browser)\n// MemoryMonitor – polls performance.memory (Chrome)\n// PerformanceProfiler – mark / measure utility for arbitrary operations\n\nimport {\n FPS_TARGET,\n FPS_SAMPLE_WINDOW,\n MEMORY_CHECK_INTERVAL,\n} from '../constants/performanceConstants.js';\n\n// ── FPS Monitor ───────────────────────────────────────────────────────────────\n\nexport class FPSMonitor {\n private frameTimes: number[] = [];\n private lastTime = 0;\n private currentFPS = FPS_TARGET;\n private rafId: number | null = null;\n\n start(): void {\n if (this.rafId !== null) return;\n\n const measure = (ts: number) => {\n if (this.lastTime > 0) {\n this.frameTimes.push(ts - this.lastTime);\n if (this.frameTimes.length > FPS_SAMPLE_WINDOW) this.frameTimes.shift();\n this.currentFPS = this.calc();\n }\n this.lastTime = ts;\n this.rafId = requestAnimationFrame(measure);\n };\n\n this.rafId = requestAnimationFrame(measure);\n }\n\n stop(): void {\n if (this.rafId !== null) { cancelAnimationFrame(this.rafId); this.rafId = null; }\n }\n\n private calc(): number {\n if (this.frameTimes.length === 0) return FPS_TARGET;\n const avg = this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length;\n return Math.round(1000 / avg);\n }\n\n getFPS(): number { return this.currentFPS; }\n getAverageFPS(): number { return this.currentFPS; }\n\n getP95FrameTime(): number {\n if (this.frameTimes.length === 0) return 0;\n const sorted = [...this.frameTimes].sort((a, b) => a - b);\n return sorted[Math.floor(sorted.length * 0.95)];\n }\n\n reset(): void { this.frameTimes = []; this.currentFPS = FPS_TARGET; }\n}\n\n// ── Memory Monitor ────────────────────────────────────────────────────────────\n\nexport interface MemoryStats {\n usedJSHeapSize: number;\n totalJSHeapSize: number;\n jsHeapSizeLimit: number;\n heapUsagePercent: number;\n}\n\nexport class MemoryMonitor {\n private timer: ReturnType<typeof setInterval> | null = null;\n private current = 0;\n\n start(onUpdate?: (mb: number) => void): void {\n if (this.timer !== null) return;\n this.timer = setInterval(() => {\n this.current = this.measure();\n onUpdate?.(this.current);\n }, MEMORY_CHECK_INTERVAL);\n }\n\n stop(): void {\n if (this.timer !== null) { clearInterval(this.timer); this.timer = null; }\n }\n\n private measure(): number {\n const mem = (performance as unknown as Record<string, unknown>)['memory'] as Record<string, number> | undefined;\n return mem ? mem['usedJSHeapSize'] / (1024 * 1024) : 0;\n }\n\n getMemoryMB(): number { return this.current; }\n\n getStats(): MemoryStats | null {\n const mem = (performance as unknown as Record<string, unknown>)['memory'] as Record<string, number> | undefined;\n if (!mem) return null;\n return {\n usedJSHeapSize: mem['usedJSHeapSize'],\n totalJSHeapSize: mem['totalJSHeapSize'],\n jsHeapSizeLimit: mem['jsHeapSizeLimit'],\n heapUsagePercent: (mem['usedJSHeapSize'] / mem['jsHeapSizeLimit']) * 100,\n };\n }\n\n static isSupported(): boolean {\n return !!(performance as unknown as Record<string, unknown>)['memory'];\n }\n}\n\n// ── Performance Profiler ──────────────────────────────────────────────────────\n\nexport class PerformanceProfiler {\n private marks: Map<string, number> = new Map();\n private measures: Map<string, number[]> = new Map();\n\n mark(label: string): void {\n this.marks.set(label, performance.now());\n }\n\n measure(label: string): number {\n const start = this.marks.get(label);\n if (start === undefined) return 0;\n const duration = performance.now() - start;\n const list = this.measures.get(label) ?? [];\n list.push(duration);\n this.measures.set(label, list);\n this.marks.delete(label);\n return duration;\n }\n\n getAverage(label: string): number {\n const list = this.measures.get(label);\n if (!list?.length) return 0;\n return list.reduce((a, b) => a + b, 0) / list.length;\n }\n\n getP95(label: string): number {\n const list = this.measures.get(label);\n if (!list?.length) return 0;\n const sorted = [...list].sort((a, b) => a - b);\n return sorted[Math.floor(sorted.length * 0.95)];\n }\n\n clear(label?: string): void {\n if (label) { this.marks.delete(label); this.measures.delete(label); }\n else { this.marks.clear(); this.measures.clear(); }\n }\n}\n","// ─── Animation Easing Functions ───────────────────────────────────────────────\n//\n// Pure math easing functions for smooth, cinematic animations.\n// No DOM / RAF dependencies – usable in any runtime.\n\nexport type EasingFunction = (t: number) => number;\n\n/** Smooth cubic – slow start, fast middle, slow end. */\nexport const easeInOutCubic: EasingFunction = (t) =>\n t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;\n\n/** Smooth quartic – more dramatic than cubic. */\nexport const easeInOutQuart: EasingFunction = (t) =>\n t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2;\n\n/** Fast start, slow end. */\nexport const easeOutCubic: EasingFunction = (t) => 1 - Math.pow(1 - t, 3);\n\n/** Slow start, fast end. */\nexport const easeInCubic: EasingFunction = (t) => t * t * t;\n\n/** Gentle ease-out (quadratic). */\nexport const easeOutQuad: EasingFunction = (t) => 1 - (1 - t) * (1 - t);\n\n/** Very smooth, organic sine easing. */\nexport const easeInOutSine: EasingFunction = (t) =>\n -(Math.cos(Math.PI * t) - 1) / 2;\n\n/**\n * Create a CSS cubic-bezier easing function from four control-point values.\n *\n * Builds a 256-entry lookup table at call time (once) so subsequent evaluations\n * are a single table lookup + linear interpolation.\n */\nexport function createCubicBezier(\n x1: number, y1: number,\n x2: number, y2: number,\n): EasingFunction {\n const N = 256;\n const lut = new Float64Array(N + 1);\n\n for (let i = 0; i <= N; i++) {\n const target = i / N;\n let lo = 0, hi = 1;\n for (let j = 0; j < 20; j++) {\n const mid = (lo + hi) / 2;\n const om = 1 - mid;\n const x = 3 * om * om * mid * x1 + 3 * om * mid * mid * x2 + mid * mid * mid;\n if (x < target) lo = mid; else hi = mid;\n }\n const u = (lo + hi) / 2;\n const ou = 1 - u;\n lut[i] = 3 * ou * ou * u * y1 + 3 * ou * u * u * y2 + u * u * u;\n }\n\n return (t: number): number => {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n const s = t * N;\n const i = s | 0;\n return lut[i] + (lut[i + 1] - lut[i]) * (s - i);\n };\n}\n\n/**\n * Zoom-transition easing — matches CSS cubic-bezier(0.2, 0.8, 0.2, 1).\n * Fast start with smooth, organic settle. Used for all layer transitions.\n * Pre-computed LUT: subsequent calls are a single table lookup + linear interpolation.\n */\nexport const easeZoomTransition: EasingFunction = createCubicBezier(0.2, 0.8, 0.2, 1);\n","// ─── Animation Constants ──────────────────────────────────────────────────────\n\n// ── Timing (ms) ───────────────────────────────────────────────────────────────\n\nexport const ANIMATION_DURATION = {\n ZOOM_IN_LAYER: 500,\n ZOOM_OUT_LAYER: 500,\n ZOOM_GESTURE: 500,\n FADE_OUT: 200,\n FADE_IN: 250,\n COLOR_TRANSITION: 500,\n CURSOR_CHANGE: 150,\n LOADING_FADE: 200,\n} as const;\n\nexport const ANIMATION_PHASES = {\n ZOOM_IN: {\n ZOOM_TO_TARGET: 500,\n FADE_OUT_START: 120,\n FADE_OUT: 280,\n CONTENT_SWAP: 310,\n FADE_IN: 200,\n TOTAL: 510,\n },\n ZOOM_OUT: {\n FADE_OUT: 200,\n ZOOM_BACK: 50,\n FADE_IN: 250,\n TOTAL: 500,\n },\n} as const;\n\n// ── Zoom Thresholds ───────────────────────────────────────────────────────────\n\nexport const ZOOM_THRESHOLDS = {\n ENTER_LAYER: 5.0,\n EXIT_LAYER: 0.5,\n GESTURE_TRIGGER: 0.8,\n} as const;\n\n// ── Cooldowns (ms) ────────────────────────────────────────────────────────────\n\nexport const COOLDOWN = {\n NAVIGATION: 1000,\n ZOOM_GESTURE: 800,\n DOUBLE_CLICK: 200,\n} as const;\n\n// ── Opacity ───────────────────────────────────────────────────────────────────\n\nexport const OPACITY = {\n VISIBLE: 1.0,\n HIDDEN: 0.0,\n TRANSITIONING: 0.3,\n} as const;\n\n// ── Target Zoom Levels ────────────────────────────────────────────────────────\n\nexport const TARGET_ZOOM = {\n NORMAL: 1.0,\n FOCUSED: 0.8,\n FILL_NODE: 3.0,\n DETAIL: 2.0,\n} as const;\n\n// ── Viewport Framing ──────────────────────────────────────────────────────────\n\nexport const VIEWPORT_FRAMING = {\n NODE_FILL_RATIO: 0.7,\n EXIT_NODE_SIZE: 0.4,\n PADDING_RATIO: 0.1,\n} as const;\n","// ─── Spatial Index ────────────────────────────────────────────────────────────\n//\n// RBush-backed R-tree for O(log n) viewport culling queries.\n// Wraps the `rbush` library with a typed, domain-specific interface.\n\nimport RBush from 'rbush';\n\nexport interface BoundingBox {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\ninterface SpatialItem extends BoundingBox {\n nodeId: string;\n}\n\nexport interface ISpatialIndex {\n insert(nodeId: string, bounds: BoundingBox): void;\n remove(nodeId: string, bounds: BoundingBox): void;\n update(nodeId: string, oldBounds: BoundingBox, newBounds: BoundingBox): void;\n query(bounds: BoundingBox): string[];\n clear(): void;\n size(): number;\n bulkLoad(items: Array<{ nodeId: string; bounds: BoundingBox }>): void;\n}\n\n/**\n * RBush-based spatial index for efficient viewport culling.\n *\n * - Insert / remove / update: O(log n)\n * - Query: O(log n + k) where k = result count\n * - Bulk load: O(n log n) — use instead of repeated inserts for initial load\n */\nexport class RBushSpatialIndex implements ISpatialIndex {\n private tree: RBush<SpatialItem>;\n private cache: Map<string, BoundingBox>;\n\n constructor() {\n this.tree = new RBush<SpatialItem>();\n this.cache = new Map();\n }\n\n insert(nodeId: string, bounds: BoundingBox): void {\n this.tree.insert({ ...bounds, nodeId });\n this.cache.set(nodeId, bounds);\n }\n\n remove(nodeId: string, bounds: BoundingBox): void {\n this.tree.remove({ ...bounds, nodeId }, (a, b) => a.nodeId === b.nodeId);\n this.cache.delete(nodeId);\n }\n\n update(nodeId: string, oldBounds: BoundingBox, newBounds: BoundingBox): void {\n this.remove(nodeId, oldBounds);\n this.insert(nodeId, newBounds);\n }\n\n query(bounds: BoundingBox): string[] {\n return this.tree.search(bounds).map(item => item.nodeId);\n }\n\n clear(): void {\n this.tree.clear();\n this.cache.clear();\n }\n\n size(): number {\n return this.cache.size;\n }\n\n bulkLoad(items: Array<{ nodeId: string; bounds: BoundingBox }>): void {\n const rbushItems = items.map(({ nodeId, bounds }) => ({ ...bounds, nodeId }));\n this.tree.load(rbushItems);\n for (const { nodeId, bounds } of items) this.cache.set(nodeId, bounds);\n }\n\n /** Return the cached bounding box for a node (undefined if not indexed). */\n getBounds(nodeId: string): BoundingBox | undefined {\n return this.cache.get(nodeId);\n }\n}\n","const createStoreImpl = (createState) => {\n let state;\n const listeners = /* @__PURE__ */ new Set();\n const setState = (partial, replace) => {\n const nextState = typeof partial === \"function\" ? partial(state) : partial;\n if (!Object.is(nextState, state)) {\n const previousState = state;\n state = (replace != null ? replace : typeof nextState !== \"object\" || nextState === null) ? nextState : Object.assign({}, state, nextState);\n listeners.forEach((listener) => listener(state, previousState));\n }\n };\n const getState = () => state;\n const getInitialState = () => initialState;\n const subscribe = (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n const destroy = () => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") {\n console.warn(\n \"[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected.\"\n );\n }\n listeners.clear();\n };\n const api = { setState, getState, getInitialState, subscribe, destroy };\n const initialState = state = createState(setState, getState, api);\n return api;\n};\nconst createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;\nvar vanilla = (createState) => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") {\n console.warn(\n \"[DEPRECATED] Default export is deprecated. Instead use import { createStore } from 'zustand/vanilla'.\"\n );\n }\n return createStore(createState);\n};\n\nexport { createStore, vanilla as default };\n","import { createStore } from 'zustand/vanilla';\nimport type { NodeSelection, RenderConfig } from '../types/index.js';\nimport {\n DEFAULT_RENDER_CONFIG,\n getOptimalQualityLevel,\n getRenderConfigForQuality,\n isFeatureEnabled,\n FEATURE_FLAGS,\n} from '../constants/renderConfig.js';\n\n// ─── Selection Store ──────────────────────────────────────────────────────────\n\nexport interface ISelectionStore extends NodeSelection {\n select: (nodeId: string) => void;\n clear: () => void;\n toggle: (nodeId: string) => void;\n isSelected: (nodeId: string) => boolean;\n}\n\nexport const selectionStore = createStore<ISelectionStore>((set, get) => ({\n selectedId: null,\n select: (nodeId) => set({ selectedId: nodeId }),\n clear: () => set({ selectedId: null }),\n toggle: (nodeId) => set((s) => ({ selectedId: s.selectedId === nodeId ? null : nodeId })),\n isSelected: (nodeId) => get().selectedId === nodeId,\n}));\n\n// ─── Render Config Store ──────────────────────────────────────────────────────\n\nexport interface IRenderConfigStore extends RenderConfig {\n setQualityLevel: (level: RenderConfig['qualityLevel']) => void;\n setRenderMode: (mode: RenderConfig['renderMode']) => void;\n setCullingEnabled: (enabled: boolean) => void;\n autoAdjustQuality: (currentFPS: number) => void;\n autoAdjustQualityByMemory: (memoryMB: number) => void;\n resetToDefaults: () => void;\n isFeatureEnabled: (feature: keyof typeof FEATURE_FLAGS) => boolean;\n}\n\nexport const renderConfigStore = createStore<IRenderConfigStore>((set, get) => ({\n ...DEFAULT_RENDER_CONFIG,\n\n setQualityLevel: (level) => set(getRenderConfigForQuality(level)),\n setRenderMode: (mode) => set({ renderMode: mode }),\n setCullingEnabled: (enabled) => set({ cullingEnabled: enabled }),\n\n autoAdjustQuality: (fps) =>\n set((s) => {\n const q = getOptimalQualityLevel(fps, s.qualityLevel);\n return q !== s.qualityLevel ? getRenderConfigForQuality(q) : s;\n }),\n\n autoAdjustQualityByMemory: (mb) =>\n set((s) => {\n const q = mb > 500 ? 'low' : mb > 400 && s.qualityLevel === 'high' ? 'medium' : s.qualityLevel;\n return q !== s.qualityLevel ? getRenderConfigForQuality(q as RenderConfig['qualityLevel']) : s;\n }),\n\n resetToDefaults: () => set({ ...DEFAULT_RENDER_CONFIG }),\n isFeatureEnabled: (feature) => isFeatureEnabled(feature, get()),\n}));\n","import type { VisualliDocument, VisualliLayer, FlatNode, MindMapConnection } from '../types/index.js';\nimport { ZOOM_MAX, ZOOM_NAV_OUT_THRESHOLD } from '../constants/performanceConstants.js';\n\n// ── Connection helpers ────────────────────────────────────────────────────────\n\n/**\n * Returns all top-level connections that originate from the given layer.\n * A \"top-level connection\" links two nodes that both live in `layerId`.\n */\nexport function getConnectionsForLayer(\n doc: VisualliDocument,\n layerId: string,\n): MindMapConnection[] {\n const layer = doc.layers.get(layerId);\n if (!layer) return [];\n // Convert schema LayerConnection to simplified mindmap MindMapConnection\n return layer.connections.map(c => ({\n from: c.from,\n to: c.to,\n level: layer.level,\n label: c.data?.label,\n } satisfies MindMapConnection));\n}\n\n/**\n * Given a node in the current layer, returns the child layer (if any) that the\n * node \"owns\" — i.e. the node is the entry-point into that child layer.\n */\nexport function getChildLayerForNode(\n doc: VisualliDocument,\n nodeId: string,\n currentLayerId: string,\n): VisualliLayer | null {\n // Walk all layers looking for one whose `parentNodeId` matches\n for (const [, layer] of doc.layers) {\n if (layer.parentLayerId === currentLayerId && layer.parentNodeId === nodeId) {\n return layer;\n }\n }\n return null;\n}\n\n/**\n * Returns the layer to navigate INTO when double-clicking `nodeId` in `currentLayerId`.\n * Returns null when the node has no child layer.\n */\nexport function getLayerForNavigation(\n doc: VisualliDocument,\n nodeId: string,\n currentLayerId: string,\n): VisualliLayer | null {\n return getChildLayerForNode(doc, nodeId, currentLayerId);\n}\n\n// ── Viewport fitting math ─────────────────────────────────────────────────────\n\nexport interface FitResult {\n centerX: number;\n centerY: number;\n zoomLevel: number;\n}\n\n/**\n * Calculates the zoom level needed to fit all `nodes` inside a canvas of\n * `(canvasWidth, canvasHeight)`.\n *\n * @param paddingFraction - Fractional padding on each side (0.15 = 15%).\n * Pixel-padding variant still available when a value >=1 is passed.\n */\nexport function calculateFitZoom(\n nodes: FlatNode[],\n canvasWidth: number,\n canvasHeight: number,\n padding = 0.15,\n): number {\n if (nodes.length === 0) return 1;\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n // Use the actual node boundaries (center +/- half-width/height)\n minX = Math.min(minX, n.x - n.width / 2);\n minY = Math.min(minY, n.y - n.height / 2);\n maxX = Math.max(maxX, n.x + n.width / 2);\n maxY = Math.max(maxY, n.y + n.height / 2);\n }\n\n const rawW = maxX - minX;\n const rawH = maxY - minY;\n\n // Minimum spread — single isolated node should appear comfortably\n // Matches visualli.ai's spread logic for single nodes\n const spreadW = nodes.length === 1 ? Math.max(rawW, 600) : rawW;\n const spreadH = nodes.length === 1 ? Math.max(rawH, 400) : rawH;\n\n const zoomX = (canvasWidth * (1 - padding)) / spreadW;\n const zoomY = (canvasHeight * (1 - padding)) / spreadH;\n\n const z = Math.min(zoomX, zoomY);\n\n // Scale back 20% so nodes aren't edge-to-edge, clamp to at least\n // ZOOM_NAV_OUT_THRESHOLD so arriving at the layer never immediately\n // re-triggers the zoom-out transition.\n return Math.max(z * 0.80, ZOOM_NAV_OUT_THRESHOLD);\n}\n\n/**\n * Calculates the world-space center point that puts all `nodes` in the middle\n * of the viewport. Matches the visualli.ai `calculateFitCenter` approach:\n * uses bounding-box midpoint rather than centroid so the layout is always\n * geometrically centred.\n */\nexport function calculateFitCenter(nodes: FlatNode[]): { x: number; y: number } {\n if (nodes.length === 0) return { x: 0, y: 0 };\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n minX = Math.min(minX, n.x - n.width / 2);\n minY = Math.min(minY, n.y - n.height / 2);\n maxX = Math.max(maxX, n.x + n.width / 2);\n maxY = Math.max(maxY, n.y + n.height / 2);\n }\n return { x: (minX + maxX) / 2, y: (minY + maxY) / 2 };\n}\n\n// ── Container helpers ────────────────────────────────────────────────────────\n\n// Inline the container shape here to avoid a circular import with KonvaContainerLayer.\nexport interface ContainerGroupInfo {\n id: string;\n label?: string;\n nodeIds: string[];\n level: number;\n}\n\n/**\n * Returns the container groups for the given layer, normalising both the\n * nested-data format `{data:{label,formation}}` and the flat format `{label}`.\n */\nexport function getContainersForLayer(\n doc: VisualliDocument,\n layerId: string,\n): ContainerGroupInfo[] {\n const layer = doc.layers.get(layerId);\n if (!layer) return [];\n return layer.containers.map(c => {\n // Schema Container has nested data.label structure\n const label = c.data?.label ?? c.id;\n return { id: c.id, label, nodeIds: c.nodes, level: layer.level };\n });\n}\n\n/** Convenience: returns both center and zoom for a single `fitView` call. */\nexport function calculateFitView(\n nodes: FlatNode[],\n canvasWidth: number,\n canvasHeight: number,\n): FitResult {\n const center = calculateFitCenter(nodes);\n const zoom = calculateFitZoom(nodes, canvasWidth, canvasHeight);\n return { centerX: center.x, centerY: center.y, zoomLevel: zoom };\n}\n\n","import type { FlatNode, ViewportState } from '../types/index.js';\nimport { RBushSpatialIndex } from '../spatial/spatialIndex.js';\nimport { calculateViewportBounds } from '../viewport/viewportUtils.js';\n\nexport interface CullingOptions {\n nodes: FlatNode[];\n viewport: ViewportState;\n canvasWidth: number;\n canvasHeight: number;\n levelFilter?: number;\n skipCulling?: boolean;\n isDragging?: boolean;\n spatialIndex?: RBushSpatialIndex | null;\n spatialIndexThreshold?: number;\n}\n\nconst DEFAULT_SPATIAL_INDEX_THRESHOLD = 200;\n\n/**\n * Returns the subset of nodes currently visible in the viewport.\n * Framework-agnostic logic for culling and spatial indexing.\n */\nexport function getViewportVisibleNodes(options: CullingOptions): FlatNode[] {\n const {\n nodes,\n viewport,\n canvasWidth,\n canvasHeight,\n levelFilter,\n skipCulling = false,\n isDragging = false,\n spatialIndex,\n spatialIndexThreshold = DEFAULT_SPATIAL_INDEX_THRESHOLD,\n } = options;\n\n const filtered = levelFilter !== undefined\n ? nodes.filter(n => n.level === levelFilter)\n : nodes;\n\n if (filtered.length === 0) return [];\n\n // During transitions or drags show all nodes to avoid partial layer appearance\n if (skipCulling || isDragging) return filtered;\n\n const bounds = calculateViewportBounds(viewport, canvasWidth, canvasHeight);\n\n if (filtered.length < spatialIndexThreshold) {\n return filtered.filter(n =>\n n.x + n.width >= bounds.minX &&\n n.x <= bounds.maxX &&\n n.y + n.height >= bounds.minY &&\n n.y <= bounds.maxY,\n );\n }\n\n if (spatialIndex) {\n const nodeIds = spatialIndex.query({\n minX: bounds.minX, minY: bounds.minY, maxX: bounds.maxX, maxY: bounds.maxY,\n });\n const idSet = new Set(nodeIds);\n return filtered.filter(n => idSet.has(n.id));\n }\n\n // Fallback to simple filter if no index provided but threshold exceeded\n return filtered.filter(n =>\n n.x + n.width >= bounds.minX &&\n n.x <= bounds.maxX &&\n n.y + n.height >= bounds.minY &&\n n.y <= bounds.maxY,\n );\n}\n","import { NODE_HEIGHT } from '../constants/performanceConstants.js';\n\nexport const NODE_TEXT_BASE_FONT_PX = 28;\nexport const DESCRIPTION_TEXT_BASE_FONT_PX = 12;\nexport const CONTAINER_LABEL_BASE_FONT_PX = 24;\nexport const EDGE_LABEL_BASE_FONT_PX = 18;\nexport const OVERLAY_FONT_UPPER_BOOST_PX = 8;\n\n// Keep text away from blob edges\nconst NODE_TEXT_SAFE_BLOB_FILL_RATIO = 0.88;\n\n/**\n * Computes world-space text scale for node title:\n * - inverse zoom for screen-space consistency\n * - clamped so text stays inside the node blob with safe padding\n *\n * Matches visualli.ai's computeNodeTextWorldScale(nodeWidth, zoomLevel).\n */\nexport function computeNodeTextWorldScale(nodeWidth: number, zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n const baseRadiusX = nodeWidth / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n const textNaturalWidth = nodeWidth - 40;\n const textNaturalHeight = NODE_HEIGHT - 20;\n\n const maxScaleX = ((baseRadiusX * 2) * NODE_TEXT_SAFE_BLOB_FILL_RATIO) / Math.max(textNaturalWidth, 1);\n const maxScaleY = ((baseRadiusY * 2) * NODE_TEXT_SAFE_BLOB_FILL_RATIO) / Math.max(textNaturalHeight, 1);\n const fitScale = Math.max(0.01, Math.min(maxScaleX, maxScaleY));\n\n return Math.min(1 / safeZoom, fitScale);\n}\n\n/** Screen-space scale (zoom-adjusted) for text overlays. */\nexport function computeNodeTextScreenScale(nodeWidth: number, zoomLevel: number): number {\n return computeNodeTextWorldScale(nodeWidth, zoomLevel) * zoomLevel;\n}\n\n/**\n * Screen-space overlay scale for description/semantic tooltips.\n * - lower bound: 1x\n * - upper bound: node-title-root + OVERLAY_FONT_UPPER_BOOST_PX\n */\nexport function computeOverlayScale(zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n const inverseScale = 1 / safeZoom;\n const maxScale = (NODE_TEXT_BASE_FONT_PX + OVERLAY_FONT_UPPER_BOOST_PX) / NODE_TEXT_BASE_FONT_PX;\n return Math.min(Math.max(inverseScale, 1), maxScale);\n}\n\n/** Scale for edge path labels in screen pixels. */\nexport function computeEdgeLabelScale(zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n return Math.min(Math.max(EDGE_LABEL_BASE_FONT_PX / safeZoom, 10), 32);\n}\n","export interface BlobPoint { x: number; y: number }\nexport type BlobShape = BlobPoint[];\n\n// ── Blob Layer Config ─────────────────────────────────────────────────────────\n\nexport const BLOB_LAYER_CONFIG = [\n { opacity: 0.3, rotation: -15, scaleUp: 1.30, strokeWidth: 3, dash: [6, 4] }, // Layer #3 (outermost)\n { opacity: 0.4, rotation: -10, scaleUp: 1.20, strokeWidth: 1, dash: undefined }, // Layer #2\n { opacity: 0.5, rotation: -5, scaleUp: 1.10, strokeWidth: 2, dash: undefined }, // Layer #1\n] as const;\n\nexport const NODE_LAYER_CONFIG = { opacity: 1, rotation: 0, strokeWidth: 3 } as const;\n\n// ── Blob Shapes ───────────────────────────────────────────────────────────────\n\nexport const ALL_BLOB_SHAPES: ReadonlyArray<BlobShape> = [\n // Shape 0 · Blob 1\n [\n { x: 1.12, y: 0 }, { x: 0.86, y: 0.56 }, { x: 0.46, y: 0.94 }, { x: -0.08, y: 1.06 },\n { x: -0.68, y: 0.82 }, { x: -0.96, y: 0.08 }, { x: -0.55, y: -0.82 }, { x: 0.04, y: -1.02 },\n { x: 0.72, y: -0.8 }, { x: 1.08, y: -0.38 },\n ],\n // Shape 1 · Blob 2\n [\n { x: -0.489, y: -0.625 }, { x: -0.384, y: -0.716 }, { x: -0.285, y: -0.792 }, { x: -0.189, y: -0.855 },\n { x: -0.090, y: -0.903 }, { x: 0.014, y: -0.932 }, { x: 0.129, y: -0.940 }, { x: 0.255, y: -0.924 },\n { x: 0.412, y: -0.876 }, { x: 0.516, y: -0.832 }, { x: 0.612, y: -0.780 }, { x: 0.695, y: -0.725 },\n { x: 0.767, y: -0.666 }, { x: 0.830, y: -0.606 }, { x: 0.885, y: -0.546 }, { x: 0.933, y: -0.486 },\n { x: 0.979, y: -0.425 }, { x: 1.006, y: -0.385 }, { x: 1.034, y: -0.334 }, { x: 1.058, y: -0.276 },\n { x: 1.078, y: -0.209 }, { x: 1.092, y: -0.133 }, { x: 1.101, y: -0.046 }, { x: 1.102, y: 0.052 },\n { x: 1.094, y: 0.173 }, { x: 1.083, y: 0.244 }, { x: 1.063, y: 0.324 }, { x: 1.034, y: 0.401 },\n { x: 0.996, y: 0.477 }, { x: 0.948, y: 0.549 }, { x: 0.889, y: 0.617 }, { x: 0.820, y: 0.681 },\n { x: 0.735, y: 0.741 }, { x: 0.658, y: 0.783 }, { x: 0.569, y: 0.822 }, { x: 0.474, y: 0.855 },\n { x: 0.372, y: 0.882 }, { x: 0.265, y: 0.904 }, { x: 0.156, y: 0.920 }, { x: 0.046, y: 0.931 },\n { x: -0.069, y: 0.938 }, { x: -0.155, y: 0.935 }, { x: -0.250, y: 0.919 }, { x: -0.346, y: 0.890 },\n { x: -0.443, y: 0.851 }, { x: -0.539, y: 0.800 }, { x: -0.633, y: 0.738 }, { x: -0.723, y: 0.667 },\n { x: -0.808, y: 0.585 }, { x: -0.882, y: 0.501 }, { x: -0.944, y: 0.421 }, { x: -0.994, y: 0.343 },\n { x: -1.034, y: 0.267 }, { x: -1.064, y: 0.192 }, { x: -1.085, y: 0.120 }, { x: -1.097, y: 0.042 },\n { x: -1.102, y: 0.001 }, { x: -1.090, y: -0.243 }, { x: -1.050, y: -0.365 }, { x: -0.990, y: -0.441 },\n { x: -0.911, y: -0.479 }, { x: -0.819, y: -0.499 }, { x: -0.715, y: -0.517 }, { x: -0.605, y: -0.551 },\n ],\n // Shape 2 · Blob 3\n [\n { x: 0.003, y: -0.970 }, { x: 0.163, y: -0.984 }, { x: 0.286, y: -1.028 }, { x: 0.389, y: -1.096 },\n { x: 0.488, y: -1.174 }, { x: 0.597, y: -1.210 }, { x: 0.728, y: -1.165 }, { x: 0.867, y: -1.036 },\n { x: 0.996, y: -0.839 }, { x: 1.098, y: -0.590 }, { x: 1.158, y: -0.304 }, { x: 1.153, y: 0.012 },\n { x: 1.080, y: 0.336 }, { x: 0.944, y: 0.639 }, { x: 0.756, y: 0.889 }, { x: 0.484, y: 1.072 },\n { x: 0.339, y: 1.079 }, { x: 0.219, y: 1.051 }, { x: 0.131, y: 0.994 }, { x: 0.059, y: 0.939 },\n { x: 0.008, y: 0.915 }, { x: -0.105, y: 0.931 }, { x: -0.176, y: 0.965 }, { x: -0.249, y: 1.005 },\n { x: -0.345, y: 1.039 }, { x: -0.497, y: 1.055 }, { x: -0.672, y: 1.032 }, { x: -0.817, y: 0.952 },\n { x: -0.945, y: 0.810 }, { x: -1.054, y: 0.600 }, { x: -1.160, y: 0.302 }, { x: -1.187, y: -0.011 },\n { x: -1.165, y: -0.326 }, { x: -1.097, y: -0.599 }, { x: -0.991, y: -0.838 }, { x: -0.852, y: -0.912 },\n { x: -0.695, y: -0.958 }, { x: -0.530, y: -0.988 }, { x: -0.357, y: -0.992 }, { x: -0.180, y: -0.983 },\n ],\n // Shape 3 · Blob 4\n [\n { x: -0.734, y: -1.127 }, { x: -0.656, y: -1.146 }, { x: -0.567, y: -1.142 }, { x: -0.468, y: -1.115 },\n { x: -0.358, y: -1.079 }, { x: -0.238, y: -1.034 }, { x: -0.107, y: -0.989 }, { x: 0.035, y: -0.953 },\n { x: 0.188, y: -0.929 }, { x: 0.325, y: -0.916 }, { x: 0.484, y: -0.896 }, { x: 0.650, y: -0.854 },\n { x: 0.811, y: -0.770 }, { x: 0.955, y: -0.631 }, { x: 1.068, y: -0.422 }, { x: 1.138, y: -0.126 },\n { x: 1.152, y: 0.272 }, { x: 1.121, y: 0.451 }, { x: 1.046, y: 0.602 }, { x: 0.928, y: 0.727 },\n { x: 0.767, y: 0.833 }, { x: 0.565, y: 0.925 }, { x: 0.323, y: 1.001 }, { x: 0.042, y: 1.075 },\n { x: -0.277, y: 1.142 }, { x: -0.368, y: 1.147 }, { x: -0.475, y: 1.136 }, { x: -0.589, y: 1.104 },\n { x: -0.704, y: 1.050 }, { x: -0.815, y: 0.973 }, { x: -0.913, y: 0.871 }, { x: -0.993, y: 0.746 },\n { x: -1.048, y: 0.593 }, { x: -1.109, y: 0.298 }, { x: -1.145, y: 0.018 }, { x: -1.154, y: -0.243 },\n { x: -1.135, y: -0.482 }, { x: -1.085, y: -0.695 }, { x: -1.003, y: -0.874 }, { x: -0.886, y: -1.020 },\n ],\n // Shape 4 · Blob 5\n [\n { x: -0.734, y: 1.127 }, { x: -0.656, y: 1.146 }, { x: -0.567, y: 1.142 }, { x: -0.468, y: 1.115 },\n { x: -0.358, y: 1.079 }, { x: -0.238, y: 1.034 }, { x: -0.107, y: 0.989 }, { x: 0.035, y: 0.953 },\n { x: 0.188, y: 0.929 }, { x: 0.325, y: 0.916 }, { x: 0.484, y: 0.896 }, { x: 0.650, y: 0.854 },\n { x: 0.811, y: 0.770 }, { x: 0.955, y: 0.631 }, { x: 1.068, y: 0.422 }, { x: 1.138, y: 0.126 },\n { x: 1.152, y: -0.272 }, { x: 1.121, y: -0.451 }, { x: 1.046, y: -0.602 }, { x: 0.928, y: -0.727 },\n { x: 0.767, y: -0.833 }, { x: 0.565, y: -0.925 }, { x: 0.323, y: -1.001 }, { x: 0.042, y: -1.075 },\n { x: -0.277, y: -1.142 }, { x: -0.368, y: -1.147 }, { x: -0.475, y: -1.136 }, { x: -0.589, y: -1.104 },\n { x: -0.704, y: -1.050 }, { x: -0.815, y: -0.973 }, { x: -0.913, y: -0.871 }, { x: -0.993, y: -0.746 },\n { x: -1.048, y: -0.593 }, { x: -1.109, y: -0.298 }, { x: -1.145, y: -0.018 }, { x: -1.154, y: 0.243 },\n { x: -1.135, y: 0.482 }, { x: -1.085, y: 0.695 }, { x: -1.003, y: 0.874 }, { x: -0.886, y: 1.020 },\n ],\n // Shape 5 · Blob 6\n [\n { x: 0.001, y: -1.006 }, { x: 0.134, y: -1.001 }, { x: 0.262, y: -1.024 },\n { x: 0.382, y: -1.073 }, { x: 0.498, y: -1.107 }, { x: 0.614, y: -1.105 },\n { x: 0.733, y: -1.049 }, { x: 0.850, y: -0.932 }, { x: 0.953, y: -0.755 },\n { x: 1.030, y: -0.529 }, { x: 1.067, y: -0.265 }, { x: 1.054, y: 0.018 },\n { x: 0.986, y: 0.300 }, { x: 0.868, y: 0.557 }, { x: 0.715, y: 0.766 },\n { x: 0.550, y: 0.909 }, { x: 0.396, y: 0.984 }, { x: 0.262, y: 1.005 },\n { x: 0.148, y: 1.003 }, { x: 0.037, y: 1.008 }, { x: -0.083, y: 1.040 },\n { x: -0.220, y: 1.118 }, { x: -0.360, y: 1.192 }, { x: -0.500, y: 1.234 },\n { x: -0.650, y: 1.175 }, { x: -0.810, y: 1.045 }, { x: -0.990, y: 0.855 },\n { x: -1.140, y: 0.610 }, { x: -1.240, y: 0.330 }, { x: -1.270, y: 0.040 },\n { x: -1.275, y: -0.250 }, { x: -1.225, y: -0.500 }, { x: -1.080, y: -0.720 },\n { x: -0.890, y: -0.920 }, { x: -0.734, y: -1.053 }, { x: -0.614, y: -1.112 },\n { x: -0.498, y: -1.127 }, { x: -0.381, y: -1.110 }, { x: -0.261, y: -1.095 },\n { x: -0.133, y: -1.058 }, { x: 0.001, y: -1.010 }, { x: 0.134, y: -1.001 },\n ],\n];\n\nexport const ACTIVE_BLOB_TYPES: ReadonlyArray<number> = [0, 1, 2, 3, 4, 5];\n\n/**\n * Per-shape text x-offset as a fraction of baseRadiusX.\n * Compensates for visually asymmetric blobs. Positive = right, negative = left.\n */\nexport const BLOB_TEXT_OFFSETS: ReadonlyArray<number> = [0, 0, 0, 0, 0, -0.10];\n\n/**\n * Deterministic pseudo-random blob-type selector per tree level.\n * Root level (0) always uses shape 0; consecutive levels use different shapes.\n */\nexport function getBlobTypeForLayer(level: number): number {\n const numTypes = ACTIVE_BLOB_TYPES.length;\n if (numTypes <= 1) return ACTIVE_BLOB_TYPES[0] ?? 0;\n let currentType = 0;\n for (let i = 1; i <= level; i++) {\n const pseudoRandom = Math.floor(Math.abs(Math.sin((i + 1) * 12.9898) * 43758.5453));\n const stepOffset = (pseudoRandom % (numTypes - 1)) + 1;\n currentType = (currentType + stepOffset) % numTypes;\n }\n return ACTIVE_BLOB_TYPES[currentType];\n}\n\n/**\n * Draw the blob path onto a canvas context (centered at 0,0).\n * Uses closed quadratic bezier curves through midpoints of control points.\n */\nexport function drawBlobPath(\n ctx: { beginPath(): void; moveTo(x: number, y: number): void; quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; closePath(): void },\n radiusX: number,\n radiusY: number,\n blobType: number,\n): void {\n const srcPts = ALL_BLOB_SHAPES[blobType] ?? ALL_BLOB_SHAPES[0];\n const pts = srcPts.map(p => ({ x: p.x * radiusX, y: p.y * radiusY }));\n ctx.beginPath();\n const last = pts[pts.length - 1];\n const first = pts[0];\n ctx.moveTo((last.x + first.x) / 2, (last.y + first.y) / 2);\n for (let i = 0; i < pts.length; i++) {\n const curr = pts[i];\n const next = pts[(i + 1) % pts.length];\n ctx.quadraticCurveTo(curr.x, curr.y, (curr.x + next.x) / 2, (curr.y + next.y) / 2);\n }\n ctx.closePath();\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/layout/circularLayout.ts","../src/layout/linearLayout.ts","../src/layout/layoutUtils.ts","../src/parser/visualliParser.ts","../src/parser/visualliConverter.ts","../src/parser/mindmapUtils.ts","../src/constants/design.ts","../src/parser/configUtils.ts","../src/constants/performanceConstants.ts","../src/constants/renderConfig.ts","../src/viewport/viewportUtils.ts","../src/performance/performanceMonitor.ts","../src/animations/easing.ts","../src/animations/constants.ts","../src/spatial/spatialIndex.ts","../../../../../node_modules/zustand/esm/vanilla.mjs","../src/stores/index.ts","../src/utils/navigation.ts","../src/rendering/culling.ts","../src/config/textScaling.ts","../src/config/blobShapes.ts"],"sourcesContent":["// ─── 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","// ─── .visualli File Parser ────────────────────────────────────────────────────\n//\n// Reads JSONL (JSON Lines) format and parses into a structured VisualliDocument.\n\nimport type { VisualliDocument } 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 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. */\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 { 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// ── Color Helpers ─────────────────────────────────────────────────────────────\n\nconst COLOR_PALETTE = [\n '#12C7D3', '#325E8C', '#8A70A6', '#F54A57', '#FF6C4D',\n '#F28C16', '#FFD347', '#12C7D3', '#7F7F7F', '#8D8D8D', '#12C7D3',\n];\n\n/**\n * Get a deterministic random color from palette based on node ID\n */\nfunction getRandomColorForNode(nodeId: string): string {\n // Simple hash function to convert string to number\n let hash = 0;\n for (let i = 0; i < nodeId.length; i++) {\n hash = nodeId.charCodeAt(i) + ((hash << 5) - hash);\n }\n \n // Use absolute value and modulo to get palette index\n const index = Math.abs(hash) % COLOR_PALETTE.length;\n return COLOR_PALETTE[index];\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\n/**\n * Calculate dynamic node width based on title length.\n * Formula matches visualli.ai: max(200, title.length * 8 + 40)\n */\nfunction calculateNodeWidth(title: string): number {\n return Math.max(200, title.length * 8 + 40);\n}\n\nfunction makeFlatNode(\n nodeId: string,\n label: string,\n summary: string,\n layer: VisualliLayer,\n color: string,\n branchCount: number,\n x = 0,\n y = 0,\n): FlatNode {\n return {\n id: nodeId,\n parentId: layer.parentNodeId ?? null,\n x,\n y,\n level: layer.level,\n title: label,\n description: summary,\n color,\n width: calculateNodeWidth(label),\n height: 80,\n isExpanded: branchCount > 0,\n branchCount,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n}\n\nfunction convertLayerWithContainers(\n layer: VisualliLayer,\n doc: VisualliDocument,\n): FlatNode[] {\n const PADDING = 80;\n const flatNodes: FlatNode[] = [];\n\n for (const node of layer.nodes) {\n const label = Array.isArray(node.data.label)\n ? (node.data.label as string[]).join(' ')\n : (node.data.label || 'Untitled');\n const branchCount = countLayersBeneath(doc, node.id);\n flatNodes.push(\n makeFlatNode(\n node.id, label, node.data.summary || '', layer,\n node.data.color || getRandomColorForNode(node.id), branchCount,\n ),\n );\n }\n\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 node of layer.nodes) {\n if (!containerNodeIds.has(node.id)) {\n const nodeWidth = calculateNodeWidth(node.data.label);\n proxies.push({ id: node.id, x: 0, y: 0, width: nodeWidth, height: 80 });\n }\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 resolveNodeOverlaps(flatNodes);\n\n return flatNodes;\n}\n\n/**\n * Convert a single layer to an array of FlatNode objects.\n * Layout algorithm is determined by `layer.layout` (default: radial).\n */\nexport function convertLayerToFlatNodes(\n layer: VisualliLayer,\n doc: VisualliDocument,\n): FlatNode[] {\n if ((layer.containers ?? []).length > 0) {\n return convertLayerWithContainers(layer, doc);\n }\n\n const flatNodes: FlatNode[] = [];\n\n for (const node of layer.nodes) {\n const label = Array.isArray(node.data.label)\n ? (node.data.label as string[]).join(' ')\n : (node.data.label || 'Untitled');\n const branchCount = countLayersBeneath(doc, node.id);\n flatNodes.push(\n makeFlatNode(\n node.id, label, node.data.summary || '', layer,\n node.data.color || getRandomColorForNode(node.id), branchCount,\n 0, 0,\n ),\n );\n }\n\n if (flatNodes.length > 0) {\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 resolveNodeOverlaps(flatNodes);\n\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): NodeMap {\n const map: NodeMap = new Map();\n\n for (const layer of doc.layers.values()) {\n for (const node of convertLayerToFlatNodes(layer, doc)) {\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 * @returns FlatNode array, or empty array if layer not found\n */\nexport function getNodesForLayer(doc: VisualliDocument, layerId: string): FlatNode[] {\n const layer = doc.layers.get(layerId);\n return layer ? convertLayerToFlatNodes(layer, doc) : [];\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","// ─── Design System Constants ──────────────────────────────────────────────────\n//\n// Single source of truth for all color tokens, typography, spacing, and\n// visual design constants used across the SDK and consuming apps.\n//\n// ## Color Priority\n// 1. Data file values (node.color, layer.backgroundColor)\n// 2. Fall back to these constants\n\n// ── Visualli Design System v2 ─────────────────────────────────────────────────\n\nexport const DS_COLORS = {\n light: {\n bgApp: '#F0EDE6',\n bgSurface: '#FAF8F4',\n bgInput: '#FFFFFF',\n border: '#DDD9D0',\n borderDivider: '#E8E4DC',\n primary: '#1B2D4F',\n primaryHover: '#243B68',\n textPrimary: '#1A1A18',\n textSecondary: '#6B6860',\n textMuted: '#747270',\n textOnPrimary: '#FAF8F4',\n hoverItem: 'rgba(27,45,79,0.07)',\n focusRing: 'rgba(27,45,79,0.40)',\n btnMuted: '#8E8C88',\n },\n dark: {\n bgApp: '#141412',\n bgSurface: '#1C1C1A',\n bgInput: '#262622',\n border: '#333330',\n borderDivider: '#2A2A28',\n primary: '#BB532D',\n primaryHover: '#CC6440',\n textPrimary: '#F0EDE6',\n textSecondary: '#B0ABA3',\n textMuted: '#8E8C88',\n textOnPrimary: '#FAF8F4',\n hoverItem: 'rgba(198,94,56,0.12)',\n focusRing: 'rgba(198,94,56,0.50)',\n btnMuted: '#4A4845',\n },\n} as const;\n\nexport const DS_TYPOGRAPHY = {\n fontDisplay: \"'Nunito', sans-serif\",\n fontBody: \"'Nunito Sans', sans-serif\",\n logo: { size: '20px', weight: 800, letterSpacing: '0.04em' },\n heading: { size: '16px', weight: 700, letterSpacing: '-0.2px' },\n cta: { size: '11px', weight: 800, letterSpacing: '0.12em', transform: 'uppercase' as const },\n body: { size: '13px', weight: 400 },\n input: { size: '13px', weight: 300, style: 'italic' as const },\n search: { size: '12px', weight: 400 },\n username: { size: '13px', weight: 600 },\n avatar: { size: '11px', weight: 700 },\n footer: { size: '12px', weight: 400 },\n empty: { size: '11px', weight: 300, style: 'italic' as const },\n} as const;\n\nexport const DS_RADII = {\n sidebar: 16,\n input: 8,\n cta: 7,\n item: 6,\n swatch: 10,\n} as const;\n\n// ── Brand Colors ──────────────────────────────────────────────────────────────\n\nexport const BRAND_COLORS = {\n primary: {\n 50: '#EFF6FF',\n 100: '#DBEAFE',\n 200: '#BFDBFE',\n 300: '#93C5FD',\n 400: '#60A5FA',\n 500: '#3B82F6',\n 600: '#2563EB',\n 700: '#1D4ED8',\n 800: '#1E40AF',\n 900: '#1E3A8A',\n },\n secondary: {\n 50: '#F0FDF4',\n 100: '#DCFCE7',\n 200: '#BBF7D0',\n 300: '#86EFAC',\n 400: '#4ADE80',\n 500: '#10B981',\n 600: '#059669',\n 700: '#047857',\n 800: '#065F46',\n 900: '#064E3B',\n },\n accent: {\n purple: '#8B5CF6',\n cyan: '#06B6D4',\n sky: '#0EA5E9',\n lime: '#84CC16',\n amber: '#F59E0B',\n red: '#EF4444',\n },\n} as const;\n\n// ── Level Colors ──────────────────────────────────────────────────────────────\n\nexport const LEVEL_COLORS = {\n level0: BRAND_COLORS.primary[500],\n level1: BRAND_COLORS.primary[400],\n level2: BRAND_COLORS.primary[300],\n level3: BRAND_COLORS.primary[200],\n level4: BRAND_COLORS.primary[300],\n level5: BRAND_COLORS.primary[400],\n level6: BRAND_COLORS.primary[500],\n level7: BRAND_COLORS.primary[600],\n level8: BRAND_COLORS.primary[700],\n} as const;\n\nexport const LEVEL_COLOR_ARRAY = [\n LEVEL_COLORS.level0,\n LEVEL_COLORS.level1,\n LEVEL_COLORS.level2,\n LEVEL_COLORS.level3,\n LEVEL_COLORS.level4,\n LEVEL_COLORS.level5,\n LEVEL_COLORS.level6,\n LEVEL_COLORS.level7,\n LEVEL_COLORS.level8,\n] as const;\n\nexport const PARENT_FALLBACK_COLORS = [\n '#12C7D3', '#325E8C', '#8A70A6', '#F54A57', '#FF6C4D',\n '#F28C16', '#FFD347', '#7F7F7F', '#8D8D8D',\n] as const;\n\nexport const SEMANTIC_COLORS = {\n success: BRAND_COLORS.secondary[500],\n error: BRAND_COLORS.accent.red,\n warning: BRAND_COLORS.accent.amber,\n info: BRAND_COLORS.primary[500],\n} as const;\n\n// ── Theme Colors ──────────────────────────────────────────────────────────────\n\nexport const THEME_COLORS = {\n light: {\n background: { primary: '#FAF8F4', secondary: '#F0EDE6', tertiary: '#FFFFFF' },\n text: { primary: '#1A1A18', secondary: '#6B6860', tertiary: '#747270' },\n border: { primary: '#DDD9D0', secondary: '#E8E4DC' },\n },\n dark: {\n background: { primary: '#1C1C1A', secondary: '#141412', tertiary: '#262622' },\n text: { primary: '#F0EDE6', secondary: '#B0ABA3', tertiary: '#8E8C88' },\n border: { primary: '#333330', secondary: '#2A2A28' },\n },\n} as const;\n\n// ── Canvas Node Colors ────────────────────────────────────────────────────────\n\nexport const CANVAS_COLORS = {\n node: {\n border: '#FFFFFF',\n titleColor: '#1e1b4b',\n badgeBackground: '#FFC107',\n badgeStroke: '#fcd34d',\n },\n} as const;\n\n// ── Spacing ───────────────────────────────────────────────────────────────────\n\nexport const SPACING = {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n '2xl': 48,\n '3xl': 64,\n '4xl': 96,\n} as const;\n\nexport const LAYOUT_SPACING = {\n nodeSpacing: 200,\n levelSpacing: 150,\n containerPadding: 20,\n gridSize: 50,\n} as const;\n\n// ── Typography ────────────────────────────────────────────────────────────────\n\nexport const FONTS = {\n primary: \"'Inter', sans-serif\",\n secondary: \"'Poppins', sans-serif\",\n mono: \"'Roboto Mono', monospace\",\n} as const;\n\nexport const FONT_SIZES = {\n xs: '0.75rem',\n sm: '0.875rem',\n base: '1rem',\n lg: '1.125rem',\n xl: '1.25rem',\n '2xl': '1.5rem',\n '3xl': '1.875rem',\n '4xl': '2.25rem',\n} as const;\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/** Get a level color, cycling back to level 0 for levels > 8. */\nexport function getColorForLevel(level: number): string {\n return LEVEL_COLOR_ARRAY[level % LEVEL_COLOR_ARRAY.length];\n}\n\n/**\n * Darken a hex color by reducing HSL lightness.\n * Returns a monochromatic darker version — used for border/stroke colors.\n * Falls back to the original string if parsing fails.\n */\nexport function darkenHexColor(hex: string, amount: number = 0.22): string {\n if (!hex || !hex.startsWith('#')) return hex;\n let r: number, g: number, b: number;\n if (hex.length === 4) {\n r = parseInt(hex[1] + hex[1], 16);\n g = parseInt(hex[2] + hex[2], 16);\n b = parseInt(hex[3] + hex[3], 16);\n } else if (hex.length === 7) {\n r = parseInt(hex.slice(1, 3), 16);\n g = parseInt(hex.slice(3, 5), 16);\n b = parseInt(hex.slice(5, 7), 16);\n } else {\n return hex;\n }\n if (isNaN(r) || isNaN(g) || isNaN(b)) return hex;\n const rn = r / 255, gn = g / 255, bn = b / 255;\n const cmax = Math.max(rn, gn, bn), cmin = Math.min(rn, gn, bn);\n const d = cmax - cmin;\n const l = (cmax + cmin) / 2;\n const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));\n let h = 0;\n if (d !== 0) {\n const seg = cmax === rn ? (gn - bn) / d : cmax === gn ? (bn - rn) / d + 2 : (rn - gn) / d + 4;\n h = ((seg * 60) + 360) % 360;\n }\n const newL = Math.max(0, l - amount);\n const c2 = (1 - Math.abs(2 * newL - 1)) * s;\n const x2 = c2 * (1 - Math.abs(((h / 60) % 2) - 1));\n const m2 = newL - c2 / 2;\n let r1 = 0, g1 = 0, b1 = 0;\n if (h < 60) { r1 = c2; g1 = x2; b1 = 0; }\n else if (h < 120) { r1 = x2; g1 = c2; b1 = 0; }\n else if (h < 180) { r1 = 0; g1 = c2; b1 = x2; }\n else if (h < 240) { r1 = 0; g1 = x2; b1 = c2; }\n else if (h < 300) { r1 = x2; g1 = 0; b1 = c2; }\n else { r1 = c2; g1 = 0; b1 = x2; }\n const toHex = (v: number) => Math.round((v + m2) * 255).toString(16).padStart(2, '0');\n return `#${toHex(r1)}${toHex(g1)}${toHex(b1)}`;\n}\n\nexport function getThemeBackground(\n isDark: boolean,\n variant: 'primary' | 'secondary' | 'tertiary' = 'primary',\n): string {\n return isDark ? THEME_COLORS.dark.background[variant] : THEME_COLORS.light.background[variant];\n}\n\nexport function getThemeText(\n isDark: boolean,\n variant: 'primary' | 'secondary' | 'tertiary' = 'primary',\n): string {\n return isDark ? THEME_COLORS.dark.text[variant] : THEME_COLORS.light.text[variant];\n}\n\nexport function getThemeBorder(\n isDark: boolean,\n variant: 'primary' | 'secondary' = 'primary',\n): string {\n return isDark ? THEME_COLORS.dark.border[variant] : THEME_COLORS.light.border[variant];\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 { LEVEL_COLORS, LAYOUT_SPACING, getColorForLevel } from '../constants/design.js';\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: {\n level0: LEVEL_COLORS.level0,\n level1: LEVEL_COLORS.level1,\n level2: LEVEL_COLORS.level2,\n level3: LEVEL_COLORS.level3,\n },\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: getColorForLevel(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: {\n level0: LEVEL_COLORS.level0,\n level1: LEVEL_COLORS.level1,\n level2: LEVEL_COLORS.level2,\n level3: LEVEL_COLORS.level3,\n level4: LEVEL_COLORS.level4,\n level5: LEVEL_COLORS.level5,\n level6: LEVEL_COLORS.level6,\n level7: LEVEL_COLORS.level7,\n level8: LEVEL_COLORS.level8,\n },\n layout: {\n nodeSpacing: LAYOUT_SPACING.nodeSpacing,\n levelSpacing: LAYOUT_SPACING.levelSpacing,\n },\n },\n };\n}\n","// ─── Performance & Rendering Constants ───────────────────────────────────────\n\n// ── FPS ───────────────────────────────────────────────────────────────────────\n\nexport const FPS_TARGET = 60;\nexport const FPS_WARNING_THRESHOLD = 45;\nexport const FPS_CRITICAL_THRESHOLD = 30;\nexport const TARGET_FRAME_TIME = 1000 / FPS_TARGET; // ~16.67 ms\nexport const MAX_FRAME_TIME = 18; // p95 threshold\n\n/** Legacy frame-rate targets kept for backward compatibility. */\nexport const FPS_TARGETS = {\n PAN_MIN: 30,\n ZOOM_TARGET: 60,\n WARNING_THRESHOLD: 20,\n} as const;\n\n// ── Timing Thresholds (ms) ────────────────────────────────────────────────────\n\nexport const TIMING_THRESHOLDS = {\n VIEWPORT_QUERY_MAX: 5,\n SPATIAL_UPDATE_MAX: 10,\n DRAG_RESPONSE_MAX: 16,\n LOAD_5K_TARGET: 2000,\n LOAD_10K_TARGET: 3000,\n VIEWPORT_DEBOUNCE: 100,\n SPATIAL_INDEX_BUILD: 50,\n} as const;\n\n// ── Memory Limits (MB) ────────────────────────────────────────────────────────\n\nexport const MEMORY_TARGET_MB = 500;\nexport const MEMORY_WARNING_MB = 600;\nexport const MEMORY_CRITICAL_MB = 800;\n\nexport const MEMORY_LIMITS = {\n MAX_10K_NODES: 500,\n MAX_GROWTH_PERCENT: 20,\n WARNING_THRESHOLD: 400,\n} as const;\n\n// ── Viewport Culling ──────────────────────────────────────────────────────────\n\nexport const VIEWPORT_MARGIN = 0.1;\nexport const MAX_VISIBLE_NODES = 800;\nexport const CULLING_QUERY_TIME_BUDGET = 5;\n\n// ── Spatial Index ─────────────────────────────────────────────────────────────\n\nexport const RBUSH_MAX_ENTRIES = 16;\nexport const SPATIAL_INDEX_BUILD_BUDGET = 50;\n\n// ── Node Dimensions ───────────────────────────────────────────────────────────\n\nexport const NODE_MIN_WIDTH = 200;\nexport const NODE_HEIGHT = 80;\nexport const NODE_PADDING = 40;\nexport const CHAR_WIDTH = 8;\nexport const TITLE_MAX_LENGTH = 150;\n\n// ── Visual Styling ────────────────────────────────────────────────────────────\n\nexport const CORNER_RADIUS = 8;\nexport const BORDER_WIDTH_NORMAL = 2;\nexport const BORDER_WIDTH_SELECTED = 3;\n\nexport const COLOR_SELECTED = '#1B2D4F';\nexport const COLOR_BORDER_LIGHT = '#4A3728';\nexport const COLOR_BORDER_DARK = '#FAF6F1';\nexport const COLOR_DEFAULT_NODE = '#FAF6F1';\n\n// ── Zoom Constraints ──────────────────────────────────────────────────────────\n\nexport const ZOOM_MIN = 0.05;\nexport const ZOOM_MAX = 5.0;\nexport const ZOOM_DEFAULT = 1.0;\nexport const ZOOM_STEP = 0.1;\nexport const ZOOM_WHEEL_SENSITIVITY = 0.001;\n\nexport const ZOOM_NAV_IN_THRESHOLD = 2.7;\nexport const ZOOM_NAV_OUT_THRESHOLD = 0.4;\nexport const TEXT_LABEL_HIDE_BELOW_ZOOM = 0.3;\n\n// ── Quality Level Presets ─────────────────────────────────────────────────────\n\nexport const QUALITY_HIGH = {\n shadows: true,\n bezierCurves: true,\n animations: true,\n textQuality: 'high' as const,\n antialiasing: true,\n};\n\nexport const QUALITY_MEDIUM = {\n shadows: false,\n bezierCurves: true,\n animations: true,\n textQuality: 'medium' as const,\n antialiasing: true,\n};\n\nexport const QUALITY_LOW = {\n shadows: false,\n bezierCurves: false,\n animations: false,\n textQuality: 'low' as const,\n antialiasing: false,\n};\n\n// ── Performance Monitoring ────────────────────────────────────────────────────\n\nexport const FPS_SAMPLE_WINDOW = 60;\nexport const FPS_UPDATE_INTERVAL = 1000;\nexport const MEMORY_CHECK_INTERVAL = 5000;\nexport const PERFORMANCE_TOAST_COOLDOWN = 10000;\n\n// ── Auto-Adjustment ───────────────────────────────────────────────────────────\n\nexport const FPS_DOWNGRADE_THRESHOLD = 45;\nexport const FPS_UPGRADE_THRESHOLD = 58;\nexport const FPS_STABILIZATION_FRAMES = 180;\n\n// ── Canvas Dimensions ─────────────────────────────────────────────────────────\n\nexport const DEFAULT_CANVAS_WIDTH = 1920;\nexport const DEFAULT_CANVAS_HEIGHT = 1080;\n\n// ── Interaction ───────────────────────────────────────────────────────────────\n\nexport const CLICK_THRESHOLD = 5;\nexport const DOUBLE_CLICK_DELAY = 300;\nexport const DRAG_START_DISTANCE = 10;\n\n// ── Data Validation ───────────────────────────────────────────────────────────\n\nexport const MAX_NODES = 20000;\nexport const CIRCULAR_REFERENCE_MAX_DEPTH = 1000;\n\n// ── Debounce / Throttle ───────────────────────────────────────────────────────\n\nexport const RESIZE_DEBOUNCE = 300;\nexport const SCROLL_THROTTLE = 16;\nexport const SEARCH_DEBOUNCE = 500;\n\n/** Node count thresholds that gate optimisation strategies. */\nexport const NODE_COUNT_THRESHOLDS = {\n SPATIAL_INDEX_MIN: 100,\n VIEWPORT_CULLING_MIN: 500,\n CANVAS_RENDERING_MIN: 2000,\n DOM_RENDERING_MAX: 5000,\n} as const;\n\n/** Viewport buffer configuration. */\nexport const VIEWPORT_CONFIG = {\n BUFFER_PERCENT: 0.2,\n MIN_VISIBLE_NODES: 10,\n} as const;\n","// ─── Render Configuration ─────────────────────────────────────────────────────\n\nimport type { RenderConfig } from '../types/mindmap.js';\nimport {\n FPS_TARGET,\n MEMORY_TARGET_MB,\n QUALITY_HIGH,\n QUALITY_MEDIUM,\n QUALITY_LOW,\n NODE_COUNT_THRESHOLDS,\n} from './performanceConstants.js';\n\n// ── Defaults ──────────────────────────────────────────────────────────────────\n\nexport const DEFAULT_RENDER_CONFIG: RenderConfig = {\n renderMode: 'canvas',\n qualityLevel: 'high',\n cullingEnabled: false,\n fpsTarget: FPS_TARGET,\n memoryLimit: MEMORY_TARGET_MB,\n};\n\nexport const SIMPLIFIED_RENDER_CONFIG: RenderConfig = {\n renderMode: 'simplified',\n qualityLevel: 'low',\n cullingEnabled: true,\n fpsTarget: 30,\n memoryLimit: 400,\n};\n\n// ── Quality Map ───────────────────────────────────────────────────────────────\n\nexport const QUALITY_SETTINGS = {\n high: QUALITY_HIGH,\n medium: QUALITY_MEDIUM,\n low: QUALITY_LOW,\n} as const;\n\n// ── Feature Flags ─────────────────────────────────────────────────────────────\n\nexport const FEATURE_FLAGS = {\n viewportCulling: true,\n spatialIndexing: true,\n shadows: true,\n bezierCurves: true,\n animations: true,\n branchBadges: true,\n autoQualityAdjustment: true,\n performanceMonitoring: true,\n performanceToasts: true,\n debugOverlay: false,\n showFPS: false,\n showMemory: false,\n showVisibleCount: false,\n} as const;\n\n// ── Render Modes ──────────────────────────────────────────────────────────────\n\nexport type RenderMode = RenderConfig['renderMode'];\nexport type QualityLevel = RenderConfig['qualityLevel'];\n\nexport const RENDER_MODES = {\n canvas: {\n name: 'Canvas',\n description: 'Full Konva canvas rendering with all features',\n features: { culling: true, shadows: true, bezierCurves: true, animations: true },\n },\n simplified: {\n name: 'Simplified',\n description: 'Reduced feature set for low-end devices',\n features: { culling: true, shadows: false, bezierCurves: false, animations: false },\n },\n} as const;\n\nexport const QUALITY_LEVELS = {\n high: { name: 'High', description: 'All visual features enabled', targetFPS: 60, features: QUALITY_HIGH },\n medium: { name: 'Medium', description: 'Shadows disabled, other features enabled', targetFPS: 60, features: QUALITY_MEDIUM },\n low: { name: 'Low', description: 'Minimal visual features, max performance', targetFPS: 30, features: QUALITY_LOW },\n} as const;\n\n// ── Auto-Adjustment Helpers ───────────────────────────────────────────────────\n\nexport function getOptimalQualityLevel(\n currentFPS: number,\n currentQuality: QualityLevel,\n): QualityLevel {\n if (currentFPS < 45 && currentQuality === 'high') return 'medium';\n if (currentFPS < 30 && currentQuality === 'medium') return 'low';\n if (currentFPS > 58 && currentQuality === 'low') return 'medium';\n if (currentFPS > 58 && currentQuality === 'medium') return 'high';\n return currentQuality;\n}\n\nexport function getRenderConfigForQuality(quality: QualityLevel): Partial<RenderConfig> {\n return { qualityLevel: quality, fpsTarget: QUALITY_LEVELS[quality].targetFPS };\n}\n\nexport function isFeatureEnabled(\n featureName: keyof typeof FEATURE_FLAGS,\n config: RenderConfig,\n): boolean {\n if (!FEATURE_FLAGS[featureName]) return false;\n\n const qs = QUALITY_SETTINGS[config.qualityLevel];\n switch (featureName) {\n case 'shadows': return qs.shadows;\n case 'bezierCurves': return qs.bezierCurves;\n case 'animations': return qs.animations;\n default: return FEATURE_FLAGS[featureName] as boolean;\n }\n}\n\n// ── Device Detection ──────────────────────────────────────────────────────────\n\n/**\n * Recommend a render config based on detected device memory (browser only).\n * Falls back to SIMPLIFIED_RENDER_CONFIG when the Performance Memory API is\n * unavailable or memory is constrained.\n */\nexport function getRecommendedRenderConfig(): RenderConfig {\n if (typeof performance === 'undefined' || !(performance as unknown as Record<string, unknown>)['memory']) {\n return SIMPLIFIED_RENDER_CONFIG;\n }\n\n const memory = (performance as unknown as Record<string, unknown>)['memory'] as Record<string, number>;\n if (memory?.['jsHeapSizeLimit'] && memory['jsHeapSizeLimit'] < 512 * 1024 * 1024) {\n return SIMPLIFIED_RENDER_CONFIG;\n }\n\n return DEFAULT_RENDER_CONFIG;\n}\n\n/** Re-export so consumers need only one import. */\nexport { NODE_COUNT_THRESHOLDS };\n","// ─── Viewport Utilities ───────────────────────────────────────────────────────\n//\n// Pure functions for viewport bounds calculation, coordinate transforms,\n// pan/zoom operations, and node visibility queries.\n\nimport type { ViewportState } from '../types/mindmap.js';\nimport {\n VIEWPORT_MARGIN,\n DEFAULT_CANVAS_WIDTH,\n DEFAULT_CANVAS_HEIGHT,\n ZOOM_MIN,\n ZOOM_MAX,\n} from '../constants/performanceConstants.js';\n\n// ── Viewport Bounds ───────────────────────────────────────────────────────────\n\nexport interface WorldBounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\n/**\n * Calculate the visible world-space bounding box including a margin buffer.\n */\nexport function calculateViewportBounds(\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): WorldBounds {\n const worldW = canvasWidth / viewport.zoomLevel;\n const worldH = canvasHeight / viewport.zoomLevel;\n const mx = worldW * VIEWPORT_MARGIN;\n const my = worldH * VIEWPORT_MARGIN;\n return {\n minX: viewport.centerX - worldW / 2 - mx,\n minY: viewport.centerY - worldH / 2 - my,\n maxX: viewport.centerX + worldW / 2 + mx,\n maxY: viewport.centerY + worldH / 2 + my,\n };\n}\n\n/**\n * Return a new ViewportState with `visibleBounds` recalculated.\n */\nexport function recalculateViewportBounds(\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): ViewportState {\n return {\n ...viewport,\n visibleBounds: calculateViewportBounds(viewport, canvasWidth, canvasHeight),\n };\n}\n\n// ── Coordinate Transforms ─────────────────────────────────────────────────────\n\n/**\n * Convert world-space coordinates to screen-space pixel coordinates.\n */\nexport function worldToScreen(\n worldX: number,\n worldY: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): { x: number; y: number } {\n return {\n x: (worldX - viewport.centerX) * viewport.zoomLevel + canvasWidth / 2,\n y: (worldY - viewport.centerY) * viewport.zoomLevel + canvasHeight / 2,\n };\n}\n\n/**\n * Convert screen-space pixel coordinates to world-space coordinates.\n */\nexport function screenToWorld(\n screenX: number,\n screenY: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): { x: number; y: number } {\n return {\n x: (screenX - canvasWidth / 2) / viewport.zoomLevel + viewport.centerX,\n y: (screenY - canvasHeight / 2) / viewport.zoomLevel + viewport.centerY,\n };\n}\n\n// ── Pan / Zoom ────────────────────────────────────────────────────────────────\n\n/** Clamp zoom to [ZOOM_MIN, ZOOM_MAX]. */\nexport function clampZoom(zoom: number): number {\n return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, zoom));\n}\n\n/**\n * Pan the viewport by a screen-space delta (positive = right/down).\n */\nexport function panViewport(\n deltaX: number,\n deltaY: number,\n viewport: ViewportState,\n): ViewportState {\n return {\n ...viewport,\n centerX: viewport.centerX - deltaX / viewport.zoomLevel,\n centerY: viewport.centerY - deltaY / viewport.zoomLevel,\n };\n}\n\n/** Teleport the viewport centre to the given world coordinates. */\nexport function setViewportCenter(\n x: number,\n y: number,\n viewport: ViewportState,\n): ViewportState {\n return { ...viewport, centerX: x, centerY: y };\n}\n\n/**\n * Zoom the viewport by a multiplicative delta, optionally around a pivot point.\n *\n * @param delta - Multiplier delta, e.g. 0.1 for +10% zoom\n * @param pivotX - Optional screen-space X pivot\n * @param pivotY - Optional screen-space Y pivot\n */\nexport function zoomViewport(\n delta: number,\n viewport: ViewportState,\n pivotX?: number,\n pivotY?: number,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): ViewportState {\n const newZoom = clampZoom(viewport.zoomLevel * (1 + delta));\n\n let cx = viewport.centerX;\n let cy = viewport.centerY;\n\n if (pivotX !== undefined && pivotY !== undefined) {\n const worldPivot = screenToWorld(pivotX, pivotY, viewport, canvasWidth, canvasHeight);\n cx = worldPivot.x - (pivotX - canvasWidth / 2) / newZoom;\n cy = worldPivot.y - (pivotY - canvasHeight / 2) / newZoom;\n }\n\n return { ...viewport, centerX: cx, centerY: cy, zoomLevel: newZoom };\n}\n\n/**\n * Create a viewport centred on a node (world coordinates) at the given zoom level.\n */\nexport function focusOnNode(\n nodeX: number,\n nodeY: number,\n zoom: number,\n): ViewportState {\n const clamped = clampZoom(zoom);\n return {\n centerX: nodeX,\n centerY: nodeY,\n zoomLevel: clamped,\n rotation: 0,\n visibleBounds: calculateViewportBounds(\n { centerX: nodeX, centerY: nodeY, zoomLevel: clamped, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } },\n ),\n };\n}\n\n// ── Visibility ────────────────────────────────────────────────────────────────\n\n/**\n * Test whether a world-space AABB intersects the viewport's visible bounds.\n */\nexport function isNodeInViewport(\n nodeX: number,\n nodeY: number,\n nodeWidth: number,\n nodeHeight: number,\n viewport: ViewportState,\n canvasWidth = DEFAULT_CANVAS_WIDTH,\n canvasHeight = DEFAULT_CANVAS_HEIGHT,\n): boolean {\n const bounds = calculateViewportBounds(viewport, canvasWidth, canvasHeight);\n const hw = nodeWidth / 2;\n const hh = nodeHeight / 2;\n return !(\n nodeX + hw < bounds.minX ||\n nodeX - hw > bounds.maxX ||\n nodeY + hh < bounds.minY ||\n nodeY - hh > bounds.maxY\n );\n}\n","// ─── Performance Monitors ─────────────────────────────────────────────────────\n//\n// FPSMonitor – tracks frame rate via requestAnimationFrame (browser)\n// MemoryMonitor – polls performance.memory (Chrome)\n// PerformanceProfiler – mark / measure utility for arbitrary operations\n\nimport {\n FPS_TARGET,\n FPS_SAMPLE_WINDOW,\n MEMORY_CHECK_INTERVAL,\n} from '../constants/performanceConstants.js';\n\n// ── FPS Monitor ───────────────────────────────────────────────────────────────\n\nexport class FPSMonitor {\n private frameTimes: number[] = [];\n private lastTime = 0;\n private currentFPS = FPS_TARGET;\n private rafId: number | null = null;\n\n start(): void {\n if (this.rafId !== null) return;\n\n const measure = (ts: number) => {\n if (this.lastTime > 0) {\n this.frameTimes.push(ts - this.lastTime);\n if (this.frameTimes.length > FPS_SAMPLE_WINDOW) this.frameTimes.shift();\n this.currentFPS = this.calc();\n }\n this.lastTime = ts;\n this.rafId = requestAnimationFrame(measure);\n };\n\n this.rafId = requestAnimationFrame(measure);\n }\n\n stop(): void {\n if (this.rafId !== null) { cancelAnimationFrame(this.rafId); this.rafId = null; }\n }\n\n private calc(): number {\n if (this.frameTimes.length === 0) return FPS_TARGET;\n const avg = this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length;\n return Math.round(1000 / avg);\n }\n\n getFPS(): number { return this.currentFPS; }\n getAverageFPS(): number { return this.currentFPS; }\n\n getP95FrameTime(): number {\n if (this.frameTimes.length === 0) return 0;\n const sorted = [...this.frameTimes].sort((a, b) => a - b);\n return sorted[Math.floor(sorted.length * 0.95)];\n }\n\n reset(): void { this.frameTimes = []; this.currentFPS = FPS_TARGET; }\n}\n\n// ── Memory Monitor ────────────────────────────────────────────────────────────\n\nexport interface MemoryStats {\n usedJSHeapSize: number;\n totalJSHeapSize: number;\n jsHeapSizeLimit: number;\n heapUsagePercent: number;\n}\n\nexport class MemoryMonitor {\n private timer: ReturnType<typeof setInterval> | null = null;\n private current = 0;\n\n start(onUpdate?: (mb: number) => void): void {\n if (this.timer !== null) return;\n this.timer = setInterval(() => {\n this.current = this.measure();\n onUpdate?.(this.current);\n }, MEMORY_CHECK_INTERVAL);\n }\n\n stop(): void {\n if (this.timer !== null) { clearInterval(this.timer); this.timer = null; }\n }\n\n private measure(): number {\n const mem = (performance as unknown as Record<string, unknown>)['memory'] as Record<string, number> | undefined;\n return mem ? mem['usedJSHeapSize'] / (1024 * 1024) : 0;\n }\n\n getMemoryMB(): number { return this.current; }\n\n getStats(): MemoryStats | null {\n const mem = (performance as unknown as Record<string, unknown>)['memory'] as Record<string, number> | undefined;\n if (!mem) return null;\n return {\n usedJSHeapSize: mem['usedJSHeapSize'],\n totalJSHeapSize: mem['totalJSHeapSize'],\n jsHeapSizeLimit: mem['jsHeapSizeLimit'],\n heapUsagePercent: (mem['usedJSHeapSize'] / mem['jsHeapSizeLimit']) * 100,\n };\n }\n\n static isSupported(): boolean {\n return !!(performance as unknown as Record<string, unknown>)['memory'];\n }\n}\n\n// ── Performance Profiler ──────────────────────────────────────────────────────\n\nexport class PerformanceProfiler {\n private marks: Map<string, number> = new Map();\n private measures: Map<string, number[]> = new Map();\n\n mark(label: string): void {\n this.marks.set(label, performance.now());\n }\n\n measure(label: string): number {\n const start = this.marks.get(label);\n if (start === undefined) return 0;\n const duration = performance.now() - start;\n const list = this.measures.get(label) ?? [];\n list.push(duration);\n this.measures.set(label, list);\n this.marks.delete(label);\n return duration;\n }\n\n getAverage(label: string): number {\n const list = this.measures.get(label);\n if (!list?.length) return 0;\n return list.reduce((a, b) => a + b, 0) / list.length;\n }\n\n getP95(label: string): number {\n const list = this.measures.get(label);\n if (!list?.length) return 0;\n const sorted = [...list].sort((a, b) => a - b);\n return sorted[Math.floor(sorted.length * 0.95)];\n }\n\n clear(label?: string): void {\n if (label) { this.marks.delete(label); this.measures.delete(label); }\n else { this.marks.clear(); this.measures.clear(); }\n }\n}\n","// ─── Animation Easing Functions ───────────────────────────────────────────────\n//\n// Pure math easing functions for smooth, cinematic animations.\n// No DOM / RAF dependencies – usable in any runtime.\n\nexport type EasingFunction = (t: number) => number;\n\n/** Smooth cubic – slow start, fast middle, slow end. */\nexport const easeInOutCubic: EasingFunction = (t) =>\n t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;\n\n/** Smooth quartic – more dramatic than cubic. */\nexport const easeInOutQuart: EasingFunction = (t) =>\n t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2;\n\n/** Fast start, slow end. */\nexport const easeOutCubic: EasingFunction = (t) => 1 - Math.pow(1 - t, 3);\n\n/** Slow start, fast end. */\nexport const easeInCubic: EasingFunction = (t) => t * t * t;\n\n/** Gentle ease-out (quadratic). */\nexport const easeOutQuad: EasingFunction = (t) => 1 - (1 - t) * (1 - t);\n\n/** Very smooth, organic sine easing. */\nexport const easeInOutSine: EasingFunction = (t) =>\n -(Math.cos(Math.PI * t) - 1) / 2;\n\n/**\n * Create a CSS cubic-bezier easing function from four control-point values.\n *\n * Builds a 256-entry lookup table at call time (once) so subsequent evaluations\n * are a single table lookup + linear interpolation.\n */\nexport function createCubicBezier(\n x1: number, y1: number,\n x2: number, y2: number,\n): EasingFunction {\n const N = 256;\n const lut = new Float64Array(N + 1);\n\n for (let i = 0; i <= N; i++) {\n const target = i / N;\n let lo = 0, hi = 1;\n for (let j = 0; j < 20; j++) {\n const mid = (lo + hi) / 2;\n const om = 1 - mid;\n const x = 3 * om * om * mid * x1 + 3 * om * mid * mid * x2 + mid * mid * mid;\n if (x < target) lo = mid; else hi = mid;\n }\n const u = (lo + hi) / 2;\n const ou = 1 - u;\n lut[i] = 3 * ou * ou * u * y1 + 3 * ou * u * u * y2 + u * u * u;\n }\n\n return (t: number): number => {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n const s = t * N;\n const i = s | 0;\n return lut[i] + (lut[i + 1] - lut[i]) * (s - i);\n };\n}\n\n/**\n * Zoom-transition easing — matches CSS cubic-bezier(0.2, 0.8, 0.2, 1).\n * Fast start with smooth, organic settle. Used for all layer transitions.\n * Pre-computed LUT: subsequent calls are a single table lookup + linear interpolation.\n */\nexport const easeZoomTransition: EasingFunction = createCubicBezier(0.2, 0.8, 0.2, 1);\n","// ─── Animation Constants ──────────────────────────────────────────────────────\n\n// ── Timing (ms) ───────────────────────────────────────────────────────────────\n\nexport const ANIMATION_DURATION = {\n ZOOM_IN_LAYER: 500,\n ZOOM_OUT_LAYER: 500,\n ZOOM_GESTURE: 500,\n FADE_OUT: 200,\n FADE_IN: 250,\n COLOR_TRANSITION: 500,\n CURSOR_CHANGE: 150,\n LOADING_FADE: 200,\n} as const;\n\nexport const ANIMATION_PHASES = {\n ZOOM_IN: {\n ZOOM_TO_TARGET: 500,\n FADE_OUT_START: 120,\n FADE_OUT: 280,\n CONTENT_SWAP: 310,\n FADE_IN: 200,\n TOTAL: 510,\n },\n ZOOM_OUT: {\n FADE_OUT: 200,\n ZOOM_BACK: 50,\n FADE_IN: 250,\n TOTAL: 500,\n },\n} as const;\n\n// ── Zoom Thresholds ───────────────────────────────────────────────────────────\n\nexport const ZOOM_THRESHOLDS = {\n ENTER_LAYER: 5.0,\n EXIT_LAYER: 0.5,\n GESTURE_TRIGGER: 0.8,\n} as const;\n\n// ── Cooldowns (ms) ────────────────────────────────────────────────────────────\n\nexport const COOLDOWN = {\n NAVIGATION: 1000,\n ZOOM_GESTURE: 800,\n DOUBLE_CLICK: 200,\n} as const;\n\n// ── Opacity ───────────────────────────────────────────────────────────────────\n\nexport const OPACITY = {\n VISIBLE: 1.0,\n HIDDEN: 0.0,\n TRANSITIONING: 0.3,\n} as const;\n\n// ── Target Zoom Levels ────────────────────────────────────────────────────────\n\nexport const TARGET_ZOOM = {\n NORMAL: 1.0,\n FOCUSED: 0.8,\n FILL_NODE: 3.0,\n DETAIL: 2.0,\n} as const;\n\n// ── Viewport Framing ──────────────────────────────────────────────────────────\n\nexport const VIEWPORT_FRAMING = {\n NODE_FILL_RATIO: 0.7,\n EXIT_NODE_SIZE: 0.4,\n PADDING_RATIO: 0.1,\n} as const;\n","// ─── Spatial Index ────────────────────────────────────────────────────────────\n//\n// RBush-backed R-tree for O(log n) viewport culling queries.\n// Wraps the `rbush` library with a typed, domain-specific interface.\n\nimport RBush from 'rbush';\n\nexport interface BoundingBox {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\ninterface SpatialItem extends BoundingBox {\n nodeId: string;\n}\n\nexport interface ISpatialIndex {\n insert(nodeId: string, bounds: BoundingBox): void;\n remove(nodeId: string, bounds: BoundingBox): void;\n update(nodeId: string, oldBounds: BoundingBox, newBounds: BoundingBox): void;\n query(bounds: BoundingBox): string[];\n clear(): void;\n size(): number;\n bulkLoad(items: Array<{ nodeId: string; bounds: BoundingBox }>): void;\n}\n\n/**\n * RBush-based spatial index for efficient viewport culling.\n *\n * - Insert / remove / update: O(log n)\n * - Query: O(log n + k) where k = result count\n * - Bulk load: O(n log n) — use instead of repeated inserts for initial load\n */\nexport class RBushSpatialIndex implements ISpatialIndex {\n private tree: RBush<SpatialItem>;\n private cache: Map<string, BoundingBox>;\n\n constructor() {\n this.tree = new RBush<SpatialItem>();\n this.cache = new Map();\n }\n\n insert(nodeId: string, bounds: BoundingBox): void {\n this.tree.insert({ ...bounds, nodeId });\n this.cache.set(nodeId, bounds);\n }\n\n remove(nodeId: string, bounds: BoundingBox): void {\n this.tree.remove({ ...bounds, nodeId }, (a, b) => a.nodeId === b.nodeId);\n this.cache.delete(nodeId);\n }\n\n update(nodeId: string, oldBounds: BoundingBox, newBounds: BoundingBox): void {\n this.remove(nodeId, oldBounds);\n this.insert(nodeId, newBounds);\n }\n\n query(bounds: BoundingBox): string[] {\n return this.tree.search(bounds).map(item => item.nodeId);\n }\n\n clear(): void {\n this.tree.clear();\n this.cache.clear();\n }\n\n size(): number {\n return this.cache.size;\n }\n\n bulkLoad(items: Array<{ nodeId: string; bounds: BoundingBox }>): void {\n const rbushItems = items.map(({ nodeId, bounds }) => ({ ...bounds, nodeId }));\n this.tree.load(rbushItems);\n for (const { nodeId, bounds } of items) this.cache.set(nodeId, bounds);\n }\n\n /** Return the cached bounding box for a node (undefined if not indexed). */\n getBounds(nodeId: string): BoundingBox | undefined {\n return this.cache.get(nodeId);\n }\n}\n","const createStoreImpl = (createState) => {\n let state;\n const listeners = /* @__PURE__ */ new Set();\n const setState = (partial, replace) => {\n const nextState = typeof partial === \"function\" ? partial(state) : partial;\n if (!Object.is(nextState, state)) {\n const previousState = state;\n state = (replace != null ? replace : typeof nextState !== \"object\" || nextState === null) ? nextState : Object.assign({}, state, nextState);\n listeners.forEach((listener) => listener(state, previousState));\n }\n };\n const getState = () => state;\n const getInitialState = () => initialState;\n const subscribe = (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n const destroy = () => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") {\n console.warn(\n \"[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected.\"\n );\n }\n listeners.clear();\n };\n const api = { setState, getState, getInitialState, subscribe, destroy };\n const initialState = state = createState(setState, getState, api);\n return api;\n};\nconst createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;\nvar vanilla = (createState) => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") {\n console.warn(\n \"[DEPRECATED] Default export is deprecated. Instead use import { createStore } from 'zustand/vanilla'.\"\n );\n }\n return createStore(createState);\n};\n\nexport { createStore, vanilla as default };\n","import { createStore } from 'zustand/vanilla';\nimport type { NodeSelection, RenderConfig } from '../types/index.js';\nimport {\n DEFAULT_RENDER_CONFIG,\n getOptimalQualityLevel,\n getRenderConfigForQuality,\n isFeatureEnabled,\n FEATURE_FLAGS,\n} from '../constants/renderConfig.js';\n\n// ─── Selection Store ──────────────────────────────────────────────────────────\n\nexport interface ISelectionStore extends NodeSelection {\n select: (nodeId: string) => void;\n clear: () => void;\n toggle: (nodeId: string) => void;\n isSelected: (nodeId: string) => boolean;\n}\n\nexport const selectionStore = createStore<ISelectionStore>((set, get) => ({\n selectedId: null,\n select: (nodeId) => set({ selectedId: nodeId }),\n clear: () => set({ selectedId: null }),\n toggle: (nodeId) => set((s) => ({ selectedId: s.selectedId === nodeId ? null : nodeId })),\n isSelected: (nodeId) => get().selectedId === nodeId,\n}));\n\n// ─── Render Config Store ──────────────────────────────────────────────────────\n\nexport interface IRenderConfigStore extends RenderConfig {\n setQualityLevel: (level: RenderConfig['qualityLevel']) => void;\n setRenderMode: (mode: RenderConfig['renderMode']) => void;\n setCullingEnabled: (enabled: boolean) => void;\n autoAdjustQuality: (currentFPS: number) => void;\n autoAdjustQualityByMemory: (memoryMB: number) => void;\n resetToDefaults: () => void;\n isFeatureEnabled: (feature: keyof typeof FEATURE_FLAGS) => boolean;\n}\n\nexport const renderConfigStore = createStore<IRenderConfigStore>((set, get) => ({\n ...DEFAULT_RENDER_CONFIG,\n\n setQualityLevel: (level) => set(getRenderConfigForQuality(level)),\n setRenderMode: (mode) => set({ renderMode: mode }),\n setCullingEnabled: (enabled) => set({ cullingEnabled: enabled }),\n\n autoAdjustQuality: (fps) =>\n set((s) => {\n const q = getOptimalQualityLevel(fps, s.qualityLevel);\n return q !== s.qualityLevel ? getRenderConfigForQuality(q) : s;\n }),\n\n autoAdjustQualityByMemory: (mb) =>\n set((s) => {\n const q = mb > 500 ? 'low' : mb > 400 && s.qualityLevel === 'high' ? 'medium' : s.qualityLevel;\n return q !== s.qualityLevel ? getRenderConfigForQuality(q as RenderConfig['qualityLevel']) : s;\n }),\n\n resetToDefaults: () => set({ ...DEFAULT_RENDER_CONFIG }),\n isFeatureEnabled: (feature) => isFeatureEnabled(feature, get()),\n}));\n","import type { VisualliDocument, VisualliLayer, FlatNode, MindMapConnection } from '../types/index.js';\nimport { ZOOM_MAX, ZOOM_NAV_OUT_THRESHOLD } from '../constants/performanceConstants.js';\n\n// ── Connection helpers ────────────────────────────────────────────────────────\n\n/**\n * Returns all top-level connections that originate from the given layer.\n * A \"top-level connection\" links two nodes that both live in `layerId`.\n */\nexport function getConnectionsForLayer(\n doc: VisualliDocument,\n layerId: string,\n): MindMapConnection[] {\n const layer = doc.layers.get(layerId);\n if (!layer) return [];\n // Convert schema LayerConnection to simplified mindmap MindMapConnection\n return layer.connections.map(c => ({\n from: c.from,\n to: c.to,\n level: layer.level,\n label: c.data?.label,\n } satisfies MindMapConnection));\n}\n\n/**\n * Given a node in the current layer, returns the child layer (if any) that the\n * node \"owns\" — i.e. the node is the entry-point into that child layer.\n */\nexport function getChildLayerForNode(\n doc: VisualliDocument,\n nodeId: string,\n currentLayerId: string,\n): VisualliLayer | null {\n // Walk all layers looking for one whose `parentNodeId` matches\n for (const [, layer] of doc.layers) {\n if (layer.parentLayerId === currentLayerId && layer.parentNodeId === nodeId) {\n return layer;\n }\n }\n return null;\n}\n\n/**\n * \n */\nexport function getLayerForNavigation(\n doc: VisualliDocument,\n nodeId: string,\n currentLayerId: string,\n): VisualliLayer | null {\n return getChildLayerForNode(doc, nodeId, currentLayerId);\n}\n\n// ── Viewport fitting math ─────────────────────────────────────────────────────\n\nexport interface FitResult {\n centerX: number;\n centerY: number;\n zoomLevel: number;\n}\n\n/**\n * Calculates the zoom level needed to fit all `nodes` inside a canvas of\n * `(canvasWidth, canvasHeight)`.\n *\n * @param paddingFraction - Fractional padding on each side (0.15 = 15%).\n * Pixel-padding variant still available when a value >=1 is passed.\n */\nexport function calculateFitZoom(\n nodes: FlatNode[],\n canvasWidth: number,\n canvasHeight: number,\n padding = 0.15,\n): number {\n if (nodes.length === 0) return 1;\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n // Use the actual node boundaries (center +/- half-width/height)\n minX = Math.min(minX, n.x - n.width / 2);\n minY = Math.min(minY, n.y - n.height / 2);\n maxX = Math.max(maxX, n.x + n.width / 2);\n maxY = Math.max(maxY, n.y + n.height / 2);\n }\n\n const rawW = maxX - minX;\n const rawH = maxY - minY;\n\n // Minimum spread — single isolated node should appear comfortably\n // Matches visualli.ai's spread logic for single nodes\n const spreadW = nodes.length === 1 ? Math.max(rawW, 600) : rawW;\n const spreadH = nodes.length === 1 ? Math.max(rawH, 400) : rawH;\n\n const zoomX = (canvasWidth * (1 - padding)) / spreadW;\n const zoomY = (canvasHeight * (1 - padding)) / spreadH;\n\n const z = Math.min(zoomX, zoomY);\n\n // Scale back 20% so nodes aren't edge-to-edge, clamp to at least\n // ZOOM_NAV_OUT_THRESHOLD so arriving at the layer never immediately\n // re-triggers the zoom-out transition.\n return Math.max(z * 0.80, ZOOM_NAV_OUT_THRESHOLD);\n}\n\n/**\n * Calculates the world-space center point that puts all `nodes` in the middle\n * of the viewport. Matches the visualli.ai `calculateFitCenter` approach:\n * uses bounding-box midpoint rather than centroid so the layout is always\n * geometrically centred.\n */\nexport function calculateFitCenter(nodes: FlatNode[]): { x: number; y: number } {\n if (nodes.length === 0) return { x: 0, y: 0 };\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n minX = Math.min(minX, n.x - n.width / 2);\n minY = Math.min(minY, n.y - n.height / 2);\n maxX = Math.max(maxX, n.x + n.width / 2);\n maxY = Math.max(maxY, n.y + n.height / 2);\n }\n return { x: (minX + maxX) / 2, y: (minY + maxY) / 2 };\n}\n\n// ── Container helpers ────────────────────────────────────────────────────────\n\n// Inline the container shape here to avoid a circular import with KonvaContainerLayer.\nexport interface ContainerGroupInfo {\n id: string;\n label?: string;\n nodeIds: string[];\n level: number;\n}\n\n/**\n * Returns the container groups for the given layer, normalising both the\n * nested-data format `{data:{label,formation}}` and the flat format `{label}`.\n */\nexport function getContainersForLayer(\n doc: VisualliDocument,\n layerId: string,\n): ContainerGroupInfo[] {\n const layer = doc.layers.get(layerId);\n if (!layer) return [];\n \n // Defensive: ensure containers is an array\n const containers = layer.containers ?? [];\n if (!Array.isArray(containers)) return [];\n \n return containers.map(c => {\n // Schema Container has nested data.label structure\n const label = c.data?.label ?? c.id;\n return { id: c.id, label, nodeIds: c.nodes, level: layer.level };\n });\n}\n\n/** Convenience: returns both center and zoom for a single `fitView` call. */\nexport function calculateFitView(\n nodes: FlatNode[],\n canvasWidth: number,\n canvasHeight: number,\n): FitResult {\n const center = calculateFitCenter(nodes);\n const zoom = calculateFitZoom(nodes, canvasWidth, canvasHeight);\n return { centerX: center.x, centerY: center.y, zoomLevel: zoom };\n}\n\n","import type { FlatNode, ViewportState } from '../types/index.js';\nimport { RBushSpatialIndex } from '../spatial/spatialIndex.js';\nimport { calculateViewportBounds } from '../viewport/viewportUtils.js';\n\nexport interface CullingOptions {\n nodes: FlatNode[];\n viewport: ViewportState;\n canvasWidth: number;\n canvasHeight: number;\n levelFilter?: number;\n skipCulling?: boolean;\n isDragging?: boolean;\n spatialIndex?: RBushSpatialIndex | null;\n spatialIndexThreshold?: number;\n}\n\nconst DEFAULT_SPATIAL_INDEX_THRESHOLD = 200;\n\n/**\n * Returns the subset of nodes currently visible in the viewport.\n * Framework-agnostic logic for culling and spatial indexing.\n */\nexport function getViewportVisibleNodes(options: CullingOptions): FlatNode[] {\n const {\n nodes,\n viewport,\n canvasWidth,\n canvasHeight,\n levelFilter,\n skipCulling = false,\n isDragging = false,\n spatialIndex,\n spatialIndexThreshold = DEFAULT_SPATIAL_INDEX_THRESHOLD,\n } = options;\n\n const filtered = levelFilter !== undefined\n ? nodes.filter(n => n.level === levelFilter)\n : nodes;\n\n if (filtered.length === 0) return [];\n\n // During transitions or drags show all nodes to avoid partial layer appearance\n if (skipCulling || isDragging) return filtered;\n\n const bounds = calculateViewportBounds(viewport, canvasWidth, canvasHeight);\n\n if (filtered.length < spatialIndexThreshold) {\n return filtered.filter(n =>\n n.x + n.width >= bounds.minX &&\n n.x <= bounds.maxX &&\n n.y + n.height >= bounds.minY &&\n n.y <= bounds.maxY,\n );\n }\n\n if (spatialIndex) {\n const nodeIds = spatialIndex.query({\n minX: bounds.minX, minY: bounds.minY, maxX: bounds.maxX, maxY: bounds.maxY,\n });\n const idSet = new Set(nodeIds);\n return filtered.filter(n => idSet.has(n.id));\n }\n\n // Fallback to simple filter if no index provided but threshold exceeded\n return filtered.filter(n =>\n n.x + n.width >= bounds.minX &&\n n.x <= bounds.maxX &&\n n.y + n.height >= bounds.minY &&\n n.y <= bounds.maxY,\n );\n}\n","import { NODE_HEIGHT } from '../constants/performanceConstants.js';\n\nexport const NODE_TEXT_BASE_FONT_PX = 28;\nexport const DESCRIPTION_TEXT_BASE_FONT_PX = 12;\nexport const CONTAINER_LABEL_BASE_FONT_PX = 24;\nexport const EDGE_LABEL_BASE_FONT_PX = 18;\nexport const OVERLAY_FONT_UPPER_BOOST_PX = 8;\n\n// Keep text away from blob edges\nconst NODE_TEXT_SAFE_BLOB_FILL_RATIO = 0.88;\n\n/**\n * Computes world-space text scale for node title:\n * - inverse zoom for screen-space consistency\n * - clamped so text stays inside the node blob with safe padding\n *\n * Matches visualli.ai's computeNodeTextWorldScale(nodeWidth, zoomLevel).\n */\nexport function computeNodeTextWorldScale(nodeWidth: number, zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n const baseRadiusX = nodeWidth / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n const textNaturalWidth = nodeWidth - 40;\n const textNaturalHeight = NODE_HEIGHT - 20;\n\n const maxScaleX = ((baseRadiusX * 2) * NODE_TEXT_SAFE_BLOB_FILL_RATIO) / Math.max(textNaturalWidth, 1);\n const maxScaleY = ((baseRadiusY * 2) * NODE_TEXT_SAFE_BLOB_FILL_RATIO) / Math.max(textNaturalHeight, 1);\n const fitScale = Math.max(0.01, Math.min(maxScaleX, maxScaleY));\n\n return Math.min(1 / safeZoom, fitScale);\n}\n\n/** Screen-space scale (zoom-adjusted) for text overlays. */\nexport function computeNodeTextScreenScale(nodeWidth: number, zoomLevel: number): number {\n return computeNodeTextWorldScale(nodeWidth, zoomLevel) * zoomLevel;\n}\n\n/**\n * Screen-space overlay scale for description/semantic tooltips.\n * - lower bound: 1x\n * - upper bound: node-title-root + OVERLAY_FONT_UPPER_BOOST_PX\n */\nexport function computeOverlayScale(zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n const inverseScale = 1 / safeZoom;\n const maxScale = (NODE_TEXT_BASE_FONT_PX + OVERLAY_FONT_UPPER_BOOST_PX) / NODE_TEXT_BASE_FONT_PX;\n return Math.min(Math.max(inverseScale, 1), maxScale);\n}\n\n/** Scale for edge path labels in screen pixels. */\nexport function computeEdgeLabelScale(zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n return Math.min(Math.max(EDGE_LABEL_BASE_FONT_PX / safeZoom, 10), 32);\n}\n","export interface BlobPoint { x: number; y: number }\nexport type BlobShape = BlobPoint[];\n\n// ── Blob Layer Config ─────────────────────────────────────────────────────────\n\nexport const BLOB_LAYER_CONFIG = [\n { opacity: 0.3, rotation: -15, scaleUp: 1.30, strokeWidth: 3, dash: [6, 4] }, // Layer #3 (outermost)\n { opacity: 0.4, rotation: -10, scaleUp: 1.20, strokeWidth: 1, dash: undefined }, // Layer #2\n { opacity: 0.5, rotation: -5, scaleUp: 1.10, strokeWidth: 2, dash: undefined }, // Layer #1\n] as const;\n\nexport const NODE_LAYER_CONFIG = { opacity: 1, rotation: 0, strokeWidth: 3 } as const;\n\n// ── Blob Shapes ───────────────────────────────────────────────────────────────\n\nexport const ALL_BLOB_SHAPES: ReadonlyArray<BlobShape> = [\n // Shape 0 · Blob 1\n [\n { x: 1.12, y: 0 }, { x: 0.86, y: 0.56 }, { x: 0.46, y: 0.94 }, { x: -0.08, y: 1.06 },\n { x: -0.68, y: 0.82 }, { x: -0.96, y: 0.08 }, { x: -0.55, y: -0.82 }, { x: 0.04, y: -1.02 },\n { x: 0.72, y: -0.8 }, { x: 1.08, y: -0.38 },\n ],\n // Shape 1 · Blob 2\n [\n { x: -0.489, y: -0.625 }, { x: -0.384, y: -0.716 }, { x: -0.285, y: -0.792 }, { x: -0.189, y: -0.855 },\n { x: -0.090, y: -0.903 }, { x: 0.014, y: -0.932 }, { x: 0.129, y: -0.940 }, { x: 0.255, y: -0.924 },\n { x: 0.412, y: -0.876 }, { x: 0.516, y: -0.832 }, { x: 0.612, y: -0.780 }, { x: 0.695, y: -0.725 },\n { x: 0.767, y: -0.666 }, { x: 0.830, y: -0.606 }, { x: 0.885, y: -0.546 }, { x: 0.933, y: -0.486 },\n { x: 0.979, y: -0.425 }, { x: 1.006, y: -0.385 }, { x: 1.034, y: -0.334 }, { x: 1.058, y: -0.276 },\n { x: 1.078, y: -0.209 }, { x: 1.092, y: -0.133 }, { x: 1.101, y: -0.046 }, { x: 1.102, y: 0.052 },\n { x: 1.094, y: 0.173 }, { x: 1.083, y: 0.244 }, { x: 1.063, y: 0.324 }, { x: 1.034, y: 0.401 },\n { x: 0.996, y: 0.477 }, { x: 0.948, y: 0.549 }, { x: 0.889, y: 0.617 }, { x: 0.820, y: 0.681 },\n { x: 0.735, y: 0.741 }, { x: 0.658, y: 0.783 }, { x: 0.569, y: 0.822 }, { x: 0.474, y: 0.855 },\n { x: 0.372, y: 0.882 }, { x: 0.265, y: 0.904 }, { x: 0.156, y: 0.920 }, { x: 0.046, y: 0.931 },\n { x: -0.069, y: 0.938 }, { x: -0.155, y: 0.935 }, { x: -0.250, y: 0.919 }, { x: -0.346, y: 0.890 },\n { x: -0.443, y: 0.851 }, { x: -0.539, y: 0.800 }, { x: -0.633, y: 0.738 }, { x: -0.723, y: 0.667 },\n { x: -0.808, y: 0.585 }, { x: -0.882, y: 0.501 }, { x: -0.944, y: 0.421 }, { x: -0.994, y: 0.343 },\n { x: -1.034, y: 0.267 }, { x: -1.064, y: 0.192 }, { x: -1.085, y: 0.120 }, { x: -1.097, y: 0.042 },\n { x: -1.102, y: 0.001 }, { x: -1.090, y: -0.243 }, { x: -1.050, y: -0.365 }, { x: -0.990, y: -0.441 },\n { x: -0.911, y: -0.479 }, { x: -0.819, y: -0.499 }, { x: -0.715, y: -0.517 }, { x: -0.605, y: -0.551 },\n ],\n // Shape 2 · Blob 3\n [\n { x: 0.003, y: -0.970 }, { x: 0.163, y: -0.984 }, { x: 0.286, y: -1.028 }, { x: 0.389, y: -1.096 },\n { x: 0.488, y: -1.174 }, { x: 0.597, y: -1.210 }, { x: 0.728, y: -1.165 }, { x: 0.867, y: -1.036 },\n { x: 0.996, y: -0.839 }, { x: 1.098, y: -0.590 }, { x: 1.158, y: -0.304 }, { x: 1.153, y: 0.012 },\n { x: 1.080, y: 0.336 }, { x: 0.944, y: 0.639 }, { x: 0.756, y: 0.889 }, { x: 0.484, y: 1.072 },\n { x: 0.339, y: 1.079 }, { x: 0.219, y: 1.051 }, { x: 0.131, y: 0.994 }, { x: 0.059, y: 0.939 },\n { x: 0.008, y: 0.915 }, { x: -0.105, y: 0.931 }, { x: -0.176, y: 0.965 }, { x: -0.249, y: 1.005 },\n { x: -0.345, y: 1.039 }, { x: -0.497, y: 1.055 }, { x: -0.672, y: 1.032 }, { x: -0.817, y: 0.952 },\n { x: -0.945, y: 0.810 }, { x: -1.054, y: 0.600 }, { x: -1.160, y: 0.302 }, { x: -1.187, y: -0.011 },\n { x: -1.165, y: -0.326 }, { x: -1.097, y: -0.599 }, { x: -0.991, y: -0.838 }, { x: -0.852, y: -0.912 },\n { x: -0.695, y: -0.958 }, { x: -0.530, y: -0.988 }, { x: -0.357, y: -0.992 }, { x: -0.180, y: -0.983 },\n ],\n // Shape 3 · Blob 4\n [\n { x: -0.734, y: -1.127 }, { x: -0.656, y: -1.146 }, { x: -0.567, y: -1.142 }, { x: -0.468, y: -1.115 },\n { x: -0.358, y: -1.079 }, { x: -0.238, y: -1.034 }, { x: -0.107, y: -0.989 }, { x: 0.035, y: -0.953 },\n { x: 0.188, y: -0.929 }, { x: 0.325, y: -0.916 }, { x: 0.484, y: -0.896 }, { x: 0.650, y: -0.854 },\n { x: 0.811, y: -0.770 }, { x: 0.955, y: -0.631 }, { x: 1.068, y: -0.422 }, { x: 1.138, y: -0.126 },\n { x: 1.152, y: 0.272 }, { x: 1.121, y: 0.451 }, { x: 1.046, y: 0.602 }, { x: 0.928, y: 0.727 },\n { x: 0.767, y: 0.833 }, { x: 0.565, y: 0.925 }, { x: 0.323, y: 1.001 }, { x: 0.042, y: 1.075 },\n { x: -0.277, y: 1.142 }, { x: -0.368, y: 1.147 }, { x: -0.475, y: 1.136 }, { x: -0.589, y: 1.104 },\n { x: -0.704, y: 1.050 }, { x: -0.815, y: 0.973 }, { x: -0.913, y: 0.871 }, { x: -0.993, y: 0.746 },\n { x: -1.048, y: 0.593 }, { x: -1.109, y: 0.298 }, { x: -1.145, y: 0.018 }, { x: -1.154, y: -0.243 },\n { x: -1.135, y: -0.482 }, { x: -1.085, y: -0.695 }, { x: -1.003, y: -0.874 }, { x: -0.886, y: -1.020 },\n ],\n // Shape 4 · Blob 5\n [\n { x: -0.734, y: 1.127 }, { x: -0.656, y: 1.146 }, { x: -0.567, y: 1.142 }, { x: -0.468, y: 1.115 },\n { x: -0.358, y: 1.079 }, { x: -0.238, y: 1.034 }, { x: -0.107, y: 0.989 }, { x: 0.035, y: 0.953 },\n { x: 0.188, y: 0.929 }, { x: 0.325, y: 0.916 }, { x: 0.484, y: 0.896 }, { x: 0.650, y: 0.854 },\n { x: 0.811, y: 0.770 }, { x: 0.955, y: 0.631 }, { x: 1.068, y: 0.422 }, { x: 1.138, y: 0.126 },\n { x: 1.152, y: -0.272 }, { x: 1.121, y: -0.451 }, { x: 1.046, y: -0.602 }, { x: 0.928, y: -0.727 },\n { x: 0.767, y: -0.833 }, { x: 0.565, y: -0.925 }, { x: 0.323, y: -1.001 }, { x: 0.042, y: -1.075 },\n { x: -0.277, y: -1.142 }, { x: -0.368, y: -1.147 }, { x: -0.475, y: -1.136 }, { x: -0.589, y: -1.104 },\n { x: -0.704, y: -1.050 }, { x: -0.815, y: -0.973 }, { x: -0.913, y: -0.871 }, { x: -0.993, y: -0.746 },\n { x: -1.048, y: -0.593 }, { x: -1.109, y: -0.298 }, { x: -1.145, y: -0.018 }, { x: -1.154, y: 0.243 },\n { x: -1.135, y: 0.482 }, { x: -1.085, y: 0.695 }, { x: -1.003, y: 0.874 }, { x: -0.886, y: 1.020 },\n ],\n // Shape 5 · Blob 6\n [\n { x: 0.001, y: -1.006 }, { x: 0.134, y: -1.001 }, { x: 0.262, y: -1.024 },\n { x: 0.382, y: -1.073 }, { x: 0.498, y: -1.107 }, { x: 0.614, y: -1.105 },\n { x: 0.733, y: -1.049 }, { x: 0.850, y: -0.932 }, { x: 0.953, y: -0.755 },\n { x: 1.030, y: -0.529 }, { x: 1.067, y: -0.265 }, { x: 1.054, y: 0.018 },\n { x: 0.986, y: 0.300 }, { x: 0.868, y: 0.557 }, { x: 0.715, y: 0.766 },\n { x: 0.550, y: 0.909 }, { x: 0.396, y: 0.984 }, { x: 0.262, y: 1.005 },\n { x: 0.148, y: 1.003 }, { x: 0.037, y: 1.008 }, { x: -0.083, y: 1.040 },\n { x: -0.220, y: 1.118 }, { x: -0.360, y: 1.192 }, { x: -0.500, y: 1.234 },\n { x: -0.650, y: 1.175 }, { x: -0.810, y: 1.045 }, { x: -0.990, y: 0.855 },\n { x: -1.140, y: 0.610 }, { x: -1.240, y: 0.330 }, { x: -1.270, y: 0.040 },\n { x: -1.275, y: -0.250 }, { x: -1.225, y: -0.500 }, { x: -1.080, y: -0.720 },\n { x: -0.890, y: -0.920 }, { x: -0.734, y: -1.053 }, { x: -0.614, y: -1.112 },\n { x: -0.498, y: -1.127 }, { x: -0.381, y: -1.110 }, { x: -0.261, y: -1.095 },\n { x: -0.133, y: -1.058 }, { x: 0.001, y: -1.010 }, { x: 0.134, y: -1.001 },\n ],\n];\n\nexport const ACTIVE_BLOB_TYPES: ReadonlyArray<number> = [0, 1, 2, 3, 4, 5];\n\n/**\n * Per-shape text x-offset as a fraction of baseRadiusX.\n * Compensates for visually asymmetric blobs. Positive = right, negative = left.\n */\nexport const BLOB_TEXT_OFFSETS: ReadonlyArray<number> = [0, 0, 0, 0, 0, -0.10];\n\n/**\n * Deterministic pseudo-random blob-type selector per tree level.\n * Root level (0) always uses shape 0; consecutive levels use different shapes.\n */\nexport function getBlobTypeForLayer(level: number): number {\n const numTypes = ACTIVE_BLOB_TYPES.length;\n if (numTypes <= 1) return ACTIVE_BLOB_TYPES[0] ?? 0;\n let currentType = 0;\n for (let i = 1; i <= level; i++) {\n const pseudoRandom = Math.floor(Math.abs(Math.sin((i + 1) * 12.9898) * 43758.5453));\n const stepOffset = (pseudoRandom % (numTypes - 1)) + 1;\n currentType = (currentType + stepOffset) % numTypes;\n }\n return ACTIVE_BLOB_TYPES[currentType];\n}\n\n/**\n * Draw the blob path onto a canvas context (centered at 0,0).\n * Uses closed quadratic bezier curves through midpoints of control points.\n */\nexport function drawBlobPath(\n ctx: { beginPath(): void; moveTo(x: number, y: number): void; quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; closePath(): void },\n radiusX: number,\n radiusY: number,\n blobType: number,\n): void {\n const srcPts = ALL_BLOB_SHAPES[blobType] ?? ALL_BLOB_SHAPES[0];\n const pts = srcPts.map(p => ({ x: p.x * radiusX, y: p.y * radiusY }));\n ctx.beginPath();\n const last = pts[pts.length - 1];\n const first = pts[0];\n ctx.moveTo((last.x + first.x) / 2, (last.y + first.y) / 2);\n for (let i = 0; i < pts.length; i++) {\n const curr = pts[i];\n const next = pts[(i + 1) % pts.length];\n ctx.quadraticCurveTo(curr.x, curr.y, (curr.x + next.x) / 2, (curr.y + next.y) / 2);\n }\n ctx.closePath();\n}\n"],"mappings":"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","names":[]}