@visualli/react 0.1.1 → 0.1.2

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/VisualliRenderer.tsx","../src/VisualliCanvas.tsx","../src/stores/useNodeStore.ts","../src/stores/useViewportStore.ts","../src/stores/stores.ts","../src/hooks/useKonvaRenderer.ts","../src/hooks/useKonvaLayerTransition.ts","../src/animations/konvaLayerTransition.ts","../src/utils/layerNavigation.ts","../src/components/KonvaStage.tsx","../src/konvaCompat.ts","../src/components/KonvaNodeLayer.tsx","../src/hooks/useViewportNodes.ts","../src/components/KonvaNode.tsx","../src/config/index.ts","../src/config/blobShapes.ts","../src/components/KonvaEdgeLayer.tsx","../src/components/KonvaEdge.tsx","../src/components/KonvaContainerLayer.tsx","../src/components/KonvaContainer.tsx","../src/config/textScaling.ts","../src/components/NavigationStack.tsx","../src/components/ZoomControls.tsx","../src/components/SketchyBoxKonva.tsx","../src/context/VisualliContext.tsx"],"sourcesContent":["// ─── VisualliRenderer ────────────────────────────────────────────────────────\n//\n// The single public-facing component for rendering a .visualli document.\n//\n// <VisualliRenderer visualliString={str} theme=\"dark\" width=\"100%\" height=\"600px\" />\n// <VisualliRenderer visualliFile={file} theme=\"auto\" width={800} height={600} />\n// <VisualliRenderer document={doc} theme=\"auto\" width={800} height={600} />\n//\n// Handles:\n// • theme: 'dark' | 'light' | 'auto' — auto follows prefers-color-scheme\n// • width / height as first-class props (CSS string or pixel number)\n// • Empty state — no data prop provided\n// • Loading state — while parsing a .visualli file/string\n// • Error state — parse failure with message\n// • useWorker — offload parsing to a Web Worker (default: false)\n// • Delegates all canvas/navigation/zoom logic to VisualliCanvas\n\nimport React, { useEffect, useRef, useState, useMemo } from 'react';\nimport type { VisualliDocument, VisualliLayer, FlatNode } from '@visualli/core';\nimport { parseVisualliFile } from '@visualli/core';\nimport VisualliCanvas from './VisualliCanvas';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type VisualliTheme = 'dark' | 'light' | 'auto';\n\nexport interface VisualliRendererProps {\n /**\n * Raw JSONL string — the content of a .visualli file.\n * Simply pass the string data directly, no preprocessing needed.\n * Example: visualliString=\"{\\\"type\\\":\\\"meta\\\"...}\\n{\\\"type\\\":\\\"layer\\\"...}\"\n */\n visualliString?: string;\n\n /**\n * A .visualli file — can be:\n * - File object (e.g. from <input type=\"file\">)\n * - String path to file (e.g. '/data/myfile.visualli' or './src/data/data.visualli')\n * The renderer automatically fetches, reads, and parses it.\n * No user code required for conversion or processing.\n */\n visualliFile?: File | string;\n\n /**\n * When true, parsing is offloaded to a Web Worker so the main thread never\n * blocks during JSON.parse. Recommended for large documents (>500 nodes).\n * Has no effect when `document` is supplied (already parsed).\n * @default true\n */\n useWorker?: boolean;\n\n /**\n * Colour theme.\n * - 'dark' → always dark background\n * - 'light' → always light background\n * - 'auto' → follows the OS/browser prefers-color-scheme\n * @default 'light'\n */\n theme?: VisualliTheme;\n\n /**\n * Enable chromatic immersion background effect.\n * When true:\n * - Root layer (level 0) shows base background color\n * - Child layers show parent node's color as semi-transparent background\n * @default false\n */\n chromaticImmersion?: boolean;\n\n /**\n * Width of the renderer. Accepts any CSS length string ('100%', '800px', '100vw')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n width?: string | number;\n\n /**\n * Height of the renderer. Accepts any CSS length string ('100%', '600px', '100vh')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n height?: string | number;\n\n /** Additional CSS class on the root element. */\n className?: string;\n\n /** Additional inline styles merged onto the root element. */\n style?: React.CSSProperties;\n}\n\n// ── System dark-mode hook ─────────────────────────────────────────────────────\n\nfunction useSystemDark(): boolean {\n const mq = typeof window !== 'undefined'\n ? window.matchMedia('(prefers-color-scheme: dark)')\n : null;\n\n const [dark, setDark] = useState<boolean>(mq?.matches ?? false);\n\n useEffect(() => {\n if (!mq) return;\n const handler = (e: MediaQueryListEvent) => setDark(e.matches);\n mq.addEventListener('change', handler);\n return () => mq.removeEventListener('change', handler);\n }, [mq]);\n\n return dark;\n}\n\n// ── Font Injection Hook ───────────────────────────────────────────────────────\n\nfunction useFontInjection() {\n useEffect(() => {\n if (typeof document === 'undefined') return;\n \n const links = [\n 'https://fonts.googleapis.com',\n 'https://fonts.gstatic.com',\n 'https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&family=Nunito+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300&display=swap',\n 'https://fonts.googleapis.com/css2?family=Playpen+Sans:wght@300;400;600;800&family=Story+Script:wght@400&display=swap'\n ];\n\n links.forEach((href, i) => {\n const id = `visualli-font-${i}`;\n if (!document.getElementById(id)) {\n const link = document.createElement('link');\n link.id = id;\n link.rel = i < 2 ? 'preconnect' : 'stylesheet';\n link.href = href;\n if (i === 1) link.crossOrigin = 'anonymous';\n document.head.appendChild(link);\n }\n });\n }, []);\n}\n\n// ── Empty / Loading / Error states ───────────────────────────────────────────\n\n// ── UI State Components ───────────────────────────────────────────────────────\n\nfunction EmptyState({ isDark }: { isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const fg = isDark ? 'rgba(240,237,230,0.35)' : 'rgba(26,26,24,0.35)';\n const bd = isDark ? '#2A2A28' : '#DDD9D0';\n const code = { fontFamily: 'monospace', fontSize: 12, padding: '1px 4px', borderRadius: 4, background: isDark ? '#222220' : '#E8E4DC', border: `1px solid ${bd}` };\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', gap: 16, background: bg, color: fg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" stroke={fg} strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"10\" y=\"6\" width=\"28\" height=\"36\" rx=\"3\" />\n <line x1=\"16\" y1=\"16\" x2=\"32\" y2=\"16\" />\n <line x1=\"16\" y1=\"22\" x2=\"32\" y2=\"22\" />\n <line x1=\"16\" y1=\"28\" x2=\"26\" y2=\"28\" />\n </svg>\n <div style={{ textAlign: 'center', lineHeight: 1.7 }}>\n <p style={{ margin: 0, fontSize: 15, fontWeight: 600, color: isDark ? 'rgba(240,237,230,0.7)' : 'rgba(26,26,24,0.7)' }}>\n No .visualli file provided\n </p>\n <p style={{ margin: '4px 0 0', fontSize: 13 }}>\n Pass a <code style={code}>visualliFile</code> or <code style={code}>visualliString</code> prop.\n </p>\n </div>\n </div>\n );\n}\n\nfunction LoadingState({ isDark }: { isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const fg = isDark ? 'rgba(240,237,230,0.5)' : 'rgba(26,26,24,0.5)';\n const dot = isDark ? 'rgba(240,237,230,0.6)' : 'rgba(26,26,24,0.45)';\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', gap: 16, background: bg, color: fg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <div style={{ display: 'flex', gap: 8 }}>\n {[0, 1, 2].map(i => (\n <div key={i} style={{ width: 8, height: 8, borderRadius: '50%', background: dot, animation: `vr-pulse 1.2s ease-in-out ${i * 0.2}s infinite` }} />\n ))}\n </div>\n <style>{`@keyframes vr-pulse{0%,80%,100%{opacity:.2;transform:scale(.9)}40%{opacity:1;transform:scale(1.1)}}`}</style>\n <p style={{ margin: 0, fontSize: 14 }}>Loading .visualli file…</p>\n </div>\n );\n}\n\nfunction ErrorState({ message, isDark }: { message: string; isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const bd = isDark ? '#3a1f1f' : '#F0CECE';\n const card = isDark ? '#1e1212' : '#FFF5F5';\n const head = isDark ? '#F87171' : '#DC2626';\n const body = isDark ? 'rgba(248,113,113,0.8)' : 'rgba(180,40,40,0.8)';\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', padding: '24px', background: bg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <div style={{ maxWidth: 480, width: '100%', padding: '20px 24px', borderRadius: 12, border: `1px solid ${bd}`, background: card }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke={head} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n <span style={{ fontSize: 15, fontWeight: 700, color: head }}>Failed to parse .visualli file</span>\n </div>\n <p style={{ margin: 0, fontSize: 13, color: body, lineHeight: 1.6, wordBreak: 'break-word', fontFamily: 'monospace' }}>{message}</p>\n </div>\n </div>\n );\n}\n\n// ── Inline worker script ──────────────────────────────────────────────────────\n// Self-contained JSONL parser that mirrors parseVisualliFile.\n// Runs in a Web Worker when useWorker=true; no external imports needed.\n\nconst WORKER_SCRIPT = `\nself.onmessage = function(e) {\n var content = e.data;\n try {\n var lines = content.trim().split('\\\\n');\n var doc = {\n meta: null,\n layers: new Map(),\n layersByLevel: new Map(),\n rootLayer: null,\n };\n for (var i = 0; i < lines.length; i++) {\n var line = lines[i].trim();\n if (!line) continue;\n var obj;\n try { obj = JSON.parse(line); }\n catch(err) { throw new Error('Failed to parse JSON at line ' + (i+1) + ': ' + err); }\n if (!obj.type) throw new Error(\"Missing 'type' field at line \" + (i+1));\n if (obj.type === 'meta') {\n doc.meta = obj;\n } else if (obj.type === 'layer') {\n doc.layers.set(obj.id, obj);\n if (!doc.layersByLevel.has(obj.level)) doc.layersByLevel.set(obj.level, []);\n doc.layersByLevel.get(obj.level).push(obj);\n if (obj.level === 0) doc.rootLayer = obj;\n }\n }\n if (!doc.meta) throw new Error('Missing required meta section');\n if (!doc.rootLayer) throw new Error('Missing root layer (level 0)');\n self.postMessage({ ok: true, doc: doc });\n } catch(err) {\n self.postMessage({ ok: false, message: err.message || String(err) });\n }\n};\n`;\n\n// Lazy-create worker URL once (module-level singleton).\nlet _workerUrl: string | null = null;\nfunction getWorkerUrl(): string {\n if (!_workerUrl) {\n _workerUrl = URL.createObjectURL(new Blob([WORKER_SCRIPT], { type: 'text/javascript' }));\n }\n return _workerUrl;\n}\n\n// ── Parse hook ────────────────────────────────────────────────────────────────\n\ntype ParseState =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'ready'; doc: VisualliDocument }\n | { status: 'error'; message: string };\n\n/**\n * Resolves a raw string + optional File into a ParseState.\n * When useWorker=true the JSON.parse work runs in a Web Worker so the main\n * thread is never blocked, even for very large documents.\n */\nfunction useAsyncParse(\n content: string | undefined,\n useWorker: boolean,\n): ParseState {\n const [state, setState] = useState<ParseState>({ status: 'idle' });\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n if (!content) { setState({ status: 'idle' }); return; }\n\n setState({ status: 'loading' });\n let cancelled = false;\n\n if (useWorker && typeof Worker !== 'undefined') {\n // Terminate any previous worker\n workerRef.current?.terminate();\n const w = new Worker(getWorkerUrl());\n workerRef.current = w;\n\n w.onmessage = (e: MessageEvent) => {\n if (cancelled) return;\n if (e.data.ok) {\n setState({ status: 'ready', doc: e.data.doc as VisualliDocument });\n } else {\n setState({ status: 'error', message: e.data.message });\n }\n };\n w.onerror = (e: ErrorEvent) => {\n if (!cancelled) setState({ status: 'error', message: e.message });\n };\n w.postMessage(content);\n\n return () => {\n cancelled = true;\n w.terminate();\n workerRef.current = null;\n };\n }\n\n // Main-thread path: defer via microtask so React paints the loading state first\n Promise.resolve().then(() => {\n if (cancelled) return;\n try {\n const doc = parseVisualliFile(content);\n if (!cancelled) setState({ status: 'ready', doc });\n } catch (err) {\n if (!cancelled) setState({ status: 'error', message: err instanceof Error ? err.message : String(err) });\n }\n });\n return () => { cancelled = true; };\n }, [content, useWorker]);\n\n // Terminate worker on unmount\n useEffect(() => () => { workerRef.current?.terminate(); }, []);\n\n return state;\n}\n\n// ── File → string hook ────────────────────────────────────────────────────────\n\nfunction useFileText(file: File | string | undefined): { text: string | undefined; error: string | undefined; loading: boolean } {\n const [text, setText] = useState<string | undefined>(undefined);\n const [error, setError] = useState<string | undefined>(undefined);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!file) { setText(undefined); setError(undefined); setLoading(false); return; }\n setLoading(true); setText(undefined); setError(undefined);\n let cancelled = false;\n\n // Handle string path - fetch the file\n if (typeof file === 'string') {\n fetch(file)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n })\n .catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n // Handle File object - read as text\n else {\n file.text().then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n }).catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n \n return () => { cancelled = true; };\n }, [file]);\n\n return { text, error, loading };\n}\n\n// ── VisualliRenderer ──────────────────────────────────────────────────────────\n\nexport default function VisualliRenderer({\n visualliString,\n visualliFile,\n theme = 'light',\n width = '100%',\n height = '100%',\n useWorker = true,\n chromaticImmersion = false,\n className,\n style,\n}: VisualliRendererProps) {\n useFontInjection();\n const systemDark = useSystemDark();\n const isDark = theme === 'dark' ? true : theme === 'light' ? false : systemDark;\n\n const cssWidth = typeof width === 'number' ? `${width}px` : width;\n const cssHeight = typeof height === 'number' ? `${height}px` : height;\n\n // Read File → text (no-op if not provided)\n const { text: fileText, error: fileReadError, loading: fileReading } = useFileText(visualliFile);\n\n // The raw JSONL string to parse: file takes priority over string prop\n const rawContent = fileText ?? visualliString;\n\n const parseState = useAsyncParse(rawContent, useWorker);\n\n const resolvedDoc: VisualliDocument | null = useMemo(() => {\n if (parseState.status === 'ready') return parseState.doc;\n return null;\n }, [parseState]);\n\n const wrapperStyle: React.CSSProperties = { width: cssWidth, height: cssHeight, overflow: 'hidden', ...style };\n\n // ── Empty state ─────────────────────────────────────────────────────────────\n if (!visualliString && !visualliFile) {\n return <div className={className} style={wrapperStyle}><EmptyState isDark={isDark} /></div>;\n }\n\n // ── Loading state ───────────────────────────────────────────────────────────\n if (fileReading || parseState.status === 'loading') {\n return <div className={className} style={wrapperStyle}><LoadingState isDark={isDark} /></div>;\n }\n\n // ── Error state ─────────────────────────────────────────────────────────────\n if (fileReadError || parseState.status === 'error') {\n const msg = fileReadError ?? (parseState.status === 'error' ? parseState.message : 'Unknown error');\n return <div className={className} style={wrapperStyle}><ErrorState message={msg} isDark={isDark} /></div>;\n }\n\n // ── Canvas ──────────────────────────────────────────────────────────────────\n return (\n <div className={className} style={wrapperStyle}>\n <VisualliCanvas\n preParsedVisualli={resolvedDoc ?? undefined}\n isDark={isDark}\n chromaticImmersion={chromaticImmersion}\n style={{ width: '100%', height: '100%' }}\n />\n </div>\n );\n}\n","// ─── VisualliCanvas ───────────────────────────────────────────────────────────\n//\n// Main canvas component for rendering a VisualliDocument.\n// Matches the visualli.ai enhanced canvas implementation:\n// • Stage-level hit detection via RBush spatial index (no Konva hit-canvas)\n// • Node description tooltip (sketchy-box style)\n// • Chromatic immersion background (color from current node)\n// • Auto-zoom navigation (zoom in → child layer, zoom out → parent layer)\n// • Professional layer transitions (zoom in / zoom out animations)\n// • Vertical left-side navigation stack\n// • Zoom controls (icon-based, top-right)\n// • Context menu (right-click to go back)\n//\n// NOT included (SDK-only, no generation UI):\n// • Sidebar, search, generation\n// • Semantic anchor tooltips (special word meanings)\n// • Branding logo\n// • Help overlay / view-source panel\n\nimport React, { useRef, useState, useCallback, useEffect, useMemo, useLayoutEffect } from 'react';\nimport type Konva from 'konva';\nimport type { VisualliDocument, VisualliLayer, FlatNode, MindMapConnection } from '@visualli/core';\nimport {\n parseVisualliFile,\n getNodesForLayer,\n getThemeBackground,\n darkenHexColor,\n RBushSpatialIndex,\n NODE_HEIGHT,\n TEXT_LABEL_HIDE_BELOW_ZOOM,\n ZOOM_NAV_IN_THRESHOLD,\n ZOOM_NAV_OUT_THRESHOLD,\n ZOOM_MIN,\n} from '@visualli/core';\n\nimport { useNodeStore } from './stores/useNodeStore';\nimport { useViewportStore } from './stores/useViewportStore';\nimport { useSelectionStore } from './stores/stores';\n\nimport { useKonvaRenderer } from './hooks/useKonvaRenderer';\nimport { useKonvaLayerTransition } from './hooks/useKonvaLayerTransition';\n\nimport KonvaStage from './components/KonvaStage';\nimport KonvaNodeLayer from './components/KonvaNodeLayer';\nimport KonvaEdgeLayer from './components/KonvaEdgeLayer';\nimport KonvaContainerLayer from './components/KonvaContainerLayer';\nimport NavigationStack, { type NavStackEntry } from './components/NavigationStack';\nimport ZoomControls from './components/ZoomControls';\nimport SketchyBoxKonva from './components/SketchyBoxKonva';\n\nimport { getChildLayerForNode, calculateFitView, getConnectionsForLayer, getContainersForLayer } from './utils/layerNavigation';\nimport type { ContainerGroup } from './components/KonvaContainerLayer';\nimport type { AnimatorViewport } from './animations/konvaLayerTransition';\nimport { DESCRIPTION_TEXT_BASE_FONT_PX } from './config/textScaling';\nimport { useVisualli } from './context/VisualliContext';\n\n// Helper to convert hex color to rgba with transparency\nfunction hexToRgba(hex: string, alpha: number): string {\n // Remove # if present\n hex = hex.replace(/^#/, '');\n \n // Parse hex values\n let r: number, g: number, b: number;\n if (hex.length === 3) {\n r = parseInt(hex[0] + hex[0], 16);\n g = parseInt(hex[1] + hex[1], 16);\n b = parseInt(hex[2] + hex[2], 16);\n } else if (hex.length === 6) {\n r = parseInt(hex.substring(0, 2), 16);\n g = parseInt(hex.substring(2, 4), 16);\n b = parseInt(hex.substring(4, 6), 16);\n } else {\n return `rgba(240, 237, 230, ${alpha})`; // fallback\n }\n \n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveDocument(props: VisualliCanvasProps, fileText?: string): VisualliDocument | null {\n if (props.preParsedVisualli) return props.preParsedVisualli;\n const rawContent = fileText ?? props.visualliString;\n if (rawContent) {\n try { return parseVisualliFile(rawContent); } catch { return null; }\n }\n return null;\n}\n\nfunction layerLabel(doc: VisualliDocument, layer: VisualliLayer, layerId: string): string {\n if (layer.parentNodeId) {\n // Find the parent node in the parent layer to get its title\n const parentLayer = layer.parentLayerId ? doc.layers.get(layer.parentLayerId) : null;\n if (parentLayer) {\n const parentNode = parentLayer.nodes.find(n => n.id === layer.parentNodeId);\n if (parentNode) {\n return Array.isArray(parentNode.data.label)\n ? (parentNode.data.label as string[]).join(' ')\n : (parentNode.data.label || 'Untitled');\n }\n }\n }\n return layer.description ?? layerId;\n}\n\nfunction getRootLayerId(doc: VisualliDocument): string | null {\n for (const [id, layer] of doc.layers) {\n if (!layer.parentLayerId) return id;\n }\n return doc.layers.keys().next().value ?? null;\n}\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\nexport interface VisualliCanvasProps {\n preParsedVisualli?: VisualliDocument;\n /**\n * Raw JSONL string — just pass the string data directly.\n * No preprocessing needed by user.\n */\n visualliString?: string;\n /**\n * A .visualli file — can be:\n * - File object (from file input)\n * - String path to file (e.g. '/data/file.visualli')\n * Component handles all fetching and parsing automatically.\n */\n visualliFile?: File | string;\n isDark?: boolean;\n chromaticImmersion?: boolean;\n onNodeClick?: (node: FlatNode) => void;\n onLayerChange?: (layerId: string, layer: VisualliLayer) => void;\n \n // Extension points for private features (implement in consuming app)\n renderOverlay?: (params: { isDark: boolean; containerWidth: number; containerHeight: number }) => React.ReactNode;\n renderNodeContent?: (params: { \n summary: string; \n nodeId: string; \n nodeColor?: string;\n zoom: number;\n }) => React.ReactNode;\n navigationStackTop?: string;\n navigationStackLeft?: string;\n \n className?: string;\n style?: React.CSSProperties;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport default function VisualliCanvas(props: VisualliCanvasProps) {\n const { isDark = false, chromaticImmersion = false, onNodeClick, onLayerChange, renderOverlay, renderNodeContent, navigationStackTop = '16px', navigationStackLeft = '16px', className = '', style } = props;\n\n // Read file if provided (handles both File objects and string paths)\n const [fileText, setFileText] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!props.visualliFile) { setFileText(undefined); return; }\n let cancelled = false;\n \n // Handle string path - fetch the file\n if (typeof props.visualliFile === 'string') {\n fetch(props.visualliFile)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) setFileText(t);\n })\n .catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n // Handle File object - read as text\n else {\n props.visualliFile.text().then(t => {\n if (!cancelled) setFileText(t);\n }).catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n \n return () => { cancelled = true; };\n }, [props.visualliFile]);\n\n const doc = useMemo(() => resolveDocument(props, fileText), [props.preParsedVisualli, props.visualliString, props.visualliFile, fileText]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Navigation ────────────────────────────────────────────────────────────\n const [navStack, setNavStack] = useState<NavStackEntry[]>([]);\n const [currentLayerId, setCurrentLayerId] = useState<string | null>(null);\n const parentViewports = useRef<AnimatorViewport[]>([]);\n const [isTransitioning, setIsTransitioning] = useState(false);\n const isTransitioningRef = useRef(false);\n\n useEffect(() => {\n if (!doc) return;\n const rootId = getRootLayerId(doc);\n if (!rootId) return;\n const rootLayer = doc.layers.get(rootId)!;\n setCurrentLayerId(rootId);\n setNavStack([{ layerId: rootId, layer: rootLayer, label: 'Home' }]);\n parentViewports.current = [];\n }, [doc]);\n\n // ── Active layer → FlatNodes ──────────────────────────────────────────────\n const { flatNodes, connections, containers } = useMemo(() => {\n if (!doc || !currentLayerId) return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] };\n try {\n return {\n flatNodes: getNodesForLayer(doc, currentLayerId),\n connections: getConnectionsForLayer(doc, currentLayerId),\n containers: getContainersForLayer(doc, currentLayerId) as ContainerGroup[],\n };\n } catch { return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] }; }\n }, [doc, currentLayerId]);\n\n // ── Stores ────────────────────────────────────────────────────────────────\n const setNodes = useNodeStore(s => s.setNodes);\n const nodes = useNodeStore(s => s.nodes);\n const updateNodePosition = useNodeStore(s => s.updateNodePosition);\n const setCenter = useViewportStore(s => s.setCenter);\n const setZoom = useViewportStore(s => s.setZoom);\n const viewport = useViewportStore(s => ({\n centerX: s.centerX, centerY: s.centerY, zoomLevel: s.zoomLevel,\n canvasWidth: s.canvasWidth, canvasHeight: s.canvasHeight,\n }));\n const clearSel = useSelectionStore(s => s.clear);\n const select = useSelectionStore(s => s.select);\n\n // Sync nodes → store\n useEffect(() => {\n const map = new Map(flatNodes.map(n => [n.id, n]));\n setNodes(map);\n clearSel();\n }, [flatNodes, setNodes, clearSel]);\n\n // ── Canvas refs ───────────────────────────────────────────────────────────\n const containerRef = useRef<HTMLDivElement | null>(null);\n const stageRef = useRef<Konva.Stage | null>(null);\n const canvasWrapperRef = useRef<HTMLDivElement>(null);\n\n // ── GPU CSS-transform transition refs (matches visualli.ai) ───────────────\n // During animations we express viewport deltas as CSS transforms on Konva's\n // container div — zero canvas redraws, handled entirely by the GPU compositor.\n const baselineTransformRef = useRef<{ x: number; y: number; scaleX: number; scaleY: number } | null>(null);\n const konvaContentDivRef = useRef<HTMLDivElement | null>(null);\n const lastAnimViewportRef = useRef<{ centerX: number; centerY: number; zoomLevel: number } | null>(null);\n const zoomOutTargetRef = useRef<{ centerX: number; centerY: number; zoomLevel: number } | null>(null);\n // canvasSizeRef is kept in sync with the measured container size (not window).\n // Initialise to 0 — it will be updated synchronously before the first frame.\n const canvasSizeRef = useRef({ width: 0, height: 0 });\n\n // ── Node drag refs (RAF-throttled, matches visualli.ai) ───────────────────\n const dragMoveRafRef = useRef<number | null>(null);\n const dragMoveLatestRef = useRef<{ nodeId: string; x: number; y: number } | null>(null);\n const dragStartPosRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n\n // ── Background color (with chromatic immersion support) ──────────────────\n const baseBgColor = isDark ? '#141412' : '#F0EDE6';\n \n // For chromatic immersion: get the parent node color for child layers\n const chromaticBgColor = useMemo(() => {\n if (!chromaticImmersion || !doc || !currentLayerId) return baseBgColor;\n \n const currentLayer = doc.layers.get(currentLayerId);\n if (!currentLayer) return baseBgColor;\n \n // Root layer always uses base background\n if (currentLayer.level === 0 || !currentLayer.parentNodeId) return baseBgColor;\n \n // For child layers, find the parent node's color\n const parentLayer = currentLayer.parentLayerId ? doc.layers.get(currentLayer.parentLayerId) : null;\n if (parentLayer) {\n const parentNode = parentLayer.nodes.find(n => n.id === currentLayer.parentNodeId);\n if (parentNode) {\n const nodeColor = parentNode.data.color || baseBgColor;\n // Add transparency to the parent node color for subtle effect\n return hexToRgba(nodeColor, 0.15);\n }\n }\n \n return baseBgColor;\n }, [chromaticImmersion, doc, currentLayerId, baseBgColor]);\n \n const bgColor = chromaticImmersion ? chromaticBgColor : baseBgColor;\n\n // ── Spatial index (for stage-level hit detection) ─────────────────────────\n const spatialIndexRef = useRef<RBushSpatialIndex | null>(null);\n useEffect(() => {\n if (flatNodes.length === 0) { spatialIndexRef.current?.clear(); return; }\n const idx = new RBushSpatialIndex();\n idx.bulkLoad(flatNodes.map(n => {\n const blobHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (n.width / 2) * 0.74);\n return {\n nodeId: n.id,\n bounds: {\n minX: n.x - n.width / 2, minY: n.y - blobHalfH,\n maxX: n.x + n.width / 2, maxY: n.y + blobHalfH,\n },\n };\n }));\n spatialIndexRef.current = idx;\n return () => { spatialIndexRef.current?.clear(); };\n }, [flatNodes]);\n\n // ── Konva renderer (resize + FPS) ─────────────────────────────────────────\n const {\n handleWheel: rendererHandleWheel,\n handleMouseDown: rendererHandleMouseDown,\n handleMouseMove: rendererHandleMouseMove,\n handleMouseUp: rendererHandleMouseUp,\n canvasWidth,\n canvasHeight,\n } = useKonvaRenderer({ containerRef, stageRef });\n\n // Keep canvasSizeRef in sync with the measured container size.\n // The fallback to containerRef.getBoundingClientRect covers the period before\n // the first ResizeObserver callback fires.\n const _cw = canvasWidth || containerRef.current?.getBoundingClientRect().width || 800;\n const _ch = canvasHeight || containerRef.current?.getBoundingClientRect().height || 600;\n canvasSizeRef.current = { width: _cw, height: _ch };\n\n // ── Individual node drag (RAF-throttled, matches visualli.ai) ────────────\n const handleDragStart = useCallback((nodeId: string) => {\n isDraggingRef.current = true;\n setIsDraggingState(true);\n setHoveredNode(null);\n const node = nodes.get(nodeId);\n if (node) dragStartPosRef.current.set(nodeId, { x: node.x, y: node.y });\n }, [nodes]);\n\n const handleDragMove = useCallback((nodeId: string, x: number, y: number) => {\n dragMoveLatestRef.current = { nodeId, x, y };\n if (dragMoveRafRef.current !== null) return;\n dragMoveRafRef.current = requestAnimationFrame(() => {\n dragMoveRafRef.current = null;\n const latest = dragMoveLatestRef.current;\n if (latest) { dragMoveLatestRef.current = null; updateNodePosition(latest.nodeId, latest.x, latest.y); }\n });\n }, [updateNodePosition]);\n\n const handleDragEnd = useCallback((nodeId: string, x: number, y: number) => {\n if (dragMoveRafRef.current !== null) { cancelAnimationFrame(dragMoveRafRef.current); dragMoveRafRef.current = null; }\n dragMoveLatestRef.current = null;\n isDraggingRef.current = false;\n setIsDraggingState(false);\n updateNodePosition(nodeId, x, y);\n // Update spatial index entry\n if (spatialIndexRef.current) {\n const node = nodes.get(nodeId);\n if (node) {\n const oldPos = dragStartPosRef.current.get(nodeId);\n if (oldPos) {\n const oldHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (node.width / 2) * 0.74);\n spatialIndexRef.current.remove(nodeId, {\n minX: oldPos.x - node.width / 2, minY: oldPos.y - oldHalfH,\n maxX: oldPos.x + node.width / 2, maxY: oldPos.y + oldHalfH,\n });\n }\n const newHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (node.width / 2) * 0.74);\n spatialIndexRef.current.insert(nodeId, {\n minX: x - node.width / 2, minY: y - newHalfH,\n maxX: x + node.width / 2, maxY: y + newHalfH,\n });\n }\n }\n dragStartPosRef.current.delete(nodeId);\n }, [updateNodePosition, nodes]);\n // Keep a ref to the latest fitToScreen so async callbacks (onComplete) always\n // call the most current version without re-creating the animation pipeline.\n const fitToScreenRef = useRef<() => void>(() => {});\n\n const fitToScreen = useCallback(() => {\n if (flatNodes.length === 0) return;\n if (isTransitioningRef.current) return; // animation is controlling viewport\n // Use the container's measured size (not window) so the fit is always\n // relative to the renderer's actual bounding box.\n const cw = canvasSizeRef.current.width || containerRef.current?.getBoundingClientRect().width || 800;\n const ch = canvasSizeRef.current.height || containerRef.current?.getBoundingClientRect().height || 600;\n const { centerX, centerY } = calculateFitView(flatNodes, cw, ch);\n // Root layer: always use 1.0 zoom to match visualli.ai reference behaviour.\n // calculateFitZoom for a single node or dense layout on a 1920-default canvas\n // produces zoom > 2 which triggers the auto-zoom-in threshold immediately.\n const isRootLayer = navStack.length <= 1;\n // Root layer: use 1.0 zoom to match visualli.ai reference behaviour.\n // Child layers use the bounding-box fit zoom (already clamped to [0.4, 5]).\n const zoomLevel = isRootLayer ? 1.0 : calculateFitView(flatNodes, cw, ch).zoomLevel;\n setCenter(centerX, centerY);\n setZoom(zoomLevel);\n }, [flatNodes, navStack.length, setCenter, setZoom]);\n\n // Keep ref in sync after every render so async callbacks always use latest closure\n fitToScreenRef.current = fitToScreen;\n\n useEffect(() => { fitToScreen(); }, [currentLayerId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Re-fit when the canvas is properly measured for the first time (the RAF in\n // useKonvaRenderer updates canvasWidth from 0 → container width asynchronously).\n const didFitAfterMeasureRef = useRef(false);\n useEffect(() => {\n if (!canvasWidth || didFitAfterMeasureRef.current) return;\n didFitAfterMeasureRef.current = true;\n fitToScreen();\n }, [canvasWidth, fitToScreen]);\n\n // ── Layer transitions ─────────────────────────────────────────────────────\n\n // Stores the target nav-back index so onSwapBack can read it\n const navBackTargetRef = useRef<number>(-1);\n\n const { zoomIntoLayer, zoomOutToParent, isTransitioning: isAnimating } = useKonvaLayerTransition({\n stageRef,\n canvasWrapperRef,\n onSwapLayer: (childLayerId) => {\n const childLayer = doc?.layers.get(childLayerId);\n if (!childLayer || !doc) return;\n setCurrentLayerId(childLayerId);\n setNavStack(prev => [...prev, { layerId: childLayerId, layer: childLayer, label: layerLabel(doc, childLayer, childLayerId) }]);\n onLayerChange?.(childLayerId, childLayer);\n },\n onSwapBack: () => {\n const targetIndex = navBackTargetRef.current;\n setNavStack(prev => {\n const newStack = prev.slice(0, targetIndex + 1);\n parentViewports.current = parentViewports.current.slice(0, targetIndex);\n const newLayerId = newStack[newStack.length - 1].layerId;\n setCurrentLayerId(newLayerId);\n onLayerChange?.(newLayerId, newStack[newStack.length - 1].layer);\n return newStack;\n });\n },\n onComplete: () => {\n setIsTransitioning(false);\n isTransitioningRef.current = false;\n // After every layer switch, snap to the fit view so zoom is always clean.\n // rAF ensures React has committed new node data before we compute the fit.\n requestAnimationFrame(() => { fitToScreenRef.current(); });\n },\n // GPU CSS-transform callbacks (matching visualli.ai exactly):\n onViewportFrame: (vp) => {\n lastAnimViewportRef.current = vp;\n const baseline = baselineTransformRef.current;\n const contentDiv = konvaContentDivRef.current;\n const { width, height } = canvasSizeRef.current;\n if (baseline && contentDiv) {\n const targetX = width / 2 - vp.centerX * vp.zoomLevel;\n const targetY = height / 2 - vp.centerY * vp.zoomLevel;\n const ratio = vp.zoomLevel / baseline.scaleX;\n const tx = targetX - baseline.x * ratio;\n const ty = targetY - baseline.y * ratio;\n contentDiv.style.transform = `translate(${tx}px, ${ty}px) scale(${ratio})`;\n } else {\n const stage = stageRef.current;\n if (stage) {\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.batchDraw();\n }\n }\n },\n onViewportFinal: (vp) => {\n if (konvaContentDivRef.current) konvaContentDivRef.current.style.transform = '';\n const stage = stageRef.current;\n if (stage) {\n const { width, height } = canvasSizeRef.current;\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n }\n setCenter(vp.centerX, vp.centerY);\n setZoom(vp.zoomLevel);\n },\n onPhaseChange: (phase) => {\n const stage = stageRef.current;\n const contentDiv = konvaContentDivRef.current;\n if (stage && contentDiv && (phase === 'swap' || phase === 'zoom-back')) {\n contentDiv.style.transform = '';\n const vp = phase === 'zoom-back' ? zoomOutTargetRef.current : lastAnimViewportRef.current;\n if (vp) {\n const { width, height } = canvasSizeRef.current;\n const nx = width / 2 - vp.centerX * vp.zoomLevel;\n const ny = height / 2 - vp.centerY * vp.zoomLevel;\n stage.x(nx); stage.y(ny);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n baselineTransformRef.current = { x: nx, y: ny, scaleX: vp.zoomLevel, scaleY: vp.zoomLevel };\n }\n }\n },\n onTransitionLifecycle: (phase) => {\n const stage = stageRef.current;\n if (phase === 'start') {\n if (canvasWrapperRef.current) canvasWrapperRef.current.style.willChange = 'opacity, transform';\n if (stage) {\n baselineTransformRef.current = { x: stage.x(), y: stage.y(), scaleX: stage.scaleX(), scaleY: stage.scaleY() };\n const container = stage.container();\n const cd = container?.querySelector('.konvajs-content') as HTMLDivElement | null;\n if (cd) {\n konvaContentDivRef.current = cd;\n cd.style.transformOrigin = '0 0';\n cd.style.willChange = 'transform';\n }\n stage.getLayers().forEach(l => { l.listening(false); });\n }\n } else {\n if (canvasWrapperRef.current) canvasWrapperRef.current.style.willChange = 'auto';\n if (konvaContentDivRef.current) { konvaContentDivRef.current.style.willChange = 'auto'; konvaContentDivRef.current = null; }\n baselineTransformRef.current = null;\n zoomOutTargetRef.current = null;\n if (stage) {\n stage.getLayers().forEach(l => { l.listening(true); });\n stage.batchDraw();\n }\n }\n },\n });\n\n const handleNavigate = useCallback((nodeId: string) => {\n if (!doc || !currentLayerId) {\n return;\n }\n if (isTransitioningRef.current || isAnimating()) {\n return;\n }\n\n const childLayer = getChildLayerForNode(doc, nodeId, currentLayerId);\n if (!childLayer) {\n return;\n }\n const childLayerId = [...doc.layers.entries()].find(([, l]) => l === childLayer)?.[0];\n if (!childLayerId) {\n return;\n }\n const childNodes = (() => { try { return getNodesForLayer(doc, childLayerId); } catch { return []; } })();\n if (childNodes.length === 0) {\n return;\n }\n\n const node = nodes.get(nodeId);\n if (!node) return;\n\n // Save the FIT viewport for this layer (not the current scroll position).\n // This ensures navigating back always returns to a clean, properly-zoomed view\n // rather than the arbitrary zoom that happened to trigger the navigation.\n const cw = canvasSizeRef.current.width || 800;\n const ch = canvasSizeRef.current.height || 600;\n const fitVp = calculateFitView(flatNodes, cw, ch);\n const isRootNow = navStack.length <= 1;\n parentViewports.current.push({ centerX: fitVp.centerX, centerY: fitVp.centerY, zoomLevel: isRootNow ? 0.85 : fitVp.zoomLevel });\n\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n\n zoomIntoLayer(\n doc, node, childLayerId, childNodes,\n node.color ?? getThemeBackground(isDark, 'secondary'),\n node.color ?? getThemeBackground(isDark, 'primary'),\n );\n }, [doc, currentLayerId, nodes, isDark, isAnimating, zoomIntoLayer]);\n\n const handleNavigateBack = useCallback((targetIndex: number) => {\n if (targetIndex >= navStack.length - 1) return;\n if (isTransitioningRef.current || isAnimating()) return;\n const savedVp = parentViewports.current[targetIndex];\n if (!savedVp) return;\n navBackTargetRef.current = targetIndex;\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n zoomOutToParent(savedVp, getThemeBackground(isDark, 'primary'), getThemeBackground(isDark, 'secondary'));\n }, [navStack.length, isDark, isAnimating, zoomOutToParent]);\n\n // ── Auto-zoom navigation (Google Maps style) ──────────────────────────────\n const baseZoomRef = useRef(1.0);\n const lastZoomTransitionRef = useRef(0);\n const ZOOM_COOLDOWN = 1000;\n\n useEffect(() => { baseZoomRef.current = 1.0; }, [currentLayerId]);\n\n useEffect(() => {\n if (isTransitioningRef.current || isAnimating()) return;\n const now = Date.now();\n if (now - lastZoomTransitionRef.current < ZOOM_COOLDOWN) return;\n const relative = viewport.zoomLevel / baseZoomRef.current;\n\n if (relative >= ZOOM_NAV_IN_THRESHOLD) {\n // Zoom in threshold — drill into closest node\n let closest: FlatNode | null = null;\n let minDist = Infinity;\n for (const node of nodes.values()) {\n const dx = node.x - viewport.centerX;\n const dy = node.y - viewport.centerY;\n const d = dx * dx + dy * dy;\n if (d < minDist) { minDist = d; closest = node; }\n }\n if (closest) {\n const childLayer = doc ? getChildLayerForNode(doc, closest.id, currentLayerId ?? '') : null;\n if (childLayer) {\n lastZoomTransitionRef.current = now;\n handleNavigate(closest.id);\n baseZoomRef.current = 1.0;\n }\n }\n } else if (relative < ZOOM_NAV_OUT_THRESHOLD && navStack.length > 1) {\n // Zoom out threshold — go back to parent\n lastZoomTransitionRef.current = now;\n handleNavigateBack(navStack.length - 2);\n baseZoomRef.current = 1.0;\n }\n }, [viewport.zoomLevel, viewport.centerX, viewport.centerY, nodes, doc, currentLayerId, navStack, isAnimating, handleNavigate, handleNavigateBack]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Stage-level hit detection ─────────────────────────────────────────────\n const toWorldCoords = useCallback((stage: Konva.Stage, pointer: { x: number; y: number }) => {\n const sp = stage.position();\n const sc = stage.scaleX();\n return { worldX: (pointer.x - sp.x) / sc, worldY: (pointer.y - sp.y) / sc };\n }, []);\n\n const hitTestNode = useCallback((worldX: number, worldY: number): string | null => {\n if (!spatialIndexRef.current) return null;\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n if (!hits.length) return null;\n let targetId: string | null = null, minDist = Infinity;\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (!node) continue;\n const d = (worldX - node.x) ** 2 + (worldY - node.y) ** 2;\n if (d < minDist) { minDist = d; targetId = nodeId; }\n }\n return targetId;\n }, [nodes]);\n\n // Stage pointer interaction state\n const stageActiveNodeIdRef = useRef<string | null>(null);\n const stageDragNodeOffsetRef = useRef({ x: 0, y: 0 });\n const stageMouseDownPosRef = useRef<{ x: number; y: number } | null>(null);\n const stageDragCommittedRef = useRef(false);\n const stageLastPointerCheckRef = useRef<number>(0);\n const pointerNodeIdRef = useRef<string | null>(null);\n const isCanvasPanningRef = useRef(false);\n const isDraggingRef = useRef(false);\n\n const [pointerNodeId, setPointerNodeId] = useState<string | null>(null);\n const [pressedNodeId, setPressedNodeId] = useState<string | null>(null);\n const [isDraggingState, setIsDraggingState] = useState(false);\n\n // ── Node hover tooltip ────────────────────────────────────────────────────\n const [hoveredNode, setHoveredNode] = useState<{\n nodeId: string; summary: string; screenX: number; screenY: number;\n } | null>(null);\n\n const tooltipHoverRef = useRef(false);\n const keepTooltipOpenRef = useRef(false); // External request to keep tooltip open (e.g., from extensions)\n const clearTooltipTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const hoveredNodePosition = useMemo(() => {\n if (!hoveredNode) return null;\n const node = nodes.get(hoveredNode.nodeId);\n if (!node) return null;\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n return {\n screenX: (node.x - viewport.centerX) * viewport.zoomLevel + cw / 2,\n screenY: (node.y - viewport.centerY) * viewport.zoomLevel + ch / 2,\n zoom: viewport.zoomLevel,\n };\n }, [hoveredNode, nodes, viewport]);\n\n // ── Context menu ──────────────────────────────────────────────────────────\n const [canvasContextMenu, setCanvasContextMenu] = useState<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!canvasContextMenu) return;\n const close = () => setCanvasContextMenu(null);\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); };\n window.addEventListener('pointerdown', close);\n window.addEventListener('keydown', onKey);\n return () => { window.removeEventListener('pointerdown', close); window.removeEventListener('keydown', onKey); };\n }, [canvasContextMenu]);\n\n // ── Stage event handlers ──────────────────────────────────────────────────\n const handleStageMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n if (e.evt.button !== 0) { rendererHandleMouseDown(e); return; }\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseDown(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseDown(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const nodeId = hitTestNode(worldX, worldY);\n if (nodeId) {\n const node = nodes.get(nodeId);\n if (node) {\n select(nodeId);\n stageActiveNodeIdRef.current = nodeId;\n stageDragNodeOffsetRef.current = { x: worldX - node.x, y: worldY - node.y };\n stageMouseDownPosRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n stageDragCommittedRef.current = false;\n setPressedNodeId(nodeId);\n setHoveredNode(null);\n return;\n }\n }\n setHoveredNode(null);\n isCanvasPanningRef.current = true;\n rendererHandleMouseDown(e);\n }, [hitTestNode, toWorldCoords, nodes, select, rendererHandleMouseDown]);\n\n const handleStageMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseMove(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseMove(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n\n if (stageActiveNodeIdRef.current && stageMouseDownPosRef.current) {\n const moved = Math.hypot(e.evt.clientX - stageMouseDownPosRef.current.x, e.evt.clientY - stageMouseDownPosRef.current.y);\n if (!stageDragCommittedRef.current && moved >= 5) {\n stageDragCommittedRef.current = true;\n isDraggingRef.current = true;\n setIsDraggingState(true);\n pointerNodeIdRef.current = null;\n setPointerNodeId(null);\n handleDragStart(stageActiveNodeIdRef.current);\n }\n if (stageDragCommittedRef.current) {\n const offset = stageDragNodeOffsetRef.current;\n handleDragMove(stageActiveNodeIdRef.current, worldX - offset.x, worldY - offset.y);\n stage.container().style.cursor = 'grabbing';\n return;\n }\n return;\n }\n\n // During canvas pan — just apply the pan, skip hover detection to avoid re-renders\n if (isCanvasPanningRef.current) {\n rendererHandleMouseMove(e);\n return;\n }\n\n // Throttled hover detection (only when not panning or dragging)\n const now = performance.now();\n if (now - stageLastPointerCheckRef.current >= 50) {\n stageLastPointerCheckRef.current = now;\n const hovered = hitTestNode(worldX, worldY);\n if (hovered !== pointerNodeIdRef.current) {\n pointerNodeIdRef.current = hovered;\n setPointerNodeId(hovered);\n }\n if (hovered) {\n stage.container().style.cursor = 'pointer';\n } else {\n stage.container().style.cursor = 'grab';\n }\n }\n\n rendererHandleMouseMove(e);\n }, [toWorldCoords, hitTestNode, handleDragStart, handleDragMove, rendererHandleMouseMove]);\n\n const handleStageMouseUp = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n setPressedNodeId(null);\n if (stageActiveNodeIdRef.current) {\n const nodeId = stageActiveNodeIdRef.current;\n if (stageDragCommittedRef.current) {\n // End drag — flush final world position\n const stage = e.target.getStage();\n if (stage) {\n const pointer = stage.getPointerPosition();\n if (pointer) {\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const offset = stageDragNodeOffsetRef.current;\n handleDragEnd(nodeId, worldX - offset.x, worldY - offset.y);\n }\n }\n } else {\n // Click — check if node has child layer (regardless of branchCount)\n const node = nodes.get(nodeId);\n if (node) {\n const childLayer = doc ? getChildLayerForNode(doc, nodeId, currentLayerId ?? '') : null;\n if (childLayer) {\n handleNavigate(nodeId);\n }\n onNodeClick?.(node);\n }\n }\n isDraggingRef.current = false;\n setIsDraggingState(false);\n stageActiveNodeIdRef.current = null;\n stageMouseDownPosRef.current = null;\n stageDragCommittedRef.current = false;\n return;\n }\n isCanvasPanningRef.current = false;\n rendererHandleMouseUp(e);\n }, [toWorldCoords, handleDragEnd, nodes, handleNavigate, onNodeClick, rendererHandleMouseUp]);\n\n const handleStageContextMenu = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n e.evt.preventDefault();\n if (navStack.length <= 1) { setCanvasContextMenu(null); return; }\n setCanvasContextMenu({ x: e.evt.clientX, y: e.evt.clientY });\n }, [navStack.length]);\n\n // Touch passthrough\n const handleStageTouchStart = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseDown(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseDown]);\n const handleStageTouchMove = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseMove(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseMove]);\n const handleStageTouchEnd = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseUp(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseUp]);\n\n // Wheel with auto-nav guard on non-root layers\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>) => {\n const isZoomOut = e.evt.deltaY > 0;\n if (!isZoomOut) { rendererHandleWheel(e); return; }\n\n const liveZoom = useViewportStore.getState().zoomLevel;\n const projected = Math.max(ZOOM_MIN, liveZoom * (1 - e.evt.deltaY / 1000));\n\n // Root layer: no parent to navigate to — let the user zoom freely down to ZOOM_MIN\n // (do NOT clamp at ZOOM_NAV_OUT_THRESHOLD; content may require lower zoom to fit)\n\n if (navStack.length > 1 && projected <= ZOOM_NAV_OUT_THRESHOLD && !isTransitioningRef.current && !isAnimating()) {\n e.evt.preventDefault();\n const now = Date.now();\n if (now - lastZoomTransitionRef.current >= ZOOM_COOLDOWN) {\n lastZoomTransitionRef.current = now;\n handleNavigateBack(navStack.length - 2);\n baseZoomRef.current = 1.0;\n }\n return;\n }\n rendererHandleWheel(e);\n }, [rendererHandleWheel, navStack, setZoom, isAnimating, handleNavigateBack]);\n\n // Canvas mouse move for description tooltip\n const lastHoverCheckRef = useRef(0);\n const handleCanvasMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (!containerRef.current || isDraggingRef.current || isCanvasPanningRef.current) {\n setHoveredNode(null);\n return;\n }\n const now = Date.now();\n if (now - lastHoverCheckRef.current < 50) return;\n lastHoverCheckRef.current = now;\n\n // Check if mouse is over a tooltip - if so, don't change hovered node\n const target = e.target as HTMLElement;\n const isOverTooltip = target.closest('[data-node-tooltip=\"true\"]') || target.closest('[data-semantic-tooltip=\"true\"]');\n \n // If tooltip is open and we're hovering it or keeping it open, don't detect new nodes\n if (tooltipHoverRef.current || keepTooltipOpenRef.current || isOverTooltip) {\n return;\n }\n\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n // e.clientX is viewport-relative; subtract the container's left/top offset\n // so world-coordinate conversion is correct when the renderer isn't full-screen.\n const rect = containerRef.current?.getBoundingClientRect();\n const localX = rect ? e.clientX - rect.left : e.clientX;\n const localY = rect ? e.clientY - rect.top : e.clientY;\n const worldX = (localX - cw / 2) / viewport.zoomLevel + viewport.centerX;\n const worldY = (localY - ch / 2) / viewport.zoomLevel + viewport.centerY;\n\n // Use RBush spatial index for O(log n) hit detection\n let found = false;\n if (spatialIndexRef.current) {\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (node?.description) {\n setHoveredNode({ nodeId: node.id, summary: node.description, screenX: e.clientX, screenY: e.clientY });\n found = true;\n break;\n }\n }\n }\n if (!found) {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) setHoveredNode(null);\n }, 150);\n } else {\n if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; }\n }\n }, [nodes, viewport, spatialIndexRef]);\n\n // Listen for external requests to keep tooltip open (e.g., from extensions)\n useEffect(() => {\n const handleKeepTooltipOpen = (event: CustomEvent) => {\n keepTooltipOpenRef.current = event.detail.keep;\n };\n \n // @ts-ignore - custom event\n window.addEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen);\n \n return () => {\n // @ts-ignore - custom event\n window.removeEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen);\n };\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n spatialIndexRef.current?.clear();\n if (dragMoveRafRef.current !== null) cancelAnimationFrame(dragMoveRafRef.current);\n };\n }, []);\n\n // ── Zoom controls ─────────────────────────────────────────────────────────\n const handleZoomIn = useCallback(() => setZoom(Math.min(viewport.zoomLevel * 1.2, 5)), [viewport.zoomLevel, setZoom]);\n const handleZoomOut = useCallback(() => {\n // Non-root: allow zoom to ZOOM_MIN so the wheel-driven ZOOM_NAV_OUT_THRESHOLD\n // transition can still trigger via scroll; button just navigates zoom value.\n // Root: also ZOOM_MIN (no parent layer to navigate to, allow full zoom-out).\n setZoom(Math.max(viewport.zoomLevel / 1.2, ZOOM_MIN));\n }, [viewport.zoomLevel, setZoom]);\n\n // Extension rendering removed - not part of open spec\n\n // ── Render ────────────────────────────────────────────────────────────────\n if (!doc) {\n return (\n <div className={className} style={{ position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center', background: bgColor, ...style }}>\n <span style={{ color: isDark ? 'rgba(255,255,255,0.4)' : 'rgba(0,0,0,0.3)', fontSize: 14 }}>No document</span>\n </div>\n );\n }\n\n const hasBackOption = navStack.length > 1;\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ \n position: 'relative', \n overflow: 'hidden', \n userSelect: 'none', \n background: bgColor, \n width: '100%', \n height: '100%', \n ...style \n }}\n onMouseMove={handleCanvasMouseMove}\n onMouseLeave={() => {\n // Only close tooltip on mouse leave if not keeping it open\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) {\n setHoveredNode(null);\n }\n }}\n >\n {/* Konva canvas — opacity driven imperatively during transitions */}\n <div ref={canvasWrapperRef} style={{ position: 'relative', zIndex: 1, pointerEvents: 'auto' }}>\n <KonvaStage\n ref={stageRef}\n onWheel={handleWheel}\n onMouseDown={handleStageMouseDown}\n onMouseMove={handleStageMouseMove}\n onMouseUp={handleStageMouseUp}\n onContextMenu={handleStageContextMenu}\n onTouchStart={handleStageTouchStart}\n onTouchMove={handleStageTouchMove}\n onTouchEnd={handleStageTouchEnd}\n >\n <KonvaContainerLayer nodes={flatNodes} containers={containers} isDark={isDark} />\n <KonvaEdgeLayer \n nodes={flatNodes} \n connections={connections} \n isDark={isDark} \n isDragging={isDraggingState} \n />\n <KonvaNodeLayer\n isTransitioning={isTransitioning}\n isDragging={isDraggingState}\n hoveredNodeId={pointerNodeId}\n pressedNodeId={pressedNodeId}\n />\n </KonvaStage>\n </div>\n\n {/* Context menu (right-click to go back) */}\n {canvasContextMenu && hasBackOption && (\n <div\n role=\"menu\"\n aria-label=\"Canvas options\"\n style={{\n position: 'fixed',\n zIndex: 60,\n pointerEvents: 'auto',\n left: `${Math.min(canvasContextMenu.x, Math.max(8, (canvasSizeRef.current.width || 800) - 152))}px`,\n top: `${Math.min(canvasContextMenu.y, Math.max(8, (canvasSizeRef.current.height || 600) - 72))}px`,\n }}\n onContextMenu={e => e.preventDefault()}\n onPointerDown={e => e.stopPropagation()}\n >\n <button\n type=\"button\"\n style={{\n padding: '6px 16px',\n borderRadius: '10px',\n border: `1px solid ${isDark ? '#333330' : '#DDD9D0'}`,\n background: isDark ? '#1C1C1A' : '#FAF8F4',\n color: isDark ? '#F0EDE6' : '#1A1A18',\n cursor: 'pointer',\n fontSize: 13,\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\n }}\n onClick={() => { setCanvasContextMenu(null); handleNavigateBack(navStack.length - 2); }}\n >\n Back\n </button>\n </div>\n )}\n\n {/* Navigation stack (left, matches reference) */}\n <NavigationStack stack={navStack} onNavigateBack={handleNavigateBack} isDark={isDark} top={navigationStackTop} left={navigationStackLeft} />\n\n {/* Zoom controls (top-right) */}\n <div data-help=\"zoom-controls\" style={{ position: 'absolute', top: '24px', right: '16px', zIndex: 50, pointerEvents: 'auto' }}>\n <ZoomControls isDark={isDark} />\n </div>\n\n {/* Custom overlay from consuming app (for private features like help button, chromatic bg, etc.) */}\n {renderOverlay?.({ isDark, containerWidth: canvasSizeRef.current.width || 0, containerHeight: canvasSizeRef.current.height || 0 })}\n\n {/* Node description tooltip (sketchy-box, above node) - rendered before extensions so extensions appear on top */}\n {hoveredNode && hoveredNodePosition && viewport.zoomLevel < 3 && viewport.zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM && (() => {\n const nodeData = nodes.get(hoveredNode.nodeId);\n const borderColor = nodeData?.color ? darkenHexColor(nodeData.color, 0.13) : '#5BA8D4';\n const VP_PAD = 8;\n const HALF_W = 160;\n const APPROX_H = 90;\n const containerW = canvasSizeRef.current.width || 800;\n const safeLeft = Math.max(HALF_W + VP_PAD, Math.min(hoveredNodePosition.screenX, containerW - HALF_W - VP_PAD));\n const rawTop = hoveredNodePosition.screenY - 60 * hoveredNodePosition.zoom;\n const safeTop = Math.max(VP_PAD + APPROX_H, rawTop);\n return (\n <div\n data-node-tooltip=\"true\"\n style={{\n position: 'fixed',\n zIndex: 50,\n left: safeLeft,\n top: safeTop,\n transform: 'translate(-50%, -100%)',\n transformOrigin: 'bottom center',\n pointerEvents: 'auto',\n }}\n onMouseEnter={() => { tooltipHoverRef.current = true; if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; } }}\n onMouseLeave={() => { \n tooltipHoverRef.current = false; \n // Delay clearing to allow external extensions to request keeping tooltip open\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!keepTooltipOpenRef.current) setHoveredNode(null);\n }, 100);\n }}\n >\n <div style={{ maxWidth: '20rem', minWidth: '12rem', maxHeight: '15rem', overflowY: 'auto' }}>\n <SketchyBoxKonva fill=\"#ffffff\" stroke={borderColor} backStroke={borderColor} padding=\"1rem 1.25rem\">\n <p style={{\n fontFamily: \"'Playpen Sans', cursive\",\n fontSize: `${DESCRIPTION_TEXT_BASE_FONT_PX}px`,\n fontWeight: 300,\n color: '#000000',\n textAlign: 'center',\n lineHeight: 1.6,\n margin: 0,\n }}>\n {renderNodeContent ? renderNodeContent({ \n summary: hoveredNode.summary, \n nodeId: hoveredNode.nodeId,\n nodeColor: nodeData?.color,\n zoom: viewport.zoomLevel,\n }) : hoveredNode.summary}\n </p>\n </SketchyBoxKonva>\n </div>\n </div>\n );\n })()}\n </div>\n );\n}\n","// ─── Node Store ───────────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { FlatNode, NodeMap } from '@visualli/core';\n\nexport interface INodeStore {\n nodes: NodeMap;\n childrenIndex: Map<string | null, Set<string>>;\n\n setNodes: (nodes: NodeMap) => void;\n updateNode: (nodeId: string, updates: Partial<FlatNode>) => void;\n updateNodePosition: (nodeId: string, x: number, y: number) => void;\n addNode: (node: FlatNode) => void;\n removeNode: (nodeId: string) => void;\n setNodeExpanded: (nodeId: string, expanded: boolean) => void;\n\n getNode: (nodeId: string) => FlatNode | undefined;\n getChildren: (parentId: string | null) => FlatNode[];\n getChildrenIds: (parentId: string | null) => Set<string>;\n getAllNodes: () => FlatNode[];\n}\n\nfunction buildChildrenIndex(nodes: NodeMap): Map<string | null, Set<string>> {\n const index = new Map<string | null, Set<string>>();\n for (const node of nodes.values()) {\n const pid = node.parentId ?? null;\n if (!index.has(pid)) index.set(pid, new Set());\n index.get(pid)!.add(node.id);\n }\n return index;\n}\n\nexport const useNodeStore = create<INodeStore>((set, get) => ({\n nodes: new Map(),\n childrenIndex: new Map(),\n\n setNodes: (nodes) =>\n set({ nodes, childrenIndex: buildChildrenIndex(nodes) }),\n\n updateNode: (nodeId, updates) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, ...updates, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n updateNodePosition: (nodeId, x, y) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node || (node.x === x && node.y === y)) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, x, y });\n return { nodes: next };\n }),\n\n addNode: (node) =>\n set((s) => {\n const next = new Map(s.nodes);\n next.set(node.id, node);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (!idx.has(pid)) idx.set(pid, new Set());\n idx.get(pid)!.add(node.id);\n return { nodes: next, childrenIndex: idx };\n }),\n\n removeNode: (nodeId) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.delete(nodeId);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (idx.has(pid)) {\n const set = new Set(idx.get(pid)!);\n set.delete(nodeId);\n if (set.size === 0) idx.delete(pid); else idx.set(pid, set);\n }\n return { nodes: next, childrenIndex: idx };\n }),\n\n setNodeExpanded: (nodeId, expanded) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, isExpanded: expanded, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n getNode: (nodeId) => get().nodes.get(nodeId),\n getChildren: (pid) => {\n const { nodes, childrenIndex } = get();\n return Array.from(childrenIndex.get(pid) ?? []).map(id => nodes.get(id)!).filter(Boolean);\n },\n getChildrenIds: (pid) => get().childrenIndex.get(pid) ?? new Set(),\n getAllNodes: () => Array.from(get().nodes.values()),\n}));\n","// ─── Viewport Store ───────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { ViewportState } from '@visualli/core';\nimport {\n panViewport,\n zoomViewport,\n setViewportCenter,\n recalculateViewportBounds,\n clampZoom,\n DEFAULT_CANVAS_WIDTH,\n DEFAULT_CANVAS_HEIGHT,\n worldToScreen,\n screenToWorld,\n ZOOM_DEFAULT,\n} from '@visualli/core';\n\nexport interface IViewportStore extends ViewportState {\n canvasWidth: number;\n canvasHeight: number;\n\n pan: (deltaX: number, deltaY: number) => void;\n zoom: (delta: number, pivotX?: number, pivotY?: number) => void;\n setCenter: (x: number, y: number) => void;\n setZoom: (level: number) => void;\n updateCanvasSize: (width: number, height: number) => void;\n\n getVisibleBounds: () => ViewportState['visibleBounds'];\n worldToScreen: (x: number, y: number) => { x: number; y: number };\n screenToWorld: (x: number, y: number) => { x: number; y: number };\n}\n\nfunction makeInitial(w: number, h: number): ViewportState {\n const vp: ViewportState = {\n centerX: 0, centerY: 0,\n zoomLevel: ZOOM_DEFAULT,\n rotation: 0,\n visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 },\n };\n return recalculateViewportBounds(vp, w, h);\n}\n\nconst getVP = (s: IViewportStore): ViewportState => ({\n centerX: s.centerX, centerY: s.centerY,\n zoomLevel: s.zoomLevel, rotation: s.rotation,\n visibleBounds: s.visibleBounds,\n});\n\nexport const useViewportStore = create<IViewportStore>((set, get) => {\n const init = makeInitial(DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT);\n return {\n ...init,\n canvasWidth: DEFAULT_CANVAS_WIDTH,\n canvasHeight: DEFAULT_CANVAS_HEIGHT,\n\n pan: (dx, dy) => set((s) => {\n const updated = recalculateViewportBounds(panViewport(dx, dy, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n zoom: (delta, pivotX, pivotY) => set((s) => {\n const updated = recalculateViewportBounds(\n zoomViewport(delta, getVP(s), pivotX, pivotY, s.canvasWidth, s.canvasHeight),\n s.canvasWidth, s.canvasHeight,\n );\n return { centerX: updated.centerX, centerY: updated.centerY, zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n setCenter: (x, y) => set((s) => {\n const updated = recalculateViewportBounds(setViewportCenter(x, y, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n setZoom: (level) => set((s) => {\n const clamped = clampZoom(level);\n const updated = recalculateViewportBounds({ ...getVP(s), zoomLevel: clamped }, s.canvasWidth, s.canvasHeight);\n return { zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n updateCanvasSize: (w, h) => set((s) => {\n const updated = recalculateViewportBounds(getVP(s), w, h);\n return { canvasWidth: w, canvasHeight: h, visibleBounds: updated.visibleBounds };\n }),\n\n getVisibleBounds: () => get().visibleBounds,\n worldToScreen: (x, y) => {\n const s = get();\n return worldToScreen(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n screenToWorld: (x, y) => {\n const s = get();\n return screenToWorld(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n };\n});\n","// ─── Selection Store ──────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport { selectionStore, renderConfigStore } from '@visualli/core';\nimport type { ISelectionStore, IRenderConfigStore } from '@visualli/core';\n\nexport const useSelectionStore = create<ISelectionStore>((set, get, store) => {\n selectionStore.subscribe((state) => set(state));\n return selectionStore.getState();\n});\n\n// ─── Render Config Store ──────────────────────────────────────────────────────\n\nexport const useRenderConfigStore = create<IRenderConfigStore>((set, get, store) => {\n renderConfigStore.subscribe((state) => set(state));\n return renderConfigStore.getState();\n});\n","// ─── useKonvaRenderer ─────────────────────────────────────────────────────────\n//\n// Manages Konva rendering lifecycle: resize, pan, zoom, and FPS monitoring.\n// Returns Konva-level event handlers to be wired onto KonvaStage.\n//\n// Design matches visualli.ai's useKonvaRenderer:\n// - handleWheel / handleMouseDown / handleMouseMove / handleMouseUp are\n// Konva.KonvaEventObject handlers (not DOM-level)\n// - Pan is applied directly to the stage during drag for 60 fps, flushed to\n// Zustand store on mouseUp (no per-frame state updates)\n// - Zoom targets the cursor position (same math as visualli.ai)\n\nimport { useEffect, useCallback, useRef, useState } from 'react';\nimport type Konva from 'konva';\nimport { ZOOM_MIN, ZOOM_MAX } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useRenderConfigStore } from '../stores/stores';\n\nexport interface UseKonvaRendererOptions {\n containerRef: React.RefObject<HTMLDivElement | null>;\n stageRef?: React.RefObject<Konva.Stage | null>;\n enabled?: boolean;\n}\n\nexport interface UseKonvaRendererReturn {\n handleWheel: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n handleMouseDown:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseMove:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseUp: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n canvasWidth: number;\n canvasHeight: number;\n}\n\nexport function useKonvaRenderer({\n containerRef,\n stageRef,\n enabled = true,\n}: UseKonvaRendererOptions): UseKonvaRendererReturn {\n const pan = useViewportStore(s => s.pan);\n const zoom = useViewportStore(s => s.zoom);\n const setZoom = useViewportStore(s => s.setZoom);\n const setCenter = useViewportStore(s => s.setCenter);\n const updateCanvasSize = useViewportStore(s => s.updateCanvasSize);\n const autoAdjust = useRenderConfigStore(s => s.autoAdjustQuality);\n\n const [canvasWidth, setCanvasWidth] = useState(0);\n const [canvasHeight, setCanvasHeight] = useState(0);\n const cachedSizeRef = useRef({ width: 0, height: 0 });\n\n const isPanningRef = useRef(false);\n const lastPanPointRef = useRef({ x: 0, y: 0 });\n const panAccumRef = useRef({ x: 0, y: 0 });\n\n // ── FPS monitor ──────────────────────────────────────────────────────────────\n const fpsRef = useRef({ frames: 0, last: performance.now() });\n const fpsRafId = useRef<number | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n const tick = (now: number): void => {\n fpsRef.current.frames++;\n if (now - fpsRef.current.last >= 2000) {\n const fps = (fpsRef.current.frames / ((now - fpsRef.current.last) / 1000)) | 0;\n autoAdjust(fps);\n fpsRef.current = { frames: 0, last: now };\n }\n fpsRafId.current = requestAnimationFrame(tick);\n };\n fpsRafId.current = requestAnimationFrame(tick);\n return () => { if (fpsRafId.current !== null) cancelAnimationFrame(fpsRafId.current); };\n }, [enabled, autoAdjust]);\n\n // ── Resize ────────────────────────────────────────────────────────────────────\n // Observes the container element (not window) so the canvas always fills\n // its parent, regardless of how the renderer is sized by the consuming app.\n useEffect(() => {\n if (!enabled) return;\n\n let rafId: number | null = null;\n\n const measure = () => {\n const el = containerRef.current;\n const w = el ? Math.round(el.getBoundingClientRect().width) : 800;\n const h = el ? Math.round(el.getBoundingClientRect().height) : 600;\n return { w, h };\n };\n\n const updateSize = () => {\n if (rafId) cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(() => {\n rafId = null;\n const { w, h } = measure();\n if (w > 0 && h > 0 &&\n (cachedSizeRef.current.width !== w || cachedSizeRef.current.height !== h)) {\n cachedSizeRef.current = { width: w, height: h };\n setCanvasWidth(w);\n setCanvasHeight(h);\n updateCanvasSize(w, h);\n }\n });\n };\n\n // Initial measurement\n updateSize();\n\n // ResizeObserver tracks the container itself (handles % / flex / grid sizing)\n let ro: ResizeObserver | null = null;\n if (typeof ResizeObserver !== 'undefined' && containerRef.current) {\n ro = new ResizeObserver(updateSize);\n ro.observe(containerRef.current);\n } else {\n // Fallback: window resize only\n window.addEventListener('resize', updateSize);\n }\n\n return () => {\n ro ? ro.disconnect() : window.removeEventListener('resize', updateSize);\n if (rafId) cancelAnimationFrame(rafId);\n };\n }, [enabled, containerRef, updateCanvasSize]);\n\n // ── Wheel zoom ────────────────────────────────────────────────────────────────\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>): void => {\n e.evt.preventDefault();\n const stage = e.target.getStage();\n if (!stage) return;\n const pointer = stage.getPointerPosition();\n if (!pointer) return;\n const delta = -e.evt.deltaY / 1000;\n zoom(delta, pointer.x, pointer.y);\n }, [zoom]);\n\n // ── Mouse pan ─────────────────────────────────────────────────────────────────\n const handleMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n const clickedOnEmpty = e.target === e.target.getStage();\n if (clickedOnEmpty && e.evt.button === 0) {\n e.evt.preventDefault();\n isPanningRef.current = true;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n panAccumRef.current = { x: 0, y: 0 };\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = 'grabbing';\n }\n }, []);\n\n const handleMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n if (!isPanningRef.current) {\n // Update cursor on empty canvas\n const isOverEmpty = e.target === e.target.getStage();\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = isOverEmpty ? 'grab' : 'default';\n return;\n }\n e.evt.preventDefault();\n const deltaX = e.evt.clientX - lastPanPointRef.current.x;\n const deltaY = e.evt.clientY - lastPanPointRef.current.y;\n\n // Apply pan directly to stage (no Zustand overhead per-frame)\n const stage = e.target.getStage();\n if (stage) {\n stage.x(stage.x() + deltaX);\n stage.y(stage.y() + deltaY);\n stage.batchDraw();\n }\n\n panAccumRef.current.x += deltaX;\n panAccumRef.current.y += deltaY;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n }, []); // No Zustand dep — pan flushed on mouseUp\n\n const handleMouseUp = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n if (isPanningRef.current) {\n isPanningRef.current = false;\n const { x, y } = panAccumRef.current;\n if (x !== 0 || y !== 0) {\n pan(x, y);\n panAccumRef.current = { x: 0, y: 0 };\n }\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = 'grab';\n }\n }, [pan]);\n\n return { handleWheel, handleMouseDown, handleMouseMove, handleMouseUp, canvasWidth, canvasHeight };\n}\n","// ─── useKonvaLayerTransition ──────────────────────────────────────────────────\n//\n// Manages layer navigation animations (zoom into child layer, zoom back to\n// parent). Uses the same callback-driven pattern as the visualli.ai reference:\n// - onViewportChange: imperatively updates the Konva stage each rAF frame\n// - onOpacityChange: writes directly to canvasWrapperRef DOM (no React state)\n// - onBackgroundColorChange: writes directly to bgRef DOM\n// - onPhaseChange('swap'|'zoom-back'): triggers React layer content swap\n// - onComplete: syncs final viewport to Zustand and ends transition\n\nimport { useCallback, useRef, useEffect } from 'react';\nimport type Konva from 'konva';\nimport type { VisualliDocument, FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { konvaLayerTransitionAnimator } from '../animations/konvaLayerTransition';\nimport type { AnimatorViewport } from '../animations/konvaLayerTransition';\nimport { calculateFitView } from '../utils/layerNavigation';\n\nexport interface LayerTransitionOptions {\n /** Ref to the Konva Stage for imperative position/scale updates each frame. */\n stageRef: React.RefObject<Konva.Stage | null>;\n /** Ref to the wrapping div whose CSS `opacity` is driven during transitions. */\n canvasWrapperRef: React.RefObject<HTMLDivElement | null>;\n /** Ref to the background color div. */\n bgRef?: React.RefObject<HTMLDivElement | null>;\n /** Called at the content-swap point — use to switch the displayed layer. */\n onSwapLayer: (newLayerId: string) => void;\n /** Called when a zoom-out swap happens — use to update the nav stack. */\n onSwapBack: () => void;\n /** Called after the transition fully completes. */\n onComplete: () => void;\n /**\n * GPU CSS-transform mode: called each rAF frame instead of applyViewport.\n * When provided, the caller is responsible for moving the canvas content.\n */\n onViewportFrame?: (vp: AnimatorViewport) => void;\n /**\n * Called once when the animation reaches its final viewport.\n * When provided, replaces the default applyViewport call at completion.\n */\n onViewportFinal?: (vp: AnimatorViewport) => void;\n /**\n * Called at phase-change points ('swap', 'zoom-back') in addition to the\n * internal content-swap logic. Use to reset CSS transforms before Konva redraws.\n */\n onPhaseChange?: (phase: string) => void;\n /**\n * Called with 'start' before the animator fires its first frame and with\n * 'end' after onComplete. Use to set up / tear down GPU hints (willChange, etc.).\n */\n onTransitionLifecycle?: (phase: 'start' | 'end') => void;\n}\n\nexport interface LayerTransitionHandlers {\n zoomIntoLayer: (\n doc: VisualliDocument,\n targetNode: FlatNode,\n childLayerId: string,\n childNodes: FlatNode[],\n fromColor: string,\n toColor: string,\n ) => void;\n zoomOutToParent: (\n parentViewport: AnimatorViewport,\n fromColor: string,\n toColor: string,\n ) => void;\n isTransitioning: () => boolean;\n}\n\nexport function useKonvaLayerTransition(opts: LayerTransitionOptions): LayerTransitionHandlers {\n const {\n stageRef, canvasWrapperRef, bgRef,\n onSwapLayer, onSwapBack, onComplete,\n onViewportFrame, onViewportFinal, onPhaseChange: onPhaseChangeExt,\n onTransitionLifecycle,\n } = opts;\n const setZoom = useViewportStore(s => s.setZoom);\n const setCenter = useViewportStore(s => s.setCenter);\n const getState = useViewportStore.getState;\n\n const swappedRef = useRef(false);\n const canvasSizeRef = useRef({ width: 800, height: 600 });\n\n // Keep canvas size ref fresh from viewport store (updated by ResizeObserver in useKonvaRenderer)\n useEffect(() => {\n const update = () => {\n const vp = useViewportStore.getState();\n canvasSizeRef.current = { width: vp.canvasWidth || 800, height: vp.canvasHeight || 600 };\n };\n update();\n // Subscribe to viewport store changes instead of window resize\n const unsubscribe = useViewportStore.subscribe(update);\n return unsubscribe;\n }, []);\n\n // Apply viewport to Konva stage imperatively (no React re-render per frame)\n const applyViewport = useCallback((vp: AnimatorViewport) => {\n const stage = stageRef.current;\n if (!stage) return;\n const { width, height } = canvasSizeRef.current;\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel);\n stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n // Sync to Zustand so viewport store reflects reality\n setCenter(vp.centerX, vp.centerY);\n setZoom(vp.zoomLevel);\n }, [stageRef, setCenter, setZoom]);\n\n const applyOpacity = useCallback((opacity: number) => {\n if (canvasWrapperRef.current) {\n canvasWrapperRef.current.style.opacity = String(opacity);\n }\n }, [canvasWrapperRef]);\n\n const applyBgColor = useCallback((color: string) => {\n if (bgRef?.current) {\n bgRef.current.style.backgroundColor = color;\n }\n }, [bgRef]);\n\n const zoomIntoLayer = useCallback((\n _doc: VisualliDocument,\n targetNode: FlatNode,\n childLayerId: string,\n childNodes: FlatNode[],\n fromColor: string,\n toColor: string,\n ): void => {\n if (konvaLayerTransitionAnimator.active) return;\n\n const vp = getState();\n const stage = stageRef.current;\n const w = stage?.width() ?? 800;\n const h = stage?.height() ?? 600;\n const fit = calculateFitView(childNodes, w, h);\n\n swappedRef.current = false;\n\n onTransitionLifecycle?.('start');\n konvaLayerTransitionAnimator.animateZoomIntoLayer(\n { centerX: vp.centerX, centerY: vp.centerY, zoomLevel: vp.zoomLevel },\n { x: targetNode.x, y: targetNode.y, width: targetNode.width, height: targetNode.height },\n { x: fit.centerX, y: fit.centerY },\n fromColor,\n toColor,\n {\n onUpdate: ({ viewport, opacity, backgroundColor }) => {\n if (onViewportFrame) { onViewportFrame(viewport); } else { applyViewport(viewport); }\n applyOpacity(opacity);\n applyBgColor(backgroundColor);\n },\n onComplete: () => {\n const finalVp = { centerX: fit.centerX, centerY: fit.centerY, zoomLevel: fit.zoomLevel };\n if (onViewportFinal) { onViewportFinal(finalVp); } else { applyViewport(finalVp); }\n applyOpacity(1);\n onComplete();\n onTransitionLifecycle?.('end');\n },\n onPhaseChange: (phase) => {\n onPhaseChangeExt?.(phase);\n if (phase === 'swap' && !swappedRef.current) {\n swappedRef.current = true;\n onSwapLayer(childLayerId);\n }\n },\n },\n fit.zoomLevel,\n w,\n h,\n );\n }, [stageRef, getState, applyViewport, applyOpacity, applyBgColor, onSwapLayer, onComplete, onViewportFrame, onViewportFinal, onPhaseChangeExt, onTransitionLifecycle]);\n\n const zoomOutToParent = useCallback((\n parentViewport: AnimatorViewport,\n fromColor: string,\n toColor: string,\n ): void => {\n if (konvaLayerTransitionAnimator.active) return;\n\n const vp = getState();\n swappedRef.current = false;\n\n onTransitionLifecycle?.('start');\n konvaLayerTransitionAnimator.animateZoomOutToParent(\n { centerX: vp.centerX, centerY: vp.centerY, zoomLevel: vp.zoomLevel },\n parentViewport,\n fromColor,\n toColor,\n {\n onUpdate: ({ viewport, opacity, backgroundColor }) => {\n if (onViewportFrame) { onViewportFrame(viewport); } else { applyViewport(viewport); }\n applyOpacity(opacity);\n applyBgColor(backgroundColor);\n },\n onComplete: () => {\n if (onViewportFinal) { onViewportFinal(parentViewport); } else { applyViewport(parentViewport); }\n applyOpacity(1);\n onComplete();\n onTransitionLifecycle?.('end');\n },\n onPhaseChange: (phase) => {\n onPhaseChangeExt?.(phase);\n if (phase === 'zoom-back' && !swappedRef.current) {\n swappedRef.current = true;\n onSwapBack();\n }\n },\n },\n );\n }, [getState, applyViewport, applyOpacity, applyBgColor, onSwapBack, onComplete, onViewportFrame, onViewportFinal, onPhaseChangeExt, onTransitionLifecycle]);\n\n const isTransitioning = useCallback(() => konvaLayerTransitionAnimator.active, []);\n\n // Cancel on unmount\n useEffect(() => () => { konvaLayerTransitionAnimator.cancel(); }, []);\n\n return { zoomIntoLayer, zoomOutToParent, isTransitioning };\n}\n","// ─── Konva Layer Transition Animator ─────────────────────────────────────────\n//\n// rAF-driven animation engine for layer navigation:\n// animateZoomIntoLayer — camera-dive into child layer\n// animateZoomOutToParent — pull back to parent layer\n// animateCrossFade — simple cross-fade between two viewports\n//\n// No React dependencies — can be instantiated once and reused.\n\nimport { easeInOutSine, easeOutCubic, easeZoomTransition } from '@visualli/core';\nimport { ANIMATION_PHASES } from '@visualli/core';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface AnimatorViewport {\n centerX: number;\n centerY: number;\n zoomLevel: number;\n}\n\nexport interface NodeBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface TransitionCallbacks {\n onUpdate: (state: { viewport: AnimatorViewport; opacity: number; backgroundColor: string }) => void;\n onComplete: () => void;\n onPhaseChange?: (phase: string) => void;\n}\n\n// ── Color helpers ─────────────────────────────────────────────────────────────\n\ninterface RGB { r: number; g: number; b: number }\n\nfunction parseColor(color: string): RGB {\n if (color.startsWith('#')) {\n const h = color.slice(1);\n return { r: parseInt(h.slice(0, 2), 16), g: parseInt(h.slice(2, 4), 16), b: parseInt(h.slice(4, 6), 16) };\n }\n const m = color.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n return m ? { r: +m[1], g: +m[2], b: +m[3] } : { r: 255, g: 255, b: 255 };\n}\n\nfunction interpolateRgb(a: RGB, b: RGB, t: number): string {\n const e = easeInOutSine(t);\n return `rgb(${(a.r + (b.r - a.r) * e + 0.5) | 0},${(a.g + (b.g - a.g) * e + 0.5) | 0},${(a.b + (b.b - a.b) * e + 0.5) | 0})`;\n}\n\n// (easeZoomTransition is imported from @visualli/core — createCubicBezier(0.2, 0.8, 0.2, 1))\n\nfunction lerp(a: number, b: number, t: number): number { return a + (b - a) * t; }\n\n// ── Animator class ────────────────────────────────────────────────────────────\n\nexport class KonvaLayerTransitionAnimator {\n private rafId: number | null = null;\n private timers: ReturnType<typeof setTimeout>[] = [];\n private _active = false;\n\n get active(): boolean { return this._active; }\n\n cancel(): void {\n if (this.rafId !== null) { cancelAnimationFrame(this.rafId); this.rafId = null; }\n this.timers.forEach(clearTimeout);\n this.timers = [];\n this._active = false;\n }\n\n // ── Zoom into child layer ──────────────────────────────────────────────────\n\n animateZoomIntoLayer(\n current: AnimatorViewport,\n targetNode: NodeBounds,\n childCenter: { x: number; y: number },\n fromColor: string,\n toColor: string,\n cb: TransitionCallbacks,\n targetZoom = 1.0,\n canvasWidth = 800,\n canvasHeight = 600,\n ): void {\n if (this._active) return;\n this._active = true;\n\n // Timing constants pulled from ANIMATION_PHASES (single source of truth)\n const ZOOM_DURATION = ANIMATION_PHASES.ZOOM_IN.ZOOM_TO_TARGET; // 500 ms\n const FADE_OUT_DELAY = ANIMATION_PHASES.ZOOM_IN.FADE_OUT_START; // 120 ms\n const FADE_OUT_DURATION = ANIMATION_PHASES.ZOOM_IN.FADE_OUT; // 280 ms — completes at 400 ms\n const SWAP_AT_MS = ANIMATION_PHASES.ZOOM_IN.CONTENT_SWAP; // 310 ms\n const FADE_IN_DURATION = ANIMATION_PHASES.ZOOM_IN.FADE_IN; // 200 ms\n const SETTLE_FACTOR = 0.94;\n\n const z0 = current.zoomLevel;\n const dx = targetNode.x - current.centerX;\n const dy = targetNode.y - current.centerY;\n const vmin = Math.min(canvasWidth, canvasHeight);\n const fillZoom = Math.max(4.0, (vmin * 1.5) / Math.max(targetNode.width, 100));\n\n const fromRgb = parseColor(fromColor);\n const toRgb = parseColor(toColor);\n const state = { viewport: { centerX: 0, centerY: 0, zoomLevel: 0 }, opacity: 1, backgroundColor: fromColor };\n\n const start = performance.now();\n let swapped = false;\n let fadeInStart = 0;\n\n cb.onPhaseChange?.('zoom');\n\n const tick = (now: number): void => {\n if (!this._active) return;\n const elapsed = now - start;\n\n if (!swapped) {\n if (elapsed >= SWAP_AT_MS) {\n swapped = true;\n fadeInStart = now;\n state.viewport = { centerX: childCenter.x, centerY: childCenter.y, zoomLevel: targetZoom * SETTLE_FACTOR };\n state.opacity = 0;\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n cb.onPhaseChange?.('swap');\n this.rafId = requestAnimationFrame(tick);\n return;\n }\n const rawT = Math.min(elapsed / ZOOM_DURATION, 1);\n const zoomT = easeZoomTransition(rawT);\n const zl = lerp(z0, fillZoom, zoomT);\n state.viewport = {\n centerX: targetNode.x - dx * z0 * (1 - zoomT) / zl,\n centerY: targetNode.y - dy * z0 * (1 - zoomT) / zl,\n zoomLevel: zl,\n };\n state.opacity = elapsed > FADE_OUT_DELAY\n ? Math.max(0, 1 - easeOutCubic(Math.min((elapsed - FADE_OUT_DELAY) / FADE_OUT_DURATION, 1)))\n : 1;\n state.backgroundColor = interpolateRgb(fromRgb, toRgb, rawT);\n cb.onUpdate(state);\n } else {\n const fi = now - fadeInStart;\n const ft = Math.min(fi / FADE_IN_DURATION, 1);\n const eased = easeOutCubic(ft);\n state.viewport = { centerX: childCenter.x, centerY: childCenter.y, zoomLevel: lerp(targetZoom * SETTLE_FACTOR, targetZoom, eased) };\n state.opacity = eased;\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n if (ft >= 1) { cb.onPhaseChange?.('fade-in'); this.rafId = null; this._complete(cb.onComplete); return; }\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n // ── Zoom out to parent layer ───────────────────────────────────────────────\n\n animateZoomOutToParent(\n current: AnimatorViewport,\n parent: AnimatorViewport,\n fromColor: string,\n toColor: string,\n cb: TransitionCallbacks,\n ): void {\n if (this._active) return;\n this._active = true;\n\n const FADE_OUT = ANIMATION_PHASES.ZOOM_OUT.FADE_OUT;\n const FADE_IN = ANIMATION_PHASES.ZOOM_OUT.FADE_IN;\n const OPACITY_SETTLE = 66;\n\n const fromRgb = parseColor(fromColor);\n const toRgb = parseColor(toColor);\n const state = { viewport: { centerX: 0, centerY: 0, zoomLevel: 0 }, opacity: 1, backgroundColor: fromColor };\n\n const start = performance.now();\n let swapped = false;\n let fadeInStart = 0;\n\n cb.onPhaseChange?.('fade-out');\n\n const tick = (now: number): void => {\n if (!this._active) return;\n const elapsed = now - start;\n\n if (!swapped) {\n if (elapsed >= FADE_OUT) {\n swapped = true; fadeInStart = now;\n state.viewport = { centerX: parent.centerX, centerY: parent.centerY, zoomLevel: parent.zoomLevel * 5 };\n state.opacity = 0;\n state.backgroundColor = toColor;\n cb.onUpdate(state); cb.onPhaseChange?.('zoom-back');\n this.rafId = requestAnimationFrame(tick); return;\n }\n const rawT = Math.min(elapsed / FADE_OUT, 1);\n const t = easeOutCubic(rawT);\n state.viewport = { centerX: current.centerX, centerY: current.centerY, zoomLevel: lerp(current.zoomLevel, current.zoomLevel * 0.6, t) };\n state.opacity = 1 - t;\n state.backgroundColor = interpolateRgb(fromRgb, toRgb, rawT);\n cb.onUpdate(state);\n } else {\n const fi = now - fadeInStart;\n const rawT = Math.min(fi / FADE_IN, 1);\n const t = easeZoomTransition(rawT);\n state.viewport = { centerX: parent.centerX, centerY: parent.centerY, zoomLevel: lerp(parent.zoomLevel * 5, parent.zoomLevel, t) };\n state.opacity = fi < OPACITY_SETTLE ? 0 : easeZoomTransition(Math.min((fi - OPACITY_SETTLE) / (FADE_IN - OPACITY_SETTLE), 1));\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n if (rawT >= 1) { cb.onPhaseChange?.('fade-in'); this.rafId = null; this._complete(cb.onComplete); return; }\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n private _complete(onComplete: () => void): void {\n this.timers.forEach(clearTimeout); this.timers = [];\n this._active = false;\n onComplete();\n }\n}\n\nexport const konvaLayerTransitionAnimator = new KonvaLayerTransitionAnimator();\n","// ─── Layer Navigation Utilities ──────────────────────────────────────────────\n//\n// React-specific re-exports or wrappers of core navigation logic.\n\nexport {\n getConnectionsForLayer,\n getChildLayerForNode,\n getLayerForNavigation,\n calculateFitZoom,\n calculateFitCenter,\n getContainersForLayer,\n calculateFitView,\n} from '@visualli/core';\n\nexport type { FitResult, ContainerGroupInfo } from '@visualli/core';\n","// ─── KonvaStage ───────────────────────────────────────────────────────────────\n//\n// Thin wrapper around react-konva <Stage> that:\n// • Binds canvas position/scale from the viewport store\n// • Accepts optional event handlers (wheel, mouse, touch, context-menu)\n// • Calls stage.destroy() on unmount (memory hygiene)\n\nimport React, { useRef, useEffect, forwardRef } from 'react';\nimport { KStage as Stage } from '../konvaCompat';\nimport type Konva from 'konva';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nexport interface KonvaStageProps {\n children: React.ReactNode;\n onWheel?: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n onMouseDown?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseMove?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseUp?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onContextMenu?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onTouchStart?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchMove?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchEnd?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onStageReady?: (stage: Konva.Stage) => void;\n}\n\nconst KonvaStage = forwardRef<Konva.Stage, KonvaStageProps>(function KonvaStage(\n {\n children,\n onWheel, onMouseDown, onMouseMove, onMouseUp, onContextMenu,\n onTouchStart, onTouchMove, onTouchEnd,\n onStageReady,\n },\n ref,\n) {\n const internalRef = useRef<Konva.Stage | null>(null);\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n useEffect(() => {\n if (internalRef.current) {\n if (typeof ref === 'function') ref(internalRef.current);\n else if (ref) (ref as React.MutableRefObject<Konva.Stage | null>).current = internalRef.current;\n onStageReady?.(internalRef.current);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n return () => { internalRef.current?.destroy(); };\n }, []);\n\n const w = canvasWidth || 800;\n const h = canvasHeight || 600;\n const stageX = w / 2 - centerX * zoomLevel;\n const stageY = h / 2 - centerY * zoomLevel;\n\n return (\n <Stage\n ref={internalRef}\n width={w}\n height={h}\n x={stageX}\n y={stageY}\n scaleX={zoomLevel}\n scaleY={zoomLevel}\n onWheel={onWheel}\n onMouseDown={onMouseDown}\n onMouseMove={onMouseMove}\n onMouseUp={onMouseUp}\n onContextMenu={onContextMenu}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onTouchEnd={onTouchEnd}\n draggable={false}\n pixelRatio={1}\n >\n {children}\n </Stage>\n );\n});\n\nexport default KonvaStage;\n","// ─── konvaCompat ──────────────────────────────────────────────────────────────\n//\n// react-konva@18.x defines KonvaNodeComponent with return type\n// `ReactNode | Promise<ReactNode>`. @types/react v19 tightened the JSX checker\n// so that signature no longer satisfies `(props: any) => ReactNode`, causing\n// TS2786 errors everywhere a Konva primitive is used as JSX.\n//\n// The fix: re-export every Konva primitive cast to React.ComponentType<any>.\n// This is purely a type-level shim — no runtime behaviour changes.\n\nimport {\n Stage, Layer, Group, Shape, Path, Rect, Text, Arrow, Line, Circle, TextPath,\n} from 'react-konva';\nimport type React from 'react';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype C = React.ComponentType<any>;\n\nexport const KStage = Stage as unknown as C;\nexport const KLayer = Layer as unknown as C;\nexport const KGroup = Group as unknown as C;\nexport const KShape = Shape as unknown as C;\nexport const KPath = Path as unknown as C;\nexport const KRect = Rect as unknown as C;\nexport const KText = Text as unknown as C;\nexport const KArrow = Arrow as unknown as C;\nexport const KLine = Line as unknown as C;\nexport const KCircle = Circle as unknown as C;\nexport const KTextPath = TextPath as unknown as C;\n","// ─── KonvaNodeLayer ───────────────────────────────────────────────────────────\n//\n// Konva <Layer> that renders all visible FlatNodes.\n// Uses viewport culling and passes external hover/pressed state to each node.\n\nimport React, { useRef, useLayoutEffect, useEffect, useMemo } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { useViewportNodes } from '../hooks/useViewportNodes';\nimport KonvaNode from './KonvaNode';\n\nexport interface KonvaNodeLayerProps {\n nodes?: FlatNode[];\n isTransitioning?: boolean;\n isDragging?: boolean;\n hoveredNodeId?: string | null;\n pressedNodeId?: string | null;\n}\n\nexport default function KonvaNodeLayer({\n nodes: propNodes,\n isTransitioning = false,\n isDragging = false,\n hoveredNodeId = null,\n pressedNodeId = null,\n}: KonvaNodeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n const storeNodes = useNodeStore(s => s.nodes);\n const allNodes: FlatNode[] = useMemo(\n () => propNodes ?? Array.from(storeNodes.values()),\n [propNodes, storeNodes],\n );\n const visibleNodes = useViewportNodes(allNodes, undefined, isTransitioning, isDragging);\n\n // Redraw synchronously before paint whenever visible content changes.\n // Tied to data deps so it does not fire on every parent re-render.\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [visibleNodes, hoveredNodeId, pressedNodeId, isDragging, zoomLevel]);\n\n // Redraw when transition state toggles (opacity wrapper controls visibility,\n // but the canvas still needs to be current when it fades back in).\n useEffect(() => { layerRef.current?.batchDraw(); }, [isTransitioning]);\n\n return (\n <Layer ref={layerRef} name=\"nodes\">\n {visibleNodes.map(n => (\n <KonvaNode\n key={n.id}\n node={n}\n zoomLevel={zoomLevel}\n isExternallyHovered={hoveredNodeId === n.id}\n isExternallyPressed={pressedNodeId === n.id}\n isDragging={isDragging}\n />\n ))}\n </Layer>\n );\n}\n","// ─── useViewportNodes ─────────────────────────────────────────────────────────\n//\n// Returns the subset of nodes currently visible in the viewport.\n// Signature: useViewportNodes(nodes, levelFilter?, skipCulling?)\n//\n// When skipCulling=true (e.g. during layer transitions) all nodes are returned\n// so the full layer is rendered when opacity ramps in.\n\nimport { useMemo, useRef } from 'react';\nimport type { FlatNode } from '@visualli/core';\nimport { RBushSpatialIndex, getViewportVisibleNodes } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nconst SPATIAL_INDEX_THRESHOLD = 200;\n\nexport function useViewportNodes(\n nodes: FlatNode[],\n levelFilter?: number,\n skipCulling = false,\n /** When true, skip culling so dragged nodes are always visible and the\n * spatial index (keyed on layout positions) is not consulted. */\n isDragging = false,\n): FlatNode[] {\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n const indexRef = useRef<RBushSpatialIndex | null>(null);\n const nodesHashRef = useRef<number>(0);\n const nodesHash = nodes.length;\n\n if (nodesHash !== nodesHashRef.current) {\n nodesHashRef.current = nodesHash;\n indexRef.current = null; // rebuild below\n }\n\n return useMemo(() => {\n if (nodes.length === 0) return [];\n\n if (!indexRef.current && nodes.length >= SPATIAL_INDEX_THRESHOLD && !skipCulling && !isDragging) {\n indexRef.current = new RBushSpatialIndex();\n indexRef.current.bulkLoad(nodes.map(n => ({\n nodeId: n.id,\n bounds: { minX: n.x, minY: n.y, maxX: n.x + n.width, maxY: n.y + n.height },\n })));\n }\n\n return getViewportVisibleNodes({\n nodes,\n viewport: { centerX, centerY, zoomLevel, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } },\n canvasWidth,\n canvasHeight,\n levelFilter,\n skipCulling,\n isDragging,\n spatialIndex: indexRef.current,\n spatialIndexThreshold: SPATIAL_INDEX_THRESHOLD,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [nodes, levelFilter, skipCulling, isDragging, centerX, centerY, zoomLevel, canvasWidth, canvasHeight]);\n}\n","// ─── KonvaNode ────────────────────────────────────────────────────────────────\n//\n// Renders a single FlatNode as a single organic blob shape with Konva.\n// Matches the visualli.ai rendering:\n// - Centered blob at node (x, y) with radiusX / radiusY scaling\n// - Single blob shape (no background depth layers)\n// - HSL-based border darkening\n// - 'Story Script' cursive font, text clipped to blob silhouette\n// - External hover / pressed state (no Konva hit-canvas dependency)\n// - All shapes are listening=false; hit detection uses spatial index\n\nimport React, { useMemo } from 'react';\nimport { KGroup as Group, KShape as Shape, KText as Text } from '../konvaCompat';\nimport type { FlatNode } from '@visualli/core';\nimport { CANVAS_COLORS, NODE_HEIGHT, TEXT_LABEL_HIDE_BELOW_ZOOM, darkenHexColor } from '@visualli/core';\nimport { getBlobTypeForLayer, BLOB_TEXT_OFFSETS, BLOB_LAYER_CONFIG, NODE_LAYER_CONFIG, drawBlobPath, computeNodeTextWorldScale } from '../config';\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport interface KonvaNodeProps {\n node: FlatNode;\n zoomLevel: number;\n /** True when the pointer is currently over this node (stage-level hit test). */\n isExternallyHovered?: boolean;\n /** True while this node is being pressed/dragged. */\n isExternallyPressed?: boolean;\n /** True while any node is being dragged — disables expensive shadows. */\n isDragging?: boolean;\n}\n\nconst KonvaNode = React.memo(function KonvaNode({\n node,\n zoomLevel,\n isExternallyHovered = false,\n isExternallyPressed = false,\n isDragging = false,\n}: KonvaNodeProps) {\n // Border: monochromatic HSL-darkened version of the fill color\n const borderColor = useMemo(() => darkenHexColor(node.color, 0.13), [node.color]);\n\n // Number of background layers (capped at 3), driven by branchCount\n const layerCount = useMemo(() => {\n const count = node.branchCount ?? 0;\n return Math.min(count, 3);\n }, [node.branchCount]);\n\n // Base blob radii (same math as visualli.ai KonvaNode)\n const baseRadiusX = node.width / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n\n // Larger, consistent font size for better readability\n // Text will wrap to multiple lines if needed\n const calculateFontSize = useMemo(() => {\n // Use a larger base font size for better visibility\n return 30;\n }, [node.title]);\n\n // Text scale and layout\n const textNaturalWidth = node.width - 40;\n // Increase text height to allow 2-3 lines of wrapped text\n const textNaturalHeight = NODE_HEIGHT * 1.2;\n const maxScale = computeNodeTextWorldScale(node.width, zoomLevel);\n\n // Blob type and text offset\n const blobType = getBlobTypeForLayer(node.level);\n const textOffsetX = (BLOB_TEXT_OFFSETS[blobType] ?? 0) * baseRadiusX;\n\n // Interaction state (purely driven from stage-level delegation)\n const effectiveHover = isExternallyHovered;\n const isPressed = isExternallyPressed;\n\n // Blob fill/stroke:\n // default → fill=node.color, stroke=borderColor\n // hover → fill=borderColor, stroke=borderColor\n // pressed → fill=borderColor, stroke=node.color\n const topFill = effectiveHover || isPressed ? borderColor : node.color;\n const topStroke = isPressed ? node.color : borderColor;\n\n // Build the background layers config (outermost first for correct z-order)\n const backgroundLayers = useMemo(() => {\n if (layerCount === 0) return [];\n const startIdx = BLOB_LAYER_CONFIG.length - layerCount;\n const layers = [];\n for (let i = startIdx; i < BLOB_LAYER_CONFIG.length; i++) {\n const config = BLOB_LAYER_CONFIG[i];\n layers.push({\n ...config,\n radiusX: baseRadiusX * config.scaleUp,\n radiusY: baseRadiusY * config.scaleUp,\n });\n }\n return layers;\n }, [layerCount, baseRadiusX, baseRadiusY]);\n\n return (\n <Group x={node.x} y={node.y} listening={false}>\n {/* Background blob layers (outermost rendered first, behind the node) */}\n {backgroundLayers.map((layer, idx) => (\n <Shape\n key={`blob-layer-${idx}`}\n rotation={layer.rotation}\n opacity={layer.opacity}\n sceneFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, layer.radiusX, layer.radiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n fill={node.color}\n stroke={borderColor}\n strokeWidth={layer.strokeWidth}\n dash={layer.dash ? [...layer.dash] : undefined}\n listening={false}\n perfectDrawEnabled={false}\n />\n ))}\n\n {/* Node (top layer) - main interactive blob */}\n <Shape\n rotation={NODE_LAYER_CONFIG.rotation}\n opacity={NODE_LAYER_CONFIG.opacity}\n sceneFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n hitFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n fill={topFill}\n stroke={topStroke}\n strokeWidth={NODE_LAYER_CONFIG.strokeWidth}\n shadowEnabled={!isDragging}\n shadowColor=\"rgba(255,255,255,1)\"\n shadowBlur={effectiveHover || isPressed ? 40 : 15}\n shadowOpacity={effectiveHover || isPressed ? 0.4 : 0.15}\n shadowOffsetX={0}\n shadowOffsetY={0}\n perfectDrawEnabled={false}\n />\n\n {/* Node Title — inverse-scaled so it stays legible at a constant screen size.\n Clipped to the blob silhouette via clipFunc so the growing text never visually\n bleeds outside the first layer boundary at low zoom levels. */}\n <Group\n clipFunc={(ctx: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n }}\n visible={zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM}\n listening={false}\n >\n <Text\n x={textOffsetX}\n y={0}\n offsetX={textNaturalWidth / 2}\n offsetY={textNaturalHeight / 2}\n width={textNaturalWidth}\n height={textNaturalHeight}\n scaleX={maxScale}\n scaleY={maxScale}\n text={node.title}\n fontSize={calculateFontSize}\n fontFamily=\"'Story Script', cursive\"\n fontStyle=\"normal\"\n fill={CANVAS_COLORS.node.titleColor}\n align=\"center\"\n verticalAlign=\"middle\"\n wrap=\"word\"\n ellipsis={false}\n listening={false}\n perfectDrawEnabled={false}\n />\n </Group>\n </Group>\n );\n});\n\nexport default KonvaNode;\n\n","export {\n ALL_BLOB_SHAPES,\n ACTIVE_BLOB_TYPES,\n BLOB_LAYER_CONFIG,\n NODE_LAYER_CONFIG,\n getBlobTypeForLayer,\n BLOB_TEXT_OFFSETS,\n drawBlobPath,\n NODE_TEXT_BASE_FONT_PX,\n DESCRIPTION_TEXT_BASE_FONT_PX,\n CONTAINER_LABEL_BASE_FONT_PX,\n EDGE_LABEL_BASE_FONT_PX,\n OVERLAY_FONT_UPPER_BOOST_PX,\n computeNodeTextWorldScale,\n computeNodeTextScreenScale,\n computeOverlayScale,\n computeEdgeLabelScale,\n} from '@visualli/core';\n\nexport { buildBlobPathData } from './blobShapes';\nexport type { BlobPoint, BlobShape } from '@visualli/core';\n","// ─── Blob Shapes Configuration ───────────────────────────────────────────────\n//\n// Blob shapes are centered at (0, 0). Coordinates are relative — multiply by\n// (radiusX, radiusY) to get world coords. Drawing uses closed quadratic bezier\n// curves through midpoints of consecutive control points (same as visualli.ai).\n//\n// Shapes match the visualli.ai reference designs exactly.\n\nexport interface BlobPoint { x: number; y: number }\nexport type BlobShape = ReadonlyArray<BlobPoint>;\n\n// ── Blob background layer depth config ────────────────────────────────────────\n// Index 0 = outermost layer (rendered first, behind the top blob).\n\nexport const BLOB_LAYER_CONFIG = [\n { opacity: 0.3, rotation: -15, scaleUp: 1.30, strokeWidth: 3, dash: [6, 4] as [number, number] },\n { opacity: 0.4, rotation: -10, scaleUp: 1.20, strokeWidth: 1, dash: undefined },\n { opacity: 0.5, rotation: -5, scaleUp: 1.10, strokeWidth: 2, dash: undefined },\n] as const;\n\nexport const NODE_LAYER_CONFIG = { opacity: 1, rotation: 0, strokeWidth: 3 } as const;\n\n// ── Six organic blob variants ─────────────────────────────────────────────────\nexport const ALL_BLOB_SHAPES: ReadonlyArray<BlobShape> = [\n // Shape 0 · Blob 1 (root / L0)\n [\n { x: 1.12, y: 0.00 }, { x: 0.86, y: 0.56 }, { x: 0.46, y: 0.94 },\n { x: -0.08, y: 1.06 }, { x: -0.68, y: 0.82 }, { x: -0.96, y: 0.08 },\n { x: -0.55, y: -0.82 }, { x: 0.04, y: -1.02 }, { x: 0.72, y: -0.80 },\n { 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 },\n { x: -0.189, y: -0.855 }, { x: -0.090, y: -0.903 }, { x: 0.014, y: -0.932 },\n { x: 0.129, y: -0.940 }, { x: 0.255, y: -0.924 }, { x: 0.412, y: -0.876 },\n { 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 },\n { x: 0.933, y: -0.486 }, { x: 0.979, y: -0.425 }, { x: 1.006, y: -0.385 },\n { x: 1.034, y: -0.334 }, { x: 1.058, y: -0.276 }, { x: 1.078, y: -0.209 },\n { 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 },\n { x: 1.034, y: 0.401 }, { x: 0.996, y: 0.477 }, { x: 0.948, y: 0.549 },\n { x: 0.889, y: 0.617 }, { x: 0.820, y: 0.681 }, { x: 0.735, y: 0.741 },\n { 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 },\n { x: 0.046, y: 0.931 }, { x: -0.069, y: 0.938 }, { x: -0.155, y: 0.935 },\n { x: -0.250, y: 0.919 }, { x: -0.346, y: 0.890 }, { x: -0.443, y: 0.851 },\n { 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 },\n { x: -0.994, y: 0.343 }, { x: -1.034, y: 0.267 }, { x: -1.064, y: 0.192 },\n { x: -1.085, y: 0.120 }, { x: -1.097, y: 0.042 }, { x: -1.102, y: 0.001 },\n { 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 },\n { 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 },\n { x: 0.389, y: -1.096 }, { x: 0.488, y: -1.174 }, { x: 0.597, y: -1.210 },\n { x: 0.728, y: -1.165 }, { x: 0.867, y: -1.036 }, { x: 0.996, y: -0.839 },\n { 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 },\n { x: 0.484, y: 1.072 }, { x: 0.339, y: 1.079 }, { x: 0.219, y: 1.051 },\n { x: 0.131, y: 0.994 }, { x: 0.059, y: 0.939 }, { x: 0.008, y: 0.915 },\n { 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 },\n { x: -0.817, y: 0.952 }, { x: -0.945, y: 0.810 }, { x: -1.054, y: 0.600 },\n { x: -1.160, y: 0.302 }, { x: -1.187, y: -0.011 }, { x: -1.165, y: -0.326 },\n { 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 },\n { 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 },\n { x: -0.468, y: -1.115 }, { x: -0.358, y: -1.079 }, { x: -0.238, y: -1.034 },\n { x: -0.107, y: -0.989 }, { x: 0.035, y: -0.953 }, { x: 0.188, y: -0.929 },\n { 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 },\n { x: 1.138, y: -0.126 }, { x: 1.152, y: 0.272 }, { x: 1.121, y: 0.451 },\n { x: 1.046, y: 0.602 }, { x: 0.928, y: 0.727 }, { x: 0.767, y: 0.833 },\n { 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 },\n { x: -0.589, y: 1.104 }, { x: -0.704, y: 1.050 }, { x: -0.815, y: 0.973 },\n { x: -0.913, y: 0.871 }, { x: -0.993, y: 0.746 }, { x: -1.048, y: 0.593 },\n { 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 },\n { x: -0.886, y: -1.020 },\n ],\n // Shape 4 · Blob 5 (inverted Blob 4)\n [\n { x: -0.734, y: 1.127 }, { x: -0.656, y: 1.146 }, { x: -0.567, y: 1.142 },\n { x: -0.468, y: 1.115 }, { x: -0.358, y: 1.079 }, { x: -0.238, y: 1.034 },\n { x: -0.107, y: 0.989 }, { x: 0.035, y: 0.953 }, { x: 0.188, y: 0.929 },\n { 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 },\n { x: 1.138, y: 0.126 }, { x: 1.152, y: -0.272 }, { x: 1.121, y: -0.451 },\n { x: 1.046, y: -0.602 }, { x: 0.928, y: -0.727 }, { x: 0.767, y: -0.833 },\n { 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 },\n { x: -0.589, y: -1.104 }, { x: -0.704, y: -1.050 }, { x: -0.815, y: -0.973 },\n { x: -0.913, y: -0.871 }, { x: -0.993, y: -0.746 }, { x: -1.048, y: -0.593 },\n { 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 },\n { 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 Konva canvas context (centered at 0,0).\n * Uses closed quadratic bezier curves through midpoints of control points.\n * Call this inside a Konva Shape's sceneFunc / hitFunc.\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\n// Legacy export kept for consumers that may import buildBlobPathData.\n// Generates an SVG path string (less accurate than the sceneFunc approach).\nexport function buildBlobPathData(\n _shape: BlobShape,\n cx: number,\n cy: number,\n width: number,\n height: number,\n): string {\n const rx = width / 2;\n const ry = height / 2;\n const blobType = 0;\n const srcPts = ALL_BLOB_SHAPES[blobType];\n const pts = srcPts.map(p => ({ x: cx + p.x * rx, y: cy + p.y * ry }));\n const mid = (a: { x: number; y: number }, b: { x: number; y: number }) =>\n ({ x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 });\n const last = pts[pts.length - 1];\n const first = pts[0];\n const s = mid(last, first);\n let d = `M ${s.x} ${s.y}`;\n for (let i = 0; i < pts.length; i++) {\n const curr = pts[i];\n const next = pts[(i + 1) % pts.length];\n const m = mid(curr, next);\n d += ` Q ${curr.x} ${curr.y} ${m.x} ${m.y}`;\n }\n d += ' Z';\n return d;\n}\n","// ─── KonvaEdgeLayer ───────────────────────────────────────────────────────────\n//\n// Renders all edges for visible nodes. An edge is only drawn when BOTH its\n// source and target node are currently in the visible set.\n//\n// NOTE: Node positions are read from useNodeStore (live) so edges always follow\n// dragged nodes. The `nodes` prop is used only for initial viewport culling.\n\nimport React, { useRef, useLayoutEffect, useMemo } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode, MindMapConnection } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useViewportNodes } from '../hooks/useViewportNodes';\nimport KonvaEdge from './KonvaEdge';\n\nexport interface KonvaEdgeLayerProps {\n nodes: FlatNode[];\n connections: MindMapConnection[];\n currentLevel?: number;\n isDark?: boolean;\n /** Pass true while a node is being dragged to skip viewport culling. */\n isDragging?: boolean;\n}\n\nexport default function KonvaEdgeLayer({\n nodes,\n connections,\n currentLevel,\n isDark = false,\n isDragging = false,\n}: KonvaEdgeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n // Live node positions from the store — updated every RAF during drag\n const storeNodes = useNodeStore(s => s.nodes);\n // Viewport culling still uses the layout snapshot for performance;\n // during drag, culling is skipped so newly-moved nodes are always visible.\n const visibleNodes = useViewportNodes(nodes, currentLevel, false, isDragging);\n\n // Set of visible node IDs for O(1) culling\n const visibleSet = useMemo(() => new Set(visibleNodes.map(n => n.id)), [visibleNodes]);\n\n // Redraw before paint whenever visible edges change.\n // storeNodes must be included: edge endpoints read live positions from the store,\n // so when a node is dragged, the edge must redraw even though visibleSet is unchanged.\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [connections, isDark, isDragging, visibleSet, storeNodes]);\n\n return (\n <Layer ref={layerRef} listening={false}>\n {connections.map((conn, idx) => {\n // Use live store positions so edges move with dragged nodes\n const src = storeNodes.get(conn.from);\n const tgt = storeNodes.get(conn.to);\n if (!src || !tgt) return null;\n if (!isDragging && !visibleSet.has(src.id) && !visibleSet.has(tgt.id)) return null;\n\n return (\n <KonvaEdge\n key={`${conn.from}-${conn.to}-${idx}`}\n sourceNode={src}\n targetNode={tgt}\n connection={conn}\n isDark={isDark}\n zoomLevel={zoomLevel}\n />\n );\n })}\n </Layer>\n );\n}\n","// ─── KonvaEdge ────────────────────────────────────────────────────────────────\n//\n// Renders a connection arrow between two FlatNodes.\n// Matches the visualli.ai KonvaEdge exactly:\n// - Cubic bezier multi-point polyline (20 segments) through ellipse boundaries\n// - Adaptive arc height (smaller for long connections)\n// - Open V arrowhead at target\n// - TextPath label following the curve (above the line)\n// - Always black stroke for maximum visibility\n\nimport React, { useMemo, memo } from 'react';\nimport { KGroup as Group, KLine as Line, KTextPath as TextPath } from '../konvaCompat';\nimport type { FlatNode, MindMapConnection } from '@visualli/core';\nimport { NODE_HEIGHT } from '@visualli/core';\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n// Returns the outermost visible blob scale for a node.\n// Mirrors BLOB_LAYER_CONFIG in KonvaNode: scaleUps are [1.30, 1.20, 1.10] (outermost→inner).\nconst getOutermostScaleUp = (branchCount: number | undefined): number => {\n const layerCount = Math.min(branchCount ?? 0, 3);\n if (layerCount === 0) return 1.0;\n const scaleUps = [1.30, 1.20, 1.10] as const;\n return scaleUps[scaleUps.length - layerCount];\n};\n\nfunction getEllipseIntersection(\n cx: number, cy: number, rx: number, ry: number, angle: number,\n): { x: number; y: number } {\n return {\n x: cx + rx * Math.cos(angle),\n y: cy + ry * Math.sin(angle),\n };\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport interface KonvaEdgeProps {\n sourceNode: FlatNode;\n targetNode: FlatNode;\n connection?: MindMapConnection;\n isDark?: boolean;\n colorOverride?: string;\n zoomLevel?: number;\n}\n\nconst EDGE_SPACING = 25; // Increased spacing to ensure arrow head stays out of organic shapes\nconst STROKE_COLOR = '#000000';\nconst STROKE_WIDTH = 2.5;\n\nconst KonvaEdge = memo(function KonvaEdge({\n sourceNode: from,\n targetNode: to,\n connection,\n zoomLevel = 1.0,\n}: KonvaEdgeProps) {\n const label = (connection as { label?: string } | undefined)?.label;\n\n // ── Build multi-point bezier curve ─────────────────────────────────────────\n const points = useMemo(() => {\n const fromBaseX = from.width / 2;\n const fromBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, fromBaseX * 0.74);\n const fromScale = getOutermostScaleUp(from.branchCount);\n const fromRadiusX = fromBaseX * fromScale;\n const fromRadiusY = fromBaseY * fromScale;\n\n const toBaseX = to.width / 2;\n const toBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, toBaseX * 0.74);\n const toScale = getOutermostScaleUp(to.branchCount);\n const toRadiusX = toBaseX * toScale;\n const toRadiusY = toBaseY * toScale;\n\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const fromEdge = getEllipseIntersection(from.x, from.y, fromRadiusX, fromRadiusY, angle);\n const toEdge = getEllipseIntersection(to.x, to.y, toRadiusX, toRadiusY, angle + Math.PI);\n\n // Apply spacing from edges (increased to 25 to avoid leaking into organic shapes)\n const fromX = fromEdge.x + EDGE_SPACING * Math.cos(angle);\n const fromY = fromEdge.y + EDGE_SPACING * Math.sin(angle);\n const toX = toEdge.x - EDGE_SPACING * Math.cos(angle);\n const toY = toEdge.y - EDGE_SPACING * Math.sin(angle);\n\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n\n const distance = Math.sqrt((toX - fromX) ** 2 + (toY - fromY) ** 2);\n const arcHeight = Math.min(45, 45 / (1 + Math.max(0, (distance - 200) / 400)));\n\n const perpX = -(toY - fromY) / distance;\n const perpY = (toX - fromX) / distance;\n\n const offsetMidX = midX + perpX * arcHeight;\n const offsetMidY = midY + perpY * arcHeight;\n\n const ctrl1X = fromX + (offsetMidX - fromX) * 0.66;\n const ctrl1Y = fromY + (offsetMidY - fromY) * 0.66;\n const ctrl2X = toX + (offsetMidX - toX) * 0.66;\n const ctrl2Y = toY + (offsetMidY - toY) * 0.66;\n\n const NUM_SEGMENTS = 20;\n const pts: number[] = [];\n for (let i = 0; i <= NUM_SEGMENTS; i++) {\n const t = i / NUM_SEGMENTS;\n const mt = 1 - t;\n const mt2 = mt * mt; const mt3 = mt2 * mt;\n const t2 = t * t; const t3 = t2 * t;\n pts.push(\n mt3 * fromX + 3 * mt2 * t * ctrl1X + 3 * mt * t2 * ctrl2X + t3 * toX,\n mt3 * fromY + 3 * mt2 * t * ctrl1Y + 3 * mt * t2 * ctrl2Y + t3 * toY,\n );\n }\n return pts;\n }, [from.x, from.y, from.width, from.branchCount, to.x, to.y, to.width, to.branchCount]);\n\n // ── Arrowhead ─────────────────────────────────────────────────────────────\n const arrowHeadPoints = useMemo(() => {\n const len = points.length;\n const tipX = points[len - 2];\n const tipY = points[len - 1];\n const prevX = points[len - 4];\n const prevY = points[len - 3];\n const angle = Math.atan2(tipY - prevY, tipX - prevX);\n const armLength = 11;\n const armAngle = Math.PI / 5.5; // ~33°\n return [\n tipX - armLength * Math.cos(angle - armAngle),\n tipY - armLength * Math.sin(angle - armAngle),\n tipX, tipY,\n tipX - armLength * Math.cos(angle + armAngle),\n tipY - armLength * Math.sin(angle + armAngle),\n ];\n }, [points]);\n\n // ── TextPath data (optional label) ────────────────────────────────────────\n const { pathData, fontSize } = useMemo(() => {\n if (!label) return { pathData: null, fontSize: 12 };\n\n const fromBaseX = from.width / 2;\n const fromBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, fromBaseX * 0.74);\n const fromScale = getOutermostScaleUp(from.branchCount);\n const fromRadiusX = fromBaseX * fromScale;\n const fromRadiusY = fromBaseY * fromScale;\n\n const toBaseX = to.width / 2;\n const toBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, toBaseX * 0.74);\n const toScale = getOutermostScaleUp(to.branchCount);\n const toRadiusX = toBaseX * toScale;\n const toRadiusY = toBaseY * toScale;\n\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const fromEdge = getEllipseIntersection(from.x, from.y, fromRadiusX, fromRadiusY, angle);\n const toEdge = getEllipseIntersection(to.x, to.y, toRadiusX, toRadiusY, angle + Math.PI);\n\n const fromX = fromEdge.x + EDGE_SPACING * Math.cos(angle);\n const fromY = fromEdge.y + EDGE_SPACING * Math.sin(angle);\n const toX = toEdge.x - EDGE_SPACING * Math.cos(angle);\n const toY = toEdge.y - EDGE_SPACING * Math.sin(angle);\n\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n const distance = Math.sqrt((toX - fromX) ** 2 + (toY - fromY) ** 2);\n const arcHeight = Math.min(45, 45 / (1 + Math.max(0, (distance - 200) / 400)));\n\n const perpX = -(toY - fromY) / distance;\n const perpY = (toX - fromX) / distance;\n\n const offsetMidX = midX + perpX * arcHeight;\n const offsetMidY = midY + perpY * arcHeight;\n\n const ctrl1X = fromX + (offsetMidX - fromX) * 0.66;\n const ctrl1Y = fromY + (offsetMidY - fromY) * 0.66;\n const ctrl2X = toX + (offsetMidX - toX) * 0.66;\n const ctrl2Y = toY + (offsetMidY - toY) * 0.66;\n\n const TEXT_OFFSET = 15;\n const fxo = fromX + perpX * TEXT_OFFSET; const fyo = fromY + perpY * TEXT_OFFSET;\n const txo = toX + perpX * TEXT_OFFSET; const tyo = toY + perpY * TEXT_OFFSET;\n const c1xo = ctrl1X + perpX * TEXT_OFFSET; const c1yo = ctrl1Y + perpY * TEXT_OFFSET;\n const c2xo = ctrl2X + perpX * TEXT_OFFSET; const c2yo = ctrl2Y + perpY * TEXT_OFFSET;\n\n // Variable font size: scales with zoom level to remain visible when zoomed out\n // and also scales with node width.\n const baseFontSize = 14;\n const zoomFactor = Math.max(1, 1 / zoomLevel); // Increase font size as we zoom out\n const scaledFontSize = Math.max(12, Math.min(24, baseFontSize * (from.width / 180) * zoomFactor));\n\n let d = '';\n if (fromX > toX) {\n d = `M ${txo},${tyo} C ${c2xo},${c2yo} ${c1xo},${c1yo} ${fxo},${fyo}`;\n } else {\n d = `M ${fxo},${fyo} C ${c1xo},${c1yo} ${c2xo},${c2yo} ${txo},${tyo}`;\n }\n return { pathData: d, fontSize: scaledFontSize };\n }, [from.x, from.y, from.width, from.branchCount, to.x, to.y, to.width, to.branchCount, label, zoomLevel]);\n\n // ── Render ────────────────────────────────────────────────────────────────\n return (\n <Group>\n <Line\n points={points}\n stroke={STROKE_COLOR}\n strokeWidth={STROKE_WIDTH}\n tension={0}\n opacity={0.9}\n lineCap=\"round\"\n lineJoin=\"round\"\n listening={false}\n perfectDrawEnabled={false}\n />\n <Line\n points={arrowHeadPoints}\n stroke={STROKE_COLOR}\n strokeWidth={STROKE_WIDTH}\n lineCap=\"round\"\n lineJoin=\"round\"\n opacity={0.9}\n listening={false}\n perfectDrawEnabled={false}\n />\n {label && pathData && (\n <>\n {/* Background text for contrast */}\n <TextPath\n data={pathData}\n text={label}\n fontSize={fontSize}\n fontFamily=\"'Playpen Sans', cursive\"\n fontStyle=\"normal\"\n fill=\"#ffffff\"\n align=\"center\"\n letterSpacing={0.5}\n listening={false}\n opacity={0.9}\n />\n {/* Foreground label text */}\n <TextPath\n data={pathData}\n text={label}\n fontSize={fontSize}\n fontFamily=\"'Playpen Sans', cursive\"\n fontStyle=\"normal\"\n fill=\"#6b6860\"\n align=\"center\"\n letterSpacing={0.5}\n listening={false}\n opacity={0.9}\n />\n </>\n )}\n </Group>\n );\n});\n\nexport default KonvaEdge;\n","// ─── KonvaContainerLayer ─────────────────────────────────────────────────────\n//\n// Renders container outlines beneath nodes (non-interactive).\n//\n// Node positions are read from useNodeStore (live), matching the visualli.ai\n// reference — containers follow dragged nodes in real-time every RAF frame.\n\nimport React, { useRef, useLayoutEffect } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport KonvaContainer from './KonvaContainer';\n\nexport interface ContainerGroup {\n id: string;\n label?: string;\n nodeIds: string[];\n level: number;\n}\n\nexport interface KonvaContainerLayerProps {\n /** Layout-snapshot nodes — used only as a seed for initial IDs. */\n nodes: FlatNode[];\n containers: ContainerGroup[];\n isDark?: boolean;\n}\n\nexport default function KonvaContainerLayer({ nodes, containers, isDark = false }: KonvaContainerLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n\n // Subscribe to live store — updated every RAF frame during drag.\n // This is the same pattern used by KonvaEdgeLayer so containers and edges\n // both track dragged nodes in real-time.\n const storeNodes = useNodeStore(s => s.nodes);\n\n // batchDraw deps include storeNodes so the layer redraws whenever any node\n // position changes (including mid-drag RAF updates).\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [containers, isDark, storeNodes]);\n\n if (containers.length === 0) return null;\n\n return (\n <Layer ref={layerRef} listening={false}>\n {containers.map(c => {\n // Read positions from live store — not from the layout snapshot\n const groupNodes = c.nodeIds\n .map(id => storeNodes.get(id))\n .filter((n): n is FlatNode => !!n);\n if (groupNodes.length === 0) return null;\n\n return (\n <KonvaContainer\n key={c.id}\n nodes={groupNodes}\n label={c.label}\n isDark={isDark}\n />\n );\n })}\n </Layer>\n );\n}\n","// ─── KonvaContainer ──────────────────────────────────────────────────────────\n//\n// Renders a smooth dashed hull around a group of nodes with an inverse-scaled\n// pill label — matches the visualli.ai KonvaContainer exactly.\n//\n// • 48-point ellipse sampling per node (not bounding box corners)\n// • Graham-scan convex hull → 6-pass Chaikin smoothing\n// • Dashed stroke \"#747270\", no fill\n// • Pill label: parchment bg (#ddd9d0), Playpen Sans 800, inverse-zoom-scaled\n// • Label anchored to the hull edge (bottom for horizontal, top for vertical)\n\nimport React, { memo, useMemo } from 'react';\nimport {\n KGroup as Group,\n KLine as Line,\n KRect as Rect,\n KText as Text,\n} from '../konvaCompat';\nimport type { FlatNode } from '@visualli/core';\nimport { NODE_HEIGHT, TEXT_LABEL_HIDE_BELOW_ZOOM } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport {\n CONTAINER_LABEL_BASE_FONT_PX,\n computeNodeTextScreenScale,\n} from '../config/textScaling';\n\n// ── Constants (mirrors visualli.ai) ──────────────────────────────────────────\n\nconst CONTAINER_PADDING = 50;\nconst CONTAINER_DASH = [10, 5] as const;\nconst LABEL_BG = '#ddd9d0';\nconst LABEL_BORDER_RADIUS = 20;\nconst LABEL_FONT_SIZE = CONTAINER_LABEL_BASE_FONT_PX;\nconst LABEL_FONT_WEIGHT = '800';\nconst LABEL_FONT_FAMILY = \"'Playpen Sans', Quicksand, sans-serif\";\nconst LABEL_PAD_H = 20;\nconst LABEL_PAD_V = 10;\nconst LABEL_LINE_HEIGHT = 1.2;\n// Max normalized blob extents — Shape 5 reaches ±1.275 X, ±1.234 Y\nconst MAX_BLOB_EXTENT_X = 1.275;\nconst MAX_BLOB_EXTENT_Y = 1.234;\n\n// ── Text measurement ──────────────────────────────────────────────────────────\n\nlet _labelCtx: CanvasRenderingContext2D | null = null;\nfunction measureLabelBoxWidth(text: string, fontSize: number): number {\n if (!_labelCtx) {\n const c = document.createElement('canvas');\n _labelCtx = c.getContext('2d');\n }\n if (!_labelCtx) return Math.ceil(text.length * fontSize * 0.65 + 2 * LABEL_PAD_H);\n _labelCtx.font = `${LABEL_FONT_WEIGHT} ${fontSize}px ${LABEL_FONT_FAMILY}`;\n return Math.ceil(_labelCtx.measureText(text).width + 2 * LABEL_PAD_H);\n}\n\n// ── Convex hull (Graham scan) ─────────────────────────────────────────────────\n\ntype Pt = { x: number; y: number };\n\nfunction isLeftTurn(p1: Pt, p2: Pt, p3: Pt): boolean {\n return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x) > 0;\n}\n\nfunction convexHull(points: Pt[]): Pt[] {\n if (points.length < 3) return points;\n let start = 0;\n for (let i = 1; i < points.length; i++) {\n if (points[i].y < points[start].y ||\n (points[i].y === points[start].y && points[i].x < points[start].x)) start = i;\n }\n const sorted = [...points];\n const sp = sorted.splice(start, 1)[0];\n sorted.sort((a, b) => {\n const da = Math.atan2(a.y - sp.y, a.x - sp.x);\n const db = Math.atan2(b.y - sp.y, b.x - sp.x);\n if (da !== db) return da - db;\n return Math.hypot(a.x - sp.x, a.y - sp.y) - Math.hypot(b.x - sp.x, b.y - sp.y);\n });\n const hull: Pt[] = [sp, sorted[0]];\n for (let i = 1; i < sorted.length; i++) {\n while (hull.length > 1 && !isLeftTurn(hull[hull.length - 2], hull[hull.length - 1], sorted[i])) hull.pop();\n hull.push(sorted[i]);\n }\n return hull;\n}\n\n// ── Chaikin smoothing (6 passes, returns flat [x,y,…] array) ─────────────────\n\nfunction chaikinSmooth(pts: Pt[], passes = 6): number[] {\n let cur = pts;\n for (let iter = 0; iter < passes; iter++) {\n const next: Pt[] = [];\n const n = cur.length;\n for (let i = 0; i < n; i++) {\n const a = cur[i], b = cur[(i + 1) % n];\n next.push({ x: 0.75 * a.x + 0.25 * b.x, y: 0.75 * a.y + 0.25 * b.y });\n next.push({ x: 0.25 * a.x + 0.75 * b.x, y: 0.25 * a.y + 0.75 * b.y });\n }\n cur = next;\n }\n return cur.flatMap(p => [p.x, p.y]);\n}\n\n// ── Hull edge Y at a given X (for label anchor) ───────────────────────────────\n\nfunction hullEdgeYAtX(points: number[], targetX: number, isBottom: boolean): number {\n const n = points.length;\n let result = isBottom ? -Infinity : Infinity;\n for (let i = 0; i < n; i += 2) {\n const x1 = points[i], y1 = points[i + 1];\n const x2 = points[(i + 2) % n], y2 = points[(i + 3) % n];\n if ((x1 < targetX && x2 >= targetX) || (x2 < targetX && x1 >= targetX)) {\n const t = (targetX - x1) / (x2 - x1);\n const y = y1 + t * (y2 - y1);\n if (isBottom) result = Math.max(result, y); else result = Math.min(result, y);\n }\n }\n if (!isFinite(result)) {\n for (let i = 1; i < n; i += 2) {\n if (isBottom) result = Math.max(result, points[i]); else result = Math.min(result, points[i]);\n }\n }\n return result;\n}\n\n// ── Hull calculation ──────────────────────────────────────────────────────────\n\nfunction calculateHull(\n containerNodes: FlatNode[],\n): { points: number[]; anchorX: number; anchorEdgeY: number } | null {\n if (containerNodes.length === 0) return null;\n\n const NUM_SAMPLES = 48;\n const samples: Pt[] = [];\n for (const node of containerNodes) {\n const baseRX = node.width / 2;\n const baseRY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRX * 0.74);\n const halfW = baseRX * MAX_BLOB_EXTENT_X + CONTAINER_PADDING;\n const halfH = baseRY * MAX_BLOB_EXTENT_Y + CONTAINER_PADDING;\n for (let j = 0; j < NUM_SAMPLES; j++) {\n const angle = (j / NUM_SAMPLES) * Math.PI * 2;\n samples.push({ x: node.x + halfW * Math.cos(angle), y: node.y + halfH * Math.sin(angle) });\n }\n }\n\n const hull = convexHull(samples);\n const points = chaikinSmooth(hull, 6);\n\n const xs = containerNodes.map(n => n.x);\n const ys = containerNodes.map(n => n.y);\n const spanX = Math.max(...xs) - Math.min(...xs);\n const spanY = Math.max(...ys) - Math.min(...ys);\n const useTopEdge = spanY > spanX * 2.0;\n\n let hullMinX = Infinity, hullMaxX = -Infinity;\n for (let i = 0; i < points.length; i += 2) {\n if (points[i] < hullMinX) hullMinX = points[i];\n if (points[i] > hullMaxX) hullMaxX = points[i];\n }\n const anchorX = (hullMinX + hullMaxX) / 2;\n const anchorEdgeY = hullEdgeYAtX(points, anchorX, !useTopEdge);\n\n return { points, anchorX, anchorEdgeY };\n}\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\nexport interface KonvaContainerProps {\n /** All nodes in this container group (already resolved from nodeMap). */\n nodes: FlatNode[];\n /** Label text shown on the pill badge. */\n label?: string;\n /** Unused – kept for API compat; stroke is always #747270. */\n color?: string;\n isDark?: boolean;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nconst KonvaContainer = memo(function KonvaContainer({\n nodes,\n label = '',\n}: KonvaContainerProps) {\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n\n const hullData = useMemo(() => calculateHull(nodes), [nodes]);\n\n if (!hullData) return null;\n\n // Inverse-scaled label metrics\n const refNode = nodes[0];\n const screenScale = refNode ? computeNodeTextScreenScale(refNode.width, zoomLevel) : 1;\n const labelFontSize = LABEL_FONT_SIZE * screenScale;\n const labelBoxHeight = Math.ceil(labelFontSize * LABEL_LINE_HEIGHT + 2 * LABEL_PAD_V);\n const boxWidth = label ? measureLabelBoxWidth(label, labelFontSize) : 0;\n const boxX = hullData.anchorX - boxWidth / 2;\n const boxY = hullData.anchorEdgeY - labelBoxHeight / 2;\n\n return (\n <Group listening={false}>\n {/* Dashed hull outline */}\n <Line\n points={hullData.points}\n stroke=\"#747270\"\n strokeWidth={1}\n dash={CONTAINER_DASH}\n closed={true}\n tension={0}\n listening={false}\n perfectDrawEnabled={false}\n />\n\n {/* Inverse-scaled pill label */}\n {label.length > 0 && (\n <Group\n x={boxX + boxWidth / 2}\n y={boxY + labelBoxHeight / 2}\n offsetX={boxWidth / 2}\n offsetY={labelBoxHeight / 2}\n scaleX={1 / zoomLevel}\n scaleY={1 / zoomLevel}\n visible={zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM}\n listening={false}\n >\n <Rect\n width={boxWidth}\n height={labelBoxHeight}\n fill={LABEL_BG}\n cornerRadius={LABEL_BORDER_RADIUS}\n shadowEnabled={false}\n perfectDrawEnabled={false}\n />\n <Text\n x={LABEL_PAD_H}\n y={LABEL_PAD_V}\n width={boxWidth - 2 * LABEL_PAD_H}\n height={labelBoxHeight - 2 * LABEL_PAD_V}\n text={label}\n fontSize={labelFontSize}\n fontFamily={LABEL_FONT_FAMILY}\n fontStyle={LABEL_FONT_WEIGHT}\n fill=\"rgba(0,0,0,1)\"\n align=\"center\"\n verticalAlign=\"middle\"\n lineHeight={LABEL_LINE_HEIGHT}\n perfectDrawEnabled={false}\n listening={false}\n />\n </Group>\n )}\n </Group>\n );\n});\n\nexport default KonvaContainer;\n","// ─── Text Scaling Helpers ─────────────────────────────────────────────────────\n//\n// Determines the scale applied to node title text, keeping text legible and\n// fitted inside the blob shape across the full zoom range.\n//\n// Matches the visualli.ai textScaling logic exactly.\n\nimport { NODE_HEIGHT } from '@visualli/core';\n\nexport const NODE_TEXT_BASE_FONT_PX = 30;\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 * - uses base width of 300px for consistent text sizing\n * - allows taller text box for multi-line wrapping\n *\n * Improved from visualli.ai to handle long labels better with multi-line support.\n */\nexport function computeNodeTextWorldScale(nodeWidth: number, zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n \n // Use a consistent base width (300px) for text scaling\n // This keeps font size more consistent across different node widths\n const baseWidth = 300;\n \n const baseRadiusX = baseWidth / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n const textNaturalWidth = baseWidth - 40;\n // Increase text height to allow 2-3 lines of wrapped text\n const textNaturalHeight = NODE_HEIGHT * 1.2;\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","// ─── NavigationStack ─────────────────────────────────────────────────────────\n//\n// Vertical navigation stack rendered as a fixed left-side overlay.\n// Matches the visualli.ai VisualliNavigationStack design:\n// • Organic hand-drawn circle SVGs per level\n// • Vertical connector lines between levels\n// • Active level highlighted, previous levels clickable to navigate back\n// • Font: Nunito\n\nimport React, { memo, useState } from 'react';\nimport type { VisualliLayer } from '@visualli/core';\n\nexport interface NavStackEntry {\n layerId: string;\n layer: VisualliLayer;\n label: string;\n}\n\nexport interface NavigationStackProps {\n stack: NavStackEntry[];\n onNavigateBack: (index: number) => void;\n isDark?: boolean;\n top?: string;\n left?: string;\n}\n\n// Pastel fills cycled across levels\nconst PASTEL_FILLS = [\n '#b6eea7', '#d5bcfe', '#a1c4fc', '#a6f5d8',\n '#ffc9de', '#c4e8ff', '#f0c4ff', '#ffe0a3',\n];\n\n// Organic circle SVG paths (small / active variants matching visualli.ai)\nconst ORGANIC_PATHS_SMALL = [\n 'M13.72,6.31 C15.12,6.29 17.96,8.57 17.99,10.60 C18.07,14.62 16.72,17.90 11.12,18.00 C7.26,18.07 4.07,14.86 4.00,10.85 C3.93,6.83 9.44,2.02 13.69,4.85',\n 'M13.88,6.41 C15.28,6.43 18.04,8.82 18.00,10.85 C17.93,14.86 16.48,18.10 10.88,18.00 C7.02,17.93 3.94,14.62 4.01,10.60 C4.08,6.59 9.76,1.97 13.91,4.95',\n];\nconst ORGANIC_PATH_ACTIVE =\n 'M16.55,9.22 C17.95,9.15 20.87,11.33 20.97,13.36 C21.19,17.37 19.96,20.70 14.37,20.99 C10.51,21.19 7.20,18.10 7.00,14.09 C6.78,10.08 12.13,5.08 16.48,7.77';\n\nconst CIRCLE_SIZE = 14;\n\nfunction hexToRgba(hex: string, opacity: number): string {\n const h = hex.replace('#', '');\n const r = parseInt(h.substring(0, 2), 16);\n const g = parseInt(h.substring(2, 4), 16);\n const b = parseInt(h.substring(4, 6), 16);\n return `rgba(${r},${g},${b},${opacity})`;\n}\n\nconst OrganicCircle = memo(function OrganicCircle({\n size, fill, stroke, strokeWidth, variant, isActive,\n}: {\n size: number; fill: string; stroke: string; strokeWidth: number; variant: number; isActive?: boolean;\n}) {\n const path = isActive ? ORGANIC_PATH_ACTIVE : ORGANIC_PATHS_SMALL[variant % ORGANIC_PATHS_SMALL.length];\n const vb = isActive ? '4 3 20 20' : '2 1 18 18';\n const vbSz = isActive ? 20 : 18;\n const sw = strokeWidth * vbSz / size;\n return (\n <svg width={size} height={size} viewBox={vb} fill=\"none\" style={{ display: 'block' }}>\n <path d={path} fill={fill} fillOpacity={1} />\n <path d={path} fill=\"none\" stroke={stroke} strokeWidth={sw} strokeLinecap=\"round\" />\n </svg>\n );\n});\n\nconst NavigationStack = memo(function NavigationStack({\n stack,\n onNavigateBack,\n isDark = false,\n top = '16px',\n left = '16px',\n}: NavigationStackProps) {\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n\n // Always render at least the root entry so the user knows where they are.\n if (stack.length === 0) return null;\n\n const visitedStroke = isDark ? '#908e8c' : '#747270';\n const visitedText = isDark ? '#908e8c' : '#747270';\n const activeStroke = isDark ? '#e8e6e4' : '#1a1a18';\n const activeText = isDark ? '#e8e6e4' : '#1a1a18';\n const connectorColor = isDark ? '#908e8c' : '#747270';\n const connectorMarginLeft = 10.5; // padding(4) + circleHalf(7) - connectorHalf(0.5)\n const currentIndex = stack.length - 1;\n\n return (\n <div\n data-help=\"navigation-stack\"\n style={{\n position: 'absolute',\n top,\n left,\n zIndex: 30,\n pointerEvents: 'auto',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', padding: '8px' }}>\n {stack.flatMap((entry, index) => {\n const isCurrent = index === currentIndex;\n const isClickable = index < currentIndex;\n const isHovered = hoveredIndex === index;\n const pastelFill = PASTEL_FILLS[index % PASTEL_FILLS.length];\n const rowBg = isCurrent\n ? hexToRgba(pastelFill, 0.6)\n : isHovered && isClickable\n ? hexToRgba(pastelFill, 0.3)\n : 'transparent';\n\n const items: React.ReactNode[] = [];\n\n if (index > 0) {\n items.push(\n <div\n key={`conn-${index}`}\n style={{\n width: '1px',\n height: '20px',\n marginLeft: `${connectorMarginLeft}px`,\n marginTop: '-6px',\n marginBottom: '-6px',\n background: connectorColor,\n alignSelf: 'flex-start',\n flexShrink: 0,\n position: 'relative',\n zIndex: 1,\n }}\n />,\n );\n }\n\n items.push(\n <div\n key={`${entry.layerId}-${index}`}\n style={{\n position: 'relative',\n zIndex: 2,\n alignSelf: 'flex-start',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n height: '22px',\n padding: '4px',\n borderRadius: '8px',\n cursor: isClickable ? 'pointer' : 'default',\n background: rowBg,\n transition: 'background 0.15s',\n }}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onClick={e => { e.stopPropagation(); if (isClickable) onNavigateBack(index); }}\n >\n <div style={{ width: CIRCLE_SIZE, height: CIRCLE_SIZE, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, zIndex: 4 }}>\n {isCurrent ? (\n <OrganicCircle size={CIRCLE_SIZE} fill={pastelFill} stroke={activeStroke} strokeWidth={1.5} variant={index} isActive />\n ) : (\n <OrganicCircle size={CIRCLE_SIZE} fill={pastelFill} stroke={visitedStroke} strokeWidth={1} variant={index} />\n )}\n </div>\n <span\n style={{\n fontFamily: \"'Nunito', sans-serif\",\n fontSize: isCurrent || (isHovered && isClickable) ? '11px' : '9px',\n fontWeight: isCurrent ? 600 : 400,\n color: isCurrent ? activeText : visitedText,\n lineHeight: 1,\n whiteSpace: 'nowrap',\n transition: 'color 0.15s, font-size 0.15s',\n }}\n >\n {entry.label}\n </span>\n </div>,\n );\n\n return items;\n })}\n </div>\n </div>\n );\n});\n\nexport default NavigationStack;\n","// ─── ZoomControls ─────────────────────────────────────────────────────────────\n//\n// Floating zoom control matching the visualli.ai design:\n// • Side-by-side ZoomIn / ZoomOut buttons (65×32px)\n// • SVG icons (no external dependency)\n// • Inline styles (no Tailwind required in SDK)\n\nimport React, { useCallback, memo } from 'react';\nimport { ZOOM_MIN, ZOOM_MAX } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nexport interface ZoomControlsProps {\n isDark?: boolean;\n}\n\n// ── ZoomIn SVG (Lucide-compatible path) ───────────────────────────────────────\nconst ZoomInIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n <line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\" />\n <line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\" />\n </svg>\n);\n\n// ── ZoomOut SVG ───────────────────────────────────────────────────────────────\nconst ZoomOutIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n <line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\" />\n </svg>\n);\n\nconst ZOOM_STEP = 0.2;\n\nconst ZoomControls = memo(function ZoomControls({ isDark = false }: ZoomControlsProps) {\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n const setZoom = useViewportStore(s => s.setZoom);\n\n const handleZoomIn = useCallback(() => setZoom(Math.min(ZOOM_MAX, zoomLevel * 1.2)), [zoomLevel, setZoom]);\n const handleZoomOut = useCallback(() => setZoom(Math.max(ZOOM_MIN, zoomLevel / 1.2)), [zoomLevel, setZoom]);\n\n const surfaceBg = isDark ? 'var(--bg-surface, #1C1C1A)' : 'var(--bg-surface, #FAF8F4)';\n const border = isDark ? 'var(--border-color, #333330)' : 'var(--border-color, #DDD9D0)';\n const primary = isDark ? 'var(--text-primary, #F0EDE6)' : 'var(--text-primary, #1A1A18)';\n const muted = isDark ? 'var(--text-muted, #8E8C88)' : 'var(--text-muted, #747270)';\n\n return (\n <div\n style={{\n position: 'relative',\n background: surfaceBg,\n border: `0.5px solid ${border}`,\n borderRadius: '8px',\n overflow: 'hidden',\n width: '65px',\n height: '32px',\n flexShrink: 0,\n }}\n role=\"group\"\n aria-label=\"Zoom controls\"\n >\n {/* Zoom In — left half */}\n <button\n onClick={handleZoomIn}\n disabled={zoomLevel >= ZOOM_MAX}\n style={{\n position: 'absolute',\n top: 0, left: 0,\n width: '32px', height: '100%',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n border: 'none', background: 'transparent', cursor: zoomLevel >= ZOOM_MAX ? 'not-allowed' : 'pointer',\n color: zoomLevel >= ZOOM_MAX ? muted : primary,\n transition: 'background 0.15s',\n }}\n onMouseEnter={e => { if (zoomLevel < ZOOM_MAX) (e.currentTarget as HTMLButtonElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLButtonElement).style.background = 'transparent'; }}\n aria-label=\"Zoom in\"\n >\n <ZoomInIcon />\n </button>\n\n {/* Divider */}\n <div style={{ position: 'absolute', top: 0, bottom: 0, left: '32px', width: '0.5px', background: border }} />\n\n {/* Zoom Out — right half */}\n <button\n onClick={handleZoomOut}\n disabled={zoomLevel <= ZOOM_MIN}\n style={{\n position: 'absolute',\n top: 0, right: 0,\n width: '33px', height: '100%',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n border: 'none', background: 'transparent', cursor: zoomLevel <= ZOOM_MIN ? 'not-allowed' : 'pointer',\n color: zoomLevel <= ZOOM_MIN ? muted : primary,\n transition: 'background 0.15s',\n }}\n onMouseEnter={e => { if (zoomLevel > ZOOM_MIN) (e.currentTarget as HTMLButtonElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLButtonElement).style.background = 'transparent'; }}\n aria-label=\"Zoom out\"\n >\n <ZoomOutIcon />\n </button>\n </div>\n );\n});\n\nexport default ZoomControls;\n","// ─── SketchyBoxKonva ─────────────────────────────────────────────────────────\n//\n// Renders the hand-drawn tooltip box using an imperative Konva canvas.\n// Two paths are scaled to fit the container:\n// - BACK_PATH : shadow stroke, offset 8px down\n// - FRONT_PATH: filled main box, offset 5.65px right\n//\n// Matches the visualli.ai SketchyBoxKonva component exactly.\n\nimport React, { useEffect, useRef } from 'react';\nimport Konva from 'konva';\n\nconst BACK_PATH =\n 'M0.653,0 L485.653,1 C485.653,1,484.782,152.773,' +\n '486.653,165 C413.653,171,14.653,178,5.653,168' +\n 'C2.653,158,0.653,0,0.653,0';\n\nconst FRONT_PATH =\n 'M485,167.524 L0,166.524' +\n 'C0,166.524,1.870,8.751,0,0' +\n 'C73,0,479,0,487,8' +\n 'C490,18,485,167.524,485,167.524';\n\nconst BACK_W = 486;\nconst BACK_H = 178;\nconst FRONT_W = 490;\nconst FRONT_H = 168;\n\nconst BACK_OFFSET_Y = 8;\nconst FRONT_OFFSET_X = 5.65;\nconst SHADOW_PAD = 12;\n\nexport interface SketchyBoxKonvaProps {\n children: React.ReactNode;\n fill: string;\n stroke: string;\n backStroke: string;\n padding?: string;\n}\n\nconst SketchyBoxKonva: React.FC<SketchyBoxKonvaProps> = ({\n children,\n fill,\n stroke,\n backStroke,\n padding = '1rem 1.25rem',\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const konvaContainerRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<Konva.Stage | null>(null);\n\n useEffect(() => {\n const wrapper = wrapperRef.current;\n const konvaEl = konvaContainerRef.current;\n if (!wrapper || !konvaEl) return;\n\n function draw(W: number, H: number) {\n if (!konvaEl || W <= 0 || H <= 0) return;\n if (stageRef.current) { stageRef.current.destroy(); stageRef.current = null; }\n\n const stage = new Konva.Stage({ container: konvaEl, width: W, height: H });\n const layer = new Konva.Layer({ listening: false });\n const contentH = H - SHADOW_PAD;\n\n layer.add(new Konva.Path({\n x: 0, y: BACK_OFFSET_Y,\n data: BACK_PATH,\n scaleX: W / BACK_W,\n scaleY: contentH / BACK_H,\n fill: '#ffffff',\n stroke: backStroke,\n strokeWidth: 2,\n strokeScaleEnabled: false,\n listening: false,\n }));\n\n layer.add(new Konva.Path({\n x: FRONT_OFFSET_X, y: 0,\n data: FRONT_PATH,\n scaleX: (W - FRONT_OFFSET_X) / FRONT_W,\n scaleY: contentH / FRONT_H,\n fill,\n stroke,\n strokeWidth: 3,\n strokeScaleEnabled: false,\n listening: false,\n }));\n\n stage.add(layer);\n stageRef.current = stage;\n }\n\n draw(wrapper.offsetWidth, wrapper.offsetHeight);\n\n const ro = new ResizeObserver(entries => {\n const el = entries[0].target as HTMLElement;\n draw(el.offsetWidth, el.offsetHeight);\n });\n ro.observe(wrapper);\n\n return () => {\n ro.disconnect();\n stageRef.current?.destroy();\n stageRef.current = null;\n };\n }, [fill, stroke, backStroke]);\n\n return (\n <div ref={wrapperRef} style={{ position: 'relative', paddingBottom: `${SHADOW_PAD}px` }}>\n <div\n ref={konvaContainerRef}\n style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 0, overflow: 'hidden' }}\n />\n <div style={{ position: 'relative', padding, zIndex: 1 }}>\n {children}\n </div>\n </div>\n );\n};\n\nexport default SketchyBoxKonva;\n","// ─── Visualli Context ─────────────────────────────────────────────────────────\n//\n// React Context for Visualli components (minimal implementation)\n\nimport React, { createContext, useContext } from 'react';\n\nexport interface VisualliContextValue {\n // Reserved for future use\n}\n\nconst VisualliContext = createContext<VisualliContextValue | null>(null);\n\nexport interface VisualliProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Provider for Visualli context\n * \n * @example\n * ```tsx\n * <VisualliProvider>\n * <VisualliCanvas document={doc} />\n * </VisualliProvider>\n * ```\n */\nexport function VisualliProvider({\n children,\n}: VisualliProviderProps) {\n const value: VisualliContextValue = {};\n\n return (\n <VisualliContext.Provider value={value}>\n {children}\n </VisualliContext.Provider>\n );\n}\n\n/**\n * Hook to access Visualli context\n * \n * Returns default empty values if used outside of VisualliProvider\n */\nexport function useVisualli(): VisualliContextValue {\n const ctx = useContext(VisualliContext);\n if (!ctx) {\n return {};\n }\n return ctx;\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useMemo","parseVisualliFile","useRef","useState","useCallback","useEffect","useMemo","darkenHexColor","RBushSpatialIndex","NODE_HEIGHT","TEXT_LABEL_HIDE_BELOW_ZOOM","ZOOM_MIN","set","create","create","stage","useCallback","useRef","useEffect","useRef","useEffect","useCallback","useRef","useEffect","KonvaStage","useRef","useEffect","useRef","useEffect","useMemo","useRef","useRef","React","useMemo","ALL_BLOB_SHAPES","jsx","React","KonvaNode","useMemo","jsx","useRef","useMemo","useEffect","useRef","useLayoutEffect","useMemo","useMemo","NODE_HEIGHT","jsx","jsxs","KonvaEdge","useMemo","jsx","useRef","useMemo","useLayoutEffect","useRef","useLayoutEffect","memo","useMemo","NODE_HEIGHT","TEXT_LABEL_HIDE_BELOW_ZOOM","NODE_HEIGHT","DESCRIPTION_TEXT_BASE_FONT_PX","CONTAINER_LABEL_BASE_FONT_PX","computeNodeTextWorldScale","NODE_HEIGHT","computeNodeTextScreenScale","jsx","jsxs","CONTAINER_LABEL_BASE_FONT_PX","NODE_HEIGHT","memo","KonvaContainer","useMemo","computeNodeTextScreenScale","TEXT_LABEL_HIDE_BELOW_ZOOM","jsx","useRef","useLayoutEffect","memo","useState","jsx","jsxs","OrganicCircle","NavigationStack","useCallback","memo","jsx","jsxs","memo","ZoomControls","useCallback","jsxs","jsx","useEffect","useRef","jsx","jsxs","jsx","jsxs","hexToRgba","useState","useEffect","useMemo","useRef","RBushSpatialIndex","NODE_HEIGHT","useCallback","ZOOM_MIN","TEXT_LABEL_HIDE_BELOW_ZOOM","darkenHexColor","DESCRIPTION_TEXT_BASE_FONT_PX","jsx","jsxs","useState","useEffect","useRef","parseVisualliFile","useMemo","jsx"]}
1
+ {"version":3,"sources":["../src/VisualliRenderer.tsx","../src/VisualliCanvas.tsx","../src/stores/useNodeStore.ts","../src/stores/useViewportStore.ts","../src/stores/stores.ts","../src/hooks/useKonvaRenderer.ts","../src/hooks/useKonvaLayerTransition.ts","../src/animations/konvaLayerTransition.ts","../src/utils/layerNavigation.ts","../src/components/KonvaStage.tsx","../src/konvaCompat.ts","../src/components/KonvaNodeLayer.tsx","../src/hooks/useViewportNodes.ts","../src/components/KonvaNode.tsx","../src/config/index.ts","../src/config/blobShapes.ts","../src/components/KonvaEdgeLayer.tsx","../src/components/KonvaEdge.tsx","../src/components/KonvaContainerLayer.tsx","../src/components/KonvaContainer.tsx","../src/config/textScaling.ts","../src/components/NavigationStack.tsx","../src/components/ZoomControls.tsx","../src/components/SketchyBoxKonva.tsx","../src/context/VisualliContext.tsx"],"sourcesContent":["// ─── VisualliRenderer ────────────────────────────────────────────────────────\n//\n// The single public-facing component for rendering a .visualli document.\n//\n// <VisualliRenderer visualliString={str} theme=\"dark\" width=\"100%\" height=\"600px\" />\n// <VisualliRenderer visualliFile={file} theme=\"auto\" width={800} height={600} />\n// <VisualliRenderer document={doc} theme=\"auto\" width={800} height={600} />\n//\n// Handles:\n// • theme: 'dark' | 'light' | 'auto' — auto follows prefers-color-scheme\n// • width / height as first-class props (CSS string or pixel number)\n// • Empty state — no data prop provided\n// • Loading state — while parsing a .visualli file/string\n// • Error state — parse failure with message\n// • useWorker — offload parsing to a Web Worker (default: false)\n// • Delegates all canvas/navigation/zoom logic to VisualliCanvas\n\nimport React, { useEffect, useRef, useState, useMemo } from 'react';\nimport type { VisualliDocument, VisualliLayer, FlatNode } from '@visualli/core';\nimport { parseVisualliFile } from '@visualli/core';\nimport VisualliCanvas from './VisualliCanvas';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type VisualliTheme = 'dark' | 'light' | 'auto';\n\nexport interface VisualliRendererProps {\n /**\n * Raw JSONL string — the content of a .visualli file.\n * Simply pass the string data directly, no preprocessing needed.\n * Example: visualliString=\"{\\\"type\\\":\\\"meta\\\"...}\\n{\\\"type\\\":\\\"layer\\\"...}\"\n */\n visualliString?: string;\n\n /**\n * A .visualli file — can be:\n * - File object (e.g. from <input type=\"file\">)\n * - String path to file (e.g. '/data/myfile.visualli' or './src/data/data.visualli')\n * The renderer automatically fetches, reads, and parses it.\n * No user code required for conversion or processing.\n */\n visualliFile?: File | string;\n\n /**\n * When true, parsing is offloaded to a Web Worker so the main thread never\n * blocks during JSON.parse. Recommended for large documents (>500 nodes).\n * Has no effect when `document` is supplied (already parsed).\n * @default true\n */\n useWorker?: boolean;\n\n /**\n * Colour theme.\n * - 'dark' → always dark background\n * - 'light' → always light background\n * - 'auto' → follows the OS/browser prefers-color-scheme\n * @default 'light'\n */\n theme?: VisualliTheme;\n\n /**\n * Enable chromatic immersion background effect.\n * When true:\n * - Root layer (level 0) shows base background color\n * - Child layers show parent node's color as semi-transparent background\n * @default false\n */\n chromaticImmersion?: boolean;\n\n /**\n * Width of the renderer. Accepts any CSS length string ('100%', '800px', '100vw')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n width?: string | number;\n\n /**\n * Height of the renderer. Accepts any CSS length string ('100%', '600px', '100vh')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n height?: string | number;\n\n /** Additional CSS class on the root element. */\n className?: string;\n\n /** Additional inline styles merged onto the root element. */\n style?: React.CSSProperties;\n}\n\n// ── System dark-mode hook ─────────────────────────────────────────────────────\n\nfunction useSystemDark(): boolean {\n const mq = typeof window !== 'undefined'\n ? window.matchMedia('(prefers-color-scheme: dark)')\n : null;\n\n const [dark, setDark] = useState<boolean>(mq?.matches ?? false);\n\n useEffect(() => {\n if (!mq) return;\n const handler = (e: MediaQueryListEvent) => setDark(e.matches);\n mq.addEventListener('change', handler);\n return () => mq.removeEventListener('change', handler);\n }, [mq]);\n\n return dark;\n}\n\n// ── Font Injection Hook ───────────────────────────────────────────────────────\n\nfunction useFontInjection() {\n useEffect(() => {\n if (typeof document === 'undefined') return;\n \n const links = [\n 'https://fonts.googleapis.com',\n 'https://fonts.gstatic.com',\n 'https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&family=Nunito+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300&display=swap',\n 'https://fonts.googleapis.com/css2?family=Playpen+Sans:wght@300;400;600;800&family=Story+Script:wght@400&display=swap'\n ];\n\n links.forEach((href, i) => {\n const id = `visualli-font-${i}`;\n if (!document.getElementById(id)) {\n const link = document.createElement('link');\n link.id = id;\n link.rel = i < 2 ? 'preconnect' : 'stylesheet';\n link.href = href;\n if (i === 1) link.crossOrigin = 'anonymous';\n document.head.appendChild(link);\n }\n });\n }, []);\n}\n\n// ── Empty / Loading / Error states ───────────────────────────────────────────\n\n// ── UI State Components ───────────────────────────────────────────────────────\n\nfunction EmptyState({ isDark }: { isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const fg = isDark ? 'rgba(240,237,230,0.35)' : 'rgba(26,26,24,0.35)';\n const bd = isDark ? '#2A2A28' : '#DDD9D0';\n const code = { fontFamily: 'monospace', fontSize: 12, padding: '1px 4px', borderRadius: 4, background: isDark ? '#222220' : '#E8E4DC', border: `1px solid ${bd}` };\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', gap: 16, background: bg, color: fg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" stroke={fg} strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"10\" y=\"6\" width=\"28\" height=\"36\" rx=\"3\" />\n <line x1=\"16\" y1=\"16\" x2=\"32\" y2=\"16\" />\n <line x1=\"16\" y1=\"22\" x2=\"32\" y2=\"22\" />\n <line x1=\"16\" y1=\"28\" x2=\"26\" y2=\"28\" />\n </svg>\n <div style={{ textAlign: 'center', lineHeight: 1.7 }}>\n <p style={{ margin: 0, fontSize: 15, fontWeight: 600, color: isDark ? 'rgba(240,237,230,0.7)' : 'rgba(26,26,24,0.7)' }}>\n No .visualli file provided\n </p>\n <p style={{ margin: '4px 0 0', fontSize: 13 }}>\n Pass a <code style={code}>visualliFile</code> or <code style={code}>visualliString</code> prop.\n </p>\n </div>\n </div>\n );\n}\n\nfunction LoadingState({ isDark }: { isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const fg = isDark ? 'rgba(240,237,230,0.5)' : 'rgba(26,26,24,0.5)';\n const dot = isDark ? 'rgba(240,237,230,0.6)' : 'rgba(26,26,24,0.45)';\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', gap: 16, background: bg, color: fg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <div style={{ display: 'flex', gap: 8 }}>\n {[0, 1, 2].map(i => (\n <div key={i} style={{ width: 8, height: 8, borderRadius: '50%', background: dot, animation: `vr-pulse 1.2s ease-in-out ${i * 0.2}s infinite` }} />\n ))}\n </div>\n <style>{`@keyframes vr-pulse{0%,80%,100%{opacity:.2;transform:scale(.9)}40%{opacity:1;transform:scale(1.1)}}`}</style>\n <p style={{ margin: 0, fontSize: 14 }}>Loading .visualli file…</p>\n </div>\n );\n}\n\nfunction ErrorState({ message, isDark }: { message: string; isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const bd = isDark ? '#3a1f1f' : '#F0CECE';\n const card = isDark ? '#1e1212' : '#FFF5F5';\n const head = isDark ? '#F87171' : '#DC2626';\n const body = isDark ? 'rgba(248,113,113,0.8)' : 'rgba(180,40,40,0.8)';\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', padding: '24px', background: bg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <div style={{ maxWidth: 480, width: '100%', padding: '20px 24px', borderRadius: 12, border: `1px solid ${bd}`, background: card }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke={head} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n <span style={{ fontSize: 15, fontWeight: 700, color: head }}>Failed to parse .visualli file</span>\n </div>\n <p style={{ margin: 0, fontSize: 13, color: body, lineHeight: 1.6, wordBreak: 'break-word', fontFamily: 'monospace' }}>{message}</p>\n </div>\n </div>\n );\n}\n\n// ── Inline worker script ──────────────────────────────────────────────────────\n// Self-contained JSONL parser that mirrors parseVisualliFile.\n// Runs in a Web Worker when useWorker=true; no external imports needed.\n\nconst WORKER_SCRIPT = `\nself.onmessage = function(e) {\n var content = e.data;\n try {\n var lines = content.trim().split('\\\\n');\n var doc = {\n meta: null,\n layers: new Map(),\n layersByLevel: new Map(),\n rootLayer: null,\n };\n for (var i = 0; i < lines.length; i++) {\n var line = lines[i].trim();\n if (!line) continue;\n var obj;\n try { obj = JSON.parse(line); }\n catch(err) { throw new Error('Failed to parse JSON at line ' + (i+1) + ': ' + err); }\n if (!obj.type) throw new Error(\"Missing 'type' field at line \" + (i+1));\n if (obj.type === 'meta') {\n doc.meta = obj;\n } else if (obj.type === 'layer') {\n doc.layers.set(obj.id, obj);\n if (!doc.layersByLevel.has(obj.level)) doc.layersByLevel.set(obj.level, []);\n doc.layersByLevel.get(obj.level).push(obj);\n if (obj.level === 0) doc.rootLayer = obj;\n }\n }\n if (!doc.meta) throw new Error('Missing required meta section');\n if (!doc.rootLayer) throw new Error('Missing root layer (level 0)');\n self.postMessage({ ok: true, doc: doc });\n } catch(err) {\n self.postMessage({ ok: false, message: err.message || String(err) });\n }\n};\n`;\n\n// Lazy-create worker URL once (module-level singleton).\nlet _workerUrl: string | null = null;\nfunction getWorkerUrl(): string {\n if (!_workerUrl) {\n _workerUrl = URL.createObjectURL(new Blob([WORKER_SCRIPT], { type: 'text/javascript' }));\n }\n return _workerUrl;\n}\n\n// ── Parse hook ────────────────────────────────────────────────────────────────\n\ntype ParseState =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'ready'; doc: VisualliDocument }\n | { status: 'error'; message: string };\n\n/**\n * Resolves a raw string + optional File into a ParseState.\n * When useWorker=true the JSON.parse work runs in a Web Worker so the main\n * thread is never blocked, even for very large documents.\n */\nfunction useAsyncParse(\n content: string | undefined,\n useWorker: boolean,\n): ParseState {\n const [state, setState] = useState<ParseState>({ status: 'idle' });\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n if (!content) { setState({ status: 'idle' }); return; }\n\n setState({ status: 'loading' });\n let cancelled = false;\n\n if (useWorker && typeof Worker !== 'undefined') {\n // Terminate any previous worker\n workerRef.current?.terminate();\n const w = new Worker(getWorkerUrl());\n workerRef.current = w;\n\n w.onmessage = (e: MessageEvent) => {\n if (cancelled) return;\n if (e.data.ok) {\n setState({ status: 'ready', doc: e.data.doc as VisualliDocument });\n } else {\n setState({ status: 'error', message: e.data.message });\n }\n };\n w.onerror = (e: ErrorEvent) => {\n if (!cancelled) setState({ status: 'error', message: e.message });\n };\n w.postMessage(content);\n\n return () => {\n cancelled = true;\n w.terminate();\n workerRef.current = null;\n };\n }\n\n // Main-thread path: defer via microtask so React paints the loading state first\n Promise.resolve().then(() => {\n if (cancelled) return;\n try {\n const doc = parseVisualliFile(content);\n if (!cancelled) setState({ status: 'ready', doc });\n } catch (err) {\n if (!cancelled) setState({ status: 'error', message: err instanceof Error ? err.message : String(err) });\n }\n });\n return () => { cancelled = true; };\n }, [content, useWorker]);\n\n // Terminate worker on unmount\n useEffect(() => () => { workerRef.current?.terminate(); }, []);\n\n return state;\n}\n\n// ── File → string hook ────────────────────────────────────────────────────────\n\nfunction useFileText(file: File | string | undefined): { text: string | undefined; error: string | undefined; loading: boolean } {\n const [text, setText] = useState<string | undefined>(undefined);\n const [error, setError] = useState<string | undefined>(undefined);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!file) { setText(undefined); setError(undefined); setLoading(false); return; }\n setLoading(true); setText(undefined); setError(undefined);\n let cancelled = false;\n\n // Handle string path - fetch the file\n if (typeof file === 'string') {\n fetch(file)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n })\n .catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n // Handle File object - read as text\n else {\n file.text().then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n }).catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n \n return () => { cancelled = true; };\n }, [file]);\n\n return { text, error, loading };\n}\n\n// ── VisualliRenderer ──────────────────────────────────────────────────────────\n\nexport default function VisualliRenderer({\n visualliString,\n visualliFile,\n theme = 'light',\n width = '100%',\n height = '100%',\n useWorker = true,\n chromaticImmersion = false,\n className,\n style,\n}: VisualliRendererProps) {\n useFontInjection();\n const systemDark = useSystemDark();\n const isDark = theme === 'dark' ? true : theme === 'light' ? false : systemDark;\n\n const cssWidth = typeof width === 'number' ? `${width}px` : width;\n const cssHeight = typeof height === 'number' ? `${height}px` : height;\n\n // Read File → text (no-op if not provided)\n const { text: fileText, error: fileReadError, loading: fileReading } = useFileText(visualliFile);\n\n // The raw JSONL string to parse: file takes priority over string prop\n const rawContent = fileText ?? visualliString;\n\n const parseState = useAsyncParse(rawContent, useWorker);\n\n const resolvedDoc: VisualliDocument | null = useMemo(() => {\n if (parseState.status === 'ready') return parseState.doc;\n return null;\n }, [parseState]);\n\n const wrapperStyle: React.CSSProperties = { width: cssWidth, height: cssHeight, overflow: 'hidden', ...style };\n\n // ── Empty state ─────────────────────────────────────────────────────────────\n if (!visualliString && !visualliFile) {\n return <div className={className} style={wrapperStyle}><EmptyState isDark={isDark} /></div>;\n }\n\n // ── Loading state ───────────────────────────────────────────────────────────\n if (fileReading || parseState.status === 'loading') {\n return <div className={className} style={wrapperStyle}><LoadingState isDark={isDark} /></div>;\n }\n\n // ── Error state ─────────────────────────────────────────────────────────────\n if (fileReadError || parseState.status === 'error') {\n const msg = fileReadError ?? (parseState.status === 'error' ? parseState.message : 'Unknown error');\n return <div className={className} style={wrapperStyle}><ErrorState message={msg} isDark={isDark} /></div>;\n }\n\n // ── Canvas ──────────────────────────────────────────────────────────────────\n return (\n <div className={className} style={wrapperStyle}>\n <VisualliCanvas\n preParsedVisualli={resolvedDoc ?? undefined}\n isDark={isDark}\n chromaticImmersion={chromaticImmersion}\n style={{ width: '100%', height: '100%' }}\n />\n </div>\n );\n}\n","// ─── VisualliCanvas ───────────────────────────────────────────────────────────\n//\n// Main canvas component for rendering a VisualliDocument.\n// Matches the visualli.ai enhanced canvas implementation:\n// • Stage-level hit detection via RBush spatial index (no Konva hit-canvas)\n// • Node description tooltip (sketchy-box style)\n// • Chromatic immersion background (color from current node)\n// • Auto-zoom navigation (zoom in → child layer, zoom out → parent layer)\n// • Professional layer transitions (zoom in / zoom out animations)\n// • Vertical left-side navigation stack\n// • Zoom controls (icon-based, top-right)\n// • Context menu (right-click to go back)\n//\n// NOT included (SDK-only, no generation UI):\n// • Sidebar, search, generation\n// • Semantic anchor tooltips (special word meanings)\n// • Branding logo\n// • Help overlay / view-source panel\n\nimport React, { useRef, useState, useCallback, useEffect, useMemo, useLayoutEffect } from 'react';\nimport type Konva from 'konva';\nimport type { VisualliDocument, VisualliLayer, FlatNode, MindMapConnection } from '@visualli/core';\nimport {\n parseVisualliFile,\n getNodesForLayer,\n getThemeBackground,\n darkenHexColor,\n RBushSpatialIndex,\n NODE_HEIGHT,\n TEXT_LABEL_HIDE_BELOW_ZOOM,\n ZOOM_NAV_IN_THRESHOLD,\n ZOOM_NAV_OUT_THRESHOLD,\n ZOOM_MIN,\n} from '@visualli/core';\n\nimport { useNodeStore } from './stores/useNodeStore';\nimport { useViewportStore } from './stores/useViewportStore';\nimport { useSelectionStore } from './stores/stores';\n\nimport { useKonvaRenderer } from './hooks/useKonvaRenderer';\nimport { useKonvaLayerTransition } from './hooks/useKonvaLayerTransition';\n\nimport KonvaStage from './components/KonvaStage';\nimport KonvaNodeLayer from './components/KonvaNodeLayer';\nimport KonvaEdgeLayer from './components/KonvaEdgeLayer';\nimport KonvaContainerLayer from './components/KonvaContainerLayer';\nimport NavigationStack, { type NavStackEntry } from './components/NavigationStack';\nimport ZoomControls from './components/ZoomControls';\nimport SketchyBoxKonva from './components/SketchyBoxKonva';\n\nimport { getChildLayerForNode, calculateFitView, getConnectionsForLayer, getContainersForLayer } from './utils/layerNavigation';\nimport type { ContainerGroup } from './components/KonvaContainerLayer';\nimport type { AnimatorViewport } from './animations/konvaLayerTransition';\nimport { DESCRIPTION_TEXT_BASE_FONT_PX } from './config/textScaling';\nimport { useVisualli } from './context/VisualliContext';\n\n// Helper to convert hex color to rgba with transparency\nfunction hexToRgba(hex: string, alpha: number): string {\n // Remove # if present\n hex = hex.replace(/^#/, '');\n \n // Parse hex values\n let r: number, g: number, b: number;\n if (hex.length === 3) {\n r = parseInt(hex[0] + hex[0], 16);\n g = parseInt(hex[1] + hex[1], 16);\n b = parseInt(hex[2] + hex[2], 16);\n } else if (hex.length === 6) {\n r = parseInt(hex.substring(0, 2), 16);\n g = parseInt(hex.substring(2, 4), 16);\n b = parseInt(hex.substring(4, 6), 16);\n } else {\n return `rgba(240, 237, 230, ${alpha})`; // fallback\n }\n \n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveDocument(props: VisualliCanvasProps, fileText?: string): VisualliDocument | null {\n if (props.preParsedVisualli) return props.preParsedVisualli;\n const rawContent = fileText ?? props.visualliString;\n if (rawContent) {\n try { return parseVisualliFile(rawContent); } catch { return null; }\n }\n return null;\n}\n\nfunction layerLabel(doc: VisualliDocument, layer: VisualliLayer, layerId: string): string {\n if (layer.parentNodeId) {\n // Find the parent node in the parent layer to get its title\n const parentLayer = layer.parentLayerId ? doc.layers.get(layer.parentLayerId) : null;\n if (parentLayer) {\n const parentNode = parentLayer.nodes.find(n => n.id === layer.parentNodeId);\n if (parentNode) {\n return Array.isArray(parentNode.data.label)\n ? (parentNode.data.label as string[]).join(' ')\n : (parentNode.data.label || 'Untitled');\n }\n }\n }\n return layer.description ?? layerId;\n}\n\nfunction getRootLayerId(doc: VisualliDocument): string | null {\n for (const [id, layer] of doc.layers) {\n if (!layer.parentLayerId) return id;\n }\n return doc.layers.keys().next().value ?? null;\n}\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\nexport interface VisualliCanvasProps {\n preParsedVisualli?: VisualliDocument;\n /**\n * Raw JSONL string — just pass the string data directly.\n * No preprocessing needed by user.\n */\n visualliString?: string;\n /**\n * A .visualli file — can be:\n * - File object (from file input)\n * - String path to file (e.g. '/data/file.visualli')\n * Component handles all fetching and parsing automatically.\n */\n visualliFile?: File | string;\n isDark?: boolean;\n chromaticImmersion?: boolean;\n onNodeClick?: (node: FlatNode) => void;\n onLayerChange?: (layerId: string, layer: VisualliLayer) => void;\n \n // Extension points for private features (implement in consuming app)\n renderOverlay?: (params: { isDark: boolean; containerWidth: number; containerHeight: number }) => React.ReactNode;\n renderNodeContent?: (params: { \n summary: string; \n nodeId: string; \n nodeColor?: string;\n zoom: number;\n }) => React.ReactNode;\n navigationStackTop?: string;\n navigationStackLeft?: string;\n \n className?: string;\n style?: React.CSSProperties;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport default function VisualliCanvas(props: VisualliCanvasProps) {\n const { isDark = false, chromaticImmersion = false, onNodeClick, onLayerChange, renderOverlay, renderNodeContent, navigationStackTop = '16px', navigationStackLeft = '16px', className = '', style } = props;\n\n // Read file if provided (handles both File objects and string paths)\n const [fileText, setFileText] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!props.visualliFile) { setFileText(undefined); return; }\n let cancelled = false;\n \n // Handle string path - fetch the file\n if (typeof props.visualliFile === 'string') {\n fetch(props.visualliFile)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) setFileText(t);\n })\n .catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n // Handle File object - read as text\n else {\n props.visualliFile.text().then(t => {\n if (!cancelled) setFileText(t);\n }).catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n \n return () => { cancelled = true; };\n }, [props.visualliFile]);\n\n const doc = useMemo(() => resolveDocument(props, fileText), [props.preParsedVisualli, props.visualliString, props.visualliFile, fileText]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Navigation ────────────────────────────────────────────────────────────\n const [navStack, setNavStack] = useState<NavStackEntry[]>([]);\n const [currentLayerId, setCurrentLayerId] = useState<string | null>(null);\n const parentViewports = useRef<AnimatorViewport[]>([]);\n const [isTransitioning, setIsTransitioning] = useState(false);\n const isTransitioningRef = useRef(false);\n\n useEffect(() => {\n if (!doc) return;\n const rootId = getRootLayerId(doc);\n if (!rootId) return;\n const rootLayer = doc.layers.get(rootId)!;\n setCurrentLayerId(rootId);\n setNavStack([{ layerId: rootId, layer: rootLayer, label: 'Home' }]);\n parentViewports.current = [];\n }, [doc]);\n\n // ── Active layer → FlatNodes ──────────────────────────────────────────────\n const { flatNodes, connections, containers } = useMemo(() => {\n if (!doc || !currentLayerId) return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] };\n try {\n return {\n flatNodes: getNodesForLayer(doc, currentLayerId),\n connections: getConnectionsForLayer(doc, currentLayerId),\n containers: getContainersForLayer(doc, currentLayerId) as ContainerGroup[],\n };\n } catch { return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] }; }\n }, [doc, currentLayerId]);\n\n // ── Stores ────────────────────────────────────────────────────────────────\n const setNodes = useNodeStore(s => s.setNodes);\n const nodes = useNodeStore(s => s.nodes);\n const updateNodePosition = useNodeStore(s => s.updateNodePosition);\n const setCenter = useViewportStore(s => s.setCenter);\n const setZoom = useViewportStore(s => s.setZoom);\n const viewport = useViewportStore(s => ({\n centerX: s.centerX, centerY: s.centerY, zoomLevel: s.zoomLevel,\n canvasWidth: s.canvasWidth, canvasHeight: s.canvasHeight,\n }));\n const clearSel = useSelectionStore(s => s.clear);\n const select = useSelectionStore(s => s.select);\n\n // Sync nodes → store\n useEffect(() => {\n const map = new Map(flatNodes.map(n => [n.id, n]));\n setNodes(map);\n clearSel();\n }, [flatNodes, setNodes, clearSel]);\n\n // ── Canvas refs ───────────────────────────────────────────────────────────\n const containerRef = useRef<HTMLDivElement | null>(null);\n const stageRef = useRef<Konva.Stage | null>(null);\n const canvasWrapperRef = useRef<HTMLDivElement>(null);\n\n // ── GPU CSS-transform transition refs (matches visualli.ai) ───────────────\n // During animations we express viewport deltas as CSS transforms on Konva's\n // container div — zero canvas redraws, handled entirely by the GPU compositor.\n const baselineTransformRef = useRef<{ x: number; y: number; scaleX: number; scaleY: number } | null>(null);\n const konvaContentDivRef = useRef<HTMLDivElement | null>(null);\n const lastAnimViewportRef = useRef<{ centerX: number; centerY: number; zoomLevel: number } | null>(null);\n const zoomOutTargetRef = useRef<{ centerX: number; centerY: number; zoomLevel: number } | null>(null);\n // canvasSizeRef is kept in sync with the measured container size (not window).\n // Initialise to 0 — it will be updated synchronously before the first frame.\n const canvasSizeRef = useRef({ width: 0, height: 0 });\n\n // ── Node drag refs (RAF-throttled, matches visualli.ai) ───────────────────\n const dragMoveRafRef = useRef<number | null>(null);\n const dragMoveLatestRef = useRef<{ nodeId: string; x: number; y: number } | null>(null);\n const dragStartPosRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n\n // ── Background color (with chromatic immersion support) ──────────────────\n const baseBgColor = isDark ? '#141412' : '#F0EDE6';\n \n // For chromatic immersion: get the parent node color for child layers\n const chromaticBgColor = useMemo(() => {\n if (!chromaticImmersion || !doc || !currentLayerId) return baseBgColor;\n \n const currentLayer = doc.layers.get(currentLayerId);\n if (!currentLayer) return baseBgColor;\n \n // Root layer always uses base background\n if (currentLayer.level === 0 || !currentLayer.parentNodeId) return baseBgColor;\n \n // For child layers, find the parent node's color\n const parentLayer = currentLayer.parentLayerId ? doc.layers.get(currentLayer.parentLayerId) : null;\n if (parentLayer) {\n const parentNode = parentLayer.nodes.find(n => n.id === currentLayer.parentNodeId);\n if (parentNode) {\n const nodeColor = parentNode.data.color || baseBgColor;\n // Add transparency to the parent node color for subtle effect\n return hexToRgba(nodeColor, 0.15);\n }\n }\n \n return baseBgColor;\n }, [chromaticImmersion, doc, currentLayerId, baseBgColor]);\n \n const bgColor = chromaticImmersion ? chromaticBgColor : baseBgColor;\n\n // ── Spatial index (for stage-level hit detection) ─────────────────────────\n const spatialIndexRef = useRef<RBushSpatialIndex | null>(null);\n useEffect(() => {\n if (flatNodes.length === 0) { spatialIndexRef.current?.clear(); return; }\n const idx = new RBushSpatialIndex();\n idx.bulkLoad(flatNodes.map(n => {\n const blobHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (n.width / 2) * 0.74);\n return {\n nodeId: n.id,\n bounds: {\n minX: n.x - n.width / 2, minY: n.y - blobHalfH,\n maxX: n.x + n.width / 2, maxY: n.y + blobHalfH,\n },\n };\n }));\n spatialIndexRef.current = idx;\n return () => { spatialIndexRef.current?.clear(); };\n }, [flatNodes]);\n\n // ── Konva renderer (resize + FPS) ─────────────────────────────────────────\n const {\n handleWheel: rendererHandleWheel,\n handleMouseDown: rendererHandleMouseDown,\n handleMouseMove: rendererHandleMouseMove,\n handleMouseUp: rendererHandleMouseUp,\n canvasWidth,\n canvasHeight,\n } = useKonvaRenderer({ containerRef, stageRef });\n\n // Keep canvasSizeRef in sync with the measured container size.\n // The fallback to containerRef.getBoundingClientRect covers the period before\n // the first ResizeObserver callback fires.\n const _cw = canvasWidth || containerRef.current?.getBoundingClientRect().width || 800;\n const _ch = canvasHeight || containerRef.current?.getBoundingClientRect().height || 600;\n canvasSizeRef.current = { width: _cw, height: _ch };\n\n // ── Individual node drag (RAF-throttled, matches visualli.ai) ────────────\n const handleDragStart = useCallback((nodeId: string) => {\n isDraggingRef.current = true;\n setIsDraggingState(true);\n setHoveredNode(null);\n const node = nodes.get(nodeId);\n if (node) dragStartPosRef.current.set(nodeId, { x: node.x, y: node.y });\n }, [nodes]);\n\n const handleDragMove = useCallback((nodeId: string, x: number, y: number) => {\n dragMoveLatestRef.current = { nodeId, x, y };\n if (dragMoveRafRef.current !== null) return;\n dragMoveRafRef.current = requestAnimationFrame(() => {\n dragMoveRafRef.current = null;\n const latest = dragMoveLatestRef.current;\n if (latest) { dragMoveLatestRef.current = null; updateNodePosition(latest.nodeId, latest.x, latest.y); }\n });\n }, [updateNodePosition]);\n\n const handleDragEnd = useCallback((nodeId: string, x: number, y: number) => {\n if (dragMoveRafRef.current !== null) { cancelAnimationFrame(dragMoveRafRef.current); dragMoveRafRef.current = null; }\n dragMoveLatestRef.current = null;\n isDraggingRef.current = false;\n setIsDraggingState(false);\n updateNodePosition(nodeId, x, y);\n // Update spatial index entry\n if (spatialIndexRef.current) {\n const node = nodes.get(nodeId);\n if (node) {\n const oldPos = dragStartPosRef.current.get(nodeId);\n if (oldPos) {\n const oldHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (node.width / 2) * 0.74);\n spatialIndexRef.current.remove(nodeId, {\n minX: oldPos.x - node.width / 2, minY: oldPos.y - oldHalfH,\n maxX: oldPos.x + node.width / 2, maxY: oldPos.y + oldHalfH,\n });\n }\n const newHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (node.width / 2) * 0.74);\n spatialIndexRef.current.insert(nodeId, {\n minX: x - node.width / 2, minY: y - newHalfH,\n maxX: x + node.width / 2, maxY: y + newHalfH,\n });\n }\n }\n dragStartPosRef.current.delete(nodeId);\n }, [updateNodePosition, nodes]);\n // Keep a ref to the latest fitToScreen so async callbacks (onComplete) always\n // call the most current version without re-creating the animation pipeline.\n const fitToScreenRef = useRef<() => void>(() => {});\n\n const fitToScreen = useCallback(() => {\n if (flatNodes.length === 0) return;\n if (isTransitioningRef.current) return; // animation is controlling viewport\n // Use the container's measured size (not window) so the fit is always\n // relative to the renderer's actual bounding box.\n const cw = canvasSizeRef.current.width || containerRef.current?.getBoundingClientRect().width || 800;\n const ch = canvasSizeRef.current.height || containerRef.current?.getBoundingClientRect().height || 600;\n const { centerX, centerY } = calculateFitView(flatNodes, cw, ch);\n // Root layer: always use 1.0 zoom to match visualli.ai reference behaviour.\n // calculateFitZoom for a single node or dense layout on a 1920-default canvas\n // produces zoom > 2 which triggers the auto-zoom-in threshold immediately.\n const isRootLayer = navStack.length <= 1;\n // Root layer: use 1.0 zoom to match visualli.ai reference behaviour.\n // Child layers use the bounding-box fit zoom (already clamped to [0.4, 5]).\n const zoomLevel = isRootLayer ? 1.0 : calculateFitView(flatNodes, cw, ch).zoomLevel;\n setCenter(centerX, centerY);\n setZoom(zoomLevel);\n }, [flatNodes, navStack.length, setCenter, setZoom]);\n\n // Keep ref in sync after every render so async callbacks always use latest closure\n fitToScreenRef.current = fitToScreen;\n\n useEffect(() => { fitToScreen(); }, [currentLayerId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Re-fit when the canvas is properly measured for the first time (the RAF in\n // useKonvaRenderer updates canvasWidth from 0 → container width asynchronously).\n const didFitAfterMeasureRef = useRef(false);\n useEffect(() => {\n if (!canvasWidth || didFitAfterMeasureRef.current) return;\n didFitAfterMeasureRef.current = true;\n fitToScreen();\n }, [canvasWidth, fitToScreen]);\n\n // ── Layer transitions ─────────────────────────────────────────────────────\n\n // Stores the target nav-back index so onSwapBack can read it\n const navBackTargetRef = useRef<number>(-1);\n\n const { zoomIntoLayer, zoomOutToParent, isTransitioning: isAnimating } = useKonvaLayerTransition({\n stageRef,\n canvasWrapperRef,\n onSwapLayer: (childLayerId) => {\n const childLayer = doc?.layers.get(childLayerId);\n if (!childLayer || !doc) return;\n setCurrentLayerId(childLayerId);\n setNavStack(prev => [...prev, { layerId: childLayerId, layer: childLayer, label: layerLabel(doc, childLayer, childLayerId) }]);\n onLayerChange?.(childLayerId, childLayer);\n },\n onSwapBack: () => {\n const targetIndex = navBackTargetRef.current;\n setNavStack(prev => {\n const newStack = prev.slice(0, targetIndex + 1);\n parentViewports.current = parentViewports.current.slice(0, targetIndex);\n const newLayerId = newStack[newStack.length - 1].layerId;\n setCurrentLayerId(newLayerId);\n onLayerChange?.(newLayerId, newStack[newStack.length - 1].layer);\n return newStack;\n });\n },\n onComplete: () => {\n setIsTransitioning(false);\n isTransitioningRef.current = false;\n // After every layer switch, snap to the fit view so zoom is always clean.\n // rAF ensures React has committed new node data before we compute the fit.\n requestAnimationFrame(() => { fitToScreenRef.current(); });\n },\n // GPU CSS-transform callbacks (matching visualli.ai exactly):\n onViewportFrame: (vp) => {\n lastAnimViewportRef.current = vp;\n const baseline = baselineTransformRef.current;\n const contentDiv = konvaContentDivRef.current;\n const { width, height } = canvasSizeRef.current;\n if (baseline && contentDiv) {\n const targetX = width / 2 - vp.centerX * vp.zoomLevel;\n const targetY = height / 2 - vp.centerY * vp.zoomLevel;\n const ratio = vp.zoomLevel / baseline.scaleX;\n const tx = targetX - baseline.x * ratio;\n const ty = targetY - baseline.y * ratio;\n contentDiv.style.transform = `translate(${tx}px, ${ty}px) scale(${ratio})`;\n } else {\n const stage = stageRef.current;\n if (stage) {\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.batchDraw();\n }\n }\n },\n onViewportFinal: (vp) => {\n if (konvaContentDivRef.current) konvaContentDivRef.current.style.transform = '';\n const stage = stageRef.current;\n if (stage) {\n const { width, height } = canvasSizeRef.current;\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n }\n setCenter(vp.centerX, vp.centerY);\n setZoom(vp.zoomLevel);\n },\n onPhaseChange: (phase) => {\n const stage = stageRef.current;\n const contentDiv = konvaContentDivRef.current;\n if (stage && contentDiv && (phase === 'swap' || phase === 'zoom-back')) {\n contentDiv.style.transform = '';\n const vp = phase === 'zoom-back' ? zoomOutTargetRef.current : lastAnimViewportRef.current;\n if (vp) {\n const { width, height } = canvasSizeRef.current;\n const nx = width / 2 - vp.centerX * vp.zoomLevel;\n const ny = height / 2 - vp.centerY * vp.zoomLevel;\n stage.x(nx); stage.y(ny);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n baselineTransformRef.current = { x: nx, y: ny, scaleX: vp.zoomLevel, scaleY: vp.zoomLevel };\n }\n }\n },\n onTransitionLifecycle: (phase) => {\n const stage = stageRef.current;\n if (phase === 'start') {\n if (canvasWrapperRef.current) canvasWrapperRef.current.style.willChange = 'opacity, transform';\n if (stage) {\n baselineTransformRef.current = { x: stage.x(), y: stage.y(), scaleX: stage.scaleX(), scaleY: stage.scaleY() };\n const container = stage.container();\n const cd = container?.querySelector('.konvajs-content') as HTMLDivElement | null;\n if (cd) {\n konvaContentDivRef.current = cd;\n cd.style.transformOrigin = '0 0';\n cd.style.willChange = 'transform';\n }\n stage.getLayers().forEach(l => { l.listening(false); });\n }\n } else {\n if (canvasWrapperRef.current) canvasWrapperRef.current.style.willChange = 'auto';\n if (konvaContentDivRef.current) { konvaContentDivRef.current.style.willChange = 'auto'; konvaContentDivRef.current = null; }\n baselineTransformRef.current = null;\n zoomOutTargetRef.current = null;\n if (stage) {\n stage.getLayers().forEach(l => { l.listening(true); });\n stage.batchDraw();\n }\n }\n },\n });\n\n const handleNavigate = useCallback((nodeId: string) => {\n if (!doc || !currentLayerId) {\n return;\n }\n if (isTransitioningRef.current || isAnimating()) {\n return;\n }\n\n const childLayer = getChildLayerForNode(doc, nodeId, currentLayerId);\n if (!childLayer) {\n return;\n }\n const childLayerId = [...doc.layers.entries()].find(([, l]) => l === childLayer)?.[0];\n if (!childLayerId) {\n return;\n }\n const childNodes = (() => { try { return getNodesForLayer(doc, childLayerId); } catch { return []; } })();\n if (childNodes.length === 0) {\n return;\n }\n\n const node = nodes.get(nodeId);\n if (!node) return;\n\n // Save the FIT viewport for this layer (not the current scroll position).\n // This ensures navigating back always returns to a clean, properly-zoomed view\n // rather than the arbitrary zoom that happened to trigger the navigation.\n const cw = canvasSizeRef.current.width || 800;\n const ch = canvasSizeRef.current.height || 600;\n const fitVp = calculateFitView(flatNodes, cw, ch);\n const isRootNow = navStack.length <= 1;\n parentViewports.current.push({ centerX: fitVp.centerX, centerY: fitVp.centerY, zoomLevel: isRootNow ? 0.85 : fitVp.zoomLevel });\n\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n\n zoomIntoLayer(\n doc, node, childLayerId, childNodes,\n node.color ?? getThemeBackground(isDark, 'secondary'),\n node.color ?? getThemeBackground(isDark, 'primary'),\n );\n }, [doc, currentLayerId, nodes, isDark, isAnimating, zoomIntoLayer]);\n\n const handleNavigateBack = useCallback((targetIndex: number) => {\n if (targetIndex >= navStack.length - 1) return;\n if (isTransitioningRef.current || isAnimating()) return;\n const savedVp = parentViewports.current[targetIndex];\n if (!savedVp) return;\n navBackTargetRef.current = targetIndex;\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n zoomOutToParent(savedVp, getThemeBackground(isDark, 'primary'), getThemeBackground(isDark, 'secondary'));\n }, [navStack.length, isDark, isAnimating, zoomOutToParent]);\n\n // ── Auto-zoom navigation (Google Maps style) ──────────────────────────────\n const baseZoomRef = useRef(1.0);\n const lastZoomTransitionRef = useRef(0);\n const ZOOM_COOLDOWN = 1000;\n\n useEffect(() => { baseZoomRef.current = 1.0; }, [currentLayerId]);\n\n useEffect(() => {\n if (isTransitioningRef.current || isAnimating()) return;\n const now = Date.now();\n if (now - lastZoomTransitionRef.current < ZOOM_COOLDOWN) return;\n const relative = viewport.zoomLevel / baseZoomRef.current;\n\n if (relative >= ZOOM_NAV_IN_THRESHOLD) {\n // Zoom in threshold — drill into closest node\n let closest: FlatNode | null = null;\n let minDist = Infinity;\n for (const node of nodes.values()) {\n const dx = node.x - viewport.centerX;\n const dy = node.y - viewport.centerY;\n const d = dx * dx + dy * dy;\n if (d < minDist) { minDist = d; closest = node; }\n }\n if (closest) {\n const childLayer = doc ? getChildLayerForNode(doc, closest.id, currentLayerId ?? '') : null;\n if (childLayer) {\n lastZoomTransitionRef.current = now;\n handleNavigate(closest.id);\n baseZoomRef.current = 1.0;\n }\n }\n } else if (relative < ZOOM_NAV_OUT_THRESHOLD && navStack.length > 1) {\n // Zoom out threshold — go back to parent\n lastZoomTransitionRef.current = now;\n handleNavigateBack(navStack.length - 2);\n baseZoomRef.current = 1.0;\n }\n }, [viewport.zoomLevel, viewport.centerX, viewport.centerY, nodes, doc, currentLayerId, navStack, isAnimating, handleNavigate, handleNavigateBack]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Stage-level hit detection ─────────────────────────────────────────────\n const toWorldCoords = useCallback((stage: Konva.Stage, pointer: { x: number; y: number }) => {\n const sp = stage.position();\n const sc = stage.scaleX();\n return { worldX: (pointer.x - sp.x) / sc, worldY: (pointer.y - sp.y) / sc };\n }, []);\n\n const hitTestNode = useCallback((worldX: number, worldY: number): string | null => {\n if (!spatialIndexRef.current) return null;\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n if (!hits.length) return null;\n let targetId: string | null = null, minDist = Infinity;\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (!node) continue;\n const d = (worldX - node.x) ** 2 + (worldY - node.y) ** 2;\n if (d < minDist) { minDist = d; targetId = nodeId; }\n }\n return targetId;\n }, [nodes]);\n\n // Stage pointer interaction state\n const stageActiveNodeIdRef = useRef<string | null>(null);\n const stageDragNodeOffsetRef = useRef({ x: 0, y: 0 });\n const stageMouseDownPosRef = useRef<{ x: number; y: number } | null>(null);\n const stageDragCommittedRef = useRef(false);\n const stageLastPointerCheckRef = useRef<number>(0);\n const pointerNodeIdRef = useRef<string | null>(null);\n const isCanvasPanningRef = useRef(false);\n const isDraggingRef = useRef(false);\n\n const [pointerNodeId, setPointerNodeId] = useState<string | null>(null);\n const [pressedNodeId, setPressedNodeId] = useState<string | null>(null);\n const [isDraggingState, setIsDraggingState] = useState(false);\n\n // ── Node hover tooltip ────────────────────────────────────────────────────\n const [hoveredNode, setHoveredNode] = useState<{\n nodeId: string; summary: string; screenX: number; screenY: number;\n } | null>(null);\n\n const tooltipHoverRef = useRef(false);\n const keepTooltipOpenRef = useRef(false); // External request to keep tooltip open (e.g., from extensions)\n const clearTooltipTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const hoveredNodePosition = useMemo(() => {\n if (!hoveredNode) return null;\n const node = nodes.get(hoveredNode.nodeId);\n if (!node) return null;\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n return {\n screenX: (node.x - viewport.centerX) * viewport.zoomLevel + cw / 2,\n screenY: (node.y - viewport.centerY) * viewport.zoomLevel + ch / 2,\n zoom: viewport.zoomLevel,\n };\n }, [hoveredNode, nodes, viewport]);\n\n // ── Context menu ──────────────────────────────────────────────────────────\n const [canvasContextMenu, setCanvasContextMenu] = useState<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!canvasContextMenu) return;\n const close = () => setCanvasContextMenu(null);\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); };\n window.addEventListener('pointerdown', close);\n window.addEventListener('keydown', onKey);\n return () => { window.removeEventListener('pointerdown', close); window.removeEventListener('keydown', onKey); };\n }, [canvasContextMenu]);\n\n // ── Stage event handlers ──────────────────────────────────────────────────\n const handleStageMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n if (e.evt.button !== 0) { rendererHandleMouseDown(e); return; }\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseDown(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseDown(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const nodeId = hitTestNode(worldX, worldY);\n if (nodeId) {\n const node = nodes.get(nodeId);\n if (node) {\n select(nodeId);\n stageActiveNodeIdRef.current = nodeId;\n stageDragNodeOffsetRef.current = { x: worldX - node.x, y: worldY - node.y };\n stageMouseDownPosRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n stageDragCommittedRef.current = false;\n setPressedNodeId(nodeId);\n setHoveredNode(null);\n return;\n }\n }\n setHoveredNode(null);\n isCanvasPanningRef.current = true;\n rendererHandleMouseDown(e);\n }, [hitTestNode, toWorldCoords, nodes, select, rendererHandleMouseDown]);\n\n const handleStageMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseMove(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseMove(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n\n if (stageActiveNodeIdRef.current && stageMouseDownPosRef.current) {\n const moved = Math.hypot(e.evt.clientX - stageMouseDownPosRef.current.x, e.evt.clientY - stageMouseDownPosRef.current.y);\n if (!stageDragCommittedRef.current && moved >= 5) {\n stageDragCommittedRef.current = true;\n isDraggingRef.current = true;\n setIsDraggingState(true);\n pointerNodeIdRef.current = null;\n setPointerNodeId(null);\n handleDragStart(stageActiveNodeIdRef.current);\n }\n if (stageDragCommittedRef.current) {\n const offset = stageDragNodeOffsetRef.current;\n handleDragMove(stageActiveNodeIdRef.current, worldX - offset.x, worldY - offset.y);\n stage.container().style.cursor = 'grabbing';\n return;\n }\n return;\n }\n\n // During canvas pan — just apply the pan, skip hover detection to avoid re-renders\n if (isCanvasPanningRef.current) {\n rendererHandleMouseMove(e);\n return;\n }\n\n // Throttled hover detection (only when not panning or dragging)\n const now = performance.now();\n if (now - stageLastPointerCheckRef.current >= 50) {\n stageLastPointerCheckRef.current = now;\n const hovered = hitTestNode(worldX, worldY);\n if (hovered !== pointerNodeIdRef.current) {\n pointerNodeIdRef.current = hovered;\n setPointerNodeId(hovered);\n }\n if (hovered) {\n stage.container().style.cursor = 'pointer';\n } else {\n stage.container().style.cursor = 'grab';\n }\n }\n\n rendererHandleMouseMove(e);\n }, [toWorldCoords, hitTestNode, handleDragStart, handleDragMove, rendererHandleMouseMove]);\n\n const handleStageMouseUp = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n setPressedNodeId(null);\n if (stageActiveNodeIdRef.current) {\n const nodeId = stageActiveNodeIdRef.current;\n if (stageDragCommittedRef.current) {\n // End drag — flush final world position\n const stage = e.target.getStage();\n if (stage) {\n const pointer = stage.getPointerPosition();\n if (pointer) {\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const offset = stageDragNodeOffsetRef.current;\n handleDragEnd(nodeId, worldX - offset.x, worldY - offset.y);\n }\n }\n } else {\n // Click — check if node has child layer (regardless of branchCount)\n const node = nodes.get(nodeId);\n if (node) {\n const childLayer = doc ? getChildLayerForNode(doc, nodeId, currentLayerId ?? '') : null;\n if (childLayer) {\n handleNavigate(nodeId);\n }\n onNodeClick?.(node);\n }\n }\n isDraggingRef.current = false;\n setIsDraggingState(false);\n stageActiveNodeIdRef.current = null;\n stageMouseDownPosRef.current = null;\n stageDragCommittedRef.current = false;\n return;\n }\n isCanvasPanningRef.current = false;\n rendererHandleMouseUp(e);\n }, [toWorldCoords, handleDragEnd, nodes, handleNavigate, onNodeClick, rendererHandleMouseUp]);\n\n const handleStageContextMenu = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n e.evt.preventDefault();\n if (navStack.length <= 1) { setCanvasContextMenu(null); return; }\n const rect = containerRef.current?.getBoundingClientRect();\n const localX = rect ? e.evt.clientX - rect.left : e.evt.clientX;\n const localY = rect ? e.evt.clientY - rect.top : e.evt.clientY;\n setCanvasContextMenu({ x: localX, y: localY });\n }, [navStack.length]);\n\n // Touch passthrough\n const handleStageTouchStart = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseDown(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseDown]);\n const handleStageTouchMove = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseMove(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseMove]);\n const handleStageTouchEnd = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseUp(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseUp]);\n\n // Wheel with auto-nav guard on non-root layers\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>) => {\n const isZoomOut = e.evt.deltaY > 0;\n if (!isZoomOut) { rendererHandleWheel(e); return; }\n\n const liveZoom = useViewportStore.getState().zoomLevel;\n const projected = Math.max(ZOOM_MIN, liveZoom * (1 - e.evt.deltaY / 1000));\n\n // Root layer: no parent to navigate to — let the user zoom freely down to ZOOM_MIN\n // (do NOT clamp at ZOOM_NAV_OUT_THRESHOLD; content may require lower zoom to fit)\n\n if (navStack.length > 1 && projected <= ZOOM_NAV_OUT_THRESHOLD && !isTransitioningRef.current && !isAnimating()) {\n e.evt.preventDefault();\n const now = Date.now();\n if (now - lastZoomTransitionRef.current >= ZOOM_COOLDOWN) {\n lastZoomTransitionRef.current = now;\n handleNavigateBack(navStack.length - 2);\n baseZoomRef.current = 1.0;\n }\n return;\n }\n rendererHandleWheel(e);\n }, [rendererHandleWheel, navStack, setZoom, isAnimating, handleNavigateBack]);\n\n // Canvas mouse move for description tooltip\n const lastHoverCheckRef = useRef(0);\n const handleCanvasMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (!containerRef.current || isDraggingRef.current || isCanvasPanningRef.current) {\n setHoveredNode(null);\n return;\n }\n const now = Date.now();\n if (now - lastHoverCheckRef.current < 50) return;\n lastHoverCheckRef.current = now;\n\n // Check if mouse is over a tooltip - if so, don't change hovered node\n const target = e.target as HTMLElement;\n const isOverTooltip = target.closest('[data-node-tooltip=\"true\"]') || target.closest('[data-semantic-tooltip=\"true\"]');\n \n // If tooltip is open and we're hovering it or keeping it open, don't detect new nodes\n if (tooltipHoverRef.current || keepTooltipOpenRef.current || isOverTooltip) {\n return;\n }\n\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n // e.clientX is viewport-relative; subtract the container's left/top offset\n // so world-coordinate conversion is correct when the renderer isn't full-screen.\n const rect = containerRef.current?.getBoundingClientRect();\n const localX = rect ? e.clientX - rect.left : e.clientX;\n const localY = rect ? e.clientY - rect.top : e.clientY;\n const worldX = (localX - cw / 2) / viewport.zoomLevel + viewport.centerX;\n const worldY = (localY - ch / 2) / viewport.zoomLevel + viewport.centerY;\n\n // Use RBush spatial index for O(log n) hit detection\n let found = false;\n if (spatialIndexRef.current) {\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (node?.description) {\n setHoveredNode({ nodeId: node.id, summary: node.description, screenX: e.clientX, screenY: e.clientY });\n found = true;\n break;\n }\n }\n }\n if (!found) {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) setHoveredNode(null);\n }, 150);\n } else {\n if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; }\n }\n }, [nodes, viewport, spatialIndexRef]);\n\n // Listen for external requests to keep tooltip open (e.g., from extensions)\n useEffect(() => {\n const handleKeepTooltipOpen = (event: CustomEvent) => {\n keepTooltipOpenRef.current = event.detail.keep;\n };\n \n // @ts-ignore - custom event\n window.addEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen);\n \n return () => {\n // @ts-ignore - custom event\n window.removeEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen);\n };\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n spatialIndexRef.current?.clear();\n if (dragMoveRafRef.current !== null) cancelAnimationFrame(dragMoveRafRef.current);\n };\n }, []);\n\n // ── Zoom controls ─────────────────────────────────────────────────────────\n const handleZoomIn = useCallback(() => setZoom(Math.min(viewport.zoomLevel * 1.2, 5)), [viewport.zoomLevel, setZoom]);\n const handleZoomOut = useCallback(() => {\n // Non-root: allow zoom to ZOOM_MIN so the wheel-driven ZOOM_NAV_OUT_THRESHOLD\n // transition can still trigger via scroll; button just navigates zoom value.\n // Root: also ZOOM_MIN (no parent layer to navigate to, allow full zoom-out).\n setZoom(Math.max(viewport.zoomLevel / 1.2, ZOOM_MIN));\n }, [viewport.zoomLevel, setZoom]);\n\n // Extension rendering removed - not part of open spec\n\n // ── Render ────────────────────────────────────────────────────────────────\n if (!doc) {\n return (\n <div className={className} style={{ position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center', background: bgColor, ...style }}>\n <span style={{ color: isDark ? 'rgba(255,255,255,0.4)' : 'rgba(0,0,0,0.3)', fontSize: 14 }}>No document</span>\n </div>\n );\n }\n\n const hasBackOption = navStack.length > 1;\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ \n position: 'relative', \n overflow: 'hidden', \n userSelect: 'none', \n background: bgColor, \n width: '100%', \n height: '100%', \n ...style \n }}\n onMouseMove={handleCanvasMouseMove}\n onMouseLeave={() => {\n // Only close tooltip on mouse leave if not keeping it open\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) {\n setHoveredNode(null);\n }\n }}\n >\n {/* Konva canvas — opacity driven imperatively during transitions */}\n <div ref={canvasWrapperRef} style={{ position: 'relative', zIndex: 1, pointerEvents: 'auto' }}>\n <KonvaStage\n ref={stageRef}\n onWheel={handleWheel}\n onMouseDown={handleStageMouseDown}\n onMouseMove={handleStageMouseMove}\n onMouseUp={handleStageMouseUp}\n onContextMenu={handleStageContextMenu}\n onTouchStart={handleStageTouchStart}\n onTouchMove={handleStageTouchMove}\n onTouchEnd={handleStageTouchEnd}\n >\n <KonvaContainerLayer nodes={flatNodes} containers={containers} isDark={isDark} />\n <KonvaEdgeLayer \n nodes={flatNodes} \n connections={connections} \n isDark={isDark} \n isDragging={isDraggingState} \n />\n <KonvaNodeLayer\n isTransitioning={isTransitioning}\n isDragging={isDraggingState}\n hoveredNodeId={pointerNodeId}\n pressedNodeId={pressedNodeId}\n />\n </KonvaStage>\n </div>\n\n {/* Context menu (right-click to go back) */}\n {canvasContextMenu && hasBackOption && (\n <div\n role=\"menu\"\n aria-label=\"Canvas options\"\n style={{\n position: 'absolute',\n zIndex: 60,\n pointerEvents: 'auto',\n left: `${Math.min(canvasContextMenu.x, Math.max(8, (canvasSizeRef.current.width || 800) - 152))}px`,\n top: `${Math.min(canvasContextMenu.y, Math.max(8, (canvasSizeRef.current.height || 600) - 72))}px`,\n }}\n onContextMenu={e => e.preventDefault()}\n onPointerDown={e => e.stopPropagation()}\n >\n <button\n type=\"button\"\n style={{\n padding: '6px 16px',\n borderRadius: '10px',\n border: `1px solid ${isDark ? '#333330' : '#DDD9D0'}`,\n background: isDark ? '#1C1C1A' : '#FAF8F4',\n color: isDark ? '#F0EDE6' : '#1A1A18',\n cursor: 'pointer',\n fontSize: 13,\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\n }}\n onClick={() => { setCanvasContextMenu(null); handleNavigateBack(navStack.length - 2); }}\n >\n Back\n </button>\n </div>\n )}\n\n {/* Navigation stack (left, matches reference) */}\n <NavigationStack stack={navStack} onNavigateBack={handleNavigateBack} isDark={isDark} top={navigationStackTop} left={navigationStackLeft} />\n\n {/* Zoom controls (top-right) */}\n <div data-help=\"zoom-controls\" style={{ position: 'absolute', top: '24px', right: '16px', zIndex: 50, pointerEvents: 'auto' }}>\n <ZoomControls isDark={isDark} />\n </div>\n\n {/* Custom overlay from consuming app (for private features like help button, chromatic bg, etc.) */}\n {renderOverlay?.({ isDark, containerWidth: canvasSizeRef.current.width || 0, containerHeight: canvasSizeRef.current.height || 0 })}\n\n {/* Node description tooltip (sketchy-box, above node) - rendered before extensions so extensions appear on top */}\n {hoveredNode && hoveredNodePosition && viewport.zoomLevel < 3 && viewport.zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM && (() => {\n const nodeData = nodes.get(hoveredNode.nodeId);\n const borderColor = nodeData?.color ? darkenHexColor(nodeData.color, 0.13) : '#5BA8D4';\n const VP_PAD = 8;\n const HALF_W = 160;\n const APPROX_H = 90;\n const containerW = canvasSizeRef.current.width || 800;\n const safeLeft = Math.max(HALF_W + VP_PAD, Math.min(hoveredNodePosition.screenX, containerW - HALF_W - VP_PAD));\n const rawTop = hoveredNodePosition.screenY - 60 * hoveredNodePosition.zoom;\n const safeTop = Math.max(VP_PAD + APPROX_H, rawTop);\n return (\n <div\n data-node-tooltip=\"true\"\n style={{\n position: 'absolute',\n zIndex: 50,\n left: safeLeft,\n top: safeTop,\n transform: 'translate(-50%, -100%)',\n transformOrigin: 'bottom center',\n pointerEvents: 'auto',\n }}\n onMouseEnter={() => { tooltipHoverRef.current = true; if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; } }}\n onMouseLeave={() => { \n tooltipHoverRef.current = false; \n // Delay clearing to allow external extensions to request keeping tooltip open\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!keepTooltipOpenRef.current) setHoveredNode(null);\n }, 100);\n }}\n >\n <div style={{ maxWidth: '20rem', minWidth: '12rem', maxHeight: '15rem', overflowY: 'auto' }}>\n <SketchyBoxKonva fill=\"#ffffff\" stroke={borderColor} backStroke={borderColor} padding=\"1rem 1.25rem\">\n <p style={{\n fontFamily: \"'Playpen Sans', cursive\",\n fontSize: `${DESCRIPTION_TEXT_BASE_FONT_PX}px`,\n fontWeight: 300,\n color: '#000000',\n textAlign: 'center',\n lineHeight: 1.6,\n margin: 0,\n }}>\n {renderNodeContent ? renderNodeContent({ \n summary: hoveredNode.summary, \n nodeId: hoveredNode.nodeId,\n nodeColor: nodeData?.color,\n zoom: viewport.zoomLevel,\n }) : hoveredNode.summary}\n </p>\n </SketchyBoxKonva>\n </div>\n </div>\n );\n })()}\n </div>\n );\n}\n","// ─── Node Store ───────────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { FlatNode, NodeMap } from '@visualli/core';\n\nexport interface INodeStore {\n nodes: NodeMap;\n childrenIndex: Map<string | null, Set<string>>;\n\n setNodes: (nodes: NodeMap) => void;\n updateNode: (nodeId: string, updates: Partial<FlatNode>) => void;\n updateNodePosition: (nodeId: string, x: number, y: number) => void;\n addNode: (node: FlatNode) => void;\n removeNode: (nodeId: string) => void;\n setNodeExpanded: (nodeId: string, expanded: boolean) => void;\n\n getNode: (nodeId: string) => FlatNode | undefined;\n getChildren: (parentId: string | null) => FlatNode[];\n getChildrenIds: (parentId: string | null) => Set<string>;\n getAllNodes: () => FlatNode[];\n}\n\nfunction buildChildrenIndex(nodes: NodeMap): Map<string | null, Set<string>> {\n const index = new Map<string | null, Set<string>>();\n for (const node of nodes.values()) {\n const pid = node.parentId ?? null;\n if (!index.has(pid)) index.set(pid, new Set());\n index.get(pid)!.add(node.id);\n }\n return index;\n}\n\nexport const useNodeStore = create<INodeStore>((set, get) => ({\n nodes: new Map(),\n childrenIndex: new Map(),\n\n setNodes: (nodes) =>\n set({ nodes, childrenIndex: buildChildrenIndex(nodes) }),\n\n updateNode: (nodeId, updates) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, ...updates, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n updateNodePosition: (nodeId, x, y) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node || (node.x === x && node.y === y)) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, x, y });\n return { nodes: next };\n }),\n\n addNode: (node) =>\n set((s) => {\n const next = new Map(s.nodes);\n next.set(node.id, node);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (!idx.has(pid)) idx.set(pid, new Set());\n idx.get(pid)!.add(node.id);\n return { nodes: next, childrenIndex: idx };\n }),\n\n removeNode: (nodeId) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.delete(nodeId);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (idx.has(pid)) {\n const set = new Set(idx.get(pid)!);\n set.delete(nodeId);\n if (set.size === 0) idx.delete(pid); else idx.set(pid, set);\n }\n return { nodes: next, childrenIndex: idx };\n }),\n\n setNodeExpanded: (nodeId, expanded) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, isExpanded: expanded, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n getNode: (nodeId) => get().nodes.get(nodeId),\n getChildren: (pid) => {\n const { nodes, childrenIndex } = get();\n return Array.from(childrenIndex.get(pid) ?? []).map(id => nodes.get(id)!).filter(Boolean);\n },\n getChildrenIds: (pid) => get().childrenIndex.get(pid) ?? new Set(),\n getAllNodes: () => Array.from(get().nodes.values()),\n}));\n","// ─── Viewport Store ───────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { ViewportState } from '@visualli/core';\nimport {\n panViewport,\n zoomViewport,\n setViewportCenter,\n recalculateViewportBounds,\n clampZoom,\n DEFAULT_CANVAS_WIDTH,\n DEFAULT_CANVAS_HEIGHT,\n worldToScreen,\n screenToWorld,\n ZOOM_DEFAULT,\n} from '@visualli/core';\n\nexport interface IViewportStore extends ViewportState {\n canvasWidth: number;\n canvasHeight: number;\n\n pan: (deltaX: number, deltaY: number) => void;\n zoom: (delta: number, pivotX?: number, pivotY?: number) => void;\n setCenter: (x: number, y: number) => void;\n setZoom: (level: number) => void;\n updateCanvasSize: (width: number, height: number) => void;\n\n getVisibleBounds: () => ViewportState['visibleBounds'];\n worldToScreen: (x: number, y: number) => { x: number; y: number };\n screenToWorld: (x: number, y: number) => { x: number; y: number };\n}\n\nfunction makeInitial(w: number, h: number): ViewportState {\n const vp: ViewportState = {\n centerX: 0, centerY: 0,\n zoomLevel: ZOOM_DEFAULT,\n rotation: 0,\n visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 },\n };\n return recalculateViewportBounds(vp, w, h);\n}\n\nconst getVP = (s: IViewportStore): ViewportState => ({\n centerX: s.centerX, centerY: s.centerY,\n zoomLevel: s.zoomLevel, rotation: s.rotation,\n visibleBounds: s.visibleBounds,\n});\n\nexport const useViewportStore = create<IViewportStore>((set, get) => {\n const init = makeInitial(DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT);\n return {\n ...init,\n canvasWidth: DEFAULT_CANVAS_WIDTH,\n canvasHeight: DEFAULT_CANVAS_HEIGHT,\n\n pan: (dx, dy) => set((s) => {\n const updated = recalculateViewportBounds(panViewport(dx, dy, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n zoom: (delta, pivotX, pivotY) => set((s) => {\n const updated = recalculateViewportBounds(\n zoomViewport(delta, getVP(s), pivotX, pivotY, s.canvasWidth, s.canvasHeight),\n s.canvasWidth, s.canvasHeight,\n );\n return { centerX: updated.centerX, centerY: updated.centerY, zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n setCenter: (x, y) => set((s) => {\n const updated = recalculateViewportBounds(setViewportCenter(x, y, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n setZoom: (level) => set((s) => {\n const clamped = clampZoom(level);\n const updated = recalculateViewportBounds({ ...getVP(s), zoomLevel: clamped }, s.canvasWidth, s.canvasHeight);\n return { zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n updateCanvasSize: (w, h) => set((s) => {\n const updated = recalculateViewportBounds(getVP(s), w, h);\n return { canvasWidth: w, canvasHeight: h, visibleBounds: updated.visibleBounds };\n }),\n\n getVisibleBounds: () => get().visibleBounds,\n worldToScreen: (x, y) => {\n const s = get();\n return worldToScreen(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n screenToWorld: (x, y) => {\n const s = get();\n return screenToWorld(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n };\n});\n","// ─── Selection Store ──────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport { selectionStore, renderConfigStore } from '@visualli/core';\nimport type { ISelectionStore, IRenderConfigStore } from '@visualli/core';\n\nexport const useSelectionStore = create<ISelectionStore>((set, get, store) => {\n selectionStore.subscribe((state) => set(state));\n return selectionStore.getState();\n});\n\n// ─── Render Config Store ──────────────────────────────────────────────────────\n\nexport const useRenderConfigStore = create<IRenderConfigStore>((set, get, store) => {\n renderConfigStore.subscribe((state) => set(state));\n return renderConfigStore.getState();\n});\n","// ─── useKonvaRenderer ─────────────────────────────────────────────────────────\n//\n// Manages Konva rendering lifecycle: resize, pan, zoom, and FPS monitoring.\n// Returns Konva-level event handlers to be wired onto KonvaStage.\n//\n// Design matches visualli.ai's useKonvaRenderer:\n// - handleWheel / handleMouseDown / handleMouseMove / handleMouseUp are\n// Konva.KonvaEventObject handlers (not DOM-level)\n// - Pan is applied directly to the stage during drag for 60 fps, flushed to\n// Zustand store on mouseUp (no per-frame state updates)\n// - Zoom targets the cursor position (same math as visualli.ai)\n\nimport { useEffect, useCallback, useRef, useState } from 'react';\nimport type Konva from 'konva';\nimport { ZOOM_MIN, ZOOM_MAX } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useRenderConfigStore } from '../stores/stores';\n\nexport interface UseKonvaRendererOptions {\n containerRef: React.RefObject<HTMLDivElement | null>;\n stageRef?: React.RefObject<Konva.Stage | null>;\n enabled?: boolean;\n}\n\nexport interface UseKonvaRendererReturn {\n handleWheel: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n handleMouseDown:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseMove:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseUp: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n canvasWidth: number;\n canvasHeight: number;\n}\n\nexport function useKonvaRenderer({\n containerRef,\n stageRef,\n enabled = true,\n}: UseKonvaRendererOptions): UseKonvaRendererReturn {\n const pan = useViewportStore(s => s.pan);\n const zoom = useViewportStore(s => s.zoom);\n const setZoom = useViewportStore(s => s.setZoom);\n const setCenter = useViewportStore(s => s.setCenter);\n const updateCanvasSize = useViewportStore(s => s.updateCanvasSize);\n const autoAdjust = useRenderConfigStore(s => s.autoAdjustQuality);\n\n const [canvasWidth, setCanvasWidth] = useState(0);\n const [canvasHeight, setCanvasHeight] = useState(0);\n const cachedSizeRef = useRef({ width: 0, height: 0 });\n\n const isPanningRef = useRef(false);\n const lastPanPointRef = useRef({ x: 0, y: 0 });\n const panAccumRef = useRef({ x: 0, y: 0 });\n\n // ── FPS monitor ──────────────────────────────────────────────────────────────\n const fpsRef = useRef({ frames: 0, last: performance.now() });\n const fpsRafId = useRef<number | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n const tick = (now: number): void => {\n fpsRef.current.frames++;\n if (now - fpsRef.current.last >= 2000) {\n const fps = (fpsRef.current.frames / ((now - fpsRef.current.last) / 1000)) | 0;\n autoAdjust(fps);\n fpsRef.current = { frames: 0, last: now };\n }\n fpsRafId.current = requestAnimationFrame(tick);\n };\n fpsRafId.current = requestAnimationFrame(tick);\n return () => { if (fpsRafId.current !== null) cancelAnimationFrame(fpsRafId.current); };\n }, [enabled, autoAdjust]);\n\n // ── Resize ────────────────────────────────────────────────────────────────────\n // Observes the container element (not window) so the canvas always fills\n // its parent, regardless of how the renderer is sized by the consuming app.\n useEffect(() => {\n if (!enabled) return;\n\n let rafId: number | null = null;\n\n const measure = () => {\n const el = containerRef.current;\n const w = el ? Math.round(el.getBoundingClientRect().width) : 800;\n const h = el ? Math.round(el.getBoundingClientRect().height) : 600;\n return { w, h };\n };\n\n const updateSize = () => {\n if (rafId) cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(() => {\n rafId = null;\n const { w, h } = measure();\n if (w > 0 && h > 0 &&\n (cachedSizeRef.current.width !== w || cachedSizeRef.current.height !== h)) {\n cachedSizeRef.current = { width: w, height: h };\n setCanvasWidth(w);\n setCanvasHeight(h);\n updateCanvasSize(w, h);\n }\n });\n };\n\n // Initial measurement\n updateSize();\n\n // ResizeObserver tracks the container itself (handles % / flex / grid sizing)\n let ro: ResizeObserver | null = null;\n if (typeof ResizeObserver !== 'undefined' && containerRef.current) {\n ro = new ResizeObserver(updateSize);\n ro.observe(containerRef.current);\n } else {\n // Fallback: window resize only\n window.addEventListener('resize', updateSize);\n }\n\n return () => {\n ro ? ro.disconnect() : window.removeEventListener('resize', updateSize);\n if (rafId) cancelAnimationFrame(rafId);\n };\n }, [enabled, containerRef, updateCanvasSize]);\n\n // ── Wheel zoom ────────────────────────────────────────────────────────────────\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>): void => {\n e.evt.preventDefault();\n const stage = e.target.getStage();\n if (!stage) return;\n const pointer = stage.getPointerPosition();\n if (!pointer) return;\n const delta = -e.evt.deltaY / 1000;\n zoom(delta, pointer.x, pointer.y);\n }, [zoom]);\n\n // ── Mouse pan ─────────────────────────────────────────────────────────────────\n const handleMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n const clickedOnEmpty = e.target === e.target.getStage();\n if (clickedOnEmpty && e.evt.button === 0) {\n e.evt.preventDefault();\n isPanningRef.current = true;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n panAccumRef.current = { x: 0, y: 0 };\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = 'grabbing';\n }\n }, []);\n\n const handleMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n if (!isPanningRef.current) {\n // Update cursor on empty canvas\n const isOverEmpty = e.target === e.target.getStage();\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = isOverEmpty ? 'grab' : 'default';\n return;\n }\n e.evt.preventDefault();\n const deltaX = e.evt.clientX - lastPanPointRef.current.x;\n const deltaY = e.evt.clientY - lastPanPointRef.current.y;\n\n // Apply pan directly to stage (no Zustand overhead per-frame)\n const stage = e.target.getStage();\n if (stage) {\n stage.x(stage.x() + deltaX);\n stage.y(stage.y() + deltaY);\n stage.batchDraw();\n }\n\n panAccumRef.current.x += deltaX;\n panAccumRef.current.y += deltaY;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n }, []); // No Zustand dep — pan flushed on mouseUp\n\n const handleMouseUp = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n if (isPanningRef.current) {\n isPanningRef.current = false;\n const { x, y } = panAccumRef.current;\n if (x !== 0 || y !== 0) {\n pan(x, y);\n panAccumRef.current = { x: 0, y: 0 };\n }\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = 'grab';\n }\n }, [pan]);\n\n return { handleWheel, handleMouseDown, handleMouseMove, handleMouseUp, canvasWidth, canvasHeight };\n}\n","// ─── useKonvaLayerTransition ──────────────────────────────────────────────────\n//\n// Manages layer navigation animations (zoom into child layer, zoom back to\n// parent). Uses the same callback-driven pattern as the visualli.ai reference:\n// - onViewportChange: imperatively updates the Konva stage each rAF frame\n// - onOpacityChange: writes directly to canvasWrapperRef DOM (no React state)\n// - onBackgroundColorChange: writes directly to bgRef DOM\n// - onPhaseChange('swap'|'zoom-back'): triggers React layer content swap\n// - onComplete: syncs final viewport to Zustand and ends transition\n\nimport { useCallback, useRef, useEffect } from 'react';\nimport type Konva from 'konva';\nimport type { VisualliDocument, FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { konvaLayerTransitionAnimator } from '../animations/konvaLayerTransition';\nimport type { AnimatorViewport } from '../animations/konvaLayerTransition';\nimport { calculateFitView } from '../utils/layerNavigation';\n\nexport interface LayerTransitionOptions {\n /** Ref to the Konva Stage for imperative position/scale updates each frame. */\n stageRef: React.RefObject<Konva.Stage | null>;\n /** Ref to the wrapping div whose CSS `opacity` is driven during transitions. */\n canvasWrapperRef: React.RefObject<HTMLDivElement | null>;\n /** Ref to the background color div. */\n bgRef?: React.RefObject<HTMLDivElement | null>;\n /** Called at the content-swap point — use to switch the displayed layer. */\n onSwapLayer: (newLayerId: string) => void;\n /** Called when a zoom-out swap happens — use to update the nav stack. */\n onSwapBack: () => void;\n /** Called after the transition fully completes. */\n onComplete: () => void;\n /**\n * GPU CSS-transform mode: called each rAF frame instead of applyViewport.\n * When provided, the caller is responsible for moving the canvas content.\n */\n onViewportFrame?: (vp: AnimatorViewport) => void;\n /**\n * Called once when the animation reaches its final viewport.\n * When provided, replaces the default applyViewport call at completion.\n */\n onViewportFinal?: (vp: AnimatorViewport) => void;\n /**\n * Called at phase-change points ('swap', 'zoom-back') in addition to the\n * internal content-swap logic. Use to reset CSS transforms before Konva redraws.\n */\n onPhaseChange?: (phase: string) => void;\n /**\n * Called with 'start' before the animator fires its first frame and with\n * 'end' after onComplete. Use to set up / tear down GPU hints (willChange, etc.).\n */\n onTransitionLifecycle?: (phase: 'start' | 'end') => void;\n}\n\nexport interface LayerTransitionHandlers {\n zoomIntoLayer: (\n doc: VisualliDocument,\n targetNode: FlatNode,\n childLayerId: string,\n childNodes: FlatNode[],\n fromColor: string,\n toColor: string,\n ) => void;\n zoomOutToParent: (\n parentViewport: AnimatorViewport,\n fromColor: string,\n toColor: string,\n ) => void;\n isTransitioning: () => boolean;\n}\n\nexport function useKonvaLayerTransition(opts: LayerTransitionOptions): LayerTransitionHandlers {\n const {\n stageRef, canvasWrapperRef, bgRef,\n onSwapLayer, onSwapBack, onComplete,\n onViewportFrame, onViewportFinal, onPhaseChange: onPhaseChangeExt,\n onTransitionLifecycle,\n } = opts;\n const setZoom = useViewportStore(s => s.setZoom);\n const setCenter = useViewportStore(s => s.setCenter);\n const getState = useViewportStore.getState;\n\n const swappedRef = useRef(false);\n const canvasSizeRef = useRef({ width: 800, height: 600 });\n\n // Keep canvas size ref fresh from viewport store (updated by ResizeObserver in useKonvaRenderer)\n useEffect(() => {\n const update = () => {\n const vp = useViewportStore.getState();\n canvasSizeRef.current = { width: vp.canvasWidth || 800, height: vp.canvasHeight || 600 };\n };\n update();\n // Subscribe to viewport store changes instead of window resize\n const unsubscribe = useViewportStore.subscribe(update);\n return unsubscribe;\n }, []);\n\n // Apply viewport to Konva stage imperatively (no React re-render per frame)\n const applyViewport = useCallback((vp: AnimatorViewport) => {\n const stage = stageRef.current;\n if (!stage) return;\n const { width, height } = canvasSizeRef.current;\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel);\n stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n // Sync to Zustand so viewport store reflects reality\n setCenter(vp.centerX, vp.centerY);\n setZoom(vp.zoomLevel);\n }, [stageRef, setCenter, setZoom]);\n\n const applyOpacity = useCallback((opacity: number) => {\n if (canvasWrapperRef.current) {\n canvasWrapperRef.current.style.opacity = String(opacity);\n }\n }, [canvasWrapperRef]);\n\n const applyBgColor = useCallback((color: string) => {\n if (bgRef?.current) {\n bgRef.current.style.backgroundColor = color;\n }\n }, [bgRef]);\n\n const zoomIntoLayer = useCallback((\n _doc: VisualliDocument,\n targetNode: FlatNode,\n childLayerId: string,\n childNodes: FlatNode[],\n fromColor: string,\n toColor: string,\n ): void => {\n if (konvaLayerTransitionAnimator.active) return;\n\n const vp = getState();\n const stage = stageRef.current;\n const w = stage?.width() ?? 800;\n const h = stage?.height() ?? 600;\n const fit = calculateFitView(childNodes, w, h);\n\n swappedRef.current = false;\n\n onTransitionLifecycle?.('start');\n konvaLayerTransitionAnimator.animateZoomIntoLayer(\n { centerX: vp.centerX, centerY: vp.centerY, zoomLevel: vp.zoomLevel },\n { x: targetNode.x, y: targetNode.y, width: targetNode.width, height: targetNode.height },\n { x: fit.centerX, y: fit.centerY },\n fromColor,\n toColor,\n {\n onUpdate: ({ viewport, opacity, backgroundColor }) => {\n if (onViewportFrame) { onViewportFrame(viewport); } else { applyViewport(viewport); }\n applyOpacity(opacity);\n applyBgColor(backgroundColor);\n },\n onComplete: () => {\n const finalVp = { centerX: fit.centerX, centerY: fit.centerY, zoomLevel: fit.zoomLevel };\n if (onViewportFinal) { onViewportFinal(finalVp); } else { applyViewport(finalVp); }\n applyOpacity(1);\n onComplete();\n onTransitionLifecycle?.('end');\n },\n onPhaseChange: (phase) => {\n onPhaseChangeExt?.(phase);\n if (phase === 'swap' && !swappedRef.current) {\n swappedRef.current = true;\n onSwapLayer(childLayerId);\n }\n },\n },\n fit.zoomLevel,\n w,\n h,\n );\n }, [stageRef, getState, applyViewport, applyOpacity, applyBgColor, onSwapLayer, onComplete, onViewportFrame, onViewportFinal, onPhaseChangeExt, onTransitionLifecycle]);\n\n const zoomOutToParent = useCallback((\n parentViewport: AnimatorViewport,\n fromColor: string,\n toColor: string,\n ): void => {\n if (konvaLayerTransitionAnimator.active) return;\n\n const vp = getState();\n swappedRef.current = false;\n\n onTransitionLifecycle?.('start');\n konvaLayerTransitionAnimator.animateZoomOutToParent(\n { centerX: vp.centerX, centerY: vp.centerY, zoomLevel: vp.zoomLevel },\n parentViewport,\n fromColor,\n toColor,\n {\n onUpdate: ({ viewport, opacity, backgroundColor }) => {\n if (onViewportFrame) { onViewportFrame(viewport); } else { applyViewport(viewport); }\n applyOpacity(opacity);\n applyBgColor(backgroundColor);\n },\n onComplete: () => {\n if (onViewportFinal) { onViewportFinal(parentViewport); } else { applyViewport(parentViewport); }\n applyOpacity(1);\n onComplete();\n onTransitionLifecycle?.('end');\n },\n onPhaseChange: (phase) => {\n onPhaseChangeExt?.(phase);\n if (phase === 'zoom-back' && !swappedRef.current) {\n swappedRef.current = true;\n onSwapBack();\n }\n },\n },\n );\n }, [getState, applyViewport, applyOpacity, applyBgColor, onSwapBack, onComplete, onViewportFrame, onViewportFinal, onPhaseChangeExt, onTransitionLifecycle]);\n\n const isTransitioning = useCallback(() => konvaLayerTransitionAnimator.active, []);\n\n // Cancel on unmount\n useEffect(() => () => { konvaLayerTransitionAnimator.cancel(); }, []);\n\n return { zoomIntoLayer, zoomOutToParent, isTransitioning };\n}\n","// ─── Konva Layer Transition Animator ─────────────────────────────────────────\n//\n// rAF-driven animation engine for layer navigation:\n// animateZoomIntoLayer — camera-dive into child layer\n// animateZoomOutToParent — pull back to parent layer\n// animateCrossFade — simple cross-fade between two viewports\n//\n// No React dependencies — can be instantiated once and reused.\n\nimport { easeInOutSine, easeOutCubic, easeZoomTransition } from '@visualli/core';\nimport { ANIMATION_PHASES } from '@visualli/core';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface AnimatorViewport {\n centerX: number;\n centerY: number;\n zoomLevel: number;\n}\n\nexport interface NodeBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface TransitionCallbacks {\n onUpdate: (state: { viewport: AnimatorViewport; opacity: number; backgroundColor: string }) => void;\n onComplete: () => void;\n onPhaseChange?: (phase: string) => void;\n}\n\n// ── Color helpers ─────────────────────────────────────────────────────────────\n\ninterface RGB { r: number; g: number; b: number }\n\nfunction parseColor(color: string): RGB {\n if (color.startsWith('#')) {\n const h = color.slice(1);\n return { r: parseInt(h.slice(0, 2), 16), g: parseInt(h.slice(2, 4), 16), b: parseInt(h.slice(4, 6), 16) };\n }\n const m = color.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n return m ? { r: +m[1], g: +m[2], b: +m[3] } : { r: 255, g: 255, b: 255 };\n}\n\nfunction interpolateRgb(a: RGB, b: RGB, t: number): string {\n const e = easeInOutSine(t);\n return `rgb(${(a.r + (b.r - a.r) * e + 0.5) | 0},${(a.g + (b.g - a.g) * e + 0.5) | 0},${(a.b + (b.b - a.b) * e + 0.5) | 0})`;\n}\n\n// (easeZoomTransition is imported from @visualli/core — createCubicBezier(0.2, 0.8, 0.2, 1))\n\nfunction lerp(a: number, b: number, t: number): number { return a + (b - a) * t; }\n\n// ── Animator class ────────────────────────────────────────────────────────────\n\nexport class KonvaLayerTransitionAnimator {\n private rafId: number | null = null;\n private timers: ReturnType<typeof setTimeout>[] = [];\n private _active = false;\n\n get active(): boolean { return this._active; }\n\n cancel(): void {\n if (this.rafId !== null) { cancelAnimationFrame(this.rafId); this.rafId = null; }\n this.timers.forEach(clearTimeout);\n this.timers = [];\n this._active = false;\n }\n\n // ── Zoom into child layer ──────────────────────────────────────────────────\n\n animateZoomIntoLayer(\n current: AnimatorViewport,\n targetNode: NodeBounds,\n childCenter: { x: number; y: number },\n fromColor: string,\n toColor: string,\n cb: TransitionCallbacks,\n targetZoom = 1.0,\n canvasWidth = 800,\n canvasHeight = 600,\n ): void {\n if (this._active) return;\n this._active = true;\n\n // Timing constants pulled from ANIMATION_PHASES (single source of truth)\n const ZOOM_DURATION = ANIMATION_PHASES.ZOOM_IN.ZOOM_TO_TARGET; // 500 ms\n const FADE_OUT_DELAY = ANIMATION_PHASES.ZOOM_IN.FADE_OUT_START; // 120 ms\n const FADE_OUT_DURATION = ANIMATION_PHASES.ZOOM_IN.FADE_OUT; // 280 ms — completes at 400 ms\n const SWAP_AT_MS = ANIMATION_PHASES.ZOOM_IN.CONTENT_SWAP; // 310 ms\n const FADE_IN_DURATION = ANIMATION_PHASES.ZOOM_IN.FADE_IN; // 200 ms\n const SETTLE_FACTOR = 0.94;\n\n const z0 = current.zoomLevel;\n const dx = targetNode.x - current.centerX;\n const dy = targetNode.y - current.centerY;\n const vmin = Math.min(canvasWidth, canvasHeight);\n const fillZoom = Math.max(4.0, (vmin * 1.5) / Math.max(targetNode.width, 100));\n\n const fromRgb = parseColor(fromColor);\n const toRgb = parseColor(toColor);\n const state = { viewport: { centerX: 0, centerY: 0, zoomLevel: 0 }, opacity: 1, backgroundColor: fromColor };\n\n const start = performance.now();\n let swapped = false;\n let fadeInStart = 0;\n\n cb.onPhaseChange?.('zoom');\n\n const tick = (now: number): void => {\n if (!this._active) return;\n const elapsed = now - start;\n\n if (!swapped) {\n if (elapsed >= SWAP_AT_MS) {\n swapped = true;\n fadeInStart = now;\n state.viewport = { centerX: childCenter.x, centerY: childCenter.y, zoomLevel: targetZoom * SETTLE_FACTOR };\n state.opacity = 0;\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n cb.onPhaseChange?.('swap');\n this.rafId = requestAnimationFrame(tick);\n return;\n }\n const rawT = Math.min(elapsed / ZOOM_DURATION, 1);\n const zoomT = easeZoomTransition(rawT);\n const zl = lerp(z0, fillZoom, zoomT);\n state.viewport = {\n centerX: targetNode.x - dx * z0 * (1 - zoomT) / zl,\n centerY: targetNode.y - dy * z0 * (1 - zoomT) / zl,\n zoomLevel: zl,\n };\n state.opacity = elapsed > FADE_OUT_DELAY\n ? Math.max(0, 1 - easeOutCubic(Math.min((elapsed - FADE_OUT_DELAY) / FADE_OUT_DURATION, 1)))\n : 1;\n state.backgroundColor = interpolateRgb(fromRgb, toRgb, rawT);\n cb.onUpdate(state);\n } else {\n const fi = now - fadeInStart;\n const ft = Math.min(fi / FADE_IN_DURATION, 1);\n const eased = easeOutCubic(ft);\n state.viewport = { centerX: childCenter.x, centerY: childCenter.y, zoomLevel: lerp(targetZoom * SETTLE_FACTOR, targetZoom, eased) };\n state.opacity = eased;\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n if (ft >= 1) { cb.onPhaseChange?.('fade-in'); this.rafId = null; this._complete(cb.onComplete); return; }\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n // ── Zoom out to parent layer ───────────────────────────────────────────────\n\n animateZoomOutToParent(\n current: AnimatorViewport,\n parent: AnimatorViewport,\n fromColor: string,\n toColor: string,\n cb: TransitionCallbacks,\n ): void {\n if (this._active) return;\n this._active = true;\n\n const FADE_OUT = ANIMATION_PHASES.ZOOM_OUT.FADE_OUT;\n const FADE_IN = ANIMATION_PHASES.ZOOM_OUT.FADE_IN;\n const OPACITY_SETTLE = 66;\n\n const fromRgb = parseColor(fromColor);\n const toRgb = parseColor(toColor);\n const state = { viewport: { centerX: 0, centerY: 0, zoomLevel: 0 }, opacity: 1, backgroundColor: fromColor };\n\n const start = performance.now();\n let swapped = false;\n let fadeInStart = 0;\n\n cb.onPhaseChange?.('fade-out');\n\n const tick = (now: number): void => {\n if (!this._active) return;\n const elapsed = now - start;\n\n if (!swapped) {\n if (elapsed >= FADE_OUT) {\n swapped = true; fadeInStart = now;\n state.viewport = { centerX: parent.centerX, centerY: parent.centerY, zoomLevel: parent.zoomLevel * 5 };\n state.opacity = 0;\n state.backgroundColor = toColor;\n cb.onUpdate(state); cb.onPhaseChange?.('zoom-back');\n this.rafId = requestAnimationFrame(tick); return;\n }\n const rawT = Math.min(elapsed / FADE_OUT, 1);\n const t = easeOutCubic(rawT);\n state.viewport = { centerX: current.centerX, centerY: current.centerY, zoomLevel: lerp(current.zoomLevel, current.zoomLevel * 0.6, t) };\n state.opacity = 1 - t;\n state.backgroundColor = interpolateRgb(fromRgb, toRgb, rawT);\n cb.onUpdate(state);\n } else {\n const fi = now - fadeInStart;\n const rawT = Math.min(fi / FADE_IN, 1);\n const t = easeZoomTransition(rawT);\n state.viewport = { centerX: parent.centerX, centerY: parent.centerY, zoomLevel: lerp(parent.zoomLevel * 5, parent.zoomLevel, t) };\n state.opacity = fi < OPACITY_SETTLE ? 0 : easeZoomTransition(Math.min((fi - OPACITY_SETTLE) / (FADE_IN - OPACITY_SETTLE), 1));\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n if (rawT >= 1) { cb.onPhaseChange?.('fade-in'); this.rafId = null; this._complete(cb.onComplete); return; }\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n private _complete(onComplete: () => void): void {\n this.timers.forEach(clearTimeout); this.timers = [];\n this._active = false;\n onComplete();\n }\n}\n\nexport const konvaLayerTransitionAnimator = new KonvaLayerTransitionAnimator();\n","// ─── Layer Navigation Utilities ──────────────────────────────────────────────\n//\n// React-specific re-exports or wrappers of core navigation logic.\n\nexport {\n getConnectionsForLayer,\n getChildLayerForNode,\n getLayerForNavigation,\n calculateFitZoom,\n calculateFitCenter,\n getContainersForLayer,\n calculateFitView,\n} from '@visualli/core';\n\nexport type { FitResult, ContainerGroupInfo } from '@visualli/core';\n","// ─── KonvaStage ───────────────────────────────────────────────────────────────\n//\n// Thin wrapper around react-konva <Stage> that:\n// • Binds canvas position/scale from the viewport store\n// • Accepts optional event handlers (wheel, mouse, touch, context-menu)\n// • Calls stage.destroy() on unmount (memory hygiene)\n\nimport React, { useRef, useEffect, forwardRef } from 'react';\nimport { KStage as Stage } from '../konvaCompat';\nimport type Konva from 'konva';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nexport interface KonvaStageProps {\n children: React.ReactNode;\n onWheel?: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n onMouseDown?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseMove?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseUp?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onContextMenu?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onTouchStart?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchMove?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchEnd?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onStageReady?: (stage: Konva.Stage) => void;\n}\n\nconst KonvaStage = forwardRef<Konva.Stage, KonvaStageProps>(function KonvaStage(\n {\n children,\n onWheel, onMouseDown, onMouseMove, onMouseUp, onContextMenu,\n onTouchStart, onTouchMove, onTouchEnd,\n onStageReady,\n },\n ref,\n) {\n const internalRef = useRef<Konva.Stage | null>(null);\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n useEffect(() => {\n if (internalRef.current) {\n if (typeof ref === 'function') ref(internalRef.current);\n else if (ref) (ref as React.MutableRefObject<Konva.Stage | null>).current = internalRef.current;\n onStageReady?.(internalRef.current);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n return () => { internalRef.current?.destroy(); };\n }, []);\n\n const w = canvasWidth || 800;\n const h = canvasHeight || 600;\n const stageX = w / 2 - centerX * zoomLevel;\n const stageY = h / 2 - centerY * zoomLevel;\n\n return (\n <Stage\n ref={internalRef}\n width={w}\n height={h}\n x={stageX}\n y={stageY}\n scaleX={zoomLevel}\n scaleY={zoomLevel}\n onWheel={onWheel}\n onMouseDown={onMouseDown}\n onMouseMove={onMouseMove}\n onMouseUp={onMouseUp}\n onContextMenu={onContextMenu}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onTouchEnd={onTouchEnd}\n draggable={false}\n pixelRatio={1}\n >\n {children}\n </Stage>\n );\n});\n\nexport default KonvaStage;\n","// ─── konvaCompat ──────────────────────────────────────────────────────────────\n//\n// react-konva@18.x defines KonvaNodeComponent with return type\n// `ReactNode | Promise<ReactNode>`. @types/react v19 tightened the JSX checker\n// so that signature no longer satisfies `(props: any) => ReactNode`, causing\n// TS2786 errors everywhere a Konva primitive is used as JSX.\n//\n// The fix: re-export every Konva primitive cast to React.ComponentType<any>.\n// This is purely a type-level shim — no runtime behaviour changes.\n\nimport {\n Stage, Layer, Group, Shape, Path, Rect, Text, Arrow, Line, Circle, TextPath,\n} from 'react-konva';\nimport type React from 'react';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype C = React.ComponentType<any>;\n\nexport const KStage = Stage as unknown as C;\nexport const KLayer = Layer as unknown as C;\nexport const KGroup = Group as unknown as C;\nexport const KShape = Shape as unknown as C;\nexport const KPath = Path as unknown as C;\nexport const KRect = Rect as unknown as C;\nexport const KText = Text as unknown as C;\nexport const KArrow = Arrow as unknown as C;\nexport const KLine = Line as unknown as C;\nexport const KCircle = Circle as unknown as C;\nexport const KTextPath = TextPath as unknown as C;\n","// ─── KonvaNodeLayer ───────────────────────────────────────────────────────────\n//\n// Konva <Layer> that renders all visible FlatNodes.\n// Uses viewport culling and passes external hover/pressed state to each node.\n\nimport React, { useRef, useLayoutEffect, useEffect, useMemo } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { useViewportNodes } from '../hooks/useViewportNodes';\nimport KonvaNode from './KonvaNode';\n\nexport interface KonvaNodeLayerProps {\n nodes?: FlatNode[];\n isTransitioning?: boolean;\n isDragging?: boolean;\n hoveredNodeId?: string | null;\n pressedNodeId?: string | null;\n}\n\nexport default function KonvaNodeLayer({\n nodes: propNodes,\n isTransitioning = false,\n isDragging = false,\n hoveredNodeId = null,\n pressedNodeId = null,\n}: KonvaNodeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n const storeNodes = useNodeStore(s => s.nodes);\n const allNodes: FlatNode[] = useMemo(\n () => propNodes ?? Array.from(storeNodes.values()),\n [propNodes, storeNodes],\n );\n const visibleNodes = useViewportNodes(allNodes, undefined, isTransitioning, isDragging);\n\n // Redraw synchronously before paint whenever visible content changes.\n // Tied to data deps so it does not fire on every parent re-render.\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [visibleNodes, hoveredNodeId, pressedNodeId, isDragging, zoomLevel]);\n\n // Redraw when transition state toggles (opacity wrapper controls visibility,\n // but the canvas still needs to be current when it fades back in).\n useEffect(() => { layerRef.current?.batchDraw(); }, [isTransitioning]);\n\n return (\n <Layer ref={layerRef} name=\"nodes\">\n {visibleNodes.map(n => (\n <KonvaNode\n key={n.id}\n node={n}\n zoomLevel={zoomLevel}\n isExternallyHovered={hoveredNodeId === n.id}\n isExternallyPressed={pressedNodeId === n.id}\n isDragging={isDragging}\n />\n ))}\n </Layer>\n );\n}\n","// ─── useViewportNodes ─────────────────────────────────────────────────────────\n//\n// Returns the subset of nodes currently visible in the viewport.\n// Signature: useViewportNodes(nodes, levelFilter?, skipCulling?)\n//\n// When skipCulling=true (e.g. during layer transitions) all nodes are returned\n// so the full layer is rendered when opacity ramps in.\n\nimport { useMemo, useRef } from 'react';\nimport type { FlatNode } from '@visualli/core';\nimport { RBushSpatialIndex, getViewportVisibleNodes } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nconst SPATIAL_INDEX_THRESHOLD = 200;\n\nexport function useViewportNodes(\n nodes: FlatNode[],\n levelFilter?: number,\n skipCulling = false,\n /** When true, skip culling so dragged nodes are always visible and the\n * spatial index (keyed on layout positions) is not consulted. */\n isDragging = false,\n): FlatNode[] {\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n const indexRef = useRef<RBushSpatialIndex | null>(null);\n const nodesHashRef = useRef<number>(0);\n const nodesHash = nodes.length;\n\n if (nodesHash !== nodesHashRef.current) {\n nodesHashRef.current = nodesHash;\n indexRef.current = null; // rebuild below\n }\n\n return useMemo(() => {\n if (nodes.length === 0) return [];\n\n if (!indexRef.current && nodes.length >= SPATIAL_INDEX_THRESHOLD && !skipCulling && !isDragging) {\n indexRef.current = new RBushSpatialIndex();\n indexRef.current.bulkLoad(nodes.map(n => ({\n nodeId: n.id,\n bounds: { minX: n.x, minY: n.y, maxX: n.x + n.width, maxY: n.y + n.height },\n })));\n }\n\n return getViewportVisibleNodes({\n nodes,\n viewport: { centerX, centerY, zoomLevel, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } },\n canvasWidth,\n canvasHeight,\n levelFilter,\n skipCulling,\n isDragging,\n spatialIndex: indexRef.current,\n spatialIndexThreshold: SPATIAL_INDEX_THRESHOLD,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [nodes, levelFilter, skipCulling, isDragging, centerX, centerY, zoomLevel, canvasWidth, canvasHeight]);\n}\n","// ─── KonvaNode ────────────────────────────────────────────────────────────────\n//\n// Renders a single FlatNode as a single organic blob shape with Konva.\n// Matches the visualli.ai rendering:\n// - Centered blob at node (x, y) with radiusX / radiusY scaling\n// - Single blob shape (no background depth layers)\n// - HSL-based border darkening\n// - 'Story Script' cursive font, text clipped to blob silhouette\n// - External hover / pressed state (no Konva hit-canvas dependency)\n// - All shapes are listening=false; hit detection uses spatial index\n\nimport React, { useMemo } from 'react';\nimport { KGroup as Group, KShape as Shape, KText as Text } from '../konvaCompat';\nimport type { FlatNode } from '@visualli/core';\nimport { CANVAS_COLORS, NODE_HEIGHT, TEXT_LABEL_HIDE_BELOW_ZOOM, darkenHexColor } from '@visualli/core';\nimport { getBlobTypeForLayer, BLOB_TEXT_OFFSETS, BLOB_LAYER_CONFIG, NODE_LAYER_CONFIG, drawBlobPath, computeNodeTextWorldScale } from '../config';\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport interface KonvaNodeProps {\n node: FlatNode;\n zoomLevel: number;\n /** True when the pointer is currently over this node (stage-level hit test). */\n isExternallyHovered?: boolean;\n /** True while this node is being pressed/dragged. */\n isExternallyPressed?: boolean;\n /** True while any node is being dragged — disables expensive shadows. */\n isDragging?: boolean;\n}\n\nconst KonvaNode = React.memo(function KonvaNode({\n node,\n zoomLevel,\n isExternallyHovered = false,\n isExternallyPressed = false,\n isDragging = false,\n}: KonvaNodeProps) {\n // Border: monochromatic HSL-darkened version of the fill color\n const borderColor = useMemo(() => darkenHexColor(node.color, 0.13), [node.color]);\n\n // Number of background layers (capped at 3), driven by branchCount\n const layerCount = useMemo(() => {\n const count = node.branchCount ?? 0;\n return Math.min(count, 3);\n }, [node.branchCount]);\n\n // Base blob radii (same math as visualli.ai KonvaNode)\n const baseRadiusX = node.width / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n\n // Larger, consistent font size for better readability\n // Text will wrap to multiple lines if needed\n const calculateFontSize = useMemo(() => {\n // Use a larger base font size for better visibility\n return 30;\n }, [node.title]);\n\n // Text scale and layout\n const textNaturalWidth = node.width - 40;\n // Increase text height to allow 2-3 lines of wrapped text\n const textNaturalHeight = NODE_HEIGHT * 1.2;\n const maxScale = computeNodeTextWorldScale(node.width, zoomLevel);\n\n // Blob type and text offset\n const blobType = getBlobTypeForLayer(node.level);\n const textOffsetX = (BLOB_TEXT_OFFSETS[blobType] ?? 0) * baseRadiusX;\n\n // Interaction state (purely driven from stage-level delegation)\n const effectiveHover = isExternallyHovered;\n const isPressed = isExternallyPressed;\n\n // Blob fill/stroke:\n // default → fill=node.color, stroke=borderColor\n // hover → fill=borderColor, stroke=borderColor\n // pressed → fill=borderColor, stroke=node.color\n const topFill = effectiveHover || isPressed ? borderColor : node.color;\n const topStroke = isPressed ? node.color : borderColor;\n\n // Build the background layers config (outermost first for correct z-order)\n const backgroundLayers = useMemo(() => {\n if (layerCount === 0) return [];\n const startIdx = BLOB_LAYER_CONFIG.length - layerCount;\n const layers = [];\n for (let i = startIdx; i < BLOB_LAYER_CONFIG.length; i++) {\n const config = BLOB_LAYER_CONFIG[i];\n layers.push({\n ...config,\n radiusX: baseRadiusX * config.scaleUp,\n radiusY: baseRadiusY * config.scaleUp,\n });\n }\n return layers;\n }, [layerCount, baseRadiusX, baseRadiusY]);\n\n return (\n <Group x={node.x} y={node.y} listening={false}>\n {/* Background blob layers (outermost rendered first, behind the node) */}\n {backgroundLayers.map((layer, idx) => (\n <Shape\n key={`blob-layer-${idx}`}\n rotation={layer.rotation}\n opacity={layer.opacity}\n sceneFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, layer.radiusX, layer.radiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n fill={node.color}\n stroke={borderColor}\n strokeWidth={layer.strokeWidth}\n dash={layer.dash ? [...layer.dash] : undefined}\n listening={false}\n perfectDrawEnabled={false}\n />\n ))}\n\n {/* Node (top layer) - main interactive blob */}\n <Shape\n rotation={NODE_LAYER_CONFIG.rotation}\n opacity={NODE_LAYER_CONFIG.opacity}\n sceneFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n hitFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n fill={topFill}\n stroke={topStroke}\n strokeWidth={NODE_LAYER_CONFIG.strokeWidth}\n shadowEnabled={!isDragging}\n shadowColor=\"rgba(255,255,255,1)\"\n shadowBlur={effectiveHover || isPressed ? 40 : 15}\n shadowOpacity={effectiveHover || isPressed ? 0.4 : 0.15}\n shadowOffsetX={0}\n shadowOffsetY={0}\n perfectDrawEnabled={false}\n />\n\n {/* Node Title — inverse-scaled so it stays legible at a constant screen size.\n Clipped to the blob silhouette via clipFunc so the growing text never visually\n bleeds outside the first layer boundary at low zoom levels. */}\n <Group\n clipFunc={(ctx: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n }}\n visible={zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM}\n listening={false}\n >\n <Text\n x={textOffsetX}\n y={0}\n offsetX={textNaturalWidth / 2}\n offsetY={textNaturalHeight / 2}\n width={textNaturalWidth}\n height={textNaturalHeight}\n scaleX={maxScale}\n scaleY={maxScale}\n text={node.title}\n fontSize={calculateFontSize}\n fontFamily=\"'Story Script', cursive\"\n fontStyle=\"normal\"\n fill={CANVAS_COLORS.node.titleColor}\n align=\"center\"\n verticalAlign=\"middle\"\n wrap=\"word\"\n ellipsis={false}\n listening={false}\n perfectDrawEnabled={false}\n />\n </Group>\n </Group>\n );\n});\n\nexport default KonvaNode;\n\n","export {\n ALL_BLOB_SHAPES,\n ACTIVE_BLOB_TYPES,\n BLOB_LAYER_CONFIG,\n NODE_LAYER_CONFIG,\n getBlobTypeForLayer,\n BLOB_TEXT_OFFSETS,\n drawBlobPath,\n NODE_TEXT_BASE_FONT_PX,\n DESCRIPTION_TEXT_BASE_FONT_PX,\n CONTAINER_LABEL_BASE_FONT_PX,\n EDGE_LABEL_BASE_FONT_PX,\n OVERLAY_FONT_UPPER_BOOST_PX,\n computeNodeTextWorldScale,\n computeNodeTextScreenScale,\n computeOverlayScale,\n computeEdgeLabelScale,\n} from '@visualli/core';\n\nexport { buildBlobPathData } from './blobShapes';\nexport type { BlobPoint, BlobShape } from '@visualli/core';\n","// ─── Blob Shapes Configuration ───────────────────────────────────────────────\n//\n// Blob shapes are centered at (0, 0). Coordinates are relative — multiply by\n// (radiusX, radiusY) to get world coords. Drawing uses closed quadratic bezier\n// curves through midpoints of consecutive control points (same as visualli.ai).\n//\n// Shapes match the visualli.ai reference designs exactly.\n\nexport interface BlobPoint { x: number; y: number }\nexport type BlobShape = ReadonlyArray<BlobPoint>;\n\n// ── Blob background layer depth config ────────────────────────────────────────\n// Index 0 = outermost layer (rendered first, behind the top blob).\n\nexport const BLOB_LAYER_CONFIG = [\n { opacity: 0.3, rotation: -15, scaleUp: 1.30, strokeWidth: 3, dash: [6, 4] as [number, number] },\n { opacity: 0.4, rotation: -10, scaleUp: 1.20, strokeWidth: 1, dash: undefined },\n { opacity: 0.5, rotation: -5, scaleUp: 1.10, strokeWidth: 2, dash: undefined },\n] as const;\n\nexport const NODE_LAYER_CONFIG = { opacity: 1, rotation: 0, strokeWidth: 3 } as const;\n\n// ── Six organic blob variants ─────────────────────────────────────────────────\nexport const ALL_BLOB_SHAPES: ReadonlyArray<BlobShape> = [\n // Shape 0 · Blob 1 (root / L0)\n [\n { x: 1.12, y: 0.00 }, { x: 0.86, y: 0.56 }, { x: 0.46, y: 0.94 },\n { x: -0.08, y: 1.06 }, { x: -0.68, y: 0.82 }, { x: -0.96, y: 0.08 },\n { x: -0.55, y: -0.82 }, { x: 0.04, y: -1.02 }, { x: 0.72, y: -0.80 },\n { 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 },\n { x: -0.189, y: -0.855 }, { x: -0.090, y: -0.903 }, { x: 0.014, y: -0.932 },\n { x: 0.129, y: -0.940 }, { x: 0.255, y: -0.924 }, { x: 0.412, y: -0.876 },\n { 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 },\n { x: 0.933, y: -0.486 }, { x: 0.979, y: -0.425 }, { x: 1.006, y: -0.385 },\n { x: 1.034, y: -0.334 }, { x: 1.058, y: -0.276 }, { x: 1.078, y: -0.209 },\n { 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 },\n { x: 1.034, y: 0.401 }, { x: 0.996, y: 0.477 }, { x: 0.948, y: 0.549 },\n { x: 0.889, y: 0.617 }, { x: 0.820, y: 0.681 }, { x: 0.735, y: 0.741 },\n { 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 },\n { x: 0.046, y: 0.931 }, { x: -0.069, y: 0.938 }, { x: -0.155, y: 0.935 },\n { x: -0.250, y: 0.919 }, { x: -0.346, y: 0.890 }, { x: -0.443, y: 0.851 },\n { 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 },\n { x: -0.994, y: 0.343 }, { x: -1.034, y: 0.267 }, { x: -1.064, y: 0.192 },\n { x: -1.085, y: 0.120 }, { x: -1.097, y: 0.042 }, { x: -1.102, y: 0.001 },\n { 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 },\n { 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 },\n { x: 0.389, y: -1.096 }, { x: 0.488, y: -1.174 }, { x: 0.597, y: -1.210 },\n { x: 0.728, y: -1.165 }, { x: 0.867, y: -1.036 }, { x: 0.996, y: -0.839 },\n { 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 },\n { x: 0.484, y: 1.072 }, { x: 0.339, y: 1.079 }, { x: 0.219, y: 1.051 },\n { x: 0.131, y: 0.994 }, { x: 0.059, y: 0.939 }, { x: 0.008, y: 0.915 },\n { 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 },\n { x: -0.817, y: 0.952 }, { x: -0.945, y: 0.810 }, { x: -1.054, y: 0.600 },\n { x: -1.160, y: 0.302 }, { x: -1.187, y: -0.011 }, { x: -1.165, y: -0.326 },\n { 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 },\n { 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 },\n { x: -0.468, y: -1.115 }, { x: -0.358, y: -1.079 }, { x: -0.238, y: -1.034 },\n { x: -0.107, y: -0.989 }, { x: 0.035, y: -0.953 }, { x: 0.188, y: -0.929 },\n { 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 },\n { x: 1.138, y: -0.126 }, { x: 1.152, y: 0.272 }, { x: 1.121, y: 0.451 },\n { x: 1.046, y: 0.602 }, { x: 0.928, y: 0.727 }, { x: 0.767, y: 0.833 },\n { 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 },\n { x: -0.589, y: 1.104 }, { x: -0.704, y: 1.050 }, { x: -0.815, y: 0.973 },\n { x: -0.913, y: 0.871 }, { x: -0.993, y: 0.746 }, { x: -1.048, y: 0.593 },\n { 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 },\n { x: -0.886, y: -1.020 },\n ],\n // Shape 4 · Blob 5 (inverted Blob 4)\n [\n { x: -0.734, y: 1.127 }, { x: -0.656, y: 1.146 }, { x: -0.567, y: 1.142 },\n { x: -0.468, y: 1.115 }, { x: -0.358, y: 1.079 }, { x: -0.238, y: 1.034 },\n { x: -0.107, y: 0.989 }, { x: 0.035, y: 0.953 }, { x: 0.188, y: 0.929 },\n { 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 },\n { x: 1.138, y: 0.126 }, { x: 1.152, y: -0.272 }, { x: 1.121, y: -0.451 },\n { x: 1.046, y: -0.602 }, { x: 0.928, y: -0.727 }, { x: 0.767, y: -0.833 },\n { 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 },\n { x: -0.589, y: -1.104 }, { x: -0.704, y: -1.050 }, { x: -0.815, y: -0.973 },\n { x: -0.913, y: -0.871 }, { x: -0.993, y: -0.746 }, { x: -1.048, y: -0.593 },\n { 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 },\n { 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 Konva canvas context (centered at 0,0).\n * Uses closed quadratic bezier curves through midpoints of control points.\n * Call this inside a Konva Shape's sceneFunc / hitFunc.\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\n// Legacy export kept for consumers that may import buildBlobPathData.\n// Generates an SVG path string (less accurate than the sceneFunc approach).\nexport function buildBlobPathData(\n _shape: BlobShape,\n cx: number,\n cy: number,\n width: number,\n height: number,\n): string {\n const rx = width / 2;\n const ry = height / 2;\n const blobType = 0;\n const srcPts = ALL_BLOB_SHAPES[blobType];\n const pts = srcPts.map(p => ({ x: cx + p.x * rx, y: cy + p.y * ry }));\n const mid = (a: { x: number; y: number }, b: { x: number; y: number }) =>\n ({ x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 });\n const last = pts[pts.length - 1];\n const first = pts[0];\n const s = mid(last, first);\n let d = `M ${s.x} ${s.y}`;\n for (let i = 0; i < pts.length; i++) {\n const curr = pts[i];\n const next = pts[(i + 1) % pts.length];\n const m = mid(curr, next);\n d += ` Q ${curr.x} ${curr.y} ${m.x} ${m.y}`;\n }\n d += ' Z';\n return d;\n}\n","// ─── KonvaEdgeLayer ───────────────────────────────────────────────────────────\n//\n// Renders all edges for visible nodes. An edge is only drawn when BOTH its\n// source and target node are currently in the visible set.\n//\n// NOTE: Node positions are read from useNodeStore (live) so edges always follow\n// dragged nodes. The `nodes` prop is used only for initial viewport culling.\n\nimport React, { useRef, useLayoutEffect, useMemo } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode, MindMapConnection } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useViewportNodes } from '../hooks/useViewportNodes';\nimport KonvaEdge from './KonvaEdge';\n\nexport interface KonvaEdgeLayerProps {\n nodes: FlatNode[];\n connections: MindMapConnection[];\n currentLevel?: number;\n isDark?: boolean;\n /** Pass true while a node is being dragged to skip viewport culling. */\n isDragging?: boolean;\n}\n\nexport default function KonvaEdgeLayer({\n nodes,\n connections,\n currentLevel,\n isDark = false,\n isDragging = false,\n}: KonvaEdgeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n // Live node positions from the store — updated every RAF during drag\n const storeNodes = useNodeStore(s => s.nodes);\n // Viewport culling still uses the layout snapshot for performance;\n // during drag, culling is skipped so newly-moved nodes are always visible.\n const visibleNodes = useViewportNodes(nodes, currentLevel, false, isDragging);\n\n // Set of visible node IDs for O(1) culling\n const visibleSet = useMemo(() => new Set(visibleNodes.map(n => n.id)), [visibleNodes]);\n\n // Redraw before paint whenever visible edges change.\n // storeNodes must be included: edge endpoints read live positions from the store,\n // so when a node is dragged, the edge must redraw even though visibleSet is unchanged.\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [connections, isDark, isDragging, visibleSet, storeNodes]);\n\n return (\n <Layer ref={layerRef} listening={false}>\n {connections.map((conn, idx) => {\n // Use live store positions so edges move with dragged nodes\n const src = storeNodes.get(conn.from);\n const tgt = storeNodes.get(conn.to);\n if (!src || !tgt) return null;\n if (!isDragging && !visibleSet.has(src.id) && !visibleSet.has(tgt.id)) return null;\n\n return (\n <KonvaEdge\n key={`${conn.from}-${conn.to}-${idx}`}\n sourceNode={src}\n targetNode={tgt}\n connection={conn}\n isDark={isDark}\n zoomLevel={zoomLevel}\n />\n );\n })}\n </Layer>\n );\n}\n","// ─── KonvaEdge ────────────────────────────────────────────────────────────────\n//\n// Renders a connection arrow between two FlatNodes.\n// Matches the visualli.ai KonvaEdge exactly:\n// - Cubic bezier multi-point polyline (20 segments) through ellipse boundaries\n// - Adaptive arc height (smaller for long connections)\n// - Open V arrowhead at target\n// - TextPath label following the curve (above the line)\n// - Always black stroke for maximum visibility\n\nimport React, { useMemo, memo } from 'react';\nimport { KGroup as Group, KLine as Line, KTextPath as TextPath } from '../konvaCompat';\nimport type { FlatNode, MindMapConnection } from '@visualli/core';\nimport { NODE_HEIGHT } from '@visualli/core';\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n// Returns the outermost visible blob scale for a node.\n// Mirrors BLOB_LAYER_CONFIG in KonvaNode: scaleUps are [1.30, 1.20, 1.10] (outermost→inner).\nconst getOutermostScaleUp = (branchCount: number | undefined): number => {\n const layerCount = Math.min(branchCount ?? 0, 3);\n if (layerCount === 0) return 1.0;\n const scaleUps = [1.30, 1.20, 1.10] as const;\n return scaleUps[scaleUps.length - layerCount];\n};\n\nfunction getEllipseIntersection(\n cx: number, cy: number, rx: number, ry: number, angle: number,\n): { x: number; y: number } {\n return {\n x: cx + rx * Math.cos(angle),\n y: cy + ry * Math.sin(angle),\n };\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport interface KonvaEdgeProps {\n sourceNode: FlatNode;\n targetNode: FlatNode;\n connection?: MindMapConnection;\n isDark?: boolean;\n colorOverride?: string;\n zoomLevel?: number;\n}\n\nconst EDGE_SPACING = 25; // Increased spacing to ensure arrow head stays out of organic shapes\nconst STROKE_COLOR = '#000000';\nconst STROKE_WIDTH = 2.5;\n\nconst KonvaEdge = memo(function KonvaEdge({\n sourceNode: from,\n targetNode: to,\n connection,\n zoomLevel = 1.0,\n}: KonvaEdgeProps) {\n const label = (connection as { label?: string } | undefined)?.label;\n\n // ── Build multi-point bezier curve ─────────────────────────────────────────\n const points = useMemo(() => {\n const fromBaseX = from.width / 2;\n const fromBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, fromBaseX * 0.74);\n const fromScale = getOutermostScaleUp(from.branchCount);\n const fromRadiusX = fromBaseX * fromScale;\n const fromRadiusY = fromBaseY * fromScale;\n\n const toBaseX = to.width / 2;\n const toBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, toBaseX * 0.74);\n const toScale = getOutermostScaleUp(to.branchCount);\n const toRadiusX = toBaseX * toScale;\n const toRadiusY = toBaseY * toScale;\n\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const fromEdge = getEllipseIntersection(from.x, from.y, fromRadiusX, fromRadiusY, angle);\n const toEdge = getEllipseIntersection(to.x, to.y, toRadiusX, toRadiusY, angle + Math.PI);\n\n // Apply spacing from edges (increased to 25 to avoid leaking into organic shapes)\n const fromX = fromEdge.x + EDGE_SPACING * Math.cos(angle);\n const fromY = fromEdge.y + EDGE_SPACING * Math.sin(angle);\n const toX = toEdge.x - EDGE_SPACING * Math.cos(angle);\n const toY = toEdge.y - EDGE_SPACING * Math.sin(angle);\n\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n\n const distance = Math.sqrt((toX - fromX) ** 2 + (toY - fromY) ** 2);\n const arcHeight = Math.min(45, 45 / (1 + Math.max(0, (distance - 200) / 400)));\n\n const perpX = -(toY - fromY) / distance;\n const perpY = (toX - fromX) / distance;\n\n const offsetMidX = midX + perpX * arcHeight;\n const offsetMidY = midY + perpY * arcHeight;\n\n const ctrl1X = fromX + (offsetMidX - fromX) * 0.66;\n const ctrl1Y = fromY + (offsetMidY - fromY) * 0.66;\n const ctrl2X = toX + (offsetMidX - toX) * 0.66;\n const ctrl2Y = toY + (offsetMidY - toY) * 0.66;\n\n const NUM_SEGMENTS = 20;\n const pts: number[] = [];\n for (let i = 0; i <= NUM_SEGMENTS; i++) {\n const t = i / NUM_SEGMENTS;\n const mt = 1 - t;\n const mt2 = mt * mt; const mt3 = mt2 * mt;\n const t2 = t * t; const t3 = t2 * t;\n pts.push(\n mt3 * fromX + 3 * mt2 * t * ctrl1X + 3 * mt * t2 * ctrl2X + t3 * toX,\n mt3 * fromY + 3 * mt2 * t * ctrl1Y + 3 * mt * t2 * ctrl2Y + t3 * toY,\n );\n }\n return pts;\n }, [from.x, from.y, from.width, from.branchCount, to.x, to.y, to.width, to.branchCount]);\n\n // ── Arrowhead ─────────────────────────────────────────────────────────────\n const arrowHeadPoints = useMemo(() => {\n const len = points.length;\n const tipX = points[len - 2];\n const tipY = points[len - 1];\n const prevX = points[len - 4];\n const prevY = points[len - 3];\n const angle = Math.atan2(tipY - prevY, tipX - prevX);\n const armLength = 11;\n const armAngle = Math.PI / 5.5; // ~33°\n return [\n tipX - armLength * Math.cos(angle - armAngle),\n tipY - armLength * Math.sin(angle - armAngle),\n tipX, tipY,\n tipX - armLength * Math.cos(angle + armAngle),\n tipY - armLength * Math.sin(angle + armAngle),\n ];\n }, [points]);\n\n // ── TextPath data (optional label) ────────────────────────────────────────\n const { pathData, fontSize } = useMemo(() => {\n if (!label) return { pathData: null, fontSize: 12 };\n\n const fromBaseX = from.width / 2;\n const fromBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, fromBaseX * 0.74);\n const fromScale = getOutermostScaleUp(from.branchCount);\n const fromRadiusX = fromBaseX * fromScale;\n const fromRadiusY = fromBaseY * fromScale;\n\n const toBaseX = to.width / 2;\n const toBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, toBaseX * 0.74);\n const toScale = getOutermostScaleUp(to.branchCount);\n const toRadiusX = toBaseX * toScale;\n const toRadiusY = toBaseY * toScale;\n\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const fromEdge = getEllipseIntersection(from.x, from.y, fromRadiusX, fromRadiusY, angle);\n const toEdge = getEllipseIntersection(to.x, to.y, toRadiusX, toRadiusY, angle + Math.PI);\n\n const fromX = fromEdge.x + EDGE_SPACING * Math.cos(angle);\n const fromY = fromEdge.y + EDGE_SPACING * Math.sin(angle);\n const toX = toEdge.x - EDGE_SPACING * Math.cos(angle);\n const toY = toEdge.y - EDGE_SPACING * Math.sin(angle);\n\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n const distance = Math.sqrt((toX - fromX) ** 2 + (toY - fromY) ** 2);\n const arcHeight = Math.min(45, 45 / (1 + Math.max(0, (distance - 200) / 400)));\n\n const perpX = -(toY - fromY) / distance;\n const perpY = (toX - fromX) / distance;\n\n const offsetMidX = midX + perpX * arcHeight;\n const offsetMidY = midY + perpY * arcHeight;\n\n const ctrl1X = fromX + (offsetMidX - fromX) * 0.66;\n const ctrl1Y = fromY + (offsetMidY - fromY) * 0.66;\n const ctrl2X = toX + (offsetMidX - toX) * 0.66;\n const ctrl2Y = toY + (offsetMidY - toY) * 0.66;\n\n const TEXT_OFFSET = 15;\n const fxo = fromX + perpX * TEXT_OFFSET; const fyo = fromY + perpY * TEXT_OFFSET;\n const txo = toX + perpX * TEXT_OFFSET; const tyo = toY + perpY * TEXT_OFFSET;\n const c1xo = ctrl1X + perpX * TEXT_OFFSET; const c1yo = ctrl1Y + perpY * TEXT_OFFSET;\n const c2xo = ctrl2X + perpX * TEXT_OFFSET; const c2yo = ctrl2Y + perpY * TEXT_OFFSET;\n\n // Variable font size: scales with zoom level to remain visible when zoomed out\n // and also scales with node width.\n const baseFontSize = 14;\n const zoomFactor = Math.max(1, 1 / zoomLevel); // Increase font size as we zoom out\n const scaledFontSize = Math.max(12, Math.min(24, baseFontSize * (from.width / 180) * zoomFactor));\n\n let d = '';\n if (fromX > toX) {\n d = `M ${txo},${tyo} C ${c2xo},${c2yo} ${c1xo},${c1yo} ${fxo},${fyo}`;\n } else {\n d = `M ${fxo},${fyo} C ${c1xo},${c1yo} ${c2xo},${c2yo} ${txo},${tyo}`;\n }\n return { pathData: d, fontSize: scaledFontSize };\n }, [from.x, from.y, from.width, from.branchCount, to.x, to.y, to.width, to.branchCount, label, zoomLevel]);\n\n // ── Render ────────────────────────────────────────────────────────────────\n return (\n <Group>\n <Line\n points={points}\n stroke={STROKE_COLOR}\n strokeWidth={STROKE_WIDTH}\n tension={0}\n opacity={0.9}\n lineCap=\"round\"\n lineJoin=\"round\"\n listening={false}\n perfectDrawEnabled={false}\n />\n <Line\n points={arrowHeadPoints}\n stroke={STROKE_COLOR}\n strokeWidth={STROKE_WIDTH}\n lineCap=\"round\"\n lineJoin=\"round\"\n opacity={0.9}\n listening={false}\n perfectDrawEnabled={false}\n />\n {label && pathData && (\n <>\n {/* Background text for contrast */}\n <TextPath\n data={pathData}\n text={label}\n fontSize={fontSize}\n fontFamily=\"'Playpen Sans', cursive\"\n fontStyle=\"normal\"\n fill=\"#ffffff\"\n align=\"center\"\n letterSpacing={0.5}\n listening={false}\n opacity={0.9}\n />\n {/* Foreground label text */}\n <TextPath\n data={pathData}\n text={label}\n fontSize={fontSize}\n fontFamily=\"'Playpen Sans', cursive\"\n fontStyle=\"normal\"\n fill=\"#6b6860\"\n align=\"center\"\n letterSpacing={0.5}\n listening={false}\n opacity={0.9}\n />\n </>\n )}\n </Group>\n );\n});\n\nexport default KonvaEdge;\n","// ─── KonvaContainerLayer ─────────────────────────────────────────────────────\n//\n// Renders container outlines beneath nodes (non-interactive).\n//\n// Node positions are read from useNodeStore (live), matching the visualli.ai\n// reference — containers follow dragged nodes in real-time every RAF frame.\n\nimport React, { useRef, useLayoutEffect } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport KonvaContainer from './KonvaContainer';\n\nexport interface ContainerGroup {\n id: string;\n label?: string;\n nodeIds: string[];\n level: number;\n}\n\nexport interface KonvaContainerLayerProps {\n /** Layout-snapshot nodes — used only as a seed for initial IDs. */\n nodes: FlatNode[];\n containers: ContainerGroup[];\n isDark?: boolean;\n}\n\nexport default function KonvaContainerLayer({ nodes, containers, isDark = false }: KonvaContainerLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n\n // Subscribe to live store — updated every RAF frame during drag.\n // This is the same pattern used by KonvaEdgeLayer so containers and edges\n // both track dragged nodes in real-time.\n const storeNodes = useNodeStore(s => s.nodes);\n\n // batchDraw deps include storeNodes so the layer redraws whenever any node\n // position changes (including mid-drag RAF updates).\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [containers, isDark, storeNodes]);\n\n if (containers.length === 0) return null;\n\n return (\n <Layer ref={layerRef} listening={false}>\n {containers.map(c => {\n // Read positions from live store — not from the layout snapshot\n const groupNodes = c.nodeIds\n .map(id => storeNodes.get(id))\n .filter((n): n is FlatNode => !!n);\n if (groupNodes.length === 0) return null;\n\n return (\n <KonvaContainer\n key={c.id}\n nodes={groupNodes}\n label={c.label}\n isDark={isDark}\n />\n );\n })}\n </Layer>\n );\n}\n","// ─── KonvaContainer ──────────────────────────────────────────────────────────\n//\n// Renders a smooth dashed hull around a group of nodes with an inverse-scaled\n// pill label — matches the visualli.ai KonvaContainer exactly.\n//\n// • 48-point ellipse sampling per node (not bounding box corners)\n// • Graham-scan convex hull → 6-pass Chaikin smoothing\n// • Dashed stroke \"#747270\", no fill\n// • Pill label: parchment bg (#ddd9d0), Playpen Sans 800, inverse-zoom-scaled\n// • Label anchored to the hull edge (bottom for horizontal, top for vertical)\n\nimport React, { memo, useMemo } from 'react';\nimport {\n KGroup as Group,\n KLine as Line,\n KRect as Rect,\n KText as Text,\n} from '../konvaCompat';\nimport type { FlatNode } from '@visualli/core';\nimport { NODE_HEIGHT, TEXT_LABEL_HIDE_BELOW_ZOOM } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport {\n CONTAINER_LABEL_BASE_FONT_PX,\n computeNodeTextScreenScale,\n} from '../config/textScaling';\n\n// ── Constants (mirrors visualli.ai) ──────────────────────────────────────────\n\nconst CONTAINER_PADDING = 50;\nconst CONTAINER_DASH = [10, 5] as const;\nconst LABEL_BG = '#ddd9d0';\nconst LABEL_BORDER_RADIUS = 20;\nconst LABEL_FONT_SIZE = CONTAINER_LABEL_BASE_FONT_PX;\nconst LABEL_FONT_WEIGHT = '800';\nconst LABEL_FONT_FAMILY = \"'Playpen Sans', Quicksand, sans-serif\";\nconst LABEL_PAD_H = 20;\nconst LABEL_PAD_V = 10;\nconst LABEL_LINE_HEIGHT = 1.2;\n// Max normalized blob extents — Shape 5 reaches ±1.275 X, ±1.234 Y\nconst MAX_BLOB_EXTENT_X = 1.275;\nconst MAX_BLOB_EXTENT_Y = 1.234;\n\n// ── Text measurement ──────────────────────────────────────────────────────────\n\nlet _labelCtx: CanvasRenderingContext2D | null = null;\nfunction measureLabelBoxWidth(text: string, fontSize: number): number {\n if (!_labelCtx) {\n const c = document.createElement('canvas');\n _labelCtx = c.getContext('2d');\n }\n if (!_labelCtx) return Math.ceil(text.length * fontSize * 0.65 + 2 * LABEL_PAD_H);\n _labelCtx.font = `${LABEL_FONT_WEIGHT} ${fontSize}px ${LABEL_FONT_FAMILY}`;\n return Math.ceil(_labelCtx.measureText(text).width + 2 * LABEL_PAD_H);\n}\n\n// ── Convex hull (Graham scan) ─────────────────────────────────────────────────\n\ntype Pt = { x: number; y: number };\n\nfunction isLeftTurn(p1: Pt, p2: Pt, p3: Pt): boolean {\n return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x) > 0;\n}\n\nfunction convexHull(points: Pt[]): Pt[] {\n if (points.length < 3) return points;\n let start = 0;\n for (let i = 1; i < points.length; i++) {\n if (points[i].y < points[start].y ||\n (points[i].y === points[start].y && points[i].x < points[start].x)) start = i;\n }\n const sorted = [...points];\n const sp = sorted.splice(start, 1)[0];\n sorted.sort((a, b) => {\n const da = Math.atan2(a.y - sp.y, a.x - sp.x);\n const db = Math.atan2(b.y - sp.y, b.x - sp.x);\n if (da !== db) return da - db;\n return Math.hypot(a.x - sp.x, a.y - sp.y) - Math.hypot(b.x - sp.x, b.y - sp.y);\n });\n const hull: Pt[] = [sp, sorted[0]];\n for (let i = 1; i < sorted.length; i++) {\n while (hull.length > 1 && !isLeftTurn(hull[hull.length - 2], hull[hull.length - 1], sorted[i])) hull.pop();\n hull.push(sorted[i]);\n }\n return hull;\n}\n\n// ── Chaikin smoothing (6 passes, returns flat [x,y,…] array) ─────────────────\n\nfunction chaikinSmooth(pts: Pt[], passes = 6): number[] {\n let cur = pts;\n for (let iter = 0; iter < passes; iter++) {\n const next: Pt[] = [];\n const n = cur.length;\n for (let i = 0; i < n; i++) {\n const a = cur[i], b = cur[(i + 1) % n];\n next.push({ x: 0.75 * a.x + 0.25 * b.x, y: 0.75 * a.y + 0.25 * b.y });\n next.push({ x: 0.25 * a.x + 0.75 * b.x, y: 0.25 * a.y + 0.75 * b.y });\n }\n cur = next;\n }\n return cur.flatMap(p => [p.x, p.y]);\n}\n\n// ── Hull edge Y at a given X (for label anchor) ───────────────────────────────\n\nfunction hullEdgeYAtX(points: number[], targetX: number, isBottom: boolean): number {\n const n = points.length;\n let result = isBottom ? -Infinity : Infinity;\n for (let i = 0; i < n; i += 2) {\n const x1 = points[i], y1 = points[i + 1];\n const x2 = points[(i + 2) % n], y2 = points[(i + 3) % n];\n if ((x1 < targetX && x2 >= targetX) || (x2 < targetX && x1 >= targetX)) {\n const t = (targetX - x1) / (x2 - x1);\n const y = y1 + t * (y2 - y1);\n if (isBottom) result = Math.max(result, y); else result = Math.min(result, y);\n }\n }\n if (!isFinite(result)) {\n for (let i = 1; i < n; i += 2) {\n if (isBottom) result = Math.max(result, points[i]); else result = Math.min(result, points[i]);\n }\n }\n return result;\n}\n\n// ── Hull calculation ──────────────────────────────────────────────────────────\n\nfunction calculateHull(\n containerNodes: FlatNode[],\n): { points: number[]; anchorX: number; anchorEdgeY: number } | null {\n if (containerNodes.length === 0) return null;\n\n const NUM_SAMPLES = 48;\n const samples: Pt[] = [];\n for (const node of containerNodes) {\n const baseRX = node.width / 2;\n const baseRY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRX * 0.74);\n const halfW = baseRX * MAX_BLOB_EXTENT_X + CONTAINER_PADDING;\n const halfH = baseRY * MAX_BLOB_EXTENT_Y + CONTAINER_PADDING;\n for (let j = 0; j < NUM_SAMPLES; j++) {\n const angle = (j / NUM_SAMPLES) * Math.PI * 2;\n samples.push({ x: node.x + halfW * Math.cos(angle), y: node.y + halfH * Math.sin(angle) });\n }\n }\n\n const hull = convexHull(samples);\n const points = chaikinSmooth(hull, 6);\n\n const xs = containerNodes.map(n => n.x);\n const ys = containerNodes.map(n => n.y);\n const spanX = Math.max(...xs) - Math.min(...xs);\n const spanY = Math.max(...ys) - Math.min(...ys);\n const useTopEdge = spanY > spanX * 2.0;\n\n let hullMinX = Infinity, hullMaxX = -Infinity;\n for (let i = 0; i < points.length; i += 2) {\n if (points[i] < hullMinX) hullMinX = points[i];\n if (points[i] > hullMaxX) hullMaxX = points[i];\n }\n const anchorX = (hullMinX + hullMaxX) / 2;\n const anchorEdgeY = hullEdgeYAtX(points, anchorX, !useTopEdge);\n\n return { points, anchorX, anchorEdgeY };\n}\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\nexport interface KonvaContainerProps {\n /** All nodes in this container group (already resolved from nodeMap). */\n nodes: FlatNode[];\n /** Label text shown on the pill badge. */\n label?: string;\n /** Unused – kept for API compat; stroke is always #747270. */\n color?: string;\n isDark?: boolean;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nconst KonvaContainer = memo(function KonvaContainer({\n nodes,\n label = '',\n}: KonvaContainerProps) {\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n\n const hullData = useMemo(() => calculateHull(nodes), [nodes]);\n\n if (!hullData) return null;\n\n // Inverse-scaled label metrics\n const refNode = nodes[0];\n const screenScale = refNode ? computeNodeTextScreenScale(refNode.width, zoomLevel) : 1;\n const labelFontSize = LABEL_FONT_SIZE * screenScale;\n const labelBoxHeight = Math.ceil(labelFontSize * LABEL_LINE_HEIGHT + 2 * LABEL_PAD_V);\n const boxWidth = label ? measureLabelBoxWidth(label, labelFontSize) : 0;\n const boxX = hullData.anchorX - boxWidth / 2;\n const boxY = hullData.anchorEdgeY - labelBoxHeight / 2;\n\n return (\n <Group listening={false}>\n {/* Dashed hull outline */}\n <Line\n points={hullData.points}\n stroke=\"#747270\"\n strokeWidth={1}\n dash={CONTAINER_DASH}\n closed={true}\n tension={0}\n listening={false}\n perfectDrawEnabled={false}\n />\n\n {/* Inverse-scaled pill label */}\n {label.length > 0 && (\n <Group\n x={boxX + boxWidth / 2}\n y={boxY + labelBoxHeight / 2}\n offsetX={boxWidth / 2}\n offsetY={labelBoxHeight / 2}\n scaleX={1 / zoomLevel}\n scaleY={1 / zoomLevel}\n visible={zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM}\n listening={false}\n >\n <Rect\n width={boxWidth}\n height={labelBoxHeight}\n fill={LABEL_BG}\n cornerRadius={LABEL_BORDER_RADIUS}\n shadowEnabled={false}\n perfectDrawEnabled={false}\n />\n <Text\n x={LABEL_PAD_H}\n y={LABEL_PAD_V}\n width={boxWidth - 2 * LABEL_PAD_H}\n height={labelBoxHeight - 2 * LABEL_PAD_V}\n text={label}\n fontSize={labelFontSize}\n fontFamily={LABEL_FONT_FAMILY}\n fontStyle={LABEL_FONT_WEIGHT}\n fill=\"rgba(0,0,0,1)\"\n align=\"center\"\n verticalAlign=\"middle\"\n lineHeight={LABEL_LINE_HEIGHT}\n perfectDrawEnabled={false}\n listening={false}\n />\n </Group>\n )}\n </Group>\n );\n});\n\nexport default KonvaContainer;\n","// ─── Text Scaling Helpers ─────────────────────────────────────────────────────\n//\n// Determines the scale applied to node title text, keeping text legible and\n// fitted inside the blob shape across the full zoom range.\n//\n// Matches the visualli.ai textScaling logic exactly.\n\nimport { NODE_HEIGHT } from '@visualli/core';\n\nexport const NODE_TEXT_BASE_FONT_PX = 30;\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 * - uses base width of 300px for consistent text sizing\n * - allows taller text box for multi-line wrapping\n *\n * Improved from visualli.ai to handle long labels better with multi-line support.\n */\nexport function computeNodeTextWorldScale(nodeWidth: number, zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n \n // Use a consistent base width (300px) for text scaling\n // This keeps font size more consistent across different node widths\n const baseWidth = 300;\n \n const baseRadiusX = baseWidth / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n const textNaturalWidth = baseWidth - 40;\n // Increase text height to allow 2-3 lines of wrapped text\n const textNaturalHeight = NODE_HEIGHT * 1.2;\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","// ─── NavigationStack ─────────────────────────────────────────────────────────\n//\n// Vertical navigation stack rendered as a fixed left-side overlay.\n// Matches the visualli.ai VisualliNavigationStack design:\n// • Organic hand-drawn circle SVGs per level\n// • Vertical connector lines between levels\n// • Active level highlighted, previous levels clickable to navigate back\n// • Font: Nunito\n\nimport React, { memo, useState } from 'react';\nimport type { VisualliLayer } from '@visualli/core';\n\nexport interface NavStackEntry {\n layerId: string;\n layer: VisualliLayer;\n label: string;\n}\n\nexport interface NavigationStackProps {\n stack: NavStackEntry[];\n onNavigateBack: (index: number) => void;\n isDark?: boolean;\n top?: string;\n left?: string;\n}\n\n// Pastel fills cycled across levels\nconst PASTEL_FILLS = [\n '#b6eea7', '#d5bcfe', '#a1c4fc', '#a6f5d8',\n '#ffc9de', '#c4e8ff', '#f0c4ff', '#ffe0a3',\n];\n\n// Organic circle SVG paths (small / active variants matching visualli.ai)\nconst ORGANIC_PATHS_SMALL = [\n 'M13.72,6.31 C15.12,6.29 17.96,8.57 17.99,10.60 C18.07,14.62 16.72,17.90 11.12,18.00 C7.26,18.07 4.07,14.86 4.00,10.85 C3.93,6.83 9.44,2.02 13.69,4.85',\n 'M13.88,6.41 C15.28,6.43 18.04,8.82 18.00,10.85 C17.93,14.86 16.48,18.10 10.88,18.00 C7.02,17.93 3.94,14.62 4.01,10.60 C4.08,6.59 9.76,1.97 13.91,4.95',\n];\nconst ORGANIC_PATH_ACTIVE =\n 'M16.55,9.22 C17.95,9.15 20.87,11.33 20.97,13.36 C21.19,17.37 19.96,20.70 14.37,20.99 C10.51,21.19 7.20,18.10 7.00,14.09 C6.78,10.08 12.13,5.08 16.48,7.77';\n\nconst CIRCLE_SIZE = 14;\n\nfunction hexToRgba(hex: string, opacity: number): string {\n const h = hex.replace('#', '');\n const r = parseInt(h.substring(0, 2), 16);\n const g = parseInt(h.substring(2, 4), 16);\n const b = parseInt(h.substring(4, 6), 16);\n return `rgba(${r},${g},${b},${opacity})`;\n}\n\nconst OrganicCircle = memo(function OrganicCircle({\n size, fill, stroke, strokeWidth, variant, isActive,\n}: {\n size: number; fill: string; stroke: string; strokeWidth: number; variant: number; isActive?: boolean;\n}) {\n const path = isActive ? ORGANIC_PATH_ACTIVE : ORGANIC_PATHS_SMALL[variant % ORGANIC_PATHS_SMALL.length];\n const vb = isActive ? '4 3 20 20' : '2 1 18 18';\n const vbSz = isActive ? 20 : 18;\n const sw = strokeWidth * vbSz / size;\n return (\n <svg width={size} height={size} viewBox={vb} fill=\"none\" style={{ display: 'block' }}>\n <path d={path} fill={fill} fillOpacity={1} />\n <path d={path} fill=\"none\" stroke={stroke} strokeWidth={sw} strokeLinecap=\"round\" />\n </svg>\n );\n});\n\nconst NavigationStack = memo(function NavigationStack({\n stack,\n onNavigateBack,\n isDark = false,\n top = '16px',\n left = '16px',\n}: NavigationStackProps) {\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n\n // Always render at least the root entry so the user knows where they are.\n if (stack.length === 0) return null;\n\n const visitedStroke = isDark ? '#908e8c' : '#747270';\n const visitedText = isDark ? '#908e8c' : '#747270';\n const activeStroke = isDark ? '#e8e6e4' : '#1a1a18';\n const activeText = isDark ? '#e8e6e4' : '#1a1a18';\n const connectorColor = isDark ? '#908e8c' : '#747270';\n const connectorMarginLeft = 10.5; // padding(4) + circleHalf(7) - connectorHalf(0.5)\n const currentIndex = stack.length - 1;\n\n return (\n <div\n data-help=\"navigation-stack\"\n style={{\n position: 'absolute',\n top,\n left,\n zIndex: 30,\n pointerEvents: 'auto',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', padding: '8px' }}>\n {stack.flatMap((entry, index) => {\n const isCurrent = index === currentIndex;\n const isClickable = index < currentIndex;\n const isHovered = hoveredIndex === index;\n const pastelFill = PASTEL_FILLS[index % PASTEL_FILLS.length];\n const rowBg = isCurrent\n ? hexToRgba(pastelFill, 0.6)\n : isHovered && isClickable\n ? hexToRgba(pastelFill, 0.3)\n : 'transparent';\n\n const items: React.ReactNode[] = [];\n\n if (index > 0) {\n items.push(\n <div\n key={`conn-${index}`}\n style={{\n width: '1px',\n height: '20px',\n marginLeft: `${connectorMarginLeft}px`,\n marginTop: '-6px',\n marginBottom: '-6px',\n background: connectorColor,\n alignSelf: 'flex-start',\n flexShrink: 0,\n position: 'relative',\n zIndex: 1,\n }}\n />,\n );\n }\n\n items.push(\n <div\n key={`${entry.layerId}-${index}`}\n style={{\n position: 'relative',\n zIndex: 2,\n alignSelf: 'flex-start',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n height: '22px',\n padding: '4px',\n borderRadius: '8px',\n cursor: isClickable ? 'pointer' : 'default',\n background: rowBg,\n transition: 'background 0.15s',\n }}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onClick={e => { e.stopPropagation(); if (isClickable) onNavigateBack(index); }}\n >\n <div style={{ width: CIRCLE_SIZE, height: CIRCLE_SIZE, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, zIndex: 4 }}>\n {isCurrent ? (\n <OrganicCircle size={CIRCLE_SIZE} fill={pastelFill} stroke={activeStroke} strokeWidth={1.5} variant={index} isActive />\n ) : (\n <OrganicCircle size={CIRCLE_SIZE} fill={pastelFill} stroke={visitedStroke} strokeWidth={1} variant={index} />\n )}\n </div>\n <span\n style={{\n fontFamily: \"'Nunito', sans-serif\",\n fontSize: isCurrent || (isHovered && isClickable) ? '11px' : '9px',\n fontWeight: isCurrent ? 600 : 400,\n color: isCurrent ? activeText : visitedText,\n lineHeight: 1,\n whiteSpace: 'nowrap',\n transition: 'color 0.15s, font-size 0.15s',\n }}\n >\n {entry.label}\n </span>\n </div>,\n );\n\n return items;\n })}\n </div>\n </div>\n );\n});\n\nexport default NavigationStack;\n","// ─── ZoomControls ─────────────────────────────────────────────────────────────\n//\n// Floating zoom control matching the visualli.ai design:\n// • Side-by-side ZoomIn / ZoomOut buttons (65×32px)\n// • SVG icons (no external dependency)\n// • Inline styles (no Tailwind required in SDK)\n\nimport React, { useCallback, memo } from 'react';\nimport { ZOOM_MIN, ZOOM_MAX } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nexport interface ZoomControlsProps {\n isDark?: boolean;\n}\n\n// ── ZoomIn SVG (Lucide-compatible path) ───────────────────────────────────────\nconst ZoomInIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n <line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\" />\n <line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\" />\n </svg>\n);\n\n// ── ZoomOut SVG ───────────────────────────────────────────────────────────────\nconst ZoomOutIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n <line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\" />\n </svg>\n);\n\nconst ZOOM_STEP = 0.2;\n\nconst ZoomControls = memo(function ZoomControls({ isDark = false }: ZoomControlsProps) {\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n const setZoom = useViewportStore(s => s.setZoom);\n\n const handleZoomIn = useCallback(() => setZoom(Math.min(ZOOM_MAX, zoomLevel * 1.2)), [zoomLevel, setZoom]);\n const handleZoomOut = useCallback(() => setZoom(Math.max(ZOOM_MIN, zoomLevel / 1.2)), [zoomLevel, setZoom]);\n\n const surfaceBg = isDark ? 'var(--bg-surface, #1C1C1A)' : 'var(--bg-surface, #FAF8F4)';\n const border = isDark ? 'var(--border-color, #333330)' : 'var(--border-color, #DDD9D0)';\n const primary = isDark ? 'var(--text-primary, #F0EDE6)' : 'var(--text-primary, #1A1A18)';\n const muted = isDark ? 'var(--text-muted, #8E8C88)' : 'var(--text-muted, #747270)';\n\n return (\n <div\n style={{\n position: 'relative',\n background: surfaceBg,\n border: `0.5px solid ${border}`,\n borderRadius: '8px',\n overflow: 'hidden',\n width: '65px',\n height: '32px',\n flexShrink: 0,\n }}\n role=\"group\"\n aria-label=\"Zoom controls\"\n >\n {/* Zoom In — left half */}\n <button\n onClick={handleZoomIn}\n disabled={zoomLevel >= ZOOM_MAX}\n style={{\n position: 'absolute',\n top: 0, left: 0,\n width: '32px', height: '100%',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n border: 'none', background: 'transparent', cursor: zoomLevel >= ZOOM_MAX ? 'not-allowed' : 'pointer',\n color: zoomLevel >= ZOOM_MAX ? muted : primary,\n transition: 'background 0.15s',\n }}\n onMouseEnter={e => { if (zoomLevel < ZOOM_MAX) (e.currentTarget as HTMLButtonElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLButtonElement).style.background = 'transparent'; }}\n aria-label=\"Zoom in\"\n >\n <ZoomInIcon />\n </button>\n\n {/* Divider */}\n <div style={{ position: 'absolute', top: 0, bottom: 0, left: '32px', width: '0.5px', background: border }} />\n\n {/* Zoom Out — right half */}\n <button\n onClick={handleZoomOut}\n disabled={zoomLevel <= ZOOM_MIN}\n style={{\n position: 'absolute',\n top: 0, right: 0,\n width: '33px', height: '100%',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n border: 'none', background: 'transparent', cursor: zoomLevel <= ZOOM_MIN ? 'not-allowed' : 'pointer',\n color: zoomLevel <= ZOOM_MIN ? muted : primary,\n transition: 'background 0.15s',\n }}\n onMouseEnter={e => { if (zoomLevel > ZOOM_MIN) (e.currentTarget as HTMLButtonElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLButtonElement).style.background = 'transparent'; }}\n aria-label=\"Zoom out\"\n >\n <ZoomOutIcon />\n </button>\n </div>\n );\n});\n\nexport default ZoomControls;\n","// ─── SketchyBoxKonva ─────────────────────────────────────────────────────────\n//\n// Renders the hand-drawn tooltip box using an imperative Konva canvas.\n// Two paths are scaled to fit the container:\n// - BACK_PATH : shadow stroke, offset 8px down\n// - FRONT_PATH: filled main box, offset 5.65px right\n//\n// Matches the visualli.ai SketchyBoxKonva component exactly.\n\nimport React, { useEffect, useRef } from 'react';\nimport Konva from 'konva';\n\nconst BACK_PATH =\n 'M0.653,0 L485.653,1 C485.653,1,484.782,152.773,' +\n '486.653,165 C413.653,171,14.653,178,5.653,168' +\n 'C2.653,158,0.653,0,0.653,0';\n\nconst FRONT_PATH =\n 'M485,167.524 L0,166.524' +\n 'C0,166.524,1.870,8.751,0,0' +\n 'C73,0,479,0,487,8' +\n 'C490,18,485,167.524,485,167.524';\n\nconst BACK_W = 486;\nconst BACK_H = 178;\nconst FRONT_W = 490;\nconst FRONT_H = 168;\n\nconst BACK_OFFSET_Y = 8;\nconst FRONT_OFFSET_X = 5.65;\nconst SHADOW_PAD = 12;\n\nexport interface SketchyBoxKonvaProps {\n children: React.ReactNode;\n fill: string;\n stroke: string;\n backStroke: string;\n padding?: string;\n}\n\nconst SketchyBoxKonva: React.FC<SketchyBoxKonvaProps> = ({\n children,\n fill,\n stroke,\n backStroke,\n padding = '1rem 1.25rem',\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const konvaContainerRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<Konva.Stage | null>(null);\n\n useEffect(() => {\n const wrapper = wrapperRef.current;\n const konvaEl = konvaContainerRef.current;\n if (!wrapper || !konvaEl) return;\n\n function draw(W: number, H: number) {\n if (!konvaEl || W <= 0 || H <= 0) return;\n if (stageRef.current) { stageRef.current.destroy(); stageRef.current = null; }\n\n const stage = new Konva.Stage({ container: konvaEl, width: W, height: H });\n const layer = new Konva.Layer({ listening: false });\n const contentH = H - SHADOW_PAD;\n\n layer.add(new Konva.Path({\n x: 0, y: BACK_OFFSET_Y,\n data: BACK_PATH,\n scaleX: W / BACK_W,\n scaleY: contentH / BACK_H,\n fill: '#ffffff',\n stroke: backStroke,\n strokeWidth: 2,\n strokeScaleEnabled: false,\n listening: false,\n }));\n\n layer.add(new Konva.Path({\n x: FRONT_OFFSET_X, y: 0,\n data: FRONT_PATH,\n scaleX: (W - FRONT_OFFSET_X) / FRONT_W,\n scaleY: contentH / FRONT_H,\n fill,\n stroke,\n strokeWidth: 3,\n strokeScaleEnabled: false,\n listening: false,\n }));\n\n stage.add(layer);\n stageRef.current = stage;\n }\n\n draw(wrapper.offsetWidth, wrapper.offsetHeight);\n\n const ro = new ResizeObserver(entries => {\n const el = entries[0].target as HTMLElement;\n draw(el.offsetWidth, el.offsetHeight);\n });\n ro.observe(wrapper);\n\n return () => {\n ro.disconnect();\n stageRef.current?.destroy();\n stageRef.current = null;\n };\n }, [fill, stroke, backStroke]);\n\n return (\n <div ref={wrapperRef} style={{ position: 'relative', paddingBottom: `${SHADOW_PAD}px` }}>\n <div\n ref={konvaContainerRef}\n style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 0, overflow: 'hidden' }}\n />\n <div style={{ position: 'relative', padding, zIndex: 1 }}>\n {children}\n </div>\n </div>\n );\n};\n\nexport default SketchyBoxKonva;\n","// ─── Visualli Context ─────────────────────────────────────────────────────────\n//\n// React Context for Visualli components (minimal implementation)\n\nimport React, { createContext, useContext } from 'react';\n\nexport interface VisualliContextValue {\n // Reserved for future use\n}\n\nconst VisualliContext = createContext<VisualliContextValue | null>(null);\n\nexport interface VisualliProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Provider for Visualli context\n * \n * @example\n * ```tsx\n * <VisualliProvider>\n * <VisualliCanvas document={doc} />\n * </VisualliProvider>\n * ```\n */\nexport function VisualliProvider({\n children,\n}: VisualliProviderProps) {\n const value: VisualliContextValue = {};\n\n return (\n <VisualliContext.Provider value={value}>\n {children}\n </VisualliContext.Provider>\n );\n}\n\n/**\n * Hook to access Visualli context\n * \n * Returns default empty values if used outside of VisualliProvider\n */\nexport function useVisualli(): VisualliContextValue {\n const ctx = useContext(VisualliContext);\n if (!ctx) {\n return {};\n }\n return ctx;\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useMemo","parseVisualliFile","useRef","useState","useCallback","useEffect","useMemo","darkenHexColor","RBushSpatialIndex","NODE_HEIGHT","TEXT_LABEL_HIDE_BELOW_ZOOM","ZOOM_MIN","set","create","create","stage","useCallback","useRef","useEffect","useRef","useEffect","useCallback","useRef","useEffect","KonvaStage","useRef","useEffect","useRef","useEffect","useMemo","useRef","useRef","React","useMemo","ALL_BLOB_SHAPES","jsx","React","KonvaNode","useMemo","jsx","useRef","useMemo","useEffect","useRef","useLayoutEffect","useMemo","useMemo","NODE_HEIGHT","jsx","jsxs","KonvaEdge","useMemo","jsx","useRef","useMemo","useLayoutEffect","useRef","useLayoutEffect","memo","useMemo","NODE_HEIGHT","TEXT_LABEL_HIDE_BELOW_ZOOM","NODE_HEIGHT","DESCRIPTION_TEXT_BASE_FONT_PX","CONTAINER_LABEL_BASE_FONT_PX","computeNodeTextWorldScale","NODE_HEIGHT","computeNodeTextScreenScale","jsx","jsxs","CONTAINER_LABEL_BASE_FONT_PX","NODE_HEIGHT","memo","KonvaContainer","useMemo","computeNodeTextScreenScale","TEXT_LABEL_HIDE_BELOW_ZOOM","jsx","useRef","useLayoutEffect","memo","useState","jsx","jsxs","OrganicCircle","NavigationStack","useCallback","memo","jsx","jsxs","memo","ZoomControls","useCallback","jsxs","jsx","useEffect","useRef","jsx","jsxs","jsx","jsxs","hexToRgba","useState","useEffect","useMemo","useRef","RBushSpatialIndex","NODE_HEIGHT","useCallback","ZOOM_MIN","TEXT_LABEL_HIDE_BELOW_ZOOM","darkenHexColor","DESCRIPTION_TEXT_BASE_FONT_PX","jsx","jsxs","useState","useEffect","useRef","parseVisualliFile","useMemo","jsx"]}