dishui 0.0.61 → 0.0.64
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Flow.js","names":[],"sources":["../../../../src/components/pro/Flow/Flow.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';\nimport { FlowProvider, useFlowContext } from './context/FlowContext';\nimport { FlowUIProvider, useFlowUI } from './context/FlowUIContext';\nimport { FlowAIProvider } from './context/FlowAIContext';\nimport FlowCanvas from './FlowCanvas';\nimport FlowToolbar, { FlowZoomControls } from './panels/FlowToolbar';\nimport { ShapePaletteContent, SvgStampContent, MediaStampContent } from './panels/ShapePalette';\nimport { InspectorPanelContent } from './panels/InspectorPanel';\nimport { OutlinePanelContent } from './panels/OutlinePanel';\nimport { AIPanelContent } from './panels/AIPanel';\nimport { PresentationMode } from './panels/PresentationMode';\nimport { MediaOverlay } from './nodes/MediaOverlay';\nimport FlowPanelGroup, { type PanelTab } from './panels/FlowPanelGroup';\nimport type { FlowPanelDock } from './context/FlowUIContext';\nimport Breadcrumb from './panels/Breadcrumb';\nimport ContextMenu from './panels/ContextMenu';\nimport type { ContextMenuItem } from './panels/ContextMenu';\nimport Select from '../../Select';\nimport { MiniMapRenderer } from './canvas/MiniMapRenderer';\nimport { CodeEditor, type CodeEditorHandle } from '../CodeEditor';\nimport { EditorView } from '@codemirror/view';\nimport { useUndoRedo } from './hooks/useUndoRedo';\nimport { useClipboard } from './hooks/useClipboard';\nimport { useCompactMode } from './hooks/useCompactMode';\nimport { downloadDataURL, safeFileBaseName } from './hooks/useFlowImportExport';\nimport { usePdfExport } from './hooks/usePdfExport';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useMindMap } from './hooks/useMindMap';\nimport { useDeleteSelection } from './hooks/useDeleteSelection';\nimport { createEmptyDocument, ROOT_CANVAS_ID, DEFAULT_NODE_DATA } from './constants';\nimport { normalizeEdgeHandles } from './edges/edgePaths';\nimport { generateId } from './nodes/nodeUtils';\nimport type { FlowProps, FlowDocument, FlowNode, SelectionState, FlowCanvasData } from './types';\nimport type { PixiApp } from './canvas/PixiApp';\nimport './styles.css';\n\nfunction normalizeDocument(doc: FlowDocument): FlowDocument {\n let changed = false;\n const canvases = { ...doc.canvases };\n for (const [id, canvas] of Object.entries(canvases)) {\n const nodes = canvas.nodes.map(node => {\n if (node.type !== 'shapeSvg') return node;\n const legacyPlacement = node.data.labelPlacement as string | undefined;\n const labelPlacement = legacyPlacement === 'above'\n ? 'top'\n : legacyPlacement === 'center'\n ? 'middle'\n : legacyPlacement === 'below'\n ? 'bottom'\n : node.data.labelPlacement;\n if (labelPlacement === node.data.labelPlacement) return node;\n changed = true;\n return { ...node, data: { ...node.data, labelPlacement } };\n });\n // Mindmap nodes/edges created before theme tokens (≤ 0.0.56) persisted\n // literal colors, so they never followed theme switches. That exact palette\n // was only ever emitted by the old mindmap creator, so remap it to the same\n // tokens the current creator uses.\n let themedNodesChanged = false;\n const themedNodes = nodes.map(node => {\n if (!node.data.isMindMapNode) return node;\n const fill = node.data.fill === '#ffffff' || node.data.fill === '#eef2ff'\n ? 'theme:base-100'\n : node.data.fill;\n const stroke = node.data.stroke === '#6366f1'\n ? 'theme:base-content'\n : node.data.stroke === '#4f46e5'\n ? 'theme:primary'\n : node.data.stroke;\n if (fill === node.data.fill && stroke === node.data.stroke) return node;\n themedNodesChanged = true;\n return { ...node, data: { ...node.data, fill, stroke } };\n });\n const nodeMap = new Map<string, FlowNode>();\n for (const node of themedNodes) nodeMap.set(node.id, node);\n let edgesChanged = false;\n const edges = normalizeEdgeHandles(canvas.edges, nodeMap).map(edge => {\n if (edge.data.strokeColor !== '#94a3b8') return edge;\n const source = nodeMap.get(edge.source);\n const target = nodeMap.get(edge.target);\n if (!source?.data.isMindMapNode || !target?.data.isMindMapNode) return edge;\n edgesChanged = true;\n return { ...edge, data: { ...edge.data, strokeColor: 'theme:base-content' } };\n });\n if (themedNodesChanged || edgesChanged) changed = true;\n if (themedNodes !== nodes || edges !== canvas.edges) {\n canvases[id] = { ...canvas, nodes: themedNodes, edges };\n }\n }\n return changed ? { ...doc, canvases } : doc;\n}\n\nconst EMPTY_SELECTION: SelectionState = {\n nodeIds: new Set(),\n edgeIds: new Set(),\n lineIds: new Set(),\n};\n\nfunction FlowKeyboardShortcutsWire({ onUndo, onRedo, groupRef, geoGroupRef, ungroupRef }: {\n onUndo: () => void;\n onRedo: () => void;\n groupRef: React.MutableRefObject<(() => void) | null>;\n geoGroupRef: React.MutableRefObject<(() => void) | null>;\n ungroupRef: React.MutableRefObject<(() => void) | null>;\n}) {\n const { selection, setSelection, currentCanvas, setDoc, currentCanvasId } = useFlowContext();\n const { viewport } = useFlowUI();\n const { copy, cut, paste, duplicate } = useClipboard();\n const deleteSelected = useDeleteSelection();\n\n const selectAll = useCallback(() => {\n setSelection({\n nodeIds: new Set(currentCanvas.nodes.map(n => n.id)),\n edgeIds: new Set(currentCanvas.edges.map(e => e.id)),\n lineIds: new Set(currentCanvas.lines.map(l => l.id)),\n });\n }, [currentCanvas, setSelection]);\n\n const createGroup = useCallback((type: 'flowGroup' | 'geometryGroup') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n const totalCount = nodeIds.size + lineIds.size;\n if (totalCount < 2) return;\n const nodes = currentCanvas.nodes.filter(n => nodeIds.has(n.id));\n const lines = currentCanvas.lines.filter(l => lineIds.has(l.id));\n const PAD = 20;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n minX = Math.min(minX, n.position.x);\n minY = Math.min(minY, n.position.y);\n maxX = Math.max(maxX, n.position.x + n.width);\n maxY = Math.max(maxY, n.position.y + n.height);\n }\n for (const l of lines) {\n for (const p of l.points) {\n minX = Math.min(minX, p.x); minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x); maxY = Math.max(maxY, p.y);\n }\n }\n const isGeo = type === 'geometryGroup';\n const groupId = generateId('group');\n const groupNode: FlowNode = {\n id: groupId,\n type,\n position: { x: minX - PAD, y: minY - PAD },\n width: maxX - minX + PAD * 2,\n height: maxY - minY + PAD * 2,\n data: {\n ...DEFAULT_NODE_DATA,\n label: isGeo ? 'Geo Group' : 'Group',\n fill: isGeo ? '#fefce8' : '#f0f9ff',\n stroke: '#9ca3af', strokeWidth: 1.5,\n borderStyle: isGeo ? 'dashed' : 'dotted',\n isGroup: true,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: isGeo\n ? [groupNode, ...canvas.nodes]\n : [groupNode, ...canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, parentId: groupId } : n)],\n lines: isGeo\n ? canvas.lines\n : canvas.lines.map(l => lineIds.has(l.id) ? { ...l, parentId: groupId } : l),\n }},\n };\n });\n setSelection({ nodeIds: new Set([groupId]), edgeIds: new Set(), lineIds: new Set() });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n const groupSelected = useCallback(() => createGroup('flowGroup'), [createGroup]);\n const geoGroupSelected = useCallback(() => createGroup('geometryGroup'), [createGroup]);\n\n const ungroupSelected = useCallback(() => {\n const ids = selection.nodeIds;\n if (ids.size === 0) return;\n const groupNodeIds = new Set<string>();\n const childNodeIds = new Set<string>();\n const childLineIds = new Set<string>();\n for (const node of currentCanvas.nodes) {\n if (ids.has(node.id) && (node.type === 'flowGroup' || node.type === 'geometryGroup' || node.data.isGroup)) {\n groupNodeIds.add(node.id);\n }\n }\n if (groupNodeIds.size === 0) return;\n for (const node of currentCanvas.nodes) {\n if (node.parentId && groupNodeIds.has(node.parentId)) {\n childNodeIds.add(node.id);\n }\n }\n for (const line of currentCanvas.lines) {\n if (line.parentId && groupNodeIds.has(line.parentId)) {\n childLineIds.add(line.id);\n }\n }\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes\n .filter(n => !groupNodeIds.has(n.id))\n .map(n => childNodeIds.has(n.id) ? { ...n, parentId: undefined } : n),\n lines: canvas.lines\n .map(l => childLineIds.has(l.id) ? { ...l, parentId: undefined } : l),\n }},\n };\n });\n setSelection({ nodeIds: childNodeIds, edgeIds: new Set(), lineIds: childLineIds });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n groupRef.current = groupSelected;\n geoGroupRef.current = geoGroupSelected;\n ungroupRef.current = ungroupSelected;\n\n const changeZIndex = useCallback((mode: 'front' | 'back' | 'up' | 'down') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n if (nodeIds.size === 0 && lineIds.size === 0) return;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n const nodeAllZ = canvas.nodes.map(n => n.zIndex ?? 0);\n const nodeMaxZ = nodeAllZ.length > 0 ? Math.max(...nodeAllZ) : 0;\n const nodeMinZ = nodeAllZ.length > 0 ? Math.min(...nodeAllZ) : 0;\n const lineAllZ = canvas.lines.map(l => l.zIndex ?? 0);\n const lineMaxZ = lineAllZ.length > 0 ? Math.max(...lineAllZ) : 0;\n const lineMinZ = lineAllZ.length > 0 ? Math.min(...lineAllZ) : 0;\n const applyZ = (z: number, maxZ: number, minZ: number) => {\n if (mode === 'front') return maxZ + 1;\n if (mode === 'back') return minZ - 1;\n if (mode === 'up') return z + 1;\n return z - 1;\n };\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, zIndex: applyZ(n.zIndex ?? 0, nodeMaxZ, nodeMinZ) } : n),\n lines: canvas.lines.map(l => lineIds.has(l.id) ? { ...l, zIndex: applyZ(l.zIndex ?? 0, lineMaxZ, lineMinZ) } : l),\n }},\n };\n });\n }, [selection, setDoc, currentCanvasId]);\n\n useEffect(() => {\n const handlePaste = (event: ClipboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target?.tagName === 'INPUT' || target?.tagName === 'TEXTAREA' || target?.isContentEditable) return;\n\n const imageItem = Array.from(event.clipboardData?.items ?? []).find(item => item.type.startsWith('image/'));\n if (!imageItem) {\n event.preventDefault();\n paste();\n return;\n }\n\n const file = imageItem.getAsFile();\n if (!file) return;\n event.preventDefault();\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result !== 'string') return;\n const selectedImage = selection.nodeIds.size === 1\n ? currentCanvas.nodes.find(node => selection.nodeIds.has(node.id) && node.type === 'mediaNode' && node.data.mediaKind === 'image')\n : undefined;\n\n if (selectedImage) {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(node => node.id === selectedImage.id\n ? { ...node, data: { ...node.data, mediaContent: reader.result as string } }\n : node),\n },\n },\n };\n });\n return;\n }\n\n const id = generateId('node');\n const width = 320;\n const height = 220;\n const screenWidth = window.innerWidth;\n const screenHeight = window.innerHeight;\n const centerX = (screenWidth / 2 - viewport.x) / viewport.zoom;\n const centerY = (screenHeight / 2 - viewport.y) / viewport.zoom;\n const highestZ = Math.max(0, ...currentCanvas.nodes.map(node => node.zIndex ?? 0));\n const imageNode: FlowNode = {\n id,\n type: 'mediaNode',\n position: { x: centerX - width / 2, y: centerY - height / 2 },\n width,\n height,\n zIndex: highestZ + 1,\n data: {\n ...DEFAULT_NODE_DATA,\n label: file.name || 'Image',\n fill: 'theme:base-100',\n stroke: 'theme:base-content',\n strokeWidth: 1.5,\n color: 'theme:base-content',\n fontSize: 13,\n borderStyle: 'solid',\n mediaKind: 'image',\n mediaContent: reader.result,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: { ...canvas, nodes: [...canvas.nodes, imageNode] },\n },\n };\n });\n setSelection({ nodeIds: new Set([id]), edgeIds: new Set(), lineIds: new Set() });\n };\n reader.readAsDataURL(file);\n };\n\n window.addEventListener('paste', handlePaste);\n return () => window.removeEventListener('paste', handlePaste);\n }, [currentCanvas, currentCanvasId, paste, selection, setDoc, setSelection, viewport]);\n\n const actions = useMemo(() => ({\n undo: onUndo, redo: onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll,\n group: groupSelected, geoGroup: geoGroupSelected, ungroup: ungroupSelected,\n bringToFront: () => changeZIndex('front'),\n bringForward: () => changeZIndex('up'),\n sendBackward: () => changeZIndex('down'),\n sendToBack: () => changeZIndex('back'),\n }), [onUndo, onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll, groupSelected, geoGroupSelected, ungroupSelected, changeZIndex]);\n\n useKeyboardShortcuts(actions);\n useMindMap();\n return null;\n}\n\n/**\n * Bridges the anchor→PDF export (which needs canvas/viewport context) out to the\n * toolbar in the outer Flow component via a ref. Renders nothing.\n */\nfunction PdfExportWire({\n pixiRef,\n exportPdfRef,\n}: {\n pixiRef: React.RefObject<PixiApp | null>;\n exportPdfRef: React.MutableRefObject<(() => Promise<boolean>) | null>;\n}) {\n const exportPdf = usePdfExport(pixiRef);\n exportPdfRef.current = exportPdf;\n return null;\n}\n\n/** Imperative handle exposed via a ref on the `<Flow>` component. */\nexport interface FlowHandle {\n /** Export the current diagram to a PNG data URL (null if unavailable). */\n exportPNG: (backgroundColor?: number) => Promise<string | null>;\n /** Get the current document. */\n getDocument: () => FlowDocument;\n}\n\nconst Flow = forwardRef<FlowHandle, FlowProps>(function Flow({\n initialDocument,\n onChange,\n width,\n height,\n readOnly = false,\n onBack,\n onExportPNG,\n onPublish,\n showMiniMap = true,\n showGrid = true,\n gridSize = 20,\n className,\n showAI = true,\n showAIConfig = true,\n aiConfig,\n}: FlowProps, ref) {\n const [doc, setDoc] = useState<FlowDocument>(() => normalizeDocument(initialDocument ?? createEmptyDocument()));\n const [selection, setSelection] = useState<SelectionState>(EMPTY_SELECTION);\n const pixiRef = useRef<PixiApp | null>(null);\n const miniMapCanvasRef = useRef<HTMLCanvasElement>(null);\n const miniMapRef = useRef<MiniMapRenderer | null>(null);\n // Small-screen detection (container width based, see useCompactMode).\n const rootRef = useRef<HTMLDivElement>(null);\n const compact = useCompactMode(rootRef);\n\n const { wrappedSetDoc, undo, redo, canUndo, canRedo } = useUndoRedo(doc, setDoc);\n const groupRef = useRef<(() => void) | null>(null);\n const geoGroupRef = useRef<(() => void) | null>(null);\n const ungroupRef = useRef<(() => void) | null>(null);\n const exportPdfRef = useRef<(() => Promise<boolean>) | null>(null);\n\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n // Keep the latest doc in a ref for the imperative handle.\n const docRef = useRef(doc);\n docRef.current = doc;\n\n useImperativeHandle(ref, () => ({\n exportPNG: async (backgroundColor?: number) => {\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return null;\n return pixi.exportPNG(backgroundColor);\n },\n getDocument: () => docRef.current,\n }), []);\n\n const outerSetDoc: React.Dispatch<React.SetStateAction<FlowDocument>> = useCallback(\n (action) => {\n wrappedSetDoc(prev => {\n const next = typeof action === 'function' ? action(prev) : action;\n if (readOnly) {\n // Read-only: discard any content mutation. Only pure canvas\n // navigation (stack push/pop — entering/leaving groups via\n // double-click or breadcrumb) is allowed through. onChange is not\n // fired, so hosts won't treat navigation as an unsaved change.\n const navigationOnly = next.canvases === prev.canvases && next.title === prev.title;\n return navigationOnly ? next : prev;\n }\n queueMicrotask(() => onChangeRef.current?.(next));\n return next;\n });\n },\n [wrappedSetDoc, readOnly],\n );\n\n // Undo/redo mutate the document directly through useUndoRedo's raw setDoc\n // (bypassing outerSetDoc), so they need their own read-only guard.\n const guardedUndo = useCallback(() => { if (!readOnly) undo(); }, [readOnly, undo]);\n const guardedRedo = useCallback(() => { if (!readOnly) redo(); }, [readOnly, redo]);\n\n const handlePixiReady = useCallback((pixi: PixiApp) => {\n pixiRef.current = pixi;\n if (miniMapCanvasRef.current && !miniMapRef.current) {\n miniMapRef.current = new MiniMapRenderer(miniMapCanvasRef.current);\n }\n }, []);\n\n // Built-in PNG export: if the host supplies `onExportPNG` we defer to it,\n // otherwise snapshot the Pixi scene and download it directly so the toolbar\n // button always works out of the box.\n const handleExportPNG = useCallback(async () => {\n if (onExportPNG) return void onExportPNG();\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return;\n const url = await pixi.exportPNG(0xffffff);\n if (url) downloadDataURL(url, `${safeFileBaseName(docRef.current.title)}.png`);\n }, [onExportPNG]);\n\n // Built-in PDF export: capture each anchor's presentation framing into a\n // multi-page PDF (implemented by PdfExportWire inside the providers).\n const handleExportPDF = useCallback(async () => {\n await exportPdfRef.current?.();\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n let subscribed: PixiApp | null = null;\n\n const tickerFn = () => {\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!pixi || pixi.destroyed || !mm) return;\n const vp = { x: pixi.world.position.x, y: pixi.world.position.y, zoom: pixi.world.scale.x };\n const currentId = doc.stack[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const canvas = doc.canvases[currentId];\n if (canvas) mm.update(canvas.nodes, vp, pixi.app.screen.width, pixi.app.screen.height);\n };\n\n // Pixi initializes asynchronously; the minimap renderer is created in\n // handlePixiReady. Poll until both exist, then attach the ticker. This\n // avoids a race where the effect runs before pixi is ready and the minimap\n // stays blank until the next document edit.\n const attach = () => {\n if (cancelled) return;\n const pixi = pixiRef.current;\n if (pixi && !pixi.destroyed && miniMapRef.current) {\n pixi.app.ticker.add(tickerFn);\n subscribed = pixi;\n } else {\n requestAnimationFrame(attach);\n }\n };\n attach();\n\n return () => {\n cancelled = true;\n if (subscribed && !subscribed.destroyed) subscribed.app.ticker.remove(tickerFn);\n };\n }, [doc]);\n\n const style: React.CSSProperties = { width: width ?? '100%', height: height ?? '100%' };\n\n return (\n <div ref={rootRef} className={`flow-container ${className ?? ''}`} style={style}>\n <FlowProvider doc={doc} setDoc={outerSetDoc} selection={selection} setSelection={setSelection}>\n <FlowUIProvider showMiniMap={showMiniMap} showGrid={showGrid} gridSize={gridSize} showAI={showAI} readOnly={readOnly}>\n <FlowAIProvider initialConfig={aiConfig} showAIConfig={showAIConfig}>\n <FlowKeyboardShortcutsWire onUndo={guardedUndo} onRedo={guardedRedo} groupRef={groupRef} geoGroupRef={geoGroupRef} ungroupRef={ungroupRef} />\n <PdfExportWire pixiRef={pixiRef} exportPdfRef={exportPdfRef} />\n <UnifiedPanelGroup\n compact={compact}\n toolbar={!readOnly ? (\n <FlowToolbar\n compact={compact}\n onBack={onBack}\n onUndo={guardedUndo} onRedo={guardedRedo} canUndo={canUndo} canRedo={canRedo}\n onGroup={() => groupRef.current?.()} onGeoGroup={() => geoGroupRef.current?.()} onUngroup={() => ungroupRef.current?.()}\n onExportPNG={handleExportPNG}\n onExportPDF={handleExportPDF}\n onPublish={onPublish}\n />\n ) : null}\n >\n <FlowCanvas onPixiReady={handlePixiReady} />\n {/* Media content (markdown/mermaid/data/…) must stay visible in\n presentation & read-only preview — PixiJS only draws the node\n frame, so hiding this layer would blank every media node. */}\n <MediaOverlay />\n <PresentationGate>\n {!readOnly && <FlowZoomControls />}\n <Breadcrumb />\n </PresentationGate>\n {!readOnly && <FlowContextMenuWire />}\n <MiniMapWrapper canvasRef={miniMapCanvasRef} pixiRef={pixiRef} miniMapRef={miniMapRef} />\n <PresentationMode />\n </UnifiedPanelGroup>\n </FlowAIProvider>\n </FlowUIProvider>\n </FlowProvider>\n </div>\n );\n});\n\nexport default Flow;\n\ninterface TabDef {\n id: string;\n label: string;\n icon: string;\n showKey?: 'showPalette' | 'showInspector' | 'showOutline' | 'showJson' | 'showAI';\n}\n\n/**\n * Hides all editable overlay UI (toolbar, panels, breadcrumb) while in\n * presentation mode, keeping only the canvas visible for the slideshow.\n */\nfunction PresentationGate({ children }: { children: React.ReactNode }) {\n const { presentation } = useFlowUI();\n return (\n <div className=\"flow-overlay\" style={{ display: presentation ? 'none' : undefined }}>\n {children}\n </div>\n );\n}\n\nconst ALL_TAB_DEFS: TabDef[] = [\n { id: 'shapes', label: 'Shapes', icon: '▢', showKey: 'showPalette' },\n { id: 'icons', label: 'Icons', icon: '★', showKey: 'showPalette' },\n { id: 'media', label: 'Media', icon: '▶', showKey: 'showPalette' },\n { id: 'inspector', label: 'Inspector', icon: '⚙', showKey: 'showInspector' },\n { id: 'outline', label: 'Outline', icon: '☰', showKey: 'showOutline' },\n { id: 'json', label: 'JSON', icon: '{ }', showKey: 'showJson' },\n { id: 'ai', label: 'AI', icon: '✨', showKey: 'showAI' },\n];\n\nfunction tabContent(id: string): React.ReactNode {\n switch (id) {\n case 'shapes': return <ShapePaletteContent />;\n case 'icons': return <SvgStampContent />;\n case 'media': return <MediaStampContent />;\n case 'inspector': return <InspectorPanelContent />;\n case 'outline': return <OutlinePanelContent />;\n case 'json': return <JsonEditorPanel />;\n case 'ai': return <AIPanelContent />;\n default: return null;\n }\n}\n\n/** Tab ids whose panels stamp objects onto the canvas (auto-collapse in compact mode). */\nconst STAMP_PANEL_IDS = new Set(['shapes', 'icons', 'media']);\n\nfunction UnifiedPanelGroup({ children, toolbar, compact }: { children: React.ReactNode; toolbar?: React.ReactNode; compact?: boolean }) {\n const ui = useFlowUI();\n const { panelDocks, setPanelDock, presentation, readOnly } = ui;\n const { setShowPalette, setShowInspector, setShowOutline, setShowJson, setShowAI } = ui;\n\n // Read-only: hide every editing panel (palette/inspector/outline/JSON/AI).\n const visibleTabs = readOnly\n ? []\n : ALL_TAB_DEFS.filter(def =>\n !def.showKey || (ui as any)[def.showKey],\n );\n\n const toPanelTab = (def: TabDef): PanelTab => ({\n id: def.id, label: def.label, icon: def.icon, content: tabContent(def.id),\n });\n\n // Compact (small-screen) mode: the chosen panel renders full-screen above\n // the canvas. Shape/icon/media stamp panels collapse automatically once a\n // stamp is picked (pendingPlacement armed) so the user is returned to the\n // canvas to tap it into place; a virtual ESC button on the canvas cancels\n // continuous placement.\n const [activePanel, setActivePanel] = useState<string | null>(null);\n const prevPlacementKeyRef = useRef<string | null>(null);\n useEffect(() => {\n if (!compact) {\n prevPlacementKeyRef.current = null;\n return;\n }\n const pp = ui.pendingPlacement;\n const key = pp ? `${pp.type}:${(pp.data as any)?.svgId ?? ''}:${(pp.data as any)?.mediaKind ?? ''}` : null;\n const prev = prevPlacementKeyRef.current;\n prevPlacementKeyRef.current = key;\n if (key && key !== prev && activePanel && STAMP_PANEL_IDS.has(activePanel)) {\n setActivePanel(null);\n }\n }, [ui.pendingPlacement, compact, activePanel]);\n\n // Floating-panel drag: highlight the dock edge it hovers over.\n const [dropHint, setDropHint] = useState<'left' | 'right' | null>(null);\n const handleDock = useCallback((tabId: string, dock: FlowPanelDock) => setPanelDock(tabId, dock), [setPanelDock]);\n // Each panel has its own close (✕) button; closed panels come back via the\n // matching toolbar toggle (shapes/icons/media share the palette flag).\n const handleClose = useCallback((tabId: string) => {\n if (tabId === 'inspector') setShowInspector(false);\n else if (tabId === 'outline') setShowOutline(false);\n else if (tabId === 'json') setShowJson(false);\n else if (tabId === 'ai') setShowAI(false);\n else setShowPalette(false);\n }, [setShowInspector, setShowOutline, setShowJson, setShowAI, setShowPalette]);\n\n // NOTE: every hook must run before this early return — moving hooks below it\n // would break the hooks-of-render contract in compact mode.\n if (compact && !presentation) {\n const activeDef = visibleTabs.find(d => d.id === activePanel) ?? null;\n return (\n <div className=\"flow-workspace\">\n {toolbar}\n {visibleTabs.length > 0 && (\n <div className=\"flow-mobile-panel-bar\">\n <Select\n placeholder=\"选择面板…\"\n options={visibleTabs.map(d => ({ value: d.id, label: d.label }))}\n value={activePanel ?? undefined}\n onChange={(v) => setActivePanel(String(v))}\n />\n </div>\n )}\n <div className=\"flow-workspace-main\">\n <div className=\"flow-stage\">\n {children}\n </div>\n {activeDef && (\n <div className=\"flow-mobile-panel\">\n <div className=\"flow-mobile-panel-header\">\n <span className=\"flow-mobile-panel-title\">\n {activeDef.icon && <span className=\"flow-panel-tab-icon\">{activeDef.icon}</span>}\n {activeDef.label}\n </span>\n <button\n type=\"button\"\n className=\"flow-mobile-panel-close\"\n aria-label=\"关闭面板\"\n onClick={() => setActivePanel(null)}\n >✕</button>\n </div>\n <div className=\"flow-mobile-panel-body\">{tabContent(activeDef.id)}</div>\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Desktop layout: the left/right panel groups are merged into one panel\n // list docked on the left by default. Panels are switched with a dropdown\n // Select; users can move any panel to the right dock or let it float (via\n // header buttons or by dragging it onto a workspace edge). Docks without\n // panels are not rendered so the canvas fills the freed space.\n const getDock = (id: string): FlowPanelDock => panelDocks[id] ?? 'left';\n const leftTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'left')\n .map(toPanelTab);\n const rightTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'right')\n .map(toPanelTab);\n const floatList = visibleTabs.filter(def => getDock(def.id) === 'float');\n\n return (\n <div className=\"flow-workspace\">\n {/* Slim full-width toolbar strip above panels + canvas. */}\n {!presentation && toolbar}\n <div className=\"flow-workspace-main\">\n {!presentation && leftTabs.length > 0 && (\n <FlowPanelGroup\n tabs={leftTabs}\n defaultTab={leftTabs[0]?.id}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"left\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n <div className=\"flow-stage\">\n {children}\n </div>\n {!presentation && rightTabs.length > 0 && (\n <FlowPanelGroup\n tabs={rightTabs}\n defaultTab={rightTabs[0]?.id}\n resizeEdge=\"left\"\n defaultWidth={220}\n dock=\"right\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n {/* Floating panels drift above the docks; dragging one over a\n workspace edge shows a drop-zone hint and dropping attaches it to\n that dock. Rendered as a direct child of the (position:relative)\n workspace-main so they are not clipped by the stage's\n `overflow: hidden`. */}\n {!presentation && floatList.map((def, i) => (\n <FlowPanelGroup\n key={def.id}\n tabs={[toPanelTab(def)]}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"float\"\n style={{ top: 48 + i * 40, left: 24 + i * 30 }}\n onDock={handleDock}\n onClose={handleClose}\n onDragHintChange={setDropHint}\n />\n ))}\n {!presentation && dropHint && (\n <div className={`flow-dock-dropzone flow-dock-dropzone--${dropHint}`}>\n <span>{dropHint === 'left' ? '⇤ 停靠左侧' : '停靠右侧 ⇥'}</span>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction MiniMapWrapper({\n canvasRef,\n pixiRef,\n miniMapRef,\n}: {\n canvasRef: React.RefObject<HTMLCanvasElement | null>;\n pixiRef: React.RefObject<PixiApp | null>;\n miniMapRef: React.RefObject<MiniMapRenderer | null>;\n}) {\n const { showMiniMap, setViewport, presentation } = useFlowUI();\n const draggingRef = useRef(false);\n\n // Move the main canvas so that the world point under the minimap click is\n // centered in the viewport. Routed through setViewport so the change syncs\n // with the ViewportManager (setting world.position directly would be\n // overwritten on the next viewport apply).\n const navigateTo = useCallback((clientX: number, clientY: number) => {\n const canvas = canvasRef.current;\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!canvas || !pixi || pixi.destroyed || !mm) return;\n\n const rect = canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return;\n // CSS pixels -> canvas backing pixels.\n const { width: cw, height: ch } = mm.size;\n const px = ((clientX - rect.left) / rect.width) * cw;\n const py = ((clientY - rect.top) / rect.height) * ch;\n\n const world = mm.minimapToWorld(px, py);\n if (!world) return;\n\n const zoom = pixi.world.scale.x || 1;\n const screenW = pixi.app.screen.width;\n const screenH = pixi.app.screen.height;\n setViewport({\n x: screenW / 2 - world.x * zoom,\n y: screenH / 2 - world.y * zoom,\n zoom,\n });\n }, [canvasRef, pixiRef, miniMapRef, setViewport]);\n\n const onPointerDown = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault();\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n draggingRef.current = true;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerMove = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerUp = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n draggingRef.current = false;\n try { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); } catch { /* noop */ }\n }, []);\n\n return (\n <div\n className=\"flow-minimap\"\n style={{ display: showMiniMap && !presentation ? undefined : 'none', cursor: 'pointer' }}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n title=\"点击或拖动以移动画布\"\n >\n <canvas ref={canvasRef} width={180} height={120} style={{ width: '100%', height: '100%', pointerEvents: 'none' }} />\n </div>\n );\n}\n\n/**\n * Find the line range (1-based) of a JSON object with the given id.\n */\nfunction findElementLineRange(jsonStr: string, elementId: string): { startLine: number; endLine: number } | null {\n const idPattern = `\"id\": \"${elementId}\"`;\n const idx = jsonStr.indexOf(idPattern);\n if (idx === -1) return null;\n\n let braceDepth = 0;\n let startIdx = -1;\n for (let i = idx; i >= 0; i--) {\n if (jsonStr[i] === '}') braceDepth++;\n if (jsonStr[i] === '{') {\n if (braceDepth === 0) { startIdx = i; break; }\n braceDepth--;\n }\n }\n if (startIdx === -1) return null;\n\n braceDepth = 0;\n let endIdx = -1;\n for (let i = startIdx; i < jsonStr.length; i++) {\n if (jsonStr[i] === '{') braceDepth++;\n if (jsonStr[i] === '}') {\n braceDepth--;\n if (braceDepth === 0) { endIdx = i; break; }\n }\n }\n if (endIdx === -1) return null;\n\n const startLine = jsonStr.slice(0, startIdx).split('\\n').length;\n const endLine = jsonStr.slice(0, endIdx + 1).split('\\n').length;\n return { startLine, endLine };\n}\n\nfunction clearLineHighlights(container: HTMLElement) {\n container.querySelectorAll('.cm-line.flow-json-hl').forEach(el => el.classList.remove('flow-json-hl'));\n}\n\nfunction applyLineHighlightsViaView(handle: CodeEditorHandle, startLine: number, endLine: number) {\n const view = handle.getView();\n if (!view) return;\n for (let ln = startLine; ln <= endLine; ln++) {\n try {\n const lineInfo = view.state.doc.line(ln);\n const dom = view.domAtPos(lineInfo.from);\n const lineEl = dom.node instanceof HTMLElement\n ? dom.node.closest('.cm-line')\n : dom.node.parentElement?.closest('.cm-line');\n if (lineEl) lineEl.classList.add('flow-json-hl');\n } catch { /* line not in viewport */ }\n }\n}\n\nfunction JsonEditorPanel() {\n const { setDoc, currentCanvasId, selection, currentCanvas } = useFlowContext();\n const [jsonStr, setJsonStr] = useState('');\n const [error, setError] = useState<string | null>(null);\n const skipNextSync = useRef(false);\n const editorRef = useRef<CodeEditorHandle>(null);\n const wrapRef = useRef<HTMLDivElement>(null);\n\n const singleId = useMemo(() => {\n const total = selection.nodeIds.size + selection.edgeIds.size + selection.lineIds.size;\n if (total !== 1) return null;\n if (selection.nodeIds.size === 1) return [...selection.nodeIds][0];\n if (selection.edgeIds.size === 1) return [...selection.edgeIds][0];\n if (selection.lineIds.size === 1) return [...selection.lineIds][0];\n return null;\n }, [selection]);\n\n useEffect(() => {\n if (skipNextSync.current) { skipNextSync.current = false; return; }\n setJsonStr(JSON.stringify(currentCanvas, null, 2));\n setError(null);\n }, [currentCanvas]);\n\n useEffect(() => {\n const wrap = wrapRef.current;\n if (wrap) clearLineHighlights(wrap);\n if (!singleId) return;\n\n const timer = setTimeout(() => {\n const range = findElementLineRange(jsonStr, singleId);\n if (!range || !wrapRef.current) return;\n\n const view = editorRef.current?.getView();\n if (!view) return;\n\n const w = wrapRef.current;\n const scroller = view.scrollDOM;\n\n scroller.style.scrollBehavior = 'smooth';\n\n const lineInfo = view.state.doc.line(range.startLine);\n view.dispatch({\n effects: EditorView.scrollIntoView(lineInfo.from, { y: 'start', yMargin: 0 }),\n });\n\n const onScrollEnd = () => {\n scroller.style.scrollBehavior = '';\n clearLineHighlights(w);\n applyLineHighlightsViaView(editorRef.current!, range.startLine, range.endLine);\n };\n\n let scrollTimer: ReturnType<typeof setTimeout>;\n const onScroll = () => {\n clearTimeout(scrollTimer);\n scrollTimer = setTimeout(onScrollEnd, 100);\n };\n scroller.addEventListener('scroll', onScroll);\n scrollTimer = setTimeout(() => {\n scroller.removeEventListener('scroll', onScroll);\n onScrollEnd();\n }, 800);\n }, 120);\n return () => clearTimeout(timer);\n }, [singleId, jsonStr]);\n\n const handleChange = useCallback((value: string) => {\n setJsonStr(value);\n try {\n const parsed = JSON.parse(value);\n if (parsed && Array.isArray(parsed.nodes) && Array.isArray(parsed.edges) && Array.isArray(parsed.lines)) {\n setError(null);\n skipNextSync.current = true;\n setDoc(prev => ({\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: parsed },\n }));\n } else {\n setError('JSON must have nodes, edges, lines arrays');\n }\n } catch (e: any) {\n setError(e.message?.slice(0, 60) ?? 'Invalid JSON');\n }\n }, [setDoc, currentCanvasId]);\n\n const label = singleId\n ? (selection.nodeIds.has(singleId) ? 'Node' : selection.edgeIds.has(singleId) ? 'Edge' : 'Line')\n : null;\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>\n <div className=\"flow-json-header\">\n <span className=\"flow-json-scope\">\n {label ? `${label}: ${singleId!.slice(0, 8)}` : `Canvas`}\n </span>\n </div>\n {error && (\n <div style={{ fontSize: 11, color: 'oklch(var(--er))', padding: '4px 0', flexShrink: 0 }}>\n {error}\n </div>\n )}\n <div ref={wrapRef} style={{ flex: 1, minHeight: 0 }}>\n <CodeEditor\n ref={editorRef}\n value={jsonStr}\n onChange={handleChange}\n language=\"json\"\n lineNumbers={false}\n height=\"100%\"\n highlightActiveLine={false}\n />\n </div>\n </div>\n );\n}\n\nfunction FlowContextMenuWire() {\n const { contextMenu, setContextMenu } = useFlowUI();\n const { doc, setDoc, currentCanvasId, pushCanvas, setSelection } = useFlowContext();\n const { duplicate } = useClipboard();\n\n if (!contextMenu) return null;\n\n const canvas = doc.canvases[currentCanvasId];\n if (!canvas) { setContextMenu(null); return null; }\n\n const node = contextMenu.nodeId ? canvas.nodes.find(n => n.id === contextMenu.nodeId) : null;\n const items: ContextMenuItem[] = [];\n\n if (node) {\n // Duplicate the node (Cmd/Ctrl+D equivalent). Ensure it is selected first so\n // the clone covers the intended target even on a right-click without a prior\n // left-click selection.\n items.push({\n label: 'Duplicate',\n icon: '⧉',\n action: () => {\n duplicate(24, 24, { nodeIds: new Set([node.id]) });\n },\n });\n items.push({ label: '---', action: () => {} });\n\n const hasChild = !!node.data.childCanvasId;\n\n if (hasChild) {\n items.push({\n label: 'Enter Sub-canvas',\n icon: '↓',\n action: () => {\n pushCanvas(node.data.childCanvasId!);\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n },\n });\n items.push({ label: '---', action: () => {} });\n items.push({\n label: 'Delete Sub-canvas',\n icon: '🗑',\n danger: true,\n action: () => {\n const childId = node.data.childCanvasId!;\n setDoc(prev => {\n const canvases = { ...prev.canvases };\n collectAndRemoveCanvases(canvases, childId);\n const c = canvases[currentCanvasId];\n if (!c) return prev;\n canvases[currentCanvasId] = {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId: undefined } }\n : n,\n ),\n };\n const stack = prev.stack.filter(id => canvases[id]);\n if (stack.length === 0) stack.push(ROOT_CANVAS_ID);\n return { ...prev, canvases, stack };\n });\n },\n });\n } else {\n items.push({\n label: 'Create Sub-canvas',\n icon: '⊞',\n action: () => {\n const childCanvasId = generateId('canvas');\n setDoc(prev => {\n const c = prev.canvases[currentCanvasId];\n if (!c) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId } }\n : n,\n ),\n },\n [childCanvasId]: { nodes: [], edges: [], lines: [] },\n },\n };\n });\n pushCanvas(childCanvasId);\n },\n });\n }\n }\n\n if (items.length === 0) return null;\n\n return (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n items={items}\n onClose={() => setContextMenu(null)}\n />\n );\n}\n\nfunction collectAndRemoveCanvases(\n canvases: Record<string, FlowCanvasData>,\n canvasId: string,\n): void {\n const canvas = canvases[canvasId];\n if (!canvas) return;\n for (const node of canvas.nodes) {\n if (node.data.childCanvasId) {\n collectAndRemoveCanvases(canvases, node.data.childCanvasId);\n }\n }\n delete canvases[canvasId];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Flow.js","names":[],"sources":["../../../../src/components/pro/Flow/Flow.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';\nimport { FlowProvider, useFlowContext } from './context/FlowContext';\nimport { FlowUIProvider, useFlowUI } from './context/FlowUIContext';\nimport { FlowAIProvider } from './context/FlowAIContext';\nimport FlowCanvas from './FlowCanvas';\nimport FlowToolbar, { FlowZoomControls } from './panels/FlowToolbar';\nimport { ShapePaletteContent, SvgStampContent, MediaStampContent } from './panels/ShapePalette';\nimport { InspectorPanelContent } from './panels/InspectorPanel';\nimport { OutlinePanelContent } from './panels/OutlinePanel';\nimport { AIPanelContent } from './panels/AIPanel';\nimport { PresentationMode } from './panels/PresentationMode';\nimport { MediaOverlay } from './nodes/MediaOverlay';\nimport FlowPanelGroup, { type PanelTab } from './panels/FlowPanelGroup';\nimport type { FlowPanelDock } from './context/FlowUIContext';\nimport Breadcrumb from './panels/Breadcrumb';\nimport ContextMenu from './panels/ContextMenu';\nimport type { ContextMenuItem } from './panels/ContextMenu';\nimport Select from '../../Select';\nimport { MiniMapRenderer } from './canvas/MiniMapRenderer';\nimport { CodeEditor, type CodeEditorHandle } from '../CodeEditor';\nimport { EditorView } from '@codemirror/view';\nimport { useUndoRedo } from './hooks/useUndoRedo';\nimport { useClipboard } from './hooks/useClipboard';\nimport { useCompactMode } from './hooks/useCompactMode';\nimport { downloadDataURL, safeFileBaseName } from './hooks/useFlowImportExport';\nimport { usePdfExport } from './hooks/usePdfExport';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useMindMap } from './hooks/useMindMap';\nimport { useDeleteSelection } from './hooks/useDeleteSelection';\nimport { createEmptyDocument, ROOT_CANVAS_ID, DEFAULT_NODE_DATA } from './constants';\nimport { normalizeEdgeHandles } from './edges/edgePaths';\nimport { generateId } from './nodes/nodeUtils';\nimport type { FlowProps, FlowDocument, FlowNode, SelectionState, FlowCanvasData } from './types';\nimport type { PixiApp } from './canvas/PixiApp';\nimport './styles.css';\n\nfunction normalizeDocument(doc: FlowDocument): FlowDocument {\n let changed = false;\n const canvases = { ...doc.canvases };\n for (const [id, canvas] of Object.entries(canvases)) {\n const nodes = canvas.nodes.map(node => {\n if (node.type !== 'shapeSvg') return node;\n const legacyPlacement = node.data.labelPlacement as string | undefined;\n const labelPlacement = legacyPlacement === 'above'\n ? 'top'\n : legacyPlacement === 'center'\n ? 'middle'\n : legacyPlacement === 'below'\n ? 'bottom'\n : node.data.labelPlacement;\n if (labelPlacement === node.data.labelPlacement) return node;\n changed = true;\n return { ...node, data: { ...node.data, labelPlacement } };\n });\n // Mindmap nodes/edges created before theme tokens (≤ 0.0.56) persisted\n // literal colors, so they never followed theme switches. That exact palette\n // was only ever emitted by the old mindmap creator, so remap it to the same\n // tokens the current creator uses.\n let themedNodesChanged = false;\n const themedNodes = nodes.map(node => {\n if (!node.data.isMindMapNode) return node;\n const fill = node.data.fill === '#ffffff' || node.data.fill === '#eef2ff'\n ? 'theme:base-100'\n : node.data.fill;\n const stroke = node.data.stroke === '#6366f1'\n ? 'theme:base-content'\n : node.data.stroke === '#4f46e5'\n ? 'theme:primary'\n : node.data.stroke;\n if (fill === node.data.fill && stroke === node.data.stroke) return node;\n themedNodesChanged = true;\n return { ...node, data: { ...node.data, fill, stroke } };\n });\n const nodeMap = new Map<string, FlowNode>();\n for (const node of themedNodes) nodeMap.set(node.id, node);\n let edgesChanged = false;\n const edges = normalizeEdgeHandles(canvas.edges, nodeMap).map(edge => {\n if (edge.data.strokeColor !== '#94a3b8') return edge;\n const source = nodeMap.get(edge.source);\n const target = nodeMap.get(edge.target);\n if (!source?.data.isMindMapNode || !target?.data.isMindMapNode) return edge;\n edgesChanged = true;\n return { ...edge, data: { ...edge.data, strokeColor: 'theme:base-content' } };\n });\n if (themedNodesChanged || edgesChanged) changed = true;\n if (themedNodes !== nodes || edges !== canvas.edges) {\n canvases[id] = { ...canvas, nodes: themedNodes, edges };\n }\n }\n return changed ? { ...doc, canvases } : doc;\n}\n\nconst EMPTY_SELECTION: SelectionState = {\n nodeIds: new Set(),\n edgeIds: new Set(),\n lineIds: new Set(),\n};\n\nfunction FlowKeyboardShortcutsWire({ onUndo, onRedo, groupRef, geoGroupRef, ungroupRef }: {\n onUndo: () => void;\n onRedo: () => void;\n groupRef: React.MutableRefObject<(() => void) | null>;\n geoGroupRef: React.MutableRefObject<(() => void) | null>;\n ungroupRef: React.MutableRefObject<(() => void) | null>;\n}) {\n const { selection, setSelection, currentCanvas, setDoc, currentCanvasId } = useFlowContext();\n const { viewport } = useFlowUI();\n const { copy, cut, paste, duplicate } = useClipboard();\n const deleteSelected = useDeleteSelection();\n\n const selectAll = useCallback(() => {\n setSelection({\n nodeIds: new Set(currentCanvas.nodes.map(n => n.id)),\n edgeIds: new Set(currentCanvas.edges.map(e => e.id)),\n lineIds: new Set(currentCanvas.lines.map(l => l.id)),\n });\n }, [currentCanvas, setSelection]);\n\n const createGroup = useCallback((type: 'flowGroup' | 'geometryGroup') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n const totalCount = nodeIds.size + lineIds.size;\n if (totalCount < 2) return;\n const nodes = currentCanvas.nodes.filter(n => nodeIds.has(n.id));\n const lines = currentCanvas.lines.filter(l => lineIds.has(l.id));\n const PAD = 20;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n minX = Math.min(minX, n.position.x);\n minY = Math.min(minY, n.position.y);\n maxX = Math.max(maxX, n.position.x + n.width);\n maxY = Math.max(maxY, n.position.y + n.height);\n }\n for (const l of lines) {\n for (const p of l.points) {\n minX = Math.min(minX, p.x); minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x); maxY = Math.max(maxY, p.y);\n }\n }\n const isGeo = type === 'geometryGroup';\n const groupId = generateId('group');\n const groupNode: FlowNode = {\n id: groupId,\n type,\n position: { x: minX - PAD, y: minY - PAD },\n width: maxX - minX + PAD * 2,\n height: maxY - minY + PAD * 2,\n data: {\n ...DEFAULT_NODE_DATA,\n label: isGeo ? 'Geo Group' : 'Group',\n fill: isGeo ? '#fefce8' : '#f0f9ff',\n stroke: '#9ca3af', strokeWidth: 1.5,\n borderStyle: isGeo ? 'dashed' : 'dotted',\n isGroup: true,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: isGeo\n ? [groupNode, ...canvas.nodes]\n : [groupNode, ...canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, parentId: groupId } : n)],\n lines: isGeo\n ? canvas.lines\n : canvas.lines.map(l => lineIds.has(l.id) ? { ...l, parentId: groupId } : l),\n }},\n };\n });\n setSelection({ nodeIds: new Set([groupId]), edgeIds: new Set(), lineIds: new Set() });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n const groupSelected = useCallback(() => createGroup('flowGroup'), [createGroup]);\n const geoGroupSelected = useCallback(() => createGroup('geometryGroup'), [createGroup]);\n\n const ungroupSelected = useCallback(() => {\n const ids = selection.nodeIds;\n if (ids.size === 0) return;\n const groupNodeIds = new Set<string>();\n const childNodeIds = new Set<string>();\n const childLineIds = new Set<string>();\n for (const node of currentCanvas.nodes) {\n if (ids.has(node.id) && (node.type === 'flowGroup' || node.type === 'geometryGroup' || node.data.isGroup)) {\n groupNodeIds.add(node.id);\n }\n }\n if (groupNodeIds.size === 0) return;\n for (const node of currentCanvas.nodes) {\n if (node.parentId && groupNodeIds.has(node.parentId)) {\n childNodeIds.add(node.id);\n }\n }\n for (const line of currentCanvas.lines) {\n if (line.parentId && groupNodeIds.has(line.parentId)) {\n childLineIds.add(line.id);\n }\n }\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes\n .filter(n => !groupNodeIds.has(n.id))\n .map(n => childNodeIds.has(n.id) ? { ...n, parentId: undefined } : n),\n lines: canvas.lines\n .map(l => childLineIds.has(l.id) ? { ...l, parentId: undefined } : l),\n }},\n };\n });\n setSelection({ nodeIds: childNodeIds, edgeIds: new Set(), lineIds: childLineIds });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n groupRef.current = groupSelected;\n geoGroupRef.current = geoGroupSelected;\n ungroupRef.current = ungroupSelected;\n\n const changeZIndex = useCallback((mode: 'front' | 'back' | 'up' | 'down') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n if (nodeIds.size === 0 && lineIds.size === 0) return;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n const nodeAllZ = canvas.nodes.map(n => n.zIndex ?? 0);\n const nodeMaxZ = nodeAllZ.length > 0 ? Math.max(...nodeAllZ) : 0;\n const nodeMinZ = nodeAllZ.length > 0 ? Math.min(...nodeAllZ) : 0;\n const lineAllZ = canvas.lines.map(l => l.zIndex ?? 0);\n const lineMaxZ = lineAllZ.length > 0 ? Math.max(...lineAllZ) : 0;\n const lineMinZ = lineAllZ.length > 0 ? Math.min(...lineAllZ) : 0;\n const applyZ = (z: number, maxZ: number, minZ: number) => {\n if (mode === 'front') return maxZ + 1;\n if (mode === 'back') return minZ - 1;\n if (mode === 'up') return z + 1;\n return z - 1;\n };\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, zIndex: applyZ(n.zIndex ?? 0, nodeMaxZ, nodeMinZ) } : n),\n lines: canvas.lines.map(l => lineIds.has(l.id) ? { ...l, zIndex: applyZ(l.zIndex ?? 0, lineMaxZ, lineMinZ) } : l),\n }},\n };\n });\n }, [selection, setDoc, currentCanvasId]);\n\n useEffect(() => {\n const handlePaste = (event: ClipboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target?.tagName === 'INPUT' || target?.tagName === 'TEXTAREA' || target?.isContentEditable) return;\n\n const imageItem = Array.from(event.clipboardData?.items ?? []).find(item => item.type.startsWith('image/'));\n if (!imageItem) {\n event.preventDefault();\n paste();\n return;\n }\n\n const file = imageItem.getAsFile();\n if (!file) return;\n event.preventDefault();\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result !== 'string') return;\n const selectedImage = selection.nodeIds.size === 1\n ? currentCanvas.nodes.find(node => selection.nodeIds.has(node.id) && node.type === 'mediaNode' && node.data.mediaKind === 'image')\n : undefined;\n\n if (selectedImage) {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(node => node.id === selectedImage.id\n ? { ...node, data: { ...node.data, mediaContent: reader.result as string } }\n : node),\n },\n },\n };\n });\n return;\n }\n\n const id = generateId('node');\n const width = 320;\n const height = 220;\n const screenWidth = window.innerWidth;\n const screenHeight = window.innerHeight;\n const centerX = (screenWidth / 2 - viewport.x) / viewport.zoom;\n const centerY = (screenHeight / 2 - viewport.y) / viewport.zoom;\n const highestZ = Math.max(0, ...currentCanvas.nodes.map(node => node.zIndex ?? 0));\n const imageNode: FlowNode = {\n id,\n type: 'mediaNode',\n position: { x: centerX - width / 2, y: centerY - height / 2 },\n width,\n height,\n zIndex: highestZ + 1,\n data: {\n ...DEFAULT_NODE_DATA,\n label: file.name || 'Image',\n fill: 'theme:base-100',\n stroke: 'theme:base-content',\n strokeWidth: 1.5,\n color: 'theme:base-content',\n fontSize: 13,\n borderStyle: 'solid',\n mediaKind: 'image',\n mediaContent: reader.result,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: { ...canvas, nodes: [...canvas.nodes, imageNode] },\n },\n };\n });\n setSelection({ nodeIds: new Set([id]), edgeIds: new Set(), lineIds: new Set() });\n };\n reader.readAsDataURL(file);\n };\n\n window.addEventListener('paste', handlePaste);\n return () => window.removeEventListener('paste', handlePaste);\n }, [currentCanvas, currentCanvasId, paste, selection, setDoc, setSelection, viewport]);\n\n const actions = useMemo(() => ({\n undo: onUndo, redo: onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll,\n group: groupSelected, geoGroup: geoGroupSelected, ungroup: ungroupSelected,\n bringToFront: () => changeZIndex('front'),\n bringForward: () => changeZIndex('up'),\n sendBackward: () => changeZIndex('down'),\n sendToBack: () => changeZIndex('back'),\n }), [onUndo, onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll, groupSelected, geoGroupSelected, ungroupSelected, changeZIndex]);\n\n useKeyboardShortcuts(actions);\n useMindMap();\n return null;\n}\n\n/**\n * Bridges the anchor→PDF export (which needs canvas/viewport context) out to the\n * toolbar in the outer Flow component via a ref. Renders nothing.\n */\nfunction PdfExportWire({\n pixiRef,\n exportPdfRef,\n}: {\n pixiRef: React.RefObject<PixiApp | null>;\n exportPdfRef: React.MutableRefObject<(() => Promise<boolean>) | null>;\n}) {\n const exportPdf = usePdfExport(pixiRef);\n exportPdfRef.current = exportPdf;\n return null;\n}\n\n/** Imperative handle exposed via a ref on the `<Flow>` component. */\nexport interface FlowHandle {\n /** Export the current diagram to a PNG data URL (null if unavailable). */\n exportPNG: (backgroundColor?: number) => Promise<string | null>;\n /** Get the current document. */\n getDocument: () => FlowDocument;\n}\n\nconst Flow = forwardRef<FlowHandle, FlowProps>(function Flow({\n initialDocument,\n onChange,\n width,\n height,\n readOnly = false,\n onBack,\n onExportPNG,\n onPublish,\n showMiniMap = true,\n showGrid = true,\n gridSize = 20,\n className,\n showAI = true,\n showAIConfig = true,\n aiConfig,\n}: FlowProps, ref) {\n const [doc, setDoc] = useState<FlowDocument>(() => normalizeDocument(initialDocument ?? createEmptyDocument()));\n const [selection, setSelection] = useState<SelectionState>(EMPTY_SELECTION);\n const pixiRef = useRef<PixiApp | null>(null);\n const miniMapCanvasRef = useRef<HTMLCanvasElement>(null);\n const miniMapRef = useRef<MiniMapRenderer | null>(null);\n // Small-screen detection (container width based, see useCompactMode).\n const rootRef = useRef<HTMLDivElement>(null);\n const compact = useCompactMode(rootRef);\n\n const { wrappedSetDoc, undo, redo, canUndo, canRedo } = useUndoRedo(doc, setDoc);\n const groupRef = useRef<(() => void) | null>(null);\n const geoGroupRef = useRef<(() => void) | null>(null);\n const ungroupRef = useRef<(() => void) | null>(null);\n const exportPdfRef = useRef<(() => Promise<boolean>) | null>(null);\n\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n // Keep the latest doc in a ref for the imperative handle.\n const docRef = useRef(doc);\n docRef.current = doc;\n\n useImperativeHandle(ref, () => ({\n exportPNG: async (backgroundColor?: number) => {\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return null;\n return pixi.exportPNG(backgroundColor);\n },\n getDocument: () => docRef.current,\n }), []);\n\n const outerSetDoc: React.Dispatch<React.SetStateAction<FlowDocument>> = useCallback(\n (action) => {\n wrappedSetDoc(prev => {\n const next = typeof action === 'function' ? action(prev) : action;\n if (readOnly) {\n // Read-only: discard any content mutation. Only pure canvas\n // navigation (stack push/pop — entering/leaving groups via\n // double-click or breadcrumb) is allowed through. onChange is not\n // fired, so hosts won't treat navigation as an unsaved change.\n const navigationOnly = next.canvases === prev.canvases && next.title === prev.title;\n return navigationOnly ? next : prev;\n }\n queueMicrotask(() => onChangeRef.current?.(next));\n return next;\n });\n },\n [wrappedSetDoc, readOnly],\n );\n\n // Undo/redo mutate the document directly through useUndoRedo's raw setDoc\n // (bypassing outerSetDoc), so they need their own read-only guard.\n const guardedUndo = useCallback(() => { if (!readOnly) undo(); }, [readOnly, undo]);\n const guardedRedo = useCallback(() => { if (!readOnly) redo(); }, [readOnly, redo]);\n\n const handlePixiReady = useCallback((pixi: PixiApp) => {\n pixiRef.current = pixi;\n if (miniMapCanvasRef.current && !miniMapRef.current) {\n miniMapRef.current = new MiniMapRenderer(miniMapCanvasRef.current);\n }\n }, []);\n\n // Built-in PNG export: if the host supplies `onExportPNG` we defer to it,\n // otherwise snapshot the Pixi scene and download it directly so the toolbar\n // button always works out of the box.\n const handleExportPNG = useCallback(async () => {\n if (onExportPNG) return void onExportPNG();\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return;\n const url = await pixi.exportPNG(0xffffff);\n if (url) downloadDataURL(url, `${safeFileBaseName(docRef.current.title)}.png`);\n }, [onExportPNG]);\n\n // Built-in PDF export: capture each anchor's presentation framing into a\n // multi-page PDF (implemented by PdfExportWire inside the providers).\n const handleExportPDF = useCallback(async () => {\n await exportPdfRef.current?.();\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n let subscribed: PixiApp | null = null;\n\n const tickerFn = () => {\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!pixi || pixi.destroyed || !mm) return;\n const vp = { x: pixi.world.position.x, y: pixi.world.position.y, zoom: pixi.world.scale.x };\n const currentId = doc.stack[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const canvas = doc.canvases[currentId];\n if (canvas) mm.update(canvas.nodes, vp, pixi.app.screen.width, pixi.app.screen.height);\n };\n\n // Pixi initializes asynchronously; the minimap renderer is created in\n // handlePixiReady. Poll until both exist, then attach the ticker. This\n // avoids a race where the effect runs before pixi is ready and the minimap\n // stays blank until the next document edit.\n const attach = () => {\n if (cancelled) return;\n const pixi = pixiRef.current;\n if (pixi && !pixi.destroyed && miniMapRef.current) {\n pixi.app.ticker.add(tickerFn);\n subscribed = pixi;\n } else {\n requestAnimationFrame(attach);\n }\n };\n attach();\n\n return () => {\n cancelled = true;\n if (subscribed && !subscribed.destroyed) subscribed.app.ticker.remove(tickerFn);\n };\n }, [doc]);\n\n const style: React.CSSProperties = { width: width ?? '100%', height: height ?? '100%' };\n\n return (\n <div ref={rootRef} className={`flow-container ${className ?? ''}`} style={style}>\n <FlowProvider doc={doc} setDoc={outerSetDoc} selection={selection} setSelection={setSelection}>\n <FlowUIProvider showMiniMap={showMiniMap} showGrid={showGrid} gridSize={gridSize} showAI={showAI} readOnly={readOnly}>\n <FlowAIProvider initialConfig={aiConfig} showAIConfig={showAIConfig}>\n <FlowKeyboardShortcutsWire onUndo={guardedUndo} onRedo={guardedRedo} groupRef={groupRef} geoGroupRef={geoGroupRef} ungroupRef={ungroupRef} />\n <PdfExportWire pixiRef={pixiRef} exportPdfRef={exportPdfRef} />\n <UnifiedPanelGroup\n compact={compact}\n toolbar={!readOnly ? (\n <FlowToolbar\n compact={compact}\n onBack={onBack}\n onUndo={guardedUndo} onRedo={guardedRedo} canUndo={canUndo} canRedo={canRedo}\n onGroup={() => groupRef.current?.()} onGeoGroup={() => geoGroupRef.current?.()} onUngroup={() => ungroupRef.current?.()}\n onExportPNG={handleExportPNG}\n onExportPDF={handleExportPDF}\n onPublish={onPublish}\n />\n ) : null}\n >\n <FlowCanvas onPixiReady={handlePixiReady} />\n {/* Media content (markdown/mermaid/data/…) must stay visible in\n presentation & read-only preview — PixiJS only draws the node\n frame, so hiding this layer would blank every media node. */}\n <MediaOverlay />\n <PresentationGate>\n {!readOnly && <FlowZoomControls />}\n <Breadcrumb />\n </PresentationGate>\n {!readOnly && <FlowContextMenuWire />}\n <MiniMapWrapper canvasRef={miniMapCanvasRef} pixiRef={pixiRef} miniMapRef={miniMapRef} />\n <PresentationMode />\n </UnifiedPanelGroup>\n </FlowAIProvider>\n </FlowUIProvider>\n </FlowProvider>\n </div>\n );\n});\n\nexport default Flow;\n\ninterface TabDef {\n id: string;\n label: string;\n icon: string;\n showKey?: 'showPalette' | 'showInspector' | 'showOutline' | 'showJson' | 'showAI';\n}\n\n/**\n * Hides all editable overlay UI (toolbar, panels, breadcrumb) while in\n * presentation mode, keeping only the canvas visible for the slideshow.\n */\nfunction PresentationGate({ children }: { children: React.ReactNode }) {\n const { presentation } = useFlowUI();\n return (\n <div className=\"flow-overlay\" style={{ display: presentation ? 'none' : undefined }}>\n {children}\n </div>\n );\n}\n\nconst ALL_TAB_DEFS: TabDef[] = [\n { id: 'shapes', label: 'Shapes', icon: '▢', showKey: 'showPalette' },\n { id: 'icons', label: 'Icons', icon: '★', showKey: 'showPalette' },\n { id: 'media', label: 'Media', icon: '▶', showKey: 'showPalette' },\n { id: 'inspector', label: 'Inspector', icon: '⚙', showKey: 'showInspector' },\n { id: 'outline', label: 'Outline', icon: '☰', showKey: 'showOutline' },\n { id: 'json', label: 'JSON', icon: '{ }', showKey: 'showJson' },\n { id: 'ai', label: 'AI', icon: '✨', showKey: 'showAI' },\n];\n\nfunction tabContent(id: string): React.ReactNode {\n switch (id) {\n case 'shapes': return <ShapePaletteContent />;\n case 'icons': return <SvgStampContent />;\n case 'media': return <MediaStampContent />;\n case 'inspector': return <InspectorPanelContent />;\n case 'outline': return <OutlinePanelContent />;\n case 'json': return <JsonEditorPanel />;\n case 'ai': return <AIPanelContent />;\n default: return null;\n }\n}\n\n/** Tab ids whose panels stamp objects onto the canvas (auto-collapse in compact mode). */\nconst STAMP_PANEL_IDS = new Set(['shapes', 'icons', 'media']);\n\nfunction UnifiedPanelGroup({ children, toolbar, compact }: { children: React.ReactNode; toolbar?: React.ReactNode; compact?: boolean }) {\n const ui = useFlowUI();\n const { panelDocks, setPanelDock, presentation, readOnly, setPendingPlacement } = ui;\n const { setShowPalette, setShowInspector, setShowOutline, setShowJson, setShowAI } = ui;\n\n // Read-only: hide every editing panel (palette/inspector/outline/JSON/AI).\n const visibleTabs = readOnly\n ? []\n : ALL_TAB_DEFS.filter(def =>\n !def.showKey || (ui as any)[def.showKey],\n );\n\n const toPanelTab = (def: TabDef): PanelTab => ({\n id: def.id, label: def.label, icon: def.icon, content: tabContent(def.id),\n });\n\n // Compact (small-screen) mode: the chosen panel renders full-screen above\n // the canvas. Shape/icon/media stamp panels collapse automatically once a\n // stamp is picked (pendingPlacement armed) so the user is returned to the\n // canvas to tap it into place; a virtual ESC button on the canvas cancels\n // continuous placement.\n const [activePanel, setActivePanel] = useState<string | null>(null);\n const prevPlacementKeyRef = useRef<string | null>(null);\n useEffect(() => {\n if (!compact) {\n prevPlacementKeyRef.current = null;\n return;\n }\n const pp = ui.pendingPlacement;\n const key = pp ? `${pp.type}:${(pp.data as any)?.svgId ?? ''}:${(pp.data as any)?.mediaKind ?? ''}` : null;\n const prev = prevPlacementKeyRef.current;\n prevPlacementKeyRef.current = key;\n if (key && key !== prev && activePanel && STAMP_PANEL_IDS.has(activePanel)) {\n setActivePanel(null);\n }\n }, [ui.pendingPlacement, compact, activePanel]);\n\n // Floating-panel drag: highlight the dock edge it hovers over.\n const [dropHint, setDropHint] = useState<'left' | 'right' | null>(null);\n const handleDock = useCallback((tabId: string, dock: FlowPanelDock) => setPanelDock(tabId, dock), [setPanelDock]);\n // Each panel has its own close (✕) button; closed panels come back via the\n // matching toolbar toggle (shapes/icons/media share the palette flag).\n const handleClose = useCallback((tabId: string) => {\n if (tabId === 'inspector') setShowInspector(false);\n else if (tabId === 'outline') setShowOutline(false);\n else if (tabId === 'json') setShowJson(false);\n else if (tabId === 'ai') setShowAI(false);\n else setShowPalette(false);\n }, [setShowInspector, setShowOutline, setShowJson, setShowAI, setShowPalette]);\n\n // NOTE: every hook must run before this early return — moving hooks below it\n // would break the hooks-of-render contract in compact mode.\n if (compact && !presentation) {\n const activeDef = visibleTabs.find(d => d.id === activePanel) ?? null;\n return (\n <div className=\"flow-workspace\">\n {toolbar}\n {visibleTabs.length > 0 && (\n <div className=\"flow-mobile-panel-bar\">\n <Select\n placeholder=\"选择面板…\"\n options={visibleTabs.map(d => ({ value: d.id, label: d.label }))}\n value={activePanel ?? undefined}\n onChange={(v) => {\n // Switching panels always opens a clean \"pick a type\" state: a\n // stale armed stamp (continuous placement) would otherwise be\n // placed by the next canvas tap or toggle the tapped item off.\n setPendingPlacement(null);\n setActivePanel(String(v));\n }}\n />\n </div>\n )}\n <div className=\"flow-workspace-main\">\n <div className=\"flow-stage\">\n {children}\n </div>\n {activeDef && (\n <div className=\"flow-mobile-panel\">\n <div className=\"flow-mobile-panel-header\">\n <span className=\"flow-mobile-panel-title\">\n {activeDef.icon && <span className=\"flow-panel-tab-icon\">{activeDef.icon}</span>}\n {activeDef.label}\n </span>\n <button\n type=\"button\"\n className=\"flow-mobile-panel-close\"\n aria-label=\"关闭面板\"\n onClick={() => setActivePanel(null)}\n >✕</button>\n </div>\n <div className=\"flow-mobile-panel-body\">{tabContent(activeDef.id)}</div>\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Desktop layout: the left/right panel groups are merged into one panel\n // list docked on the left by default. Panels are switched with a dropdown\n // Select; users can move any panel to the right dock or let it float (via\n // header buttons or by dragging it onto a workspace edge). Docks without\n // panels are not rendered so the canvas fills the freed space.\n const getDock = (id: string): FlowPanelDock => panelDocks[id] ?? 'left';\n const leftTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'left')\n .map(toPanelTab);\n const rightTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'right')\n .map(toPanelTab);\n const floatList = visibleTabs.filter(def => getDock(def.id) === 'float');\n\n return (\n <div className=\"flow-workspace\">\n {/* Slim full-width toolbar strip above panels + canvas. */}\n {!presentation && toolbar}\n <div className=\"flow-workspace-main\">\n {!presentation && leftTabs.length > 0 && (\n <FlowPanelGroup\n tabs={leftTabs}\n defaultTab={leftTabs[0]?.id}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"left\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n <div className=\"flow-stage\">\n {children}\n </div>\n {!presentation && rightTabs.length > 0 && (\n <FlowPanelGroup\n tabs={rightTabs}\n defaultTab={rightTabs[0]?.id}\n resizeEdge=\"left\"\n defaultWidth={220}\n dock=\"right\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n {/* Floating panels drift above the docks; dragging one over a\n workspace edge shows a drop-zone hint and dropping attaches it to\n that dock. Rendered as a direct child of the (position:relative)\n workspace-main so they are not clipped by the stage's\n `overflow: hidden`. */}\n {!presentation && floatList.map((def, i) => (\n <FlowPanelGroup\n key={def.id}\n tabs={[toPanelTab(def)]}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"float\"\n style={{ top: 48 + i * 40, left: 24 + i * 30 }}\n onDock={handleDock}\n onClose={handleClose}\n onDragHintChange={setDropHint}\n />\n ))}\n {!presentation && dropHint && (\n <div className={`flow-dock-dropzone flow-dock-dropzone--${dropHint}`}>\n <span>{dropHint === 'left' ? '⇤ 停靠左侧' : '停靠右侧 ⇥'}</span>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction MiniMapWrapper({\n canvasRef,\n pixiRef,\n miniMapRef,\n}: {\n canvasRef: React.RefObject<HTMLCanvasElement | null>;\n pixiRef: React.RefObject<PixiApp | null>;\n miniMapRef: React.RefObject<MiniMapRenderer | null>;\n}) {\n const { showMiniMap, setViewport, presentation } = useFlowUI();\n const draggingRef = useRef(false);\n\n // Move the main canvas so that the world point under the minimap click is\n // centered in the viewport. Routed through setViewport so the change syncs\n // with the ViewportManager (setting world.position directly would be\n // overwritten on the next viewport apply).\n const navigateTo = useCallback((clientX: number, clientY: number) => {\n const canvas = canvasRef.current;\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!canvas || !pixi || pixi.destroyed || !mm) return;\n\n const rect = canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return;\n // CSS pixels -> canvas backing pixels.\n const { width: cw, height: ch } = mm.size;\n const px = ((clientX - rect.left) / rect.width) * cw;\n const py = ((clientY - rect.top) / rect.height) * ch;\n\n const world = mm.minimapToWorld(px, py);\n if (!world) return;\n\n const zoom = pixi.world.scale.x || 1;\n const screenW = pixi.app.screen.width;\n const screenH = pixi.app.screen.height;\n setViewport({\n x: screenW / 2 - world.x * zoom,\n y: screenH / 2 - world.y * zoom,\n zoom,\n });\n }, [canvasRef, pixiRef, miniMapRef, setViewport]);\n\n const onPointerDown = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault();\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n draggingRef.current = true;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerMove = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerUp = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n draggingRef.current = false;\n try { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); } catch { /* noop */ }\n }, []);\n\n return (\n <div\n className=\"flow-minimap\"\n style={{ display: showMiniMap && !presentation ? undefined : 'none', cursor: 'pointer' }}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n title=\"点击或拖动以移动画布\"\n >\n <canvas ref={canvasRef} width={180} height={120} style={{ width: '100%', height: '100%', pointerEvents: 'none' }} />\n </div>\n );\n}\n\n/**\n * Find the line range (1-based) of a JSON object with the given id.\n */\nfunction findElementLineRange(jsonStr: string, elementId: string): { startLine: number; endLine: number } | null {\n const idPattern = `\"id\": \"${elementId}\"`;\n const idx = jsonStr.indexOf(idPattern);\n if (idx === -1) return null;\n\n let braceDepth = 0;\n let startIdx = -1;\n for (let i = idx; i >= 0; i--) {\n if (jsonStr[i] === '}') braceDepth++;\n if (jsonStr[i] === '{') {\n if (braceDepth === 0) { startIdx = i; break; }\n braceDepth--;\n }\n }\n if (startIdx === -1) return null;\n\n braceDepth = 0;\n let endIdx = -1;\n for (let i = startIdx; i < jsonStr.length; i++) {\n if (jsonStr[i] === '{') braceDepth++;\n if (jsonStr[i] === '}') {\n braceDepth--;\n if (braceDepth === 0) { endIdx = i; break; }\n }\n }\n if (endIdx === -1) return null;\n\n const startLine = jsonStr.slice(0, startIdx).split('\\n').length;\n const endLine = jsonStr.slice(0, endIdx + 1).split('\\n').length;\n return { startLine, endLine };\n}\n\nfunction clearLineHighlights(container: HTMLElement) {\n container.querySelectorAll('.cm-line.flow-json-hl').forEach(el => el.classList.remove('flow-json-hl'));\n}\n\nfunction applyLineHighlightsViaView(handle: CodeEditorHandle, startLine: number, endLine: number) {\n const view = handle.getView();\n if (!view) return;\n for (let ln = startLine; ln <= endLine; ln++) {\n try {\n const lineInfo = view.state.doc.line(ln);\n const dom = view.domAtPos(lineInfo.from);\n const lineEl = dom.node instanceof HTMLElement\n ? dom.node.closest('.cm-line')\n : dom.node.parentElement?.closest('.cm-line');\n if (lineEl) lineEl.classList.add('flow-json-hl');\n } catch { /* line not in viewport */ }\n }\n}\n\nfunction JsonEditorPanel() {\n const { setDoc, currentCanvasId, selection, currentCanvas } = useFlowContext();\n const [jsonStr, setJsonStr] = useState('');\n const [error, setError] = useState<string | null>(null);\n const skipNextSync = useRef(false);\n const editorRef = useRef<CodeEditorHandle>(null);\n const wrapRef = useRef<HTMLDivElement>(null);\n\n const singleId = useMemo(() => {\n const total = selection.nodeIds.size + selection.edgeIds.size + selection.lineIds.size;\n if (total !== 1) return null;\n if (selection.nodeIds.size === 1) return [...selection.nodeIds][0];\n if (selection.edgeIds.size === 1) return [...selection.edgeIds][0];\n if (selection.lineIds.size === 1) return [...selection.lineIds][0];\n return null;\n }, [selection]);\n\n useEffect(() => {\n if (skipNextSync.current) { skipNextSync.current = false; return; }\n setJsonStr(JSON.stringify(currentCanvas, null, 2));\n setError(null);\n }, [currentCanvas]);\n\n useEffect(() => {\n const wrap = wrapRef.current;\n if (wrap) clearLineHighlights(wrap);\n if (!singleId) return;\n\n const timer = setTimeout(() => {\n const range = findElementLineRange(jsonStr, singleId);\n if (!range || !wrapRef.current) return;\n\n const view = editorRef.current?.getView();\n if (!view) return;\n\n const w = wrapRef.current;\n const scroller = view.scrollDOM;\n\n scroller.style.scrollBehavior = 'smooth';\n\n const lineInfo = view.state.doc.line(range.startLine);\n view.dispatch({\n effects: EditorView.scrollIntoView(lineInfo.from, { y: 'start', yMargin: 0 }),\n });\n\n const onScrollEnd = () => {\n scroller.style.scrollBehavior = '';\n clearLineHighlights(w);\n applyLineHighlightsViaView(editorRef.current!, range.startLine, range.endLine);\n };\n\n let scrollTimer: ReturnType<typeof setTimeout>;\n const onScroll = () => {\n clearTimeout(scrollTimer);\n scrollTimer = setTimeout(onScrollEnd, 100);\n };\n scroller.addEventListener('scroll', onScroll);\n scrollTimer = setTimeout(() => {\n scroller.removeEventListener('scroll', onScroll);\n onScrollEnd();\n }, 800);\n }, 120);\n return () => clearTimeout(timer);\n }, [singleId, jsonStr]);\n\n const handleChange = useCallback((value: string) => {\n setJsonStr(value);\n try {\n const parsed = JSON.parse(value);\n if (parsed && Array.isArray(parsed.nodes) && Array.isArray(parsed.edges) && Array.isArray(parsed.lines)) {\n setError(null);\n skipNextSync.current = true;\n setDoc(prev => ({\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: parsed },\n }));\n } else {\n setError('JSON must have nodes, edges, lines arrays');\n }\n } catch (e: any) {\n setError(e.message?.slice(0, 60) ?? 'Invalid JSON');\n }\n }, [setDoc, currentCanvasId]);\n\n const label = singleId\n ? (selection.nodeIds.has(singleId) ? 'Node' : selection.edgeIds.has(singleId) ? 'Edge' : 'Line')\n : null;\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>\n <div className=\"flow-json-header\">\n <span className=\"flow-json-scope\">\n {label ? `${label}: ${singleId!.slice(0, 8)}` : `Canvas`}\n </span>\n </div>\n {error && (\n <div style={{ fontSize: 11, color: 'oklch(var(--er))', padding: '4px 0', flexShrink: 0 }}>\n {error}\n </div>\n )}\n <div ref={wrapRef} style={{ flex: 1, minHeight: 0 }}>\n <CodeEditor\n ref={editorRef}\n value={jsonStr}\n onChange={handleChange}\n language=\"json\"\n lineNumbers={false}\n height=\"100%\"\n highlightActiveLine={false}\n />\n </div>\n </div>\n );\n}\n\nfunction FlowContextMenuWire() {\n const { contextMenu, setContextMenu } = useFlowUI();\n const { doc, setDoc, currentCanvasId, pushCanvas, setSelection } = useFlowContext();\n const { duplicate } = useClipboard();\n\n if (!contextMenu) return null;\n\n const canvas = doc.canvases[currentCanvasId];\n if (!canvas) { setContextMenu(null); return null; }\n\n const node = contextMenu.nodeId ? canvas.nodes.find(n => n.id === contextMenu.nodeId) : null;\n const items: ContextMenuItem[] = [];\n\n if (node) {\n // Duplicate the node (Cmd/Ctrl+D equivalent). Ensure it is selected first so\n // the clone covers the intended target even on a right-click without a prior\n // left-click selection.\n items.push({\n label: 'Duplicate',\n icon: '⧉',\n action: () => {\n duplicate(24, 24, { nodeIds: new Set([node.id]) });\n },\n });\n items.push({ label: '---', action: () => {} });\n\n const hasChild = !!node.data.childCanvasId;\n\n if (hasChild) {\n items.push({\n label: 'Enter Sub-canvas',\n icon: '↓',\n action: () => {\n pushCanvas(node.data.childCanvasId!);\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n },\n });\n items.push({ label: '---', action: () => {} });\n items.push({\n label: 'Delete Sub-canvas',\n icon: '🗑',\n danger: true,\n action: () => {\n const childId = node.data.childCanvasId!;\n setDoc(prev => {\n const canvases = { ...prev.canvases };\n collectAndRemoveCanvases(canvases, childId);\n const c = canvases[currentCanvasId];\n if (!c) return prev;\n canvases[currentCanvasId] = {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId: undefined } }\n : n,\n ),\n };\n const stack = prev.stack.filter(id => canvases[id]);\n if (stack.length === 0) stack.push(ROOT_CANVAS_ID);\n return { ...prev, canvases, stack };\n });\n },\n });\n } else {\n items.push({\n label: 'Create Sub-canvas',\n icon: '⊞',\n action: () => {\n const childCanvasId = generateId('canvas');\n setDoc(prev => {\n const c = prev.canvases[currentCanvasId];\n if (!c) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId } }\n : n,\n ),\n },\n [childCanvasId]: { nodes: [], edges: [], lines: [] },\n },\n };\n });\n pushCanvas(childCanvasId);\n },\n });\n }\n }\n\n if (items.length === 0) return null;\n\n return (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n items={items}\n onClose={() => setContextMenu(null)}\n />\n );\n}\n\nfunction collectAndRemoveCanvases(\n canvases: Record<string, FlowCanvasData>,\n canvasId: string,\n): void {\n const canvas = canvases[canvasId];\n if (!canvas) return;\n for (const node of canvas.nodes) {\n if (node.data.childCanvasId) {\n collectAndRemoveCanvases(canvases, node.data.childCanvasId);\n }\n }\n delete canvases[canvasId];\n}\n"],"mappings":"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"}
|