dishui 0.0.55 → 0.0.56

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 Breadcrumb from './panels/Breadcrumb';\nimport ContextMenu from './panels/ContextMenu';\nimport type { ContextMenuItem } from './panels/ContextMenu';\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 { downloadDataURL, safeFileBaseName } from './hooks/useFlowImportExport';\nimport { usePdfExport } from './hooks/usePdfExport';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useMindMap } from './hooks/useMindMap';\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 const nodeMap = new Map<string, FlowNode>();\n for (const node of nodes) nodeMap.set(node.id, node);\n const edges = normalizeEdgeHandles(canvas.edges, nodeMap);\n if (nodes !== canvas.nodes || edges !== canvas.edges) {\n canvases[id] = { ...canvas, nodes, edges };\n if (edges !== canvas.edges) changed = true;\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\n const deleteSelected = useCallback(() => {\n const { nodeIds, edgeIds, lineIds } = selection;\n if (nodeIds.size === 0 && edgeIds.size === 0 && lineIds.size === 0) return;\n if (nodeIds.size > 1 && !window.confirm(`确定要删除选中的 ${nodeIds.size} 个节点吗?`)) return;\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\n .filter(n => !nodeIds.has(n.id))\n .map(n => n.parentId && nodeIds.has(n.parentId) ? { ...n, parentId: undefined } : n),\n edges: canvas.edges.filter(e =>\n !edgeIds.has(e.id) && !nodeIds.has(e.source) && !nodeIds.has(e.target),\n ),\n lines: canvas.lines\n .filter(l => !lineIds.has(l.id))\n .map(l => l.parentId && nodeIds.has(l.parentId) ? { ...l, parentId: undefined } : l),\n },\n },\n };\n });\n setSelection(EMPTY_SELECTION);\n }, [selection, setDoc, currentCanvasId, setSelection]);\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\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 queueMicrotask(() => onChangeRef.current?.(next));\n return next;\n });\n },\n [wrappedSetDoc],\n );\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 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}>\n <FlowAIProvider initialConfig={aiConfig} showAIConfig={showAIConfig}>\n <FlowKeyboardShortcutsWire onUndo={undo} onRedo={redo} groupRef={groupRef} geoGroupRef={geoGroupRef} ungroupRef={ungroupRef} />\n <PdfExportWire pixiRef={pixiRef} exportPdfRef={exportPdfRef} />\n <UnifiedPanelGroup\n toolbar={!readOnly ? (\n <FlowToolbar\n onBack={onBack}\n onUndo={undo} onRedo={redo} 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 <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 side: 'left' | 'right';\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: '▢', side: 'left', showKey: 'showPalette' },\n { id: 'icons', label: 'Icons', icon: '★', side: 'left', showKey: 'showPalette' },\n { id: 'media', label: 'Media', icon: '▶', side: 'left', showKey: 'showPalette' },\n { id: 'inspector', label: 'Inspector', icon: '⚙', side: 'right', showKey: 'showInspector' },\n { id: 'outline', label: 'Outline', icon: '☰', side: 'right', showKey: 'showOutline' },\n { id: 'json', label: 'JSON', icon: '{ }', side: 'right', showKey: 'showJson' },\n { id: 'ai', label: 'AI', icon: '✨', side: 'right', 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\nfunction UnifiedPanelGroup({ children, toolbar }: { children: React.ReactNode; toolbar?: React.ReactNode }) {\n const ui = useFlowUI();\n const { detachedTabs, toggleDetach, presentation } = ui;\n\n const visibleTabs = 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 const leftTabs: PanelTab[] = visibleTabs\n .filter(def => def.side === 'left' && !detachedTabs.has(def.id))\n .map(toPanelTab);\n const rightTabs: PanelTab[] = visibleTabs\n .filter(def => def.side === 'right' && !detachedTabs.has(def.id))\n .map(toPanelTab);\n\n const detachedList = visibleTabs.filter(def => detachedTabs.has(def.id));\n\n const handleDetach = useCallback((tabId: string) => toggleDetach(tabId), [toggleDetach]);\n const handleAttach = useCallback((tabId: string) => toggleDetach(tabId), [toggleDetach]);\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={132}\n onDetach={handleDetach}\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 onDetach={handleDetach}\n />\n )}\n {/* Detached panels float above every docked panel. Rendered as a direct\n child of the (position:relative) workspace-main so they are not\n clipped by the stage's `overflow: hidden` and can overlap the side\n panels. */}\n {!presentation && detachedList.map((def, i) => (\n <FlowPanelGroup\n key={def.id}\n tabs={[toPanelTab(def)]}\n resizeEdge=\"right\"\n defaultWidth={220}\n style={{ top: 48 + i * 40, left: 24 + i * 30 }}\n isDetached\n onAttach={handleAttach}\n />\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 Breadcrumb from './panels/Breadcrumb';\nimport ContextMenu from './panels/ContextMenu';\nimport type { ContextMenuItem } from './panels/ContextMenu';\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 { downloadDataURL, safeFileBaseName } from './hooks/useFlowImportExport';\nimport { usePdfExport } from './hooks/usePdfExport';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useMindMap } from './hooks/useMindMap';\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 const nodeMap = new Map<string, FlowNode>();\n for (const node of nodes) nodeMap.set(node.id, node);\n const edges = normalizeEdgeHandles(canvas.edges, nodeMap);\n if (nodes !== canvas.nodes || edges !== canvas.edges) {\n canvases[id] = { ...canvas, nodes, edges };\n if (edges !== canvas.edges) changed = true;\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\n const deleteSelected = useCallback(() => {\n const { nodeIds, edgeIds, lineIds } = selection;\n if (nodeIds.size === 0 && edgeIds.size === 0 && lineIds.size === 0) return;\n if (nodeIds.size > 1 && !window.confirm(`确定要删除选中的 ${nodeIds.size} 个节点吗?`)) return;\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\n .filter(n => !nodeIds.has(n.id))\n .map(n => n.parentId && nodeIds.has(n.parentId) ? { ...n, parentId: undefined } : n),\n edges: canvas.edges.filter(e =>\n !edgeIds.has(e.id) && !nodeIds.has(e.source) && !nodeIds.has(e.target),\n ),\n lines: canvas.lines\n .filter(l => !lineIds.has(l.id))\n .map(l => l.parentId && nodeIds.has(l.parentId) ? { ...l, parentId: undefined } : l),\n },\n },\n };\n });\n setSelection(EMPTY_SELECTION);\n }, [selection, setDoc, currentCanvasId, setSelection]);\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\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 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 toolbar={!readOnly ? (\n <FlowToolbar\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 side: 'left' | 'right';\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: '▢', side: 'left', showKey: 'showPalette' },\n { id: 'icons', label: 'Icons', icon: '★', side: 'left', showKey: 'showPalette' },\n { id: 'media', label: 'Media', icon: '▶', side: 'left', showKey: 'showPalette' },\n { id: 'inspector', label: 'Inspector', icon: '⚙', side: 'right', showKey: 'showInspector' },\n { id: 'outline', label: 'Outline', icon: '☰', side: 'right', showKey: 'showOutline' },\n { id: 'json', label: 'JSON', icon: '{ }', side: 'right', showKey: 'showJson' },\n { id: 'ai', label: 'AI', icon: '✨', side: 'right', 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\nfunction UnifiedPanelGroup({ children, toolbar }: { children: React.ReactNode; toolbar?: React.ReactNode }) {\n const ui = useFlowUI();\n const { detachedTabs, toggleDetach, presentation, readOnly } = 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 const leftTabs: PanelTab[] = visibleTabs\n .filter(def => def.side === 'left' && !detachedTabs.has(def.id))\n .map(toPanelTab);\n const rightTabs: PanelTab[] = visibleTabs\n .filter(def => def.side === 'right' && !detachedTabs.has(def.id))\n .map(toPanelTab);\n\n const detachedList = visibleTabs.filter(def => detachedTabs.has(def.id));\n\n const handleDetach = useCallback((tabId: string) => toggleDetach(tabId), [toggleDetach]);\n const handleAttach = useCallback((tabId: string) => toggleDetach(tabId), [toggleDetach]);\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={132}\n onDetach={handleDetach}\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 onDetach={handleDetach}\n />\n )}\n {/* Detached panels float above every docked panel. Rendered as a direct\n child of the (position:relative) workspace-main so they are not\n clipped by the stage's `overflow: hidden` and can overlap the side\n panels. */}\n {!presentation && detachedList.map((def, i) => (\n <FlowPanelGroup\n key={def.id}\n tabs={[toPanelTab(def)]}\n resizeEdge=\"right\"\n defaultWidth={220}\n style={{ top: 48 + i * 40, left: 24 + i * 30 }}\n isDetached\n onAttach={handleAttach}\n />\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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"}
@@ -66,6 +66,8 @@ export interface FlowUIContextValue {
66
66
  * between animation anchors, navigable via arrow keys. */
67
67
  presentation: PresentationState | null;
68
68
  setPresentation: (p: PresentationState | null) => void;
69
+ /** When true, all editing affordances are suppressed (read-only preview). */
70
+ readOnly: boolean;
69
71
  }
70
72
  export interface PresentationState {
71
73
  /** Index into the anchor sequence (0-based). */
@@ -85,6 +87,9 @@ export interface FlowUIProviderProps {
85
87
  showGrid?: boolean;
86
88
  gridSize?: number;
87
89
  showAI?: boolean;
90
+ /** Suppresses context menu, inline text editing and palette placement.
91
+ * Document mutations are additionally blocked in `Flow` (single choke point). */
92
+ readOnly?: boolean;
88
93
  children: React.ReactNode;
89
94
  }
90
- export declare function FlowUIProvider({ showMiniMap: initMiniMap, showGrid: initGrid, gridSize: initGridSize, showAI: initShowAI, children }: FlowUIProviderProps): React.JSX.Element;
95
+ export declare function FlowUIProvider({ showMiniMap: initMiniMap, showGrid: initGrid, gridSize: initGridSize, showAI: initShowAI, readOnly, children }: FlowUIProviderProps): React.JSX.Element;
@@ -1,110 +1,118 @@
1
- import { createContext as ae, useCallback as o, useContext as le, useMemo as we, useRef as i, useState as e } from "react";
2
- import { jsx as de } from "react/jsx-runtime";
3
- var G = ae(null);
4
- function fe() {
5
- const n = le(G);
6
- if (!n) throw new Error("useFlowUI must be used within FlowUIProvider");
7
- return n;
1
+ import { createContext as lt, useCallback as o, useContext as gt, useMemo as ft, useRef as w, useState as t } from "react";
2
+ import { jsx as pt } from "react/jsx-runtime";
3
+ var b = lt(null);
4
+ function mt() {
5
+ const c = gt(b);
6
+ if (!c) throw new Error("useFlowUI must be used within FlowUIProvider");
7
+ return c;
8
8
  }
9
- function Se({ showMiniMap: n = !0, showGrid: b = !0, gridSize: y = 20, showAI: E = !0, children: V }) {
10
- const [a, J] = e("select"), [l, j] = e("smoothstep"), [w, d] = e({
9
+ function xt({ showMiniMap: c = !0, showGrid: V = !0, gridSize: J = 20, showAI: j = !0, readOnly: s = !1, children: k }) {
10
+ const [a, q] = t("select"), [d, B] = t("smoothstep"), [h, l] = t({
11
11
  x: 0,
12
12
  y: 0,
13
13
  zoom: 1
14
- }), h = i(0), k = o((t) => {
15
- h.current += 1, d(t);
16
- }, []), q = o((t) => {
17
- d(t);
18
- }, []), [g, B] = e(!1), [p, H] = e(null), r = i(0), [c, f] = e(!1), S = o(() => {
19
- r.current += 1, c || f(!0);
20
- }, [c]), I = o(() => {
21
- r.current = Math.max(0, r.current - 1), r.current === 0 && f(!1);
22
- }, []), [M, K] = e(!0), [m, L] = e(!0), [x, Q] = e(!0), [P, W] = e(!0), [R, X] = e(E), [F, Y] = e(n), [v, Z] = e(b), [A, _] = e(!0), [C, $] = e(y), [D, ee] = e(null), [N, te] = e(null), [O, oe] = e(null), [T, se] = e(/* @__PURE__ */ new Set()), U = o((t) => {
23
- se((u) => {
24
- const s = new Set(u);
25
- return s.has(t) ? s.delete(t) : s.add(t), s;
14
+ }), g = w(0), H = o((e) => {
15
+ g.current += 1, l(e);
16
+ }, []), K = o((e) => {
17
+ l(e);
18
+ }, []), [f, L] = t(!1), [p, Q] = t(null), W = o((e) => {
19
+ s || Q(e);
20
+ }, [s]), r = w(0), [i, S] = t(!1), I = o(() => {
21
+ r.current += 1, i || S(!0);
22
+ }, [i]), M = o(() => {
23
+ r.current = Math.max(0, r.current - 1), r.current === 0 && S(!1);
24
+ }, []), [m, X] = t(!0), [x, Y] = t(!0), [R, Z] = t(!0), [P, _] = t(!0), [F, $] = t(j), [v, O] = t(c), [C, y] = t(V), [N, tt] = t(!0), [A, et] = t(J), [D, ot] = t(null), [T, st] = t(null), nt = o((e) => {
25
+ s || ot(e);
26
+ }, [s]), ct = o((e) => {
27
+ s || st(e);
28
+ }, [s]), [U, rt] = t(null), [z, it] = t(/* @__PURE__ */ new Set()), E = o((e) => {
29
+ it((u) => {
30
+ const n = new Set(u);
31
+ return n.has(e) ? n.delete(e) : n.add(e), n;
26
32
  });
27
- }, []), z = i(() => {
28
- }), ne = o((t, u, s, ue, ie) => {
29
- z.current(t, u, s, ue, ie);
30
- }, []), re = o((t) => {
31
- z.current = t;
32
- }, []), ce = we(() => ({
33
+ }, []), G = w(() => {
34
+ }), ut = o((e, u, n, dt, ht) => {
35
+ G.current(e, u, n, dt, ht);
36
+ }, []), wt = o((e) => {
37
+ G.current = e;
38
+ }, []), at = ft(() => ({
33
39
  toolMode: a,
34
- setToolMode: J,
35
- edgeType: l,
36
- setEdgeType: j,
37
- viewport: w,
38
- setViewport: k,
39
- setViewportInternal: q,
40
- viewportReqRef: h,
41
- focusOnRect: ne,
42
- setFocusOnRect: re,
43
- autoFocus: g,
44
- setAutoFocus: B,
40
+ setToolMode: q,
41
+ edgeType: d,
42
+ setEdgeType: B,
43
+ viewport: h,
44
+ setViewport: H,
45
+ setViewportInternal: K,
46
+ viewportReqRef: g,
47
+ focusOnRect: ut,
48
+ setFocusOnRect: wt,
49
+ autoFocus: f,
50
+ setAutoFocus: L,
45
51
  editingNodeId: p,
46
- setEditingNodeId: H,
47
- isNodeDragging: c,
48
- beginNodeDrag: S,
49
- endNodeDrag: I,
50
- showPalette: M,
51
- setShowPalette: K,
52
- showInspector: m,
53
- setShowInspector: L,
54
- showOutline: x,
55
- setShowOutline: Q,
52
+ setEditingNodeId: W,
53
+ isNodeDragging: i,
54
+ beginNodeDrag: I,
55
+ endNodeDrag: M,
56
+ showPalette: m,
57
+ setShowPalette: X,
58
+ showInspector: x,
59
+ setShowInspector: Y,
60
+ showOutline: R,
61
+ setShowOutline: Z,
56
62
  showJson: P,
57
- setShowJson: W,
58
- showAI: R,
59
- setShowAI: X,
60
- showMiniMap: F,
61
- setShowMiniMap: Y,
62
- showGrid: v,
63
- setShowGrid: Z,
64
- showAnchors: A,
65
- setShowAnchors: _,
66
- gridSize: C,
67
- setGridSize: $,
63
+ setShowJson: _,
64
+ showAI: F,
65
+ setShowAI: $,
66
+ showMiniMap: v,
67
+ setShowMiniMap: O,
68
+ showGrid: C,
69
+ setShowGrid: y,
70
+ showAnchors: N,
71
+ setShowAnchors: tt,
72
+ gridSize: A,
73
+ setGridSize: et,
68
74
  pendingPlacement: D,
69
- setPendingPlacement: ee,
70
- contextMenu: N,
71
- setContextMenu: te,
72
- presentation: O,
73
- setPresentation: oe,
74
- detachedTabs: T,
75
- toggleDetach: U
75
+ setPendingPlacement: nt,
76
+ contextMenu: T,
77
+ setContextMenu: ct,
78
+ presentation: U,
79
+ setPresentation: rt,
80
+ detachedTabs: z,
81
+ toggleDetach: E,
82
+ readOnly: s
76
83
  }), [
77
84
  a,
78
- l,
79
- w,
80
- g,
85
+ d,
86
+ h,
87
+ f,
81
88
  p,
82
- c,
83
- S,
89
+ i,
84
90
  I,
85
91
  M,
86
92
  m,
87
93
  x,
88
- P,
89
94
  R,
95
+ P,
90
96
  F,
91
97
  v,
92
- A,
93
98
  C,
94
- D,
95
99
  N,
96
- O,
100
+ A,
101
+ D,
97
102
  T,
98
- U
103
+ U,
104
+ z,
105
+ E,
106
+ s
99
107
  ]);
100
- return /* @__PURE__ */ de(G.Provider, {
101
- value: ce,
102
- children: V
108
+ return /* @__PURE__ */ pt(b.Provider, {
109
+ value: at,
110
+ children: k
103
111
  });
104
112
  }
105
113
  export {
106
- Se as FlowUIProvider,
107
- fe as useFlowUI
114
+ xt as FlowUIProvider,
115
+ mt as useFlowUI
108
116
  };
109
117
 
110
118
  //# sourceMappingURL=FlowUIContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FlowUIContext.js","names":[],"sources":["../../../../../src/components/pro/Flow/context/FlowUIContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo, useState, useRef, useCallback } from 'react';\nimport type { FlowToolMode, FlowEdgeTypeName, FlowShapeType, FlowNodeData, ViewportState } from '../types';\n\nexport interface ContextMenuState {\n x: number;\n y: number;\n nodeId: string | null;\n}\n\nexport interface FocusOnRectOptions {\n /** Screen-space padding around the focused rectangle, in pixels. */\n padding?: number;\n /** Maximum zoom allowed for this focus operation. */\n maxZoom?: number;\n /** Viewport transition duration in milliseconds. */\n duration?: number;\n /** Keep the current zoom and only animate the focused rectangle to center. */\n preserveZoom?: boolean;\n}\n\nexport interface FlowUIContextValue {\n toolMode: FlowToolMode;\n setToolMode: (mode: FlowToolMode) => void;\n edgeType: FlowEdgeTypeName;\n setEdgeType: (type: FlowEdgeTypeName) => void;\n viewport: ViewportState;\n setViewport: (v: ViewportState) => void;\n /** Internal VM→React bridge setter (does not request a VM apply). */\n setViewportInternal: (v: ViewportState) => void;\n /** Monotonic counter of external viewport commands. */\n viewportReqRef: React.MutableRefObject<number>;\n focusOnRect: (wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void;\n setFocusOnRect: (fn: (wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void) => void;\n autoFocus: boolean;\n setAutoFocus: (v: boolean) => void;\n editingNodeId: string | null;\n setEditingNodeId: (id: string | null) => void;\n /** True while any node/line is being dragged. Used to suppress interactive\n * DOM overlays (e.g. HTML iframes) that would otherwise swallow pointerup. */\n isNodeDragging: boolean;\n beginNodeDrag: () => void;\n endNodeDrag: () => void;\n showPalette: boolean;\n setShowPalette: (v: boolean) => void;\n showInspector: boolean;\n setShowInspector: (v: boolean) => void;\n showOutline: boolean;\n setShowOutline: (v: boolean) => void;\n showJson: boolean;\n setShowJson: (v: boolean) => void;\n showAI: boolean;\n setShowAI: (v: boolean) => void;\n showMiniMap: boolean;\n setShowMiniMap: (v: boolean) => void;\n showGrid: boolean;\n setShowGrid: (v: boolean) => void;\n /** Global editor-only visibility for animation anchor objects. */\n showAnchors: boolean;\n setShowAnchors: (v: boolean) => void;\n gridSize: number;\n setGridSize: (s: number) => void;\n pendingPlacement: PendingPlacement | null;\n setPendingPlacement: (p: PendingPlacement | null) => void;\n contextMenu: ContextMenuState | null;\n setContextMenu: (m: ContextMenuState | null) => void;\n detachedTabs: Set<string>;\n toggleDetach: (tabId: string) => void;\n /** PPT-style presentation mode. When set, the overlay animates the viewport\n * between animation anchors, navigable via arrow keys. */\n presentation: PresentationState | null;\n setPresentation: (p: PresentationState | null) => void;\n}\n\nexport interface PresentationState {\n /** Index into the anchor sequence (0-based). */\n current: number;\n /** Whether to show the active anchor frame and sequence badge in preview. */\n showAnchor?: boolean;\n}\n\nexport interface PendingPlacement {\n type: FlowShapeType;\n width: number;\n height: number;\n data: FlowNodeData;\n}\n\nconst FlowUIContext = createContext<FlowUIContextValue | null>(null);\n\nexport function useFlowUI(): FlowUIContextValue {\n const ctx = useContext(FlowUIContext);\n if (!ctx) throw new Error('useFlowUI must be used within FlowUIProvider');\n return ctx;\n}\n\nexport interface FlowUIProviderProps {\n showMiniMap?: boolean;\n showGrid?: boolean;\n gridSize?: number;\n showAI?: boolean;\n children: React.ReactNode;\n}\n\nexport function FlowUIProvider({ showMiniMap: initMiniMap = true, showGrid: initGrid = true, gridSize: initGridSize = 20, showAI: initShowAI = true, children }: FlowUIProviderProps) {\n const [toolMode, setToolMode] = useState<FlowToolMode>('select');\n const [edgeType, setEdgeType] = useState<FlowEdgeTypeName>('smoothstep');\n const [viewport, setViewportState] = useState<ViewportState>({ x: 0, y: 0, zoom: 1 });\n // Distinguishes EXTERNAL viewport commands (toolbar, minimap, outline) from\n // internal echoes emitted by the ViewportManager. Only external commands\n // should be pushed back into the VM; echoing VM changes causes jitter.\n const viewportReqRef = useRef(0);\n const setViewport = useCallback((v: ViewportState) => {\n viewportReqRef.current += 1;\n setViewportState(v);\n }, []);\n // Internal setter used by the VM→React bridge; does NOT bump the request\n // counter, so the sync effect will not echo it back to the VM.\n const setViewportInternal = useCallback((v: ViewportState) => {\n setViewportState(v);\n }, []);\n const [autoFocus, setAutoFocus] = useState(false);\n const [editingNodeId, setEditingNodeId] = useState<string | null>(null);\n // Counter so concurrent drags (multi-node) don't flip the flag early.\n const dragCountRef = useRef(0);\n const [isNodeDragging, setIsNodeDragging] = useState(false);\n const beginNodeDrag = useCallback(() => {\n dragCountRef.current += 1;\n if (!isNodeDragging) setIsNodeDragging(true);\n }, [isNodeDragging]);\n const endNodeDrag = useCallback(() => {\n dragCountRef.current = Math.max(0, dragCountRef.current - 1);\n if (dragCountRef.current === 0) setIsNodeDragging(false);\n }, []);\n const [showPalette, setShowPalette] = useState(true);\n const [showInspector, setShowInspector] = useState(true);\n const [showOutline, setShowOutline] = useState(true);\n const [showJson, setShowJson] = useState(true);\n const [showAI, setShowAI] = useState(initShowAI);\n const [showMiniMap, setShowMiniMap] = useState(initMiniMap);\n const [showGrid, setShowGrid] = useState(initGrid);\n const [showAnchors, setShowAnchors] = useState(true);\n const [gridSize, setGridSize] = useState(initGridSize);\n const [pendingPlacement, setPendingPlacement] = useState<PendingPlacement | null>(null);\n const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);\n const [presentation, setPresentation] = useState<PresentationState | null>(null);\n const [detachedTabs, setDetachedTabs] = useState<Set<string>>(new Set());\n const toggleDetach = useCallback((tabId: string) => {\n setDetachedTabs(prev => {\n const next = new Set(prev);\n if (next.has(tabId)) next.delete(tabId); else next.add(tabId);\n return next;\n });\n }, []);\n\n const focusOnRectRef = useRef<(wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void>(() => {});\n const focusOnRect = useCallback((wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => {\n focusOnRectRef.current(wx, wy, ww, wh, options);\n }, []);\n const setFocusOnRect = useCallback((fn: (wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void) => {\n focusOnRectRef.current = fn;\n }, []);\n\n const value = useMemo<FlowUIContextValue>(() => ({\n toolMode, setToolMode,\n edgeType, setEdgeType,\n viewport, setViewport,\n setViewportInternal,\n viewportReqRef,\n focusOnRect, setFocusOnRect,\n autoFocus, setAutoFocus,\n editingNodeId, setEditingNodeId,\n isNodeDragging, beginNodeDrag, endNodeDrag,\n showPalette, setShowPalette,\n showInspector, setShowInspector,\n showOutline, setShowOutline,\n showJson, setShowJson,\n showAI, setShowAI,\n showMiniMap, setShowMiniMap,\n showGrid, setShowGrid,\n showAnchors, setShowAnchors,\n gridSize, setGridSize,\n pendingPlacement, setPendingPlacement,\n contextMenu, setContextMenu,\n presentation, setPresentation,\n detachedTabs, toggleDetach,\n }), [toolMode, edgeType, viewport, autoFocus, editingNodeId, isNodeDragging, beginNodeDrag, endNodeDrag, showPalette, showInspector, showOutline, showJson, showAI, showMiniMap, showGrid, showAnchors, gridSize, pendingPlacement, contextMenu, presentation, detachedTabs, toggleDetach]);\n\n return <FlowUIContext.Provider value={value}>{children}</FlowUIContext.Provider>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FlowUIContext.js","names":[],"sources":["../../../../../src/components/pro/Flow/context/FlowUIContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo, useState, useRef, useCallback } from 'react';\nimport type { FlowToolMode, FlowEdgeTypeName, FlowShapeType, FlowNodeData, ViewportState } from '../types';\n\nexport interface ContextMenuState {\n x: number;\n y: number;\n nodeId: string | null;\n}\n\nexport interface FocusOnRectOptions {\n /** Screen-space padding around the focused rectangle, in pixels. */\n padding?: number;\n /** Maximum zoom allowed for this focus operation. */\n maxZoom?: number;\n /** Viewport transition duration in milliseconds. */\n duration?: number;\n /** Keep the current zoom and only animate the focused rectangle to center. */\n preserveZoom?: boolean;\n}\n\nexport interface FlowUIContextValue {\n toolMode: FlowToolMode;\n setToolMode: (mode: FlowToolMode) => void;\n edgeType: FlowEdgeTypeName;\n setEdgeType: (type: FlowEdgeTypeName) => void;\n viewport: ViewportState;\n setViewport: (v: ViewportState) => void;\n /** Internal VM→React bridge setter (does not request a VM apply). */\n setViewportInternal: (v: ViewportState) => void;\n /** Monotonic counter of external viewport commands. */\n viewportReqRef: React.MutableRefObject<number>;\n focusOnRect: (wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void;\n setFocusOnRect: (fn: (wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void) => void;\n autoFocus: boolean;\n setAutoFocus: (v: boolean) => void;\n editingNodeId: string | null;\n setEditingNodeId: (id: string | null) => void;\n /** True while any node/line is being dragged. Used to suppress interactive\n * DOM overlays (e.g. HTML iframes) that would otherwise swallow pointerup. */\n isNodeDragging: boolean;\n beginNodeDrag: () => void;\n endNodeDrag: () => void;\n showPalette: boolean;\n setShowPalette: (v: boolean) => void;\n showInspector: boolean;\n setShowInspector: (v: boolean) => void;\n showOutline: boolean;\n setShowOutline: (v: boolean) => void;\n showJson: boolean;\n setShowJson: (v: boolean) => void;\n showAI: boolean;\n setShowAI: (v: boolean) => void;\n showMiniMap: boolean;\n setShowMiniMap: (v: boolean) => void;\n showGrid: boolean;\n setShowGrid: (v: boolean) => void;\n /** Global editor-only visibility for animation anchor objects. */\n showAnchors: boolean;\n setShowAnchors: (v: boolean) => void;\n gridSize: number;\n setGridSize: (s: number) => void;\n pendingPlacement: PendingPlacement | null;\n setPendingPlacement: (p: PendingPlacement | null) => void;\n contextMenu: ContextMenuState | null;\n setContextMenu: (m: ContextMenuState | null) => void;\n detachedTabs: Set<string>;\n toggleDetach: (tabId: string) => void;\n /** PPT-style presentation mode. When set, the overlay animates the viewport\n * between animation anchors, navigable via arrow keys. */\n presentation: PresentationState | null;\n setPresentation: (p: PresentationState | null) => void;\n /** When true, all editing affordances are suppressed (read-only preview). */\n readOnly: boolean;\n}\n\nexport interface PresentationState {\n /** Index into the anchor sequence (0-based). */\n current: number;\n /** Whether to show the active anchor frame and sequence badge in preview. */\n showAnchor?: boolean;\n}\n\nexport interface PendingPlacement {\n type: FlowShapeType;\n width: number;\n height: number;\n data: FlowNodeData;\n}\n\nconst FlowUIContext = createContext<FlowUIContextValue | null>(null);\n\nexport function useFlowUI(): FlowUIContextValue {\n const ctx = useContext(FlowUIContext);\n if (!ctx) throw new Error('useFlowUI must be used within FlowUIProvider');\n return ctx;\n}\n\nexport interface FlowUIProviderProps {\n showMiniMap?: boolean;\n showGrid?: boolean;\n gridSize?: number;\n showAI?: boolean;\n /** Suppresses context menu, inline text editing and palette placement.\n * Document mutations are additionally blocked in `Flow` (single choke point). */\n readOnly?: boolean;\n children: React.ReactNode;\n}\n\nexport function FlowUIProvider({ showMiniMap: initMiniMap = true, showGrid: initGrid = true, gridSize: initGridSize = 20, showAI: initShowAI = true, readOnly = false, children }: FlowUIProviderProps) {\n const [toolMode, setToolMode] = useState<FlowToolMode>('select');\n const [edgeType, setEdgeType] = useState<FlowEdgeTypeName>('smoothstep');\n const [viewport, setViewportState] = useState<ViewportState>({ x: 0, y: 0, zoom: 1 });\n // Distinguishes EXTERNAL viewport commands (toolbar, minimap, outline) from\n // internal echoes emitted by the ViewportManager. Only external commands\n // should be pushed back into the VM; echoing VM changes causes jitter.\n const viewportReqRef = useRef(0);\n const setViewport = useCallback((v: ViewportState) => {\n viewportReqRef.current += 1;\n setViewportState(v);\n }, []);\n // Internal setter used by the VM→React bridge; does NOT bump the request\n // counter, so the sync effect will not echo it back to the VM.\n const setViewportInternal = useCallback((v: ViewportState) => {\n setViewportState(v);\n }, []);\n const [autoFocus, setAutoFocus] = useState(false);\n const [editingNodeId, setEditingNodeIdRaw] = useState<string | null>(null);\n // In read-only mode the inline node/edge text editor must never open.\n const setEditingNodeId = useCallback((id: string | null) => {\n if (readOnly) return;\n setEditingNodeIdRaw(id);\n }, [readOnly]);\n // Counter so concurrent drags (multi-node) don't flip the flag early.\n const dragCountRef = useRef(0);\n const [isNodeDragging, setIsNodeDragging] = useState(false);\n const beginNodeDrag = useCallback(() => {\n dragCountRef.current += 1;\n if (!isNodeDragging) setIsNodeDragging(true);\n }, [isNodeDragging]);\n const endNodeDrag = useCallback(() => {\n dragCountRef.current = Math.max(0, dragCountRef.current - 1);\n if (dragCountRef.current === 0) setIsNodeDragging(false);\n }, []);\n const [showPalette, setShowPalette] = useState(true);\n const [showInspector, setShowInspector] = useState(true);\n const [showOutline, setShowOutline] = useState(true);\n const [showJson, setShowJson] = useState(true);\n const [showAI, setShowAI] = useState(initShowAI);\n const [showMiniMap, setShowMiniMap] = useState(initMiniMap);\n const [showGrid, setShowGrid] = useState(initGrid);\n const [showAnchors, setShowAnchors] = useState(true);\n const [gridSize, setGridSize] = useState(initGridSize);\n const [pendingPlacement, setPendingPlacementRaw] = useState<PendingPlacement | null>(null);\n const [contextMenu, setContextMenuRaw] = useState<ContextMenuState | null>(null);\n // Read-only: palette drops and the right-click menu are editing affordances.\n const setPendingPlacement = useCallback((p: PendingPlacement | null) => {\n if (readOnly) return;\n setPendingPlacementRaw(p);\n }, [readOnly]);\n const setContextMenu = useCallback((m: ContextMenuState | null) => {\n if (readOnly) return;\n setContextMenuRaw(m);\n }, [readOnly]);\n const [presentation, setPresentation] = useState<PresentationState | null>(null);\n const [detachedTabs, setDetachedTabs] = useState<Set<string>>(new Set());\n const toggleDetach = useCallback((tabId: string) => {\n setDetachedTabs(prev => {\n const next = new Set(prev);\n if (next.has(tabId)) next.delete(tabId); else next.add(tabId);\n return next;\n });\n }, []);\n\n const focusOnRectRef = useRef<(wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void>(() => {});\n const focusOnRect = useCallback((wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => {\n focusOnRectRef.current(wx, wy, ww, wh, options);\n }, []);\n const setFocusOnRect = useCallback((fn: (wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => void) => {\n focusOnRectRef.current = fn;\n }, []);\n\n const value = useMemo<FlowUIContextValue>(() => ({\n toolMode, setToolMode,\n edgeType, setEdgeType,\n viewport, setViewport,\n setViewportInternal,\n viewportReqRef,\n focusOnRect, setFocusOnRect,\n autoFocus, setAutoFocus,\n editingNodeId, setEditingNodeId,\n isNodeDragging, beginNodeDrag, endNodeDrag,\n showPalette, setShowPalette,\n showInspector, setShowInspector,\n showOutline, setShowOutline,\n showJson, setShowJson,\n showAI, setShowAI,\n showMiniMap, setShowMiniMap,\n showGrid, setShowGrid,\n showAnchors, setShowAnchors,\n gridSize, setGridSize,\n pendingPlacement, setPendingPlacement,\n contextMenu, setContextMenu,\n presentation, setPresentation,\n detachedTabs, toggleDetach,\n readOnly,\n }), [toolMode, edgeType, viewport, autoFocus, editingNodeId, isNodeDragging, beginNodeDrag, endNodeDrag, showPalette, showInspector, showOutline, showJson, showAI, showMiniMap, showGrid, showAnchors, gridSize, pendingPlacement, contextMenu, presentation, detachedTabs, toggleDetach, readOnly]);\n\n return <FlowUIContext.Provider value={value}>{children}</FlowUIContext.Provider>;\n}\n"],"mappings":"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"}
@@ -283,6 +283,11 @@ var e = {
283
283
  id: "flow",
284
284
  label: "流程图编辑器 Flow",
285
285
  path: "/components/flow"
286
+ },
287
+ flowUsage: {
288
+ id: "flow-usage",
289
+ label: "Flow 使用示例",
290
+ path: "/components/flow/usage"
286
291
  }
287
292
  }
288
293
  }
@@ -572,6 +577,11 @@ var e = {
572
577
  id: "flow",
573
578
  label: "Flow Editor",
574
579
  path: "/components/flow"
580
+ },
581
+ flowUsage: {
582
+ id: "flow-usage",
583
+ label: "Flow Usage Guide",
584
+ path: "/components/flow/usage"
575
585
  }
576
586
  }
577
587
  }