dishui 0.0.69 → 0.0.72

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.
@@ -342,11 +342,11 @@ function oe({ pixiRef: e, exportPdfRef: t }) {
342
342
  return t.current = j(e), null;
343
343
  }
344
344
  var U = P(function({ initialDocument: e, onChange: t, width: n, height: r, readOnly: o = !1, onBack: c, onExportPNG: u, onPublish: d, showMiniMap: f = !0, showGrid: v = !0, gridSize: y = 20, className: b, showAI: x = !0, showAIConfig: S = !0, aiConfig: C }, E) {
345
- let [O, A] = z(() => re(e ?? i())), [j, M] = z(ie), N = R(null), P = R(null), L = R(null), H = R(null), U = te(H), { wrappedSetDoc: W, undo: G, redo: K, canUndo: q, canRedo: J } = ee(O, A), Y = R(null), X = R(null), Z = R(null), Q = R(null), de = R(t);
346
- de.current = t;
347
- let fe = R(O);
345
+ let [O, A] = z(() => re(e ?? i())), [j, M] = z(ie), N = R(null), P = R(null), L = R(null), H = R(null), U = te(H), { wrappedSetDoc: W, setDocTransient: G, undo: K, redo: q, canUndo: J, canRedo: Y } = ee(O, A), X = R(null), Z = R(null), Q = R(null), de = R(null), fe = R(t);
346
+ fe.current = t;
347
+ let pe = R(O);
348
348
  I(() => {
349
- fe.current !== O && (fe.current = O, o || de.current?.(O));
349
+ pe.current !== O && (pe.current = O, o || fe.current?.(O));
350
350
  }, [O, o]);
351
351
  let $ = R(O);
352
352
  $.current = O, ne(E, () => ({
@@ -356,25 +356,30 @@ var U = P(function({ initialDocument: e, onChange: t, width: n, height: r, readO
356
356
  },
357
357
  getDocument: () => $.current
358
358
  }), []);
359
- let pe = F((e) => {
359
+ let me = F((e) => {
360
360
  W((t) => {
361
361
  let n = typeof e == "function" ? e(t) : e;
362
362
  return o ? n.canvases === t.canvases && n.title === t.title ? n : t : n;
363
363
  });
364
- }, [W, o]), me = F(() => {
365
- o || G();
366
- }, [o, G]), he = F(() => {
364
+ }, [W, o]), he = F((e) => {
365
+ G((t) => {
366
+ let n = typeof e == "function" ? e(t) : e;
367
+ return o ? n.canvases === t.canvases && n.title === t.title ? n : t : n;
368
+ });
369
+ }, [G, o]), ge = F(() => {
367
370
  o || K();
368
- }, [o, K]), ge = F((e) => {
371
+ }, [o, K]), _e = F(() => {
372
+ o || q();
373
+ }, [o, q]), ve = F((e) => {
369
374
  N.current = e, P.current && !L.current && (L.current = new k(P.current));
370
- }, []), _e = F(async () => {
375
+ }, []), ye = F(async () => {
371
376
  if (u) return void u();
372
377
  let e = N.current;
373
378
  if (!e || e.destroyed) return;
374
379
  let t = await e.exportPNG(16777215);
375
380
  t && m(t, `${h($.current.title)}.png`);
376
- }, [u]), ve = F(async () => {
377
- await Q.current?.();
381
+ }, [u]), be = F(async () => {
382
+ await de.current?.();
378
383
  }, []);
379
384
  I(() => {
380
385
  let e = !1, t = null, n = () => {
@@ -395,17 +400,18 @@ var U = P(function({ initialDocument: e, onChange: t, width: n, height: r, readO
395
400
  e = !0, t && !t.destroyed && t.app.ticker.remove(n);
396
401
  };
397
402
  }, [O]);
398
- let ye = {
403
+ let xe = {
399
404
  width: n ?? "100%",
400
405
  height: r ?? "100%"
401
406
  };
402
407
  return /* @__PURE__ */ B("div", {
403
408
  ref: H,
404
409
  className: `flow-container ${b ?? ""}`,
405
- style: ye,
410
+ style: xe,
406
411
  children: /* @__PURE__ */ B(a, {
407
412
  doc: O,
408
- setDoc: pe,
413
+ setDoc: me,
414
+ setDocTransient: he,
409
415
  selection: j,
410
416
  setSelection: M,
411
417
  children: /* @__PURE__ */ B(s, {
@@ -419,34 +425,34 @@ var U = P(function({ initialDocument: e, onChange: t, width: n, height: r, readO
419
425
  showAIConfig: S,
420
426
  children: [
421
427
  /* @__PURE__ */ B(ae, {
422
- onUndo: me,
423
- onRedo: he,
424
- groupRef: Y,
425
- geoGroupRef: X,
426
- ungroupRef: Z
428
+ onUndo: ge,
429
+ onRedo: _e,
430
+ groupRef: X,
431
+ geoGroupRef: Z,
432
+ ungroupRef: Q
427
433
  }),
428
434
  /* @__PURE__ */ B(oe, {
429
435
  pixiRef: N,
430
- exportPdfRef: Q
436
+ exportPdfRef: de
431
437
  }),
432
438
  /* @__PURE__ */ V(ce, {
433
439
  compact: U,
434
440
  toolbar: o ? null : /* @__PURE__ */ B(g, {
435
441
  compact: U,
436
442
  onBack: c,
437
- onUndo: me,
438
- onRedo: he,
439
- canUndo: q,
440
- canRedo: J,
441
- onGroup: () => Y.current?.(),
442
- onGeoGroup: () => X.current?.(),
443
- onUngroup: () => Z.current?.(),
444
- onExportPNG: _e,
445
- onExportPDF: ve,
443
+ onUndo: ge,
444
+ onRedo: _e,
445
+ canUndo: J,
446
+ canRedo: Y,
447
+ onGroup: () => X.current?.(),
448
+ onGeoGroup: () => Z.current?.(),
449
+ onUngroup: () => Q.current?.(),
450
+ onExportPNG: ye,
451
+ onExportPDF: be,
446
452
  onPublish: d
447
453
  }),
448
454
  children: [
449
- /* @__PURE__ */ B(p, { onPixiReady: ge }),
455
+ /* @__PURE__ */ B(p, { onPixiReady: ve }),
450
456
  /* @__PURE__ */ B(T, {}),
451
457
  /* @__PURE__ */ V(se, { children: [!o && /* @__PURE__ */ B(_, {}), /* @__PURE__ */ B(D, {})] }),
452
458
  !o && /* @__PURE__ */ B(ue, {}),
@@ -1 +1 @@
1
- {"version":3,"file":"Flow.js","names":[],"sources":["../../../../src/components/pro/Flow/Flow.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';\nimport { FlowProvider, useFlowContext } from './context/FlowContext';\nimport { FlowUIProvider, useFlowUI } from './context/FlowUIContext';\nimport { FlowAIProvider } from './context/FlowAIContext';\nimport FlowCanvas from './FlowCanvas';\nimport FlowToolbar, { FlowZoomControls } from './panels/FlowToolbar';\nimport { ShapePaletteContent, SvgStampContent, MediaStampContent } from './panels/ShapePalette';\nimport { InspectorPanelContent } from './panels/InspectorPanel';\nimport { OutlinePanelContent } from './panels/OutlinePanel';\nimport { AIPanelContent } from './panels/AIPanel';\nimport { PresentationMode } from './panels/PresentationMode';\nimport { MediaOverlay } from './nodes/MediaOverlay';\nimport FlowPanelGroup, { type PanelTab } from './panels/FlowPanelGroup';\nimport type { FlowPanelDock } from './context/FlowUIContext';\nimport Breadcrumb from './panels/Breadcrumb';\nimport ContextMenu from './panels/ContextMenu';\nimport type { ContextMenuItem } from './panels/ContextMenu';\nimport Select from '../../Select';\nimport { MiniMapRenderer } from './canvas/MiniMapRenderer';\nimport { CodeEditor, type CodeEditorHandle } from '../CodeEditor';\nimport { EditorView } from '@codemirror/view';\nimport { useUndoRedo } from './hooks/useUndoRedo';\nimport { useClipboard } from './hooks/useClipboard';\nimport { useCompactMode } from './hooks/useCompactMode';\nimport { downloadDataURL, safeFileBaseName } from './hooks/useFlowImportExport';\nimport { usePdfExport } from './hooks/usePdfExport';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useMindMap } from './hooks/useMindMap';\nimport { useDeleteSelection } from './hooks/useDeleteSelection';\nimport { createEmptyDocument, ROOT_CANVAS_ID, DEFAULT_NODE_DATA } from './constants';\nimport { normalizeEdgeHandles } from './edges/edgePaths';\nimport { generateId } from './nodes/nodeUtils';\nimport type { FlowProps, FlowDocument, FlowNode, SelectionState, FlowCanvasData } from './types';\nimport type { PixiApp } from './canvas/PixiApp';\nimport './styles.css';\n\nfunction normalizeDocument(doc: FlowDocument): FlowDocument {\n let changed = false;\n const canvases = { ...doc.canvases };\n for (const [id, canvas] of Object.entries(canvases)) {\n const nodes = canvas.nodes.map(node => {\n if (node.type !== 'shapeSvg') return node;\n const legacyPlacement = node.data.labelPlacement as string | undefined;\n const labelPlacement = legacyPlacement === 'above'\n ? 'top'\n : legacyPlacement === 'center'\n ? 'middle'\n : legacyPlacement === 'below'\n ? 'bottom'\n : node.data.labelPlacement;\n if (labelPlacement === node.data.labelPlacement) return node;\n changed = true;\n return { ...node, data: { ...node.data, labelPlacement } };\n });\n // Mindmap nodes/edges created before theme tokens (≤ 0.0.56) persisted\n // literal colors, so they never followed theme switches. That exact palette\n // was only ever emitted by the old mindmap creator, so remap it to the same\n // tokens the current creator uses.\n let themedNodesChanged = false;\n const themedNodes = nodes.map(node => {\n if (!node.data.isMindMapNode) return node;\n const fill = node.data.fill === '#ffffff' || node.data.fill === '#eef2ff'\n ? 'theme:base-100'\n : node.data.fill;\n const stroke = node.data.stroke === '#6366f1'\n ? 'theme:base-content'\n : node.data.stroke === '#4f46e5'\n ? 'theme:primary'\n : node.data.stroke;\n if (fill === node.data.fill && stroke === node.data.stroke) return node;\n themedNodesChanged = true;\n return { ...node, data: { ...node.data, fill, stroke } };\n });\n const nodeMap = new Map<string, FlowNode>();\n for (const node of themedNodes) nodeMap.set(node.id, node);\n let edgesChanged = false;\n const edges = normalizeEdgeHandles(canvas.edges, nodeMap).map(edge => {\n if (edge.data.strokeColor !== '#94a3b8') return edge;\n const source = nodeMap.get(edge.source);\n const target = nodeMap.get(edge.target);\n if (!source?.data.isMindMapNode || !target?.data.isMindMapNode) return edge;\n edgesChanged = true;\n return { ...edge, data: { ...edge.data, strokeColor: 'theme:base-content' } };\n });\n if (themedNodesChanged || edgesChanged) changed = true;\n if (themedNodes !== nodes || edges !== canvas.edges) {\n canvases[id] = { ...canvas, nodes: themedNodes, edges };\n }\n }\n return changed ? { ...doc, canvases } : doc;\n}\n\nconst EMPTY_SELECTION: SelectionState = {\n nodeIds: new Set(),\n edgeIds: new Set(),\n lineIds: new Set(),\n};\n\nfunction FlowKeyboardShortcutsWire({ onUndo, onRedo, groupRef, geoGroupRef, ungroupRef }: {\n onUndo: () => void;\n onRedo: () => void;\n groupRef: React.MutableRefObject<(() => void) | null>;\n geoGroupRef: React.MutableRefObject<(() => void) | null>;\n ungroupRef: React.MutableRefObject<(() => void) | null>;\n}) {\n const { selection, setSelection, currentCanvas, setDoc, currentCanvasId } = useFlowContext();\n const { viewport } = useFlowUI();\n const { copy, cut, paste, duplicate } = useClipboard();\n const deleteSelected = useDeleteSelection();\n\n const selectAll = useCallback(() => {\n setSelection({\n nodeIds: new Set(currentCanvas.nodes.map(n => n.id)),\n edgeIds: new Set(currentCanvas.edges.map(e => e.id)),\n lineIds: new Set(currentCanvas.lines.map(l => l.id)),\n });\n }, [currentCanvas, setSelection]);\n\n const createGroup = useCallback((type: 'flowGroup' | 'geometryGroup') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n const totalCount = nodeIds.size + lineIds.size;\n if (totalCount < 2) return;\n const nodes = currentCanvas.nodes.filter(n => nodeIds.has(n.id));\n const lines = currentCanvas.lines.filter(l => lineIds.has(l.id));\n const PAD = 20;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n minX = Math.min(minX, n.position.x);\n minY = Math.min(minY, n.position.y);\n maxX = Math.max(maxX, n.position.x + n.width);\n maxY = Math.max(maxY, n.position.y + n.height);\n }\n for (const l of lines) {\n for (const p of l.points) {\n minX = Math.min(minX, p.x); minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x); maxY = Math.max(maxY, p.y);\n }\n }\n const isGeo = type === 'geometryGroup';\n const groupId = generateId('group');\n const groupNode: FlowNode = {\n id: groupId,\n type,\n position: { x: minX - PAD, y: minY - PAD },\n width: maxX - minX + PAD * 2,\n height: maxY - minY + PAD * 2,\n data: {\n ...DEFAULT_NODE_DATA,\n label: isGeo ? 'Geo Group' : 'Group',\n fill: isGeo ? '#fefce8' : '#f0f9ff',\n stroke: '#9ca3af', strokeWidth: 1.5,\n borderStyle: isGeo ? 'dashed' : 'dotted',\n isGroup: true,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: isGeo\n ? [groupNode, ...canvas.nodes]\n : [groupNode, ...canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, parentId: groupId } : n)],\n lines: isGeo\n ? canvas.lines\n : canvas.lines.map(l => lineIds.has(l.id) ? { ...l, parentId: groupId } : l),\n }},\n };\n });\n setSelection({ nodeIds: new Set([groupId]), edgeIds: new Set(), lineIds: new Set() });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n const groupSelected = useCallback(() => createGroup('flowGroup'), [createGroup]);\n const geoGroupSelected = useCallback(() => createGroup('geometryGroup'), [createGroup]);\n\n const ungroupSelected = useCallback(() => {\n const ids = selection.nodeIds;\n if (ids.size === 0) return;\n const groupNodeIds = new Set<string>();\n const childNodeIds = new Set<string>();\n const childLineIds = new Set<string>();\n for (const node of currentCanvas.nodes) {\n if (ids.has(node.id) && (node.type === 'flowGroup' || node.type === 'geometryGroup' || node.data.isGroup)) {\n groupNodeIds.add(node.id);\n }\n }\n if (groupNodeIds.size === 0) return;\n for (const node of currentCanvas.nodes) {\n if (node.parentId && groupNodeIds.has(node.parentId)) {\n childNodeIds.add(node.id);\n }\n }\n for (const line of currentCanvas.lines) {\n if (line.parentId && groupNodeIds.has(line.parentId)) {\n childLineIds.add(line.id);\n }\n }\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes\n .filter(n => !groupNodeIds.has(n.id))\n .map(n => childNodeIds.has(n.id) ? { ...n, parentId: undefined } : n),\n lines: canvas.lines\n .map(l => childLineIds.has(l.id) ? { ...l, parentId: undefined } : l),\n }},\n };\n });\n setSelection({ nodeIds: childNodeIds, edgeIds: new Set(), lineIds: childLineIds });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n groupRef.current = groupSelected;\n geoGroupRef.current = geoGroupSelected;\n ungroupRef.current = ungroupSelected;\n\n const changeZIndex = useCallback((mode: 'front' | 'back' | 'up' | 'down') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n if (nodeIds.size === 0 && lineIds.size === 0) return;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n const nodeAllZ = canvas.nodes.map(n => n.zIndex ?? 0);\n const nodeMaxZ = nodeAllZ.length > 0 ? Math.max(...nodeAllZ) : 0;\n const nodeMinZ = nodeAllZ.length > 0 ? Math.min(...nodeAllZ) : 0;\n const lineAllZ = canvas.lines.map(l => l.zIndex ?? 0);\n const lineMaxZ = lineAllZ.length > 0 ? Math.max(...lineAllZ) : 0;\n const lineMinZ = lineAllZ.length > 0 ? Math.min(...lineAllZ) : 0;\n const applyZ = (z: number, maxZ: number, minZ: number) => {\n if (mode === 'front') return maxZ + 1;\n if (mode === 'back') return minZ - 1;\n if (mode === 'up') return z + 1;\n return z - 1;\n };\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, zIndex: applyZ(n.zIndex ?? 0, nodeMaxZ, nodeMinZ) } : n),\n lines: canvas.lines.map(l => lineIds.has(l.id) ? { ...l, zIndex: applyZ(l.zIndex ?? 0, lineMaxZ, lineMinZ) } : l),\n }},\n };\n });\n }, [selection, setDoc, currentCanvasId]);\n\n useEffect(() => {\n const handlePaste = (event: ClipboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target?.tagName === 'INPUT' || target?.tagName === 'TEXTAREA' || target?.isContentEditable) return;\n\n const imageItem = Array.from(event.clipboardData?.items ?? []).find(item => item.type.startsWith('image/'));\n if (!imageItem) {\n event.preventDefault();\n paste();\n return;\n }\n\n const file = imageItem.getAsFile();\n if (!file) return;\n event.preventDefault();\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result !== 'string') return;\n const selectedImage = selection.nodeIds.size === 1\n ? currentCanvas.nodes.find(node => selection.nodeIds.has(node.id) && node.type === 'mediaNode' && node.data.mediaKind === 'image')\n : undefined;\n\n if (selectedImage) {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(node => node.id === selectedImage.id\n ? { ...node, data: { ...node.data, mediaContent: reader.result as string } }\n : node),\n },\n },\n };\n });\n return;\n }\n\n const id = generateId('node');\n const width = 320;\n const height = 220;\n const screenWidth = window.innerWidth;\n const screenHeight = window.innerHeight;\n const centerX = (screenWidth / 2 - viewport.x) / viewport.zoom;\n const centerY = (screenHeight / 2 - viewport.y) / viewport.zoom;\n const highestZ = Math.max(0, ...currentCanvas.nodes.map(node => node.zIndex ?? 0));\n const imageNode: FlowNode = {\n id,\n type: 'mediaNode',\n position: { x: centerX - width / 2, y: centerY - height / 2 },\n width,\n height,\n zIndex: highestZ + 1,\n data: {\n ...DEFAULT_NODE_DATA,\n label: file.name || 'Image',\n fill: 'theme:base-100',\n stroke: 'theme:base-content',\n strokeWidth: 1.5,\n color: 'theme:base-content',\n fontSize: 13,\n borderStyle: 'solid',\n mediaKind: 'image',\n mediaContent: reader.result,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: { ...canvas, nodes: [...canvas.nodes, imageNode] },\n },\n };\n });\n setSelection({ nodeIds: new Set([id]), edgeIds: new Set(), lineIds: new Set() });\n };\n reader.readAsDataURL(file);\n };\n\n window.addEventListener('paste', handlePaste);\n return () => window.removeEventListener('paste', handlePaste);\n }, [currentCanvas, currentCanvasId, paste, selection, setDoc, setSelection, viewport]);\n\n const actions = useMemo(() => ({\n undo: onUndo, redo: onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll,\n group: groupSelected, geoGroup: geoGroupSelected, ungroup: ungroupSelected,\n bringToFront: () => changeZIndex('front'),\n bringForward: () => changeZIndex('up'),\n sendBackward: () => changeZIndex('down'),\n sendToBack: () => changeZIndex('back'),\n }), [onUndo, onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll, groupSelected, geoGroupSelected, ungroupSelected, changeZIndex]);\n\n useKeyboardShortcuts(actions);\n useMindMap();\n return null;\n}\n\n/**\n * Bridges the anchor→PDF export (which needs canvas/viewport context) out to the\n * toolbar in the outer Flow component via a ref. Renders nothing.\n */\nfunction PdfExportWire({\n pixiRef,\n exportPdfRef,\n}: {\n pixiRef: React.RefObject<PixiApp | null>;\n exportPdfRef: React.MutableRefObject<(() => Promise<boolean>) | null>;\n}) {\n const exportPdf = usePdfExport(pixiRef);\n exportPdfRef.current = exportPdf;\n return null;\n}\n\n/** Imperative handle exposed via a ref on the `<Flow>` component. */\nexport interface FlowHandle {\n /** Export the current diagram to a PNG data URL (null if unavailable). */\n exportPNG: (backgroundColor?: number) => Promise<string | null>;\n /** Get the current document. */\n getDocument: () => FlowDocument;\n}\n\nconst Flow = forwardRef<FlowHandle, FlowProps>(function Flow({\n initialDocument,\n onChange,\n width,\n height,\n readOnly = false,\n onBack,\n onExportPNG,\n onPublish,\n showMiniMap = true,\n showGrid = true,\n gridSize = 20,\n className,\n showAI = true,\n showAIConfig = true,\n aiConfig,\n}: FlowProps, ref) {\n const [doc, setDoc] = useState<FlowDocument>(() => normalizeDocument(initialDocument ?? createEmptyDocument()));\n const [selection, setSelection] = useState<SelectionState>(EMPTY_SELECTION);\n const pixiRef = useRef<PixiApp | null>(null);\n const miniMapCanvasRef = useRef<HTMLCanvasElement>(null);\n const miniMapRef = useRef<MiniMapRenderer | null>(null);\n // Small-screen detection (container width based, see useCompactMode).\n const rootRef = useRef<HTMLDivElement>(null);\n const compact = useCompactMode(rootRef);\n\n const { wrappedSetDoc, undo, redo, canUndo, canRedo } = useUndoRedo(doc, setDoc);\n const groupRef = useRef<(() => void) | null>(null);\n const geoGroupRef = useRef<(() => void) | null>(null);\n const ungroupRef = useRef<(() => void) | null>(null);\n const exportPdfRef = useRef<(() => Promise<boolean>) | null>(null);\n\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const notifiedDocRef = useRef(doc);\n\n // Notify only committed changes, including undo/redo; skip mount and\n // read-only navigation rather than scheduling callbacks inside an updater.\n useEffect(() => {\n if (notifiedDocRef.current === doc) return;\n notifiedDocRef.current = doc;\n if (!readOnly) onChangeRef.current?.(doc);\n }, [doc, readOnly]);\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 return next;\n });\n },\n [wrappedSetDoc, readOnly],\n );\n\n // Undo/redo mutate the document directly through useUndoRedo's raw setDoc\n // (bypassing outerSetDoc), so they need their own read-only guard.\n const guardedUndo = useCallback(() => { if (!readOnly) undo(); }, [readOnly, undo]);\n const guardedRedo = useCallback(() => { if (!readOnly) redo(); }, [readOnly, redo]);\n\n const handlePixiReady = useCallback((pixi: PixiApp) => {\n pixiRef.current = pixi;\n if (miniMapCanvasRef.current && !miniMapRef.current) {\n miniMapRef.current = new MiniMapRenderer(miniMapCanvasRef.current);\n }\n }, []);\n\n // Built-in PNG export: if the host supplies `onExportPNG` we defer to it,\n // otherwise snapshot the Pixi scene and download it directly so the toolbar\n // button always works out of the box.\n const handleExportPNG = useCallback(async () => {\n if (onExportPNG) return void onExportPNG();\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return;\n const url = await pixi.exportPNG(0xffffff);\n if (url) downloadDataURL(url, `${safeFileBaseName(docRef.current.title)}.png`);\n }, [onExportPNG]);\n\n // Built-in PDF export: capture each anchor's presentation framing into a\n // multi-page PDF (implemented by PdfExportWire inside the providers).\n const handleExportPDF = useCallback(async () => {\n await exportPdfRef.current?.();\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n let subscribed: PixiApp | null = null;\n\n const tickerFn = () => {\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!pixi || pixi.destroyed || !mm) return;\n const vp = { x: pixi.world.position.x, y: pixi.world.position.y, zoom: pixi.world.scale.x };\n const currentId = doc.stack[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const canvas = doc.canvases[currentId];\n if (canvas) mm.update(canvas.nodes, vp, pixi.app.screen.width, pixi.app.screen.height);\n };\n\n // Pixi initializes asynchronously; the minimap renderer is created in\n // handlePixiReady. Poll until both exist, then attach the ticker. This\n // avoids a race where the effect runs before pixi is ready and the minimap\n // stays blank until the next document edit.\n const attach = () => {\n if (cancelled) return;\n const pixi = pixiRef.current;\n if (pixi && !pixi.destroyed && miniMapRef.current) {\n pixi.app.ticker.add(tickerFn);\n subscribed = pixi;\n } else {\n requestAnimationFrame(attach);\n }\n };\n attach();\n\n return () => {\n cancelled = true;\n if (subscribed && !subscribed.destroyed) subscribed.app.ticker.remove(tickerFn);\n };\n }, [doc]);\n\n const style: React.CSSProperties = { width: width ?? '100%', height: height ?? '100%' };\n\n return (\n <div ref={rootRef} className={`flow-container ${className ?? ''}`} style={style}>\n <FlowProvider doc={doc} setDoc={outerSetDoc} selection={selection} setSelection={setSelection}>\n <FlowUIProvider showMiniMap={showMiniMap} showGrid={showGrid} gridSize={gridSize} showAI={showAI} readOnly={readOnly}>\n <FlowAIProvider initialConfig={aiConfig} showAIConfig={showAIConfig}>\n <FlowKeyboardShortcutsWire onUndo={guardedUndo} onRedo={guardedRedo} groupRef={groupRef} geoGroupRef={geoGroupRef} ungroupRef={ungroupRef} />\n <PdfExportWire pixiRef={pixiRef} exportPdfRef={exportPdfRef} />\n <UnifiedPanelGroup\n compact={compact}\n toolbar={!readOnly ? (\n <FlowToolbar\n compact={compact}\n onBack={onBack}\n onUndo={guardedUndo} onRedo={guardedRedo} canUndo={canUndo} canRedo={canRedo}\n onGroup={() => groupRef.current?.()} onGeoGroup={() => geoGroupRef.current?.()} onUngroup={() => ungroupRef.current?.()}\n onExportPNG={handleExportPNG}\n onExportPDF={handleExportPDF}\n onPublish={onPublish}\n />\n ) : null}\n >\n <FlowCanvas onPixiReady={handlePixiReady} />\n {/* Media content (markdown/mermaid/data/…) must stay visible in\n presentation & read-only preview — PixiJS only draws the node\n frame, so hiding this layer would blank every media node. */}\n <MediaOverlay />\n <PresentationGate>\n {!readOnly && <FlowZoomControls />}\n <Breadcrumb />\n </PresentationGate>\n {!readOnly && <FlowContextMenuWire />}\n <MiniMapWrapper canvasRef={miniMapCanvasRef} pixiRef={pixiRef} miniMapRef={miniMapRef} />\n <PresentationMode />\n </UnifiedPanelGroup>\n </FlowAIProvider>\n </FlowUIProvider>\n </FlowProvider>\n </div>\n );\n});\n\nexport default Flow;\n\ninterface TabDef {\n id: string;\n label: string;\n icon: string;\n showKey?: 'showPalette' | 'showInspector' | 'showOutline' | 'showJson' | 'showAI';\n}\n\n/**\n * Hides all editable overlay UI (toolbar, panels, breadcrumb) while in\n * presentation mode, keeping only the canvas visible for the slideshow.\n */\nfunction PresentationGate({ children }: { children: React.ReactNode }) {\n const { presentation } = useFlowUI();\n return (\n <div className=\"flow-overlay\" style={{ display: presentation ? 'none' : undefined }}>\n {children}\n </div>\n );\n}\n\nconst ALL_TAB_DEFS: TabDef[] = [\n { id: 'shapes', label: 'Shapes', icon: '▢', showKey: 'showPalette' },\n { id: 'icons', label: 'Icons', icon: '★', showKey: 'showPalette' },\n { id: 'media', label: 'Media', icon: '▶', showKey: 'showPalette' },\n { id: 'inspector', label: 'Inspector', icon: '⚙', showKey: 'showInspector' },\n { id: 'outline', label: 'Outline', icon: '☰', showKey: 'showOutline' },\n { id: 'json', label: 'JSON', icon: '{ }', showKey: 'showJson' },\n { id: 'ai', label: 'AI', icon: '✨', showKey: 'showAI' },\n];\n\nfunction tabContent(id: string): React.ReactNode {\n switch (id) {\n case 'shapes': return <ShapePaletteContent />;\n case 'icons': return <SvgStampContent />;\n case 'media': return <MediaStampContent />;\n case 'inspector': return <InspectorPanelContent />;\n case 'outline': return <OutlinePanelContent />;\n case 'json': return <JsonEditorPanel />;\n case 'ai': return <AIPanelContent />;\n default: return null;\n }\n}\n\n/** Tab ids whose panels stamp objects onto the canvas (auto-collapse in compact mode). */\nconst STAMP_PANEL_IDS = new Set(['shapes', 'icons', 'media']);\n\nfunction UnifiedPanelGroup({ children, toolbar, compact }: { children: React.ReactNode; toolbar?: React.ReactNode; compact?: boolean }) {\n const ui = useFlowUI();\n const { panelDocks, setPanelDock, presentation, readOnly, setPendingPlacement } = ui;\n const { setShowPalette, setShowInspector, setShowOutline, setShowJson, setShowAI } = ui;\n\n // Read-only: hide every editing panel (palette/inspector/outline/JSON/AI).\n const visibleTabs = readOnly\n ? []\n : ALL_TAB_DEFS.filter(def =>\n !def.showKey || (ui as any)[def.showKey],\n );\n\n const toPanelTab = (def: TabDef): PanelTab => ({\n id: def.id, label: def.label, icon: def.icon, content: tabContent(def.id),\n });\n\n // Compact (small-screen) mode: the chosen panel renders full-screen above\n // the canvas. Shape/icon/media stamp panels collapse automatically once a\n // stamp is picked (pendingPlacement armed) so the user is returned to the\n // canvas to tap it into place; a virtual ESC button on the canvas cancels\n // continuous placement.\n const [activePanel, setActivePanel] = useState<string | null>(null);\n const prevPlacementKeyRef = useRef<string | null>(null);\n useEffect(() => {\n if (!compact) {\n prevPlacementKeyRef.current = null;\n return;\n }\n const pp = ui.pendingPlacement;\n const key = pp ? `${pp.type}:${(pp.data as any)?.svgId ?? ''}:${(pp.data as any)?.mediaKind ?? ''}` : null;\n const prev = prevPlacementKeyRef.current;\n prevPlacementKeyRef.current = key;\n if (key && key !== prev && activePanel && STAMP_PANEL_IDS.has(activePanel)) {\n setActivePanel(null);\n }\n }, [ui.pendingPlacement, compact, activePanel]);\n\n // Floating-panel drag: highlight the dock edge it hovers over.\n const [dropHint, setDropHint] = useState<'left' | 'right' | null>(null);\n const handleDock = useCallback((tabId: string, dock: FlowPanelDock) => setPanelDock(tabId, dock), [setPanelDock]);\n // Each panel has its own close (✕) button; closed panels come back via the\n // matching toolbar toggle (shapes/icons/media share the palette flag).\n const handleClose = useCallback((tabId: string) => {\n if (tabId === 'inspector') setShowInspector(false);\n else if (tabId === 'outline') setShowOutline(false);\n else if (tabId === 'json') setShowJson(false);\n else if (tabId === 'ai') setShowAI(false);\n else setShowPalette(false);\n }, [setShowInspector, setShowOutline, setShowJson, setShowAI, setShowPalette]);\n\n // NOTE: every hook must run before this early return — moving hooks below it\n // would break the hooks-of-render contract in compact mode.\n if (compact && !presentation) {\n const activeDef = visibleTabs.find(d => d.id === activePanel) ?? null;\n return (\n <div className=\"flow-workspace\">\n {toolbar}\n {visibleTabs.length > 0 && (\n <div className=\"flow-mobile-panel-bar\">\n <Select\n placeholder=\"选择面板…\"\n options={visibleTabs.map(d => ({ value: d.id, label: d.label }))}\n value={activePanel ?? undefined}\n onChange={(v) => {\n // Switching panels always opens a clean \"pick a type\" state: a\n // stale armed stamp (continuous placement) would otherwise be\n // placed by the next canvas tap or toggle the tapped item off.\n setPendingPlacement(null);\n setActivePanel(String(v));\n }}\n />\n </div>\n )}\n <div className=\"flow-workspace-main\">\n <div className=\"flow-stage\">\n {children}\n </div>\n {activeDef && (\n <div className=\"flow-mobile-panel\">\n <div className=\"flow-mobile-panel-header\">\n <span className=\"flow-mobile-panel-title\">\n {activeDef.icon && <span className=\"flow-panel-tab-icon\">{activeDef.icon}</span>}\n {activeDef.label}\n </span>\n <button\n type=\"button\"\n className=\"flow-mobile-panel-close\"\n aria-label=\"关闭面板\"\n onClick={() => setActivePanel(null)}\n >✕</button>\n </div>\n <div className=\"flow-mobile-panel-body\">{tabContent(activeDef.id)}</div>\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Desktop layout: the left/right panel groups are merged into one panel\n // list docked on the left by default. Panels are switched with a dropdown\n // Select; users can move any panel to the right dock or let it float (via\n // header buttons or by dragging it onto a workspace edge). Docks without\n // panels are not rendered so the canvas fills the freed space.\n const getDock = (id: string): FlowPanelDock => panelDocks[id] ?? 'left';\n const leftTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'left')\n .map(toPanelTab);\n const rightTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'right')\n .map(toPanelTab);\n const floatList = visibleTabs.filter(def => getDock(def.id) === 'float');\n\n return (\n <div className=\"flow-workspace\">\n {/* Slim full-width toolbar strip above panels + canvas. */}\n {!presentation && toolbar}\n <div className=\"flow-workspace-main\">\n {!presentation && leftTabs.length > 0 && (\n <FlowPanelGroup\n tabs={leftTabs}\n defaultTab={leftTabs[0]?.id}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"left\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n <div className=\"flow-stage\">\n {children}\n </div>\n {!presentation && rightTabs.length > 0 && (\n <FlowPanelGroup\n tabs={rightTabs}\n defaultTab={rightTabs[0]?.id}\n resizeEdge=\"left\"\n defaultWidth={220}\n dock=\"right\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n {/* Floating panels drift above the docks; dragging one over a\n workspace edge shows a drop-zone hint and dropping attaches it to\n that dock. Rendered as a direct child of the (position:relative)\n workspace-main so they are not clipped by the stage's\n `overflow: hidden`. */}\n {!presentation && floatList.map((def, i) => (\n <FlowPanelGroup\n key={def.id}\n tabs={[toPanelTab(def)]}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"float\"\n style={{ top: 48 + i * 40, left: 24 + i * 30 }}\n onDock={handleDock}\n onClose={handleClose}\n onDragHintChange={setDropHint}\n />\n ))}\n {!presentation && dropHint && (\n <div className={`flow-dock-dropzone flow-dock-dropzone--${dropHint}`}>\n <span>{dropHint === 'left' ? '⇤ 停靠左侧' : '停靠右侧 ⇥'}</span>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction MiniMapWrapper({\n canvasRef,\n pixiRef,\n miniMapRef,\n}: {\n canvasRef: React.RefObject<HTMLCanvasElement | null>;\n pixiRef: React.RefObject<PixiApp | null>;\n miniMapRef: React.RefObject<MiniMapRenderer | null>;\n}) {\n const { showMiniMap, setViewport, presentation } = useFlowUI();\n const draggingRef = useRef(false);\n\n // Move the main canvas so that the world point under the minimap click is\n // centered in the viewport. Routed through setViewport so the change syncs\n // with the ViewportManager (setting world.position directly would be\n // overwritten on the next viewport apply).\n const navigateTo = useCallback((clientX: number, clientY: number) => {\n const canvas = canvasRef.current;\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!canvas || !pixi || pixi.destroyed || !mm) return;\n\n const rect = canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return;\n // CSS pixels -> canvas backing pixels.\n const { width: cw, height: ch } = mm.size;\n const px = ((clientX - rect.left) / rect.width) * cw;\n const py = ((clientY - rect.top) / rect.height) * ch;\n\n const world = mm.minimapToWorld(px, py);\n if (!world) return;\n\n const zoom = pixi.world.scale.x || 1;\n const screenW = pixi.app.screen.width;\n const screenH = pixi.app.screen.height;\n setViewport({\n x: screenW / 2 - world.x * zoom,\n y: screenH / 2 - world.y * zoom,\n zoom,\n });\n }, [canvasRef, pixiRef, miniMapRef, setViewport]);\n\n const onPointerDown = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault();\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n draggingRef.current = true;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerMove = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerUp = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n draggingRef.current = false;\n try { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); } catch { /* noop */ }\n }, []);\n\n return (\n <div\n className=\"flow-minimap\"\n style={{ display: showMiniMap && !presentation ? undefined : 'none', cursor: 'pointer' }}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n title=\"点击或拖动以移动画布\"\n >\n <canvas ref={canvasRef} width={180} height={120} style={{ width: '100%', height: '100%', pointerEvents: 'none' }} />\n </div>\n );\n}\n\n/**\n * Find the line range (1-based) of a JSON object with the given id.\n */\nfunction findElementLineRange(jsonStr: string, elementId: string): { startLine: number; endLine: number } | null {\n const idPattern = `\"id\": \"${elementId}\"`;\n const idx = jsonStr.indexOf(idPattern);\n if (idx === -1) return null;\n\n let braceDepth = 0;\n let startIdx = -1;\n for (let i = idx; i >= 0; i--) {\n if (jsonStr[i] === '}') braceDepth++;\n if (jsonStr[i] === '{') {\n if (braceDepth === 0) { startIdx = i; break; }\n braceDepth--;\n }\n }\n if (startIdx === -1) return null;\n\n braceDepth = 0;\n let endIdx = -1;\n for (let i = startIdx; i < jsonStr.length; i++) {\n if (jsonStr[i] === '{') braceDepth++;\n if (jsonStr[i] === '}') {\n braceDepth--;\n if (braceDepth === 0) { endIdx = i; break; }\n }\n }\n if (endIdx === -1) return null;\n\n const startLine = jsonStr.slice(0, startIdx).split('\\n').length;\n const endLine = jsonStr.slice(0, endIdx + 1).split('\\n').length;\n return { startLine, endLine };\n}\n\nfunction clearLineHighlights(container: HTMLElement) {\n container.querySelectorAll('.cm-line.flow-json-hl').forEach(el => el.classList.remove('flow-json-hl'));\n}\n\nfunction applyLineHighlightsViaView(handle: CodeEditorHandle, startLine: number, endLine: number) {\n const view = handle.getView();\n if (!view) return;\n for (let ln = startLine; ln <= endLine; ln++) {\n try {\n const lineInfo = view.state.doc.line(ln);\n const dom = view.domAtPos(lineInfo.from);\n const lineEl = dom.node instanceof HTMLElement\n ? dom.node.closest('.cm-line')\n : dom.node.parentElement?.closest('.cm-line');\n if (lineEl) lineEl.classList.add('flow-json-hl');\n } catch { /* line not in viewport */ }\n }\n}\n\nfunction JsonEditorPanel() {\n const { setDoc, currentCanvasId, selection, currentCanvas } = useFlowContext();\n const [jsonStr, setJsonStr] = useState('');\n const [error, setError] = useState<string | null>(null);\n const skipNextSync = useRef(false);\n const editorRef = useRef<CodeEditorHandle>(null);\n const wrapRef = useRef<HTMLDivElement>(null);\n\n const singleId = useMemo(() => {\n const total = selection.nodeIds.size + selection.edgeIds.size + selection.lineIds.size;\n if (total !== 1) return null;\n if (selection.nodeIds.size === 1) return [...selection.nodeIds][0];\n if (selection.edgeIds.size === 1) return [...selection.edgeIds][0];\n if (selection.lineIds.size === 1) return [...selection.lineIds][0];\n return null;\n }, [selection]);\n\n useEffect(() => {\n if (skipNextSync.current) { skipNextSync.current = false; return; }\n setJsonStr(JSON.stringify(currentCanvas, null, 2));\n setError(null);\n }, [currentCanvas]);\n\n useEffect(() => {\n const wrap = wrapRef.current;\n if (wrap) clearLineHighlights(wrap);\n if (!singleId) return;\n\n const timer = setTimeout(() => {\n const range = findElementLineRange(jsonStr, singleId);\n if (!range || !wrapRef.current) return;\n\n const view = editorRef.current?.getView();\n if (!view) return;\n\n const w = wrapRef.current;\n const scroller = view.scrollDOM;\n\n scroller.style.scrollBehavior = 'smooth';\n\n const lineInfo = view.state.doc.line(range.startLine);\n view.dispatch({\n effects: EditorView.scrollIntoView(lineInfo.from, { y: 'start', yMargin: 0 }),\n });\n\n const onScrollEnd = () => {\n scroller.style.scrollBehavior = '';\n clearLineHighlights(w);\n applyLineHighlightsViaView(editorRef.current!, range.startLine, range.endLine);\n };\n\n let scrollTimer: ReturnType<typeof setTimeout>;\n const onScroll = () => {\n clearTimeout(scrollTimer);\n scrollTimer = setTimeout(onScrollEnd, 100);\n };\n scroller.addEventListener('scroll', onScroll);\n scrollTimer = setTimeout(() => {\n scroller.removeEventListener('scroll', onScroll);\n onScrollEnd();\n }, 800);\n }, 120);\n return () => clearTimeout(timer);\n }, [singleId, jsonStr]);\n\n const handleChange = useCallback((value: string) => {\n setJsonStr(value);\n try {\n const parsed = JSON.parse(value);\n if (parsed && Array.isArray(parsed.nodes) && Array.isArray(parsed.edges) && Array.isArray(parsed.lines)) {\n setError(null);\n skipNextSync.current = true;\n setDoc(prev => ({\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: parsed },\n }));\n } else {\n setError('JSON must have nodes, edges, lines arrays');\n }\n } catch (e: any) {\n setError(e.message?.slice(0, 60) ?? 'Invalid JSON');\n }\n }, [setDoc, currentCanvasId]);\n\n const label = singleId\n ? (selection.nodeIds.has(singleId) ? 'Node' : selection.edgeIds.has(singleId) ? 'Edge' : 'Line')\n : null;\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>\n <div className=\"flow-json-header\">\n <span className=\"flow-json-scope\">\n {label ? `${label}: ${singleId!.slice(0, 8)}` : `Canvas`}\n </span>\n </div>\n {error && (\n <div style={{ fontSize: 11, color: 'oklch(var(--er))', padding: '4px 0', flexShrink: 0 }}>\n {error}\n </div>\n )}\n <div ref={wrapRef} style={{ flex: 1, minHeight: 0 }}>\n <CodeEditor\n ref={editorRef}\n value={jsonStr}\n onChange={handleChange}\n language=\"json\"\n lineNumbers={false}\n height=\"100%\"\n highlightActiveLine={false}\n />\n </div>\n </div>\n );\n}\n\nfunction FlowContextMenuWire() {\n const { contextMenu, setContextMenu } = useFlowUI();\n const { doc, setDoc, currentCanvasId, pushCanvas, setSelection } = useFlowContext();\n const { duplicate } = useClipboard();\n\n if (!contextMenu) return null;\n\n const canvas = doc.canvases[currentCanvasId];\n if (!canvas) { setContextMenu(null); return null; }\n\n const node = contextMenu.nodeId ? canvas.nodes.find(n => n.id === contextMenu.nodeId) : null;\n const items: ContextMenuItem[] = [];\n\n if (node) {\n // Duplicate the node (Cmd/Ctrl+D equivalent). Ensure it is selected first so\n // the clone covers the intended target even on a right-click without a prior\n // left-click selection.\n items.push({\n label: 'Duplicate',\n icon: '⧉',\n action: () => {\n duplicate(24, 24, { nodeIds: new Set([node.id]) });\n },\n });\n items.push({ label: '---', action: () => {} });\n\n const hasChild = !!node.data.childCanvasId;\n\n if (hasChild) {\n items.push({\n label: 'Enter Sub-canvas',\n icon: '↓',\n action: () => {\n pushCanvas(node.data.childCanvasId!);\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n },\n });\n items.push({ label: '---', action: () => {} });\n items.push({\n label: 'Delete Sub-canvas',\n icon: '🗑',\n danger: true,\n action: () => {\n const childId = node.data.childCanvasId!;\n setDoc(prev => {\n const canvases = { ...prev.canvases };\n collectAndRemoveCanvases(canvases, childId);\n const c = canvases[currentCanvasId];\n if (!c) return prev;\n canvases[currentCanvasId] = {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId: undefined } }\n : n,\n ),\n };\n const stack = prev.stack.filter(id => canvases[id]);\n if (stack.length === 0) stack.push(ROOT_CANVAS_ID);\n return { ...prev, canvases, stack };\n });\n },\n });\n } else {\n items.push({\n label: 'Create Sub-canvas',\n icon: '⊞',\n action: () => {\n const childCanvasId = generateId('canvas');\n setDoc(prev => {\n const c = prev.canvases[currentCanvasId];\n if (!c) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId } }\n : n,\n ),\n },\n [childCanvasId]: { nodes: [], edges: [], lines: [] },\n },\n };\n });\n pushCanvas(childCanvasId);\n },\n });\n }\n }\n\n if (items.length === 0) return null;\n\n return (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n items={items}\n onClose={() => setContextMenu(null)}\n />\n );\n}\n\nfunction collectAndRemoveCanvases(\n canvases: Record<string, FlowCanvasData>,\n canvasId: string,\n): void {\n const canvas = canvases[canvasId];\n if (!canvas) return;\n for (const node of canvas.nodes) {\n if (node.data.childCanvasId) {\n collectAndRemoveCanvases(canvases, node.data.childCanvasId);\n }\n }\n delete canvases[canvasId];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Flow.js","names":[],"sources":["../../../../src/components/pro/Flow/Flow.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';\nimport { FlowProvider, useFlowContext } from './context/FlowContext';\nimport { FlowUIProvider, useFlowUI } from './context/FlowUIContext';\nimport { FlowAIProvider } from './context/FlowAIContext';\nimport FlowCanvas from './FlowCanvas';\nimport FlowToolbar, { FlowZoomControls } from './panels/FlowToolbar';\nimport { ShapePaletteContent, SvgStampContent, MediaStampContent } from './panels/ShapePalette';\nimport { InspectorPanelContent } from './panels/InspectorPanel';\nimport { OutlinePanelContent } from './panels/OutlinePanel';\nimport { AIPanelContent } from './panels/AIPanel';\nimport { PresentationMode } from './panels/PresentationMode';\nimport { MediaOverlay } from './nodes/MediaOverlay';\nimport FlowPanelGroup, { type PanelTab } from './panels/FlowPanelGroup';\nimport type { FlowPanelDock } from './context/FlowUIContext';\nimport Breadcrumb from './panels/Breadcrumb';\nimport ContextMenu from './panels/ContextMenu';\nimport type { ContextMenuItem } from './panels/ContextMenu';\nimport Select from '../../Select';\nimport { MiniMapRenderer } from './canvas/MiniMapRenderer';\nimport { CodeEditor, type CodeEditorHandle } from '../CodeEditor';\nimport { EditorView } from '@codemirror/view';\nimport { useUndoRedo } from './hooks/useUndoRedo';\nimport { useClipboard } from './hooks/useClipboard';\nimport { useCompactMode } from './hooks/useCompactMode';\nimport { downloadDataURL, safeFileBaseName } from './hooks/useFlowImportExport';\nimport { usePdfExport } from './hooks/usePdfExport';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useMindMap } from './hooks/useMindMap';\nimport { useDeleteSelection } from './hooks/useDeleteSelection';\nimport { createEmptyDocument, ROOT_CANVAS_ID, DEFAULT_NODE_DATA } from './constants';\nimport { normalizeEdgeHandles } from './edges/edgePaths';\nimport { generateId } from './nodes/nodeUtils';\nimport type { FlowProps, FlowDocument, FlowNode, SelectionState, FlowCanvasData } from './types';\nimport type { PixiApp } from './canvas/PixiApp';\nimport './styles.css';\n\nfunction normalizeDocument(doc: FlowDocument): FlowDocument {\n let changed = false;\n const canvases = { ...doc.canvases };\n for (const [id, canvas] of Object.entries(canvases)) {\n const nodes = canvas.nodes.map(node => {\n if (node.type !== 'shapeSvg') return node;\n const legacyPlacement = node.data.labelPlacement as string | undefined;\n const labelPlacement = legacyPlacement === 'above'\n ? 'top'\n : legacyPlacement === 'center'\n ? 'middle'\n : legacyPlacement === 'below'\n ? 'bottom'\n : node.data.labelPlacement;\n if (labelPlacement === node.data.labelPlacement) return node;\n changed = true;\n return { ...node, data: { ...node.data, labelPlacement } };\n });\n // Mindmap nodes/edges created before theme tokens (≤ 0.0.56) persisted\n // literal colors, so they never followed theme switches. That exact palette\n // was only ever emitted by the old mindmap creator, so remap it to the same\n // tokens the current creator uses.\n let themedNodesChanged = false;\n const themedNodes = nodes.map(node => {\n if (!node.data.isMindMapNode) return node;\n const fill = node.data.fill === '#ffffff' || node.data.fill === '#eef2ff'\n ? 'theme:base-100'\n : node.data.fill;\n const stroke = node.data.stroke === '#6366f1'\n ? 'theme:base-content'\n : node.data.stroke === '#4f46e5'\n ? 'theme:primary'\n : node.data.stroke;\n if (fill === node.data.fill && stroke === node.data.stroke) return node;\n themedNodesChanged = true;\n return { ...node, data: { ...node.data, fill, stroke } };\n });\n const nodeMap = new Map<string, FlowNode>();\n for (const node of themedNodes) nodeMap.set(node.id, node);\n let edgesChanged = false;\n const edges = normalizeEdgeHandles(canvas.edges, nodeMap).map(edge => {\n if (edge.data.strokeColor !== '#94a3b8') return edge;\n const source = nodeMap.get(edge.source);\n const target = nodeMap.get(edge.target);\n if (!source?.data.isMindMapNode || !target?.data.isMindMapNode) return edge;\n edgesChanged = true;\n return { ...edge, data: { ...edge.data, strokeColor: 'theme:base-content' } };\n });\n if (themedNodesChanged || edgesChanged) changed = true;\n if (themedNodes !== nodes || edges !== canvas.edges) {\n canvases[id] = { ...canvas, nodes: themedNodes, edges };\n }\n }\n return changed ? { ...doc, canvases } : doc;\n}\n\nconst EMPTY_SELECTION: SelectionState = {\n nodeIds: new Set(),\n edgeIds: new Set(),\n lineIds: new Set(),\n};\n\nfunction FlowKeyboardShortcutsWire({ onUndo, onRedo, groupRef, geoGroupRef, ungroupRef }: {\n onUndo: () => void;\n onRedo: () => void;\n groupRef: React.MutableRefObject<(() => void) | null>;\n geoGroupRef: React.MutableRefObject<(() => void) | null>;\n ungroupRef: React.MutableRefObject<(() => void) | null>;\n}) {\n const { selection, setSelection, currentCanvas, setDoc, currentCanvasId } = useFlowContext();\n const { viewport } = useFlowUI();\n const { copy, cut, paste, duplicate } = useClipboard();\n const deleteSelected = useDeleteSelection();\n\n const selectAll = useCallback(() => {\n setSelection({\n nodeIds: new Set(currentCanvas.nodes.map(n => n.id)),\n edgeIds: new Set(currentCanvas.edges.map(e => e.id)),\n lineIds: new Set(currentCanvas.lines.map(l => l.id)),\n });\n }, [currentCanvas, setSelection]);\n\n const createGroup = useCallback((type: 'flowGroup' | 'geometryGroup') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n const totalCount = nodeIds.size + lineIds.size;\n if (totalCount < 2) return;\n const nodes = currentCanvas.nodes.filter(n => nodeIds.has(n.id));\n const lines = currentCanvas.lines.filter(l => lineIds.has(l.id));\n const PAD = 20;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n minX = Math.min(minX, n.position.x);\n minY = Math.min(minY, n.position.y);\n maxX = Math.max(maxX, n.position.x + n.width);\n maxY = Math.max(maxY, n.position.y + n.height);\n }\n for (const l of lines) {\n for (const p of l.points) {\n minX = Math.min(minX, p.x); minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x); maxY = Math.max(maxY, p.y);\n }\n }\n const isGeo = type === 'geometryGroup';\n const groupId = generateId('group');\n const groupNode: FlowNode = {\n id: groupId,\n type,\n position: { x: minX - PAD, y: minY - PAD },\n width: maxX - minX + PAD * 2,\n height: maxY - minY + PAD * 2,\n data: {\n ...DEFAULT_NODE_DATA,\n label: isGeo ? 'Geo Group' : 'Group',\n fill: isGeo ? '#fefce8' : '#f0f9ff',\n stroke: '#9ca3af', strokeWidth: 1.5,\n borderStyle: isGeo ? 'dashed' : 'dotted',\n isGroup: true,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: isGeo\n ? [groupNode, ...canvas.nodes]\n : [groupNode, ...canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, parentId: groupId } : n)],\n lines: isGeo\n ? canvas.lines\n : canvas.lines.map(l => lineIds.has(l.id) ? { ...l, parentId: groupId } : l),\n }},\n };\n });\n setSelection({ nodeIds: new Set([groupId]), edgeIds: new Set(), lineIds: new Set() });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n const groupSelected = useCallback(() => createGroup('flowGroup'), [createGroup]);\n const geoGroupSelected = useCallback(() => createGroup('geometryGroup'), [createGroup]);\n\n const ungroupSelected = useCallback(() => {\n const ids = selection.nodeIds;\n if (ids.size === 0) return;\n const groupNodeIds = new Set<string>();\n const childNodeIds = new Set<string>();\n const childLineIds = new Set<string>();\n for (const node of currentCanvas.nodes) {\n if (ids.has(node.id) && (node.type === 'flowGroup' || node.type === 'geometryGroup' || node.data.isGroup)) {\n groupNodeIds.add(node.id);\n }\n }\n if (groupNodeIds.size === 0) return;\n for (const node of currentCanvas.nodes) {\n if (node.parentId && groupNodeIds.has(node.parentId)) {\n childNodeIds.add(node.id);\n }\n }\n for (const line of currentCanvas.lines) {\n if (line.parentId && groupNodeIds.has(line.parentId)) {\n childLineIds.add(line.id);\n }\n }\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes\n .filter(n => !groupNodeIds.has(n.id))\n .map(n => childNodeIds.has(n.id) ? { ...n, parentId: undefined } : n),\n lines: canvas.lines\n .map(l => childLineIds.has(l.id) ? { ...l, parentId: undefined } : l),\n }},\n };\n });\n setSelection({ nodeIds: childNodeIds, edgeIds: new Set(), lineIds: childLineIds });\n }, [selection, currentCanvas, setDoc, currentCanvasId, setSelection]);\n\n groupRef.current = groupSelected;\n geoGroupRef.current = geoGroupSelected;\n ungroupRef.current = ungroupSelected;\n\n const changeZIndex = useCallback((mode: 'front' | 'back' | 'up' | 'down') => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n if (nodeIds.size === 0 && lineIds.size === 0) return;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n const nodeAllZ = canvas.nodes.map(n => n.zIndex ?? 0);\n const nodeMaxZ = nodeAllZ.length > 0 ? Math.max(...nodeAllZ) : 0;\n const nodeMinZ = nodeAllZ.length > 0 ? Math.min(...nodeAllZ) : 0;\n const lineAllZ = canvas.lines.map(l => l.zIndex ?? 0);\n const lineMaxZ = lineAllZ.length > 0 ? Math.max(...lineAllZ) : 0;\n const lineMinZ = lineAllZ.length > 0 ? Math.min(...lineAllZ) : 0;\n const applyZ = (z: number, maxZ: number, minZ: number) => {\n if (mode === 'front') return maxZ + 1;\n if (mode === 'back') return minZ - 1;\n if (mode === 'up') return z + 1;\n return z - 1;\n };\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(n => nodeIds.has(n.id) ? { ...n, zIndex: applyZ(n.zIndex ?? 0, nodeMaxZ, nodeMinZ) } : n),\n lines: canvas.lines.map(l => lineIds.has(l.id) ? { ...l, zIndex: applyZ(l.zIndex ?? 0, lineMaxZ, lineMinZ) } : l),\n }},\n };\n });\n }, [selection, setDoc, currentCanvasId]);\n\n useEffect(() => {\n const handlePaste = (event: ClipboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target?.tagName === 'INPUT' || target?.tagName === 'TEXTAREA' || target?.isContentEditable) return;\n\n const imageItem = Array.from(event.clipboardData?.items ?? []).find(item => item.type.startsWith('image/'));\n if (!imageItem) {\n event.preventDefault();\n paste();\n return;\n }\n\n const file = imageItem.getAsFile();\n if (!file) return;\n event.preventDefault();\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result !== 'string') return;\n const selectedImage = selection.nodeIds.size === 1\n ? currentCanvas.nodes.find(node => selection.nodeIds.has(node.id) && node.type === 'mediaNode' && node.data.mediaKind === 'image')\n : undefined;\n\n if (selectedImage) {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...canvas,\n nodes: canvas.nodes.map(node => node.id === selectedImage.id\n ? { ...node, data: { ...node.data, mediaContent: reader.result as string } }\n : node),\n },\n },\n };\n });\n return;\n }\n\n const id = generateId('node');\n const width = 320;\n const height = 220;\n const screenWidth = window.innerWidth;\n const screenHeight = window.innerHeight;\n const centerX = (screenWidth / 2 - viewport.x) / viewport.zoom;\n const centerY = (screenHeight / 2 - viewport.y) / viewport.zoom;\n const highestZ = Math.max(0, ...currentCanvas.nodes.map(node => node.zIndex ?? 0));\n const imageNode: FlowNode = {\n id,\n type: 'mediaNode',\n position: { x: centerX - width / 2, y: centerY - height / 2 },\n width,\n height,\n zIndex: highestZ + 1,\n data: {\n ...DEFAULT_NODE_DATA,\n label: file.name || 'Image',\n fill: 'theme:base-100',\n stroke: 'theme:base-content',\n strokeWidth: 1.5,\n color: 'theme:base-content',\n fontSize: 13,\n borderStyle: 'solid',\n mediaKind: 'image',\n mediaContent: reader.result,\n },\n };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasId];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: { ...canvas, nodes: [...canvas.nodes, imageNode] },\n },\n };\n });\n setSelection({ nodeIds: new Set([id]), edgeIds: new Set(), lineIds: new Set() });\n };\n reader.readAsDataURL(file);\n };\n\n window.addEventListener('paste', handlePaste);\n return () => window.removeEventListener('paste', handlePaste);\n }, [currentCanvas, currentCanvasId, paste, selection, setDoc, setSelection, viewport]);\n\n const actions = useMemo(() => ({\n undo: onUndo, redo: onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll,\n group: groupSelected, geoGroup: geoGroupSelected, ungroup: ungroupSelected,\n bringToFront: () => changeZIndex('front'),\n bringForward: () => changeZIndex('up'),\n sendBackward: () => changeZIndex('down'),\n sendToBack: () => changeZIndex('back'),\n }), [onUndo, onRedo, copy, cut, paste, duplicate, deleteSelected, selectAll, groupSelected, geoGroupSelected, ungroupSelected, changeZIndex]);\n\n useKeyboardShortcuts(actions);\n useMindMap();\n return null;\n}\n\n/**\n * Bridges the anchor→PDF export (which needs canvas/viewport context) out to the\n * toolbar in the outer Flow component via a ref. Renders nothing.\n */\nfunction PdfExportWire({\n pixiRef,\n exportPdfRef,\n}: {\n pixiRef: React.RefObject<PixiApp | null>;\n exportPdfRef: React.MutableRefObject<(() => Promise<boolean>) | null>;\n}) {\n const exportPdf = usePdfExport(pixiRef);\n exportPdfRef.current = exportPdf;\n return null;\n}\n\n/** Imperative handle exposed via a ref on the `<Flow>` component. */\nexport interface FlowHandle {\n /** Export the current diagram to a PNG data URL (null if unavailable). */\n exportPNG: (backgroundColor?: number) => Promise<string | null>;\n /** Get the current document. */\n getDocument: () => FlowDocument;\n}\n\nconst Flow = forwardRef<FlowHandle, FlowProps>(function Flow({\n initialDocument,\n onChange,\n width,\n height,\n readOnly = false,\n onBack,\n onExportPNG,\n onPublish,\n showMiniMap = true,\n showGrid = true,\n gridSize = 20,\n className,\n showAI = true,\n showAIConfig = true,\n aiConfig,\n}: FlowProps, ref) {\n const [doc, setDoc] = useState<FlowDocument>(() => normalizeDocument(initialDocument ?? createEmptyDocument()));\n const [selection, setSelection] = useState<SelectionState>(EMPTY_SELECTION);\n const pixiRef = useRef<PixiApp | null>(null);\n const miniMapCanvasRef = useRef<HTMLCanvasElement>(null);\n const miniMapRef = useRef<MiniMapRenderer | null>(null);\n // Small-screen detection (container width based, see useCompactMode).\n const rootRef = useRef<HTMLDivElement>(null);\n const compact = useCompactMode(rootRef);\n\n const { wrappedSetDoc, setDocTransient, 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 const notifiedDocRef = useRef(doc);\n\n // Notify only committed changes, including undo/redo; skip mount and\n // read-only navigation rather than scheduling callbacks inside an updater.\n useEffect(() => {\n if (notifiedDocRef.current === doc) return;\n notifiedDocRef.current = doc;\n if (!readOnly) onChangeRef.current?.(doc);\n }, [doc, readOnly]);\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 return next;\n });\n },\n [wrappedSetDoc, readOnly],\n );\n\n // Transient (history-free) updates share the same read-only guard: temporary\n // canvas navigation is allowed, content mutations are discarded.\n const outerSetDocTransient: React.Dispatch<React.SetStateAction<FlowDocument>> = useCallback(\n (action) => {\n setDocTransient(prev => {\n const next = typeof action === 'function' ? action(prev) : action;\n if (readOnly) {\n const navigationOnly = next.canvases === prev.canvases && next.title === prev.title;\n return navigationOnly ? next : prev;\n }\n return next;\n });\n },\n [setDocTransient, readOnly],\n );\n\n // Undo/redo mutate the document directly through useUndoRedo's raw setDoc\n // (bypassing outerSetDoc), so they need their own read-only guard.\n const guardedUndo = useCallback(() => { if (!readOnly) undo(); }, [readOnly, undo]);\n const guardedRedo = useCallback(() => { if (!readOnly) redo(); }, [readOnly, redo]);\n\n const handlePixiReady = useCallback((pixi: PixiApp) => {\n pixiRef.current = pixi;\n if (miniMapCanvasRef.current && !miniMapRef.current) {\n miniMapRef.current = new MiniMapRenderer(miniMapCanvasRef.current);\n }\n }, []);\n\n // Built-in PNG export: if the host supplies `onExportPNG` we defer to it,\n // otherwise snapshot the Pixi scene and download it directly so the toolbar\n // button always works out of the box.\n const handleExportPNG = useCallback(async () => {\n if (onExportPNG) return void onExportPNG();\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return;\n const url = await pixi.exportPNG(0xffffff);\n if (url) downloadDataURL(url, `${safeFileBaseName(docRef.current.title)}.png`);\n }, [onExportPNG]);\n\n // Built-in PDF export: capture each anchor's presentation framing into a\n // multi-page PDF (implemented by PdfExportWire inside the providers).\n const handleExportPDF = useCallback(async () => {\n await exportPdfRef.current?.();\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n let subscribed: PixiApp | null = null;\n\n const tickerFn = () => {\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!pixi || pixi.destroyed || !mm) return;\n const vp = { x: pixi.world.position.x, y: pixi.world.position.y, zoom: pixi.world.scale.x };\n const currentId = doc.stack[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const canvas = doc.canvases[currentId];\n if (canvas) mm.update(canvas.nodes, vp, pixi.app.screen.width, pixi.app.screen.height);\n };\n\n // Pixi initializes asynchronously; the minimap renderer is created in\n // handlePixiReady. Poll until both exist, then attach the ticker. This\n // avoids a race where the effect runs before pixi is ready and the minimap\n // stays blank until the next document edit.\n const attach = () => {\n if (cancelled) return;\n const pixi = pixiRef.current;\n if (pixi && !pixi.destroyed && miniMapRef.current) {\n pixi.app.ticker.add(tickerFn);\n subscribed = pixi;\n } else {\n requestAnimationFrame(attach);\n }\n };\n attach();\n\n return () => {\n cancelled = true;\n if (subscribed && !subscribed.destroyed) subscribed.app.ticker.remove(tickerFn);\n };\n }, [doc]);\n\n const style: React.CSSProperties = { width: width ?? '100%', height: height ?? '100%' };\n\n return (\n <div ref={rootRef} className={`flow-container ${className ?? ''}`} style={style}>\n <FlowProvider doc={doc} setDoc={outerSetDoc} setDocTransient={outerSetDocTransient} selection={selection} setSelection={setSelection}>\n <FlowUIProvider showMiniMap={showMiniMap} showGrid={showGrid} gridSize={gridSize} showAI={showAI} readOnly={readOnly}>\n <FlowAIProvider initialConfig={aiConfig} showAIConfig={showAIConfig}>\n <FlowKeyboardShortcutsWire onUndo={guardedUndo} onRedo={guardedRedo} groupRef={groupRef} geoGroupRef={geoGroupRef} ungroupRef={ungroupRef} />\n <PdfExportWire pixiRef={pixiRef} exportPdfRef={exportPdfRef} />\n <UnifiedPanelGroup\n compact={compact}\n toolbar={!readOnly ? (\n <FlowToolbar\n compact={compact}\n onBack={onBack}\n onUndo={guardedUndo} onRedo={guardedRedo} canUndo={canUndo} canRedo={canRedo}\n onGroup={() => groupRef.current?.()} onGeoGroup={() => geoGroupRef.current?.()} onUngroup={() => ungroupRef.current?.()}\n onExportPNG={handleExportPNG}\n onExportPDF={handleExportPDF}\n onPublish={onPublish}\n />\n ) : null}\n >\n <FlowCanvas onPixiReady={handlePixiReady} />\n {/* Media content (markdown/mermaid/data/…) must stay visible in\n presentation & read-only preview — PixiJS only draws the node\n frame, so hiding this layer would blank every media node. */}\n <MediaOverlay />\n <PresentationGate>\n {!readOnly && <FlowZoomControls />}\n <Breadcrumb />\n </PresentationGate>\n {!readOnly && <FlowContextMenuWire />}\n <MiniMapWrapper canvasRef={miniMapCanvasRef} pixiRef={pixiRef} miniMapRef={miniMapRef} />\n <PresentationMode />\n </UnifiedPanelGroup>\n </FlowAIProvider>\n </FlowUIProvider>\n </FlowProvider>\n </div>\n );\n});\n\nexport default Flow;\n\ninterface TabDef {\n id: string;\n label: string;\n icon: string;\n showKey?: 'showPalette' | 'showInspector' | 'showOutline' | 'showJson' | 'showAI';\n}\n\n/**\n * Hides all editable overlay UI (toolbar, panels, breadcrumb) while in\n * presentation mode, keeping only the canvas visible for the slideshow.\n */\nfunction PresentationGate({ children }: { children: React.ReactNode }) {\n const { presentation } = useFlowUI();\n return (\n <div className=\"flow-overlay\" style={{ display: presentation ? 'none' : undefined }}>\n {children}\n </div>\n );\n}\n\nconst ALL_TAB_DEFS: TabDef[] = [\n { id: 'shapes', label: 'Shapes', icon: '▢', showKey: 'showPalette' },\n { id: 'icons', label: 'Icons', icon: '★', showKey: 'showPalette' },\n { id: 'media', label: 'Media', icon: '▶', showKey: 'showPalette' },\n { id: 'inspector', label: 'Inspector', icon: '⚙', showKey: 'showInspector' },\n { id: 'outline', label: 'Outline', icon: '☰', showKey: 'showOutline' },\n { id: 'json', label: 'JSON', icon: '{ }', showKey: 'showJson' },\n { id: 'ai', label: 'AI', icon: '✨', showKey: 'showAI' },\n];\n\nfunction tabContent(id: string): React.ReactNode {\n switch (id) {\n case 'shapes': return <ShapePaletteContent />;\n case 'icons': return <SvgStampContent />;\n case 'media': return <MediaStampContent />;\n case 'inspector': return <InspectorPanelContent />;\n case 'outline': return <OutlinePanelContent />;\n case 'json': return <JsonEditorPanel />;\n case 'ai': return <AIPanelContent />;\n default: return null;\n }\n}\n\n/** Tab ids whose panels stamp objects onto the canvas (auto-collapse in compact mode). */\nconst STAMP_PANEL_IDS = new Set(['shapes', 'icons', 'media']);\n\nfunction UnifiedPanelGroup({ children, toolbar, compact }: { children: React.ReactNode; toolbar?: React.ReactNode; compact?: boolean }) {\n const ui = useFlowUI();\n const { panelDocks, setPanelDock, presentation, readOnly, setPendingPlacement } = ui;\n const { setShowPalette, setShowInspector, setShowOutline, setShowJson, setShowAI } = ui;\n\n // Read-only: hide every editing panel (palette/inspector/outline/JSON/AI).\n const visibleTabs = readOnly\n ? []\n : ALL_TAB_DEFS.filter(def =>\n !def.showKey || (ui as any)[def.showKey],\n );\n\n const toPanelTab = (def: TabDef): PanelTab => ({\n id: def.id, label: def.label, icon: def.icon, content: tabContent(def.id),\n });\n\n // Compact (small-screen) mode: the chosen panel renders full-screen above\n // the canvas. Shape/icon/media stamp panels collapse automatically once a\n // stamp is picked (pendingPlacement armed) so the user is returned to the\n // canvas to tap it into place; a virtual ESC button on the canvas cancels\n // continuous placement.\n const [activePanel, setActivePanel] = useState<string | null>(null);\n const prevPlacementKeyRef = useRef<string | null>(null);\n useEffect(() => {\n if (!compact) {\n prevPlacementKeyRef.current = null;\n return;\n }\n const pp = ui.pendingPlacement;\n const key = pp ? `${pp.type}:${(pp.data as any)?.svgId ?? ''}:${(pp.data as any)?.mediaKind ?? ''}` : null;\n const prev = prevPlacementKeyRef.current;\n prevPlacementKeyRef.current = key;\n if (key && key !== prev && activePanel && STAMP_PANEL_IDS.has(activePanel)) {\n setActivePanel(null);\n }\n }, [ui.pendingPlacement, compact, activePanel]);\n\n // Floating-panel drag: highlight the dock edge it hovers over.\n const [dropHint, setDropHint] = useState<'left' | 'right' | null>(null);\n const handleDock = useCallback((tabId: string, dock: FlowPanelDock) => setPanelDock(tabId, dock), [setPanelDock]);\n // Each panel has its own close (✕) button; closed panels come back via the\n // matching toolbar toggle (shapes/icons/media share the palette flag).\n const handleClose = useCallback((tabId: string) => {\n if (tabId === 'inspector') setShowInspector(false);\n else if (tabId === 'outline') setShowOutline(false);\n else if (tabId === 'json') setShowJson(false);\n else if (tabId === 'ai') setShowAI(false);\n else setShowPalette(false);\n }, [setShowInspector, setShowOutline, setShowJson, setShowAI, setShowPalette]);\n\n // NOTE: every hook must run before this early return — moving hooks below it\n // would break the hooks-of-render contract in compact mode.\n if (compact && !presentation) {\n const activeDef = visibleTabs.find(d => d.id === activePanel) ?? null;\n return (\n <div className=\"flow-workspace\">\n {toolbar}\n {visibleTabs.length > 0 && (\n <div className=\"flow-mobile-panel-bar\">\n <Select\n placeholder=\"选择面板…\"\n options={visibleTabs.map(d => ({ value: d.id, label: d.label }))}\n value={activePanel ?? undefined}\n onChange={(v) => {\n // Switching panels always opens a clean \"pick a type\" state: a\n // stale armed stamp (continuous placement) would otherwise be\n // placed by the next canvas tap or toggle the tapped item off.\n setPendingPlacement(null);\n setActivePanel(String(v));\n }}\n />\n </div>\n )}\n <div className=\"flow-workspace-main\">\n <div className=\"flow-stage\">\n {children}\n </div>\n {activeDef && (\n <div className=\"flow-mobile-panel\">\n <div className=\"flow-mobile-panel-header\">\n <span className=\"flow-mobile-panel-title\">\n {activeDef.icon && <span className=\"flow-panel-tab-icon\">{activeDef.icon}</span>}\n {activeDef.label}\n </span>\n <button\n type=\"button\"\n className=\"flow-mobile-panel-close\"\n aria-label=\"关闭面板\"\n onClick={() => setActivePanel(null)}\n >✕</button>\n </div>\n <div className=\"flow-mobile-panel-body\">{tabContent(activeDef.id)}</div>\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Desktop layout: the left/right panel groups are merged into one panel\n // list docked on the left by default. Panels are switched with a dropdown\n // Select; users can move any panel to the right dock or let it float (via\n // header buttons or by dragging it onto a workspace edge). Docks without\n // panels are not rendered so the canvas fills the freed space.\n const getDock = (id: string): FlowPanelDock => panelDocks[id] ?? 'left';\n const leftTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'left')\n .map(toPanelTab);\n const rightTabs: PanelTab[] = visibleTabs\n .filter(def => getDock(def.id) === 'right')\n .map(toPanelTab);\n const floatList = visibleTabs.filter(def => getDock(def.id) === 'float');\n\n return (\n <div className=\"flow-workspace\">\n {/* Slim full-width toolbar strip above panels + canvas. */}\n {!presentation && toolbar}\n <div className=\"flow-workspace-main\">\n {!presentation && leftTabs.length > 0 && (\n <FlowPanelGroup\n tabs={leftTabs}\n defaultTab={leftTabs[0]?.id}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"left\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n <div className=\"flow-stage\">\n {children}\n </div>\n {!presentation && rightTabs.length > 0 && (\n <FlowPanelGroup\n tabs={rightTabs}\n defaultTab={rightTabs[0]?.id}\n resizeEdge=\"left\"\n defaultWidth={220}\n dock=\"right\"\n onDock={handleDock}\n onClose={handleClose}\n />\n )}\n {/* Floating panels drift above the docks; dragging one over a\n workspace edge shows a drop-zone hint and dropping attaches it to\n that dock. Rendered as a direct child of the (position:relative)\n workspace-main so they are not clipped by the stage's\n `overflow: hidden`. */}\n {!presentation && floatList.map((def, i) => (\n <FlowPanelGroup\n key={def.id}\n tabs={[toPanelTab(def)]}\n resizeEdge=\"right\"\n defaultWidth={220}\n dock=\"float\"\n style={{ top: 48 + i * 40, left: 24 + i * 30 }}\n onDock={handleDock}\n onClose={handleClose}\n onDragHintChange={setDropHint}\n />\n ))}\n {!presentation && dropHint && (\n <div className={`flow-dock-dropzone flow-dock-dropzone--${dropHint}`}>\n <span>{dropHint === 'left' ? '⇤ 停靠左侧' : '停靠右侧 ⇥'}</span>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction MiniMapWrapper({\n canvasRef,\n pixiRef,\n miniMapRef,\n}: {\n canvasRef: React.RefObject<HTMLCanvasElement | null>;\n pixiRef: React.RefObject<PixiApp | null>;\n miniMapRef: React.RefObject<MiniMapRenderer | null>;\n}) {\n const { showMiniMap, setViewport, presentation } = useFlowUI();\n const draggingRef = useRef(false);\n\n // Move the main canvas so that the world point under the minimap click is\n // centered in the viewport. Routed through setViewport so the change syncs\n // with the ViewportManager (setting world.position directly would be\n // overwritten on the next viewport apply).\n const navigateTo = useCallback((clientX: number, clientY: number) => {\n const canvas = canvasRef.current;\n const pixi = pixiRef.current;\n const mm = miniMapRef.current;\n if (!canvas || !pixi || pixi.destroyed || !mm) return;\n\n const rect = canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return;\n // CSS pixels -> canvas backing pixels.\n const { width: cw, height: ch } = mm.size;\n const px = ((clientX - rect.left) / rect.width) * cw;\n const py = ((clientY - rect.top) / rect.height) * ch;\n\n const world = mm.minimapToWorld(px, py);\n if (!world) return;\n\n const zoom = pixi.world.scale.x || 1;\n const screenW = pixi.app.screen.width;\n const screenH = pixi.app.screen.height;\n setViewport({\n x: screenW / 2 - world.x * zoom,\n y: screenH / 2 - world.y * zoom,\n zoom,\n });\n }, [canvasRef, pixiRef, miniMapRef, setViewport]);\n\n const onPointerDown = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault();\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n draggingRef.current = true;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerMove = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n navigateTo(e.clientX, e.clientY);\n }, [navigateTo]);\n\n const onPointerUp = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n draggingRef.current = false;\n try { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); } catch { /* noop */ }\n }, []);\n\n return (\n <div\n className=\"flow-minimap\"\n style={{ display: showMiniMap && !presentation ? undefined : 'none', cursor: 'pointer' }}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n title=\"点击或拖动以移动画布\"\n >\n <canvas ref={canvasRef} width={180} height={120} style={{ width: '100%', height: '100%', pointerEvents: 'none' }} />\n </div>\n );\n}\n\n/**\n * Find the line range (1-based) of a JSON object with the given id.\n */\nfunction findElementLineRange(jsonStr: string, elementId: string): { startLine: number; endLine: number } | null {\n const idPattern = `\"id\": \"${elementId}\"`;\n const idx = jsonStr.indexOf(idPattern);\n if (idx === -1) return null;\n\n let braceDepth = 0;\n let startIdx = -1;\n for (let i = idx; i >= 0; i--) {\n if (jsonStr[i] === '}') braceDepth++;\n if (jsonStr[i] === '{') {\n if (braceDepth === 0) { startIdx = i; break; }\n braceDepth--;\n }\n }\n if (startIdx === -1) return null;\n\n braceDepth = 0;\n let endIdx = -1;\n for (let i = startIdx; i < jsonStr.length; i++) {\n if (jsonStr[i] === '{') braceDepth++;\n if (jsonStr[i] === '}') {\n braceDepth--;\n if (braceDepth === 0) { endIdx = i; break; }\n }\n }\n if (endIdx === -1) return null;\n\n const startLine = jsonStr.slice(0, startIdx).split('\\n').length;\n const endLine = jsonStr.slice(0, endIdx + 1).split('\\n').length;\n return { startLine, endLine };\n}\n\nfunction clearLineHighlights(container: HTMLElement) {\n container.querySelectorAll('.cm-line.flow-json-hl').forEach(el => el.classList.remove('flow-json-hl'));\n}\n\nfunction applyLineHighlightsViaView(handle: CodeEditorHandle, startLine: number, endLine: number) {\n const view = handle.getView();\n if (!view) return;\n for (let ln = startLine; ln <= endLine; ln++) {\n try {\n const lineInfo = view.state.doc.line(ln);\n const dom = view.domAtPos(lineInfo.from);\n const lineEl = dom.node instanceof HTMLElement\n ? dom.node.closest('.cm-line')\n : dom.node.parentElement?.closest('.cm-line');\n if (lineEl) lineEl.classList.add('flow-json-hl');\n } catch { /* line not in viewport */ }\n }\n}\n\nfunction JsonEditorPanel() {\n const { setDoc, currentCanvasId, selection, currentCanvas } = useFlowContext();\n const [jsonStr, setJsonStr] = useState('');\n const [error, setError] = useState<string | null>(null);\n const skipNextSync = useRef(false);\n const editorRef = useRef<CodeEditorHandle>(null);\n const wrapRef = useRef<HTMLDivElement>(null);\n\n const singleId = useMemo(() => {\n const total = selection.nodeIds.size + selection.edgeIds.size + selection.lineIds.size;\n if (total !== 1) return null;\n if (selection.nodeIds.size === 1) return [...selection.nodeIds][0];\n if (selection.edgeIds.size === 1) return [...selection.edgeIds][0];\n if (selection.lineIds.size === 1) return [...selection.lineIds][0];\n return null;\n }, [selection]);\n\n useEffect(() => {\n if (skipNextSync.current) { skipNextSync.current = false; return; }\n setJsonStr(JSON.stringify(currentCanvas, null, 2));\n setError(null);\n }, [currentCanvas]);\n\n useEffect(() => {\n const wrap = wrapRef.current;\n if (wrap) clearLineHighlights(wrap);\n if (!singleId) return;\n\n const timer = setTimeout(() => {\n const range = findElementLineRange(jsonStr, singleId);\n if (!range || !wrapRef.current) return;\n\n const view = editorRef.current?.getView();\n if (!view) return;\n\n const w = wrapRef.current;\n const scroller = view.scrollDOM;\n\n scroller.style.scrollBehavior = 'smooth';\n\n const lineInfo = view.state.doc.line(range.startLine);\n view.dispatch({\n effects: EditorView.scrollIntoView(lineInfo.from, { y: 'start', yMargin: 0 }),\n });\n\n const onScrollEnd = () => {\n scroller.style.scrollBehavior = '';\n clearLineHighlights(w);\n applyLineHighlightsViaView(editorRef.current!, range.startLine, range.endLine);\n };\n\n let scrollTimer: ReturnType<typeof setTimeout>;\n const onScroll = () => {\n clearTimeout(scrollTimer);\n scrollTimer = setTimeout(onScrollEnd, 100);\n };\n scroller.addEventListener('scroll', onScroll);\n scrollTimer = setTimeout(() => {\n scroller.removeEventListener('scroll', onScroll);\n onScrollEnd();\n }, 800);\n }, 120);\n return () => clearTimeout(timer);\n }, [singleId, jsonStr]);\n\n const handleChange = useCallback((value: string) => {\n setJsonStr(value);\n try {\n const parsed = JSON.parse(value);\n if (parsed && Array.isArray(parsed.nodes) && Array.isArray(parsed.edges) && Array.isArray(parsed.lines)) {\n setError(null);\n skipNextSync.current = true;\n setDoc(prev => ({\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasId]: parsed },\n }));\n } else {\n setError('JSON must have nodes, edges, lines arrays');\n }\n } catch (e: any) {\n setError(e.message?.slice(0, 60) ?? 'Invalid JSON');\n }\n }, [setDoc, currentCanvasId]);\n\n const label = singleId\n ? (selection.nodeIds.has(singleId) ? 'Node' : selection.edgeIds.has(singleId) ? 'Edge' : 'Line')\n : null;\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>\n <div className=\"flow-json-header\">\n <span className=\"flow-json-scope\">\n {label ? `${label}: ${singleId!.slice(0, 8)}` : `Canvas`}\n </span>\n </div>\n {error && (\n <div style={{ fontSize: 11, color: 'oklch(var(--er))', padding: '4px 0', flexShrink: 0 }}>\n {error}\n </div>\n )}\n <div ref={wrapRef} style={{ flex: 1, minHeight: 0 }}>\n <CodeEditor\n ref={editorRef}\n value={jsonStr}\n onChange={handleChange}\n language=\"json\"\n lineNumbers={false}\n height=\"100%\"\n highlightActiveLine={false}\n />\n </div>\n </div>\n );\n}\n\nfunction FlowContextMenuWire() {\n const { contextMenu, setContextMenu } = useFlowUI();\n const { doc, setDoc, currentCanvasId, pushCanvas, setSelection } = useFlowContext();\n const { duplicate } = useClipboard();\n\n if (!contextMenu) return null;\n\n const canvas = doc.canvases[currentCanvasId];\n if (!canvas) { setContextMenu(null); return null; }\n\n const node = contextMenu.nodeId ? canvas.nodes.find(n => n.id === contextMenu.nodeId) : null;\n const items: ContextMenuItem[] = [];\n\n if (node) {\n // Duplicate the node (Cmd/Ctrl+D equivalent). Ensure it is selected first so\n // the clone covers the intended target even on a right-click without a prior\n // left-click selection.\n items.push({\n label: 'Duplicate',\n icon: '⧉',\n action: () => {\n duplicate(24, 24, { nodeIds: new Set([node.id]) });\n },\n });\n items.push({ label: '---', action: () => {} });\n\n const hasChild = !!node.data.childCanvasId;\n\n if (hasChild) {\n items.push({\n label: 'Enter Sub-canvas',\n icon: '↓',\n action: () => {\n pushCanvas(node.data.childCanvasId!);\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n },\n });\n items.push({ label: '---', action: () => {} });\n items.push({\n label: 'Delete Sub-canvas',\n icon: '🗑',\n danger: true,\n action: () => {\n const childId = node.data.childCanvasId!;\n setDoc(prev => {\n const canvases = { ...prev.canvases };\n collectAndRemoveCanvases(canvases, childId);\n const c = canvases[currentCanvasId];\n if (!c) return prev;\n canvases[currentCanvasId] = {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId: undefined } }\n : n,\n ),\n };\n const stack = prev.stack.filter(id => canvases[id]);\n if (stack.length === 0) stack.push(ROOT_CANVAS_ID);\n return { ...prev, canvases, stack };\n });\n },\n });\n } else {\n items.push({\n label: 'Create Sub-canvas',\n icon: '⊞',\n action: () => {\n const childCanvasId = generateId('canvas');\n setDoc(prev => {\n const c = prev.canvases[currentCanvasId];\n if (!c) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasId]: {\n ...c,\n nodes: c.nodes.map(n =>\n n.id === node.id\n ? { ...n, data: { ...n.data, childCanvasId } }\n : n,\n ),\n },\n [childCanvasId]: { nodes: [], edges: [], lines: [] },\n },\n };\n });\n pushCanvas(childCanvasId);\n },\n });\n }\n }\n\n if (items.length === 0) return null;\n\n return (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n items={items}\n onClose={() => setContextMenu(null)}\n />\n );\n}\n\nfunction collectAndRemoveCanvases(\n canvases: Record<string, FlowCanvasData>,\n canvasId: string,\n): void {\n const canvas = canvases[canvasId];\n if (!canvas) return;\n for (const node of canvas.nodes) {\n if (node.data.childCanvasId) {\n collectAndRemoveCanvases(canvases, node.data.childCanvasId);\n }\n }\n delete canvases[canvasId];\n}\n"],"mappings":"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"}
@@ -3,6 +3,8 @@ import type { FlowDocument, SelectionState, FlowCanvasData } from '../types';
3
3
  export interface FlowContextValue {
4
4
  doc: FlowDocument;
5
5
  setDoc: React.Dispatch<React.SetStateAction<FlowDocument>>;
6
+ /** Commit without recording undo history (transient canvas navigation, e.g. PDF export). */
7
+ setDocTransient: React.Dispatch<React.SetStateAction<FlowDocument>>;
6
8
  currentCanvasId: string;
7
9
  currentCanvas: FlowCanvasData;
8
10
  selection: SelectionState;
@@ -16,8 +18,10 @@ export declare function useFlowContext(): FlowContextValue;
16
18
  export interface FlowProviderProps {
17
19
  doc: FlowDocument;
18
20
  setDoc: React.Dispatch<React.SetStateAction<FlowDocument>>;
21
+ /** History-free update channel; falls back to `setDoc` when not provided. */
22
+ setDocTransient?: React.Dispatch<React.SetStateAction<FlowDocument>>;
19
23
  selection: SelectionState;
20
24
  setSelection: React.Dispatch<React.SetStateAction<SelectionState>>;
21
25
  children: React.ReactNode;
22
26
  }
23
- export declare function FlowProvider({ doc, setDoc, selection, setSelection, children }: FlowProviderProps): React.JSX.Element;
27
+ export declare function FlowProvider({ doc, setDoc, setDocTransient, selection, setSelection, children }: FlowProviderProps): React.JSX.Element;
@@ -13,51 +13,53 @@ var o = {
13
13
  edges: [],
14
14
  lines: []
15
15
  };
16
- function s({ doc: e, setDoc: t, selection: a, setSelection: s, children: c }) {
17
- let l = e.stack[e.stack.length - 1] ?? "root", u = e.canvases[l] ?? o, d = n(() => ({
16
+ function s({ doc: e, setDoc: t, setDocTransient: a, selection: s, setSelection: c, children: l }) {
17
+ let u = e.stack[e.stack.length - 1] ?? "root", d = e.canvases[u] ?? o, f = a ?? t, p = n(() => ({
18
18
  nodeIds: /* @__PURE__ */ new Set(),
19
19
  edgeIds: /* @__PURE__ */ new Set(),
20
20
  lineIds: /* @__PURE__ */ new Set()
21
- }), []), f = n(() => (e) => {
21
+ }), []), m = n(() => (e) => {
22
22
  t((t) => ({
23
23
  ...t,
24
24
  stack: [...t.stack, e]
25
- })), s(d);
25
+ })), c(p);
26
26
  }, [
27
27
  t,
28
- s,
29
- d
30
- ]), p = n(() => () => {
28
+ c,
29
+ p
30
+ ]), h = n(() => () => {
31
31
  t((e) => ({
32
32
  ...e,
33
33
  stack: e.stack.length > 1 ? e.stack.slice(0, -1) : e.stack
34
- })), s(d);
34
+ })), c(p);
35
35
  }, [
36
36
  t,
37
- s,
38
- d
39
- ]), m = n(() => ({
37
+ c,
38
+ p
39
+ ]), g = n(() => ({
40
40
  doc: e,
41
41
  setDoc: t,
42
- currentCanvasId: l,
43
- currentCanvas: u,
44
- selection: a,
45
- setSelection: s,
46
- pushCanvas: f,
47
- popCanvas: p
42
+ setDocTransient: f,
43
+ currentCanvasId: u,
44
+ currentCanvas: d,
45
+ selection: s,
46
+ setSelection: c,
47
+ pushCanvas: m,
48
+ popCanvas: h
48
49
  }), [
49
50
  e,
50
51
  t,
51
- l,
52
+ f,
52
53
  u,
53
- a,
54
+ d,
54
55
  s,
55
- f,
56
- p
56
+ c,
57
+ m,
58
+ h
57
59
  ]);
58
60
  return /* @__PURE__ */ r(i.Provider, {
59
- value: m,
60
- children: c
61
+ value: g,
62
+ children: l
61
63
  });
62
64
  }
63
65
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"FlowContext.js","names":[],"sources":["../../../../../src/components/pro/Flow/context/FlowContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react';\nimport type {\n FlowDocument,\n FlowNode,\n FlowEdge,\n FlowLine,\n SelectionState,\n FlowCanvasData,\n} from '../types';\nimport { ROOT_CANVAS_ID } from '../constants';\n\nexport interface FlowContextValue {\n doc: FlowDocument;\n setDoc: React.Dispatch<React.SetStateAction<FlowDocument>>;\n currentCanvasId: string;\n currentCanvas: FlowCanvasData;\n selection: SelectionState;\n setSelection: React.Dispatch<React.SetStateAction<SelectionState>>;\n /** Push into child canvas */\n pushCanvas: (canvasId: string) => void;\n /** Pop back to parent canvas */\n popCanvas: () => void;\n}\n\nconst FlowContext = createContext<FlowContextValue | null>(null);\n\nexport function useFlowContext(): FlowContextValue {\n const ctx = useContext(FlowContext);\n if (!ctx) throw new Error('useFlowContext must be used within FlowProvider');\n return ctx;\n}\n\nexport interface FlowProviderProps {\n doc: FlowDocument;\n setDoc: React.Dispatch<React.SetStateAction<FlowDocument>>;\n selection: SelectionState;\n setSelection: React.Dispatch<React.SetStateAction<SelectionState>>;\n children: React.ReactNode;\n}\n\nconst EMPTY_CANVAS: FlowCanvasData = { nodes: [], edges: [], lines: [] };\n\nexport function FlowProvider({ doc, setDoc, selection, setSelection, children }: FlowProviderProps) {\n const currentCanvasId = doc.stack[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const currentCanvas = doc.canvases[currentCanvasId] ?? EMPTY_CANVAS;\n\n const emptySelection: SelectionState = useMemo(() => ({\n nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set(),\n }), []);\n\n const pushCanvas = useMemo(() => (canvasId: string) => {\n setDoc(prev => ({ ...prev, stack: [...prev.stack, canvasId] }));\n setSelection(emptySelection);\n }, [setDoc, setSelection, emptySelection]);\n\n const popCanvas = useMemo(() => () => {\n setDoc(prev => ({\n ...prev,\n stack: prev.stack.length > 1 ? prev.stack.slice(0, -1) : prev.stack,\n }));\n setSelection(emptySelection);\n }, [setDoc, setSelection, emptySelection]);\n\n const value = useMemo<FlowContextValue>(() => ({\n doc,\n setDoc,\n currentCanvasId,\n currentCanvas,\n selection,\n setSelection,\n pushCanvas,\n popCanvas,\n }), [doc, setDoc, currentCanvasId, currentCanvas, selection, setSelection, pushCanvas, popCanvas]);\n\n return <FlowContext.Provider value={value}>{children}</FlowContext.Provider>;\n}\n"],"mappings":";;;;AAwBA,IAAM,IAAc,EAAuC,IAAI;AAE/D,SAAgB,IAAmC;CACjD,IAAM,IAAM,EAAW,CAAW;CAClC,IAAI,CAAC,GAAK,MAAU,MAAM,iDAAiD;CAC3E,OAAO;AACT;AAUA,IAAM,IAA+B;CAAE,OAAO,CAAC;CAAG,OAAO,CAAC;CAAG,OAAO,CAAC;AAAE;AAEvE,SAAgB,EAAa,EAAE,QAAK,WAAQ,cAAW,iBAAc,eAA+B;CAClG,IAAM,IAAkB,EAAI,MAAM,EAAI,MAAM,SAAS,MAAA,QAC/C,IAAgB,EAAI,SAAS,MAAoB,GAEjD,IAAiC,SAAe;EACpD,yBAAS,IAAI,IAAI;EAAG,yBAAS,IAAI,IAAI;EAAG,yBAAS,IAAI,IAAI;CAC3D,IAAI,CAAC,CAAC,GAEA,IAAa,SAAe,MAAqB;EAErD,AADA,GAAO,OAAS;GAAE,GAAG;GAAM,OAAO,CAAC,GAAG,EAAK,OAAO,CAAQ;EAAE,EAAE,GAC9D,EAAa,CAAc;CAC7B,GAAG;EAAC;EAAQ;EAAc;CAAc,CAAC,GAEnC,IAAY,cAAoB;EAKpC,AAJA,GAAO,OAAS;GACd,GAAG;GACH,OAAO,EAAK,MAAM,SAAS,IAAI,EAAK,MAAM,MAAM,GAAG,EAAE,IAAI,EAAK;EAChE,EAAE,GACF,EAAa,CAAc;CAC7B,GAAG;EAAC;EAAQ;EAAc;CAAc,CAAC,GAEnC,IAAQ,SAAiC;EAC7C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,IAAI;EAAC;EAAK;EAAQ;EAAiB;EAAe;EAAW;EAAc;EAAY;CAAS,CAAC;CAEjG,OAAO,kBAAC,EAAY,UAAb;EAA6B;EAAQ;CAA+B,CAAA;AAC7E"}
1
+ {"version":3,"file":"FlowContext.js","names":[],"sources":["../../../../../src/components/pro/Flow/context/FlowContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react';\nimport type {\n FlowDocument,\n FlowLine,\n SelectionState,\n FlowCanvasData,\n} from '../types';\nimport { ROOT_CANVAS_ID } from '../constants';\n\nexport interface FlowContextValue {\n doc: FlowDocument;\n setDoc: React.Dispatch<React.SetStateAction<FlowDocument>>;\n /** Commit without recording undo history (transient canvas navigation, e.g. PDF export). */\n setDocTransient: React.Dispatch<React.SetStateAction<FlowDocument>>;\n currentCanvasId: string;\n currentCanvas: FlowCanvasData;\n selection: SelectionState;\n setSelection: React.Dispatch<React.SetStateAction<SelectionState>>;\n /** Push into child canvas */\n pushCanvas: (canvasId: string) => void;\n /** Pop back to parent canvas */\n popCanvas: () => void;\n}\n\nconst FlowContext = createContext<FlowContextValue | null>(null);\n\nexport function useFlowContext(): FlowContextValue {\n const ctx = useContext(FlowContext);\n if (!ctx) throw new Error('useFlowContext must be used within FlowProvider');\n return ctx;\n}\n\nexport interface FlowProviderProps {\n doc: FlowDocument;\n setDoc: React.Dispatch<React.SetStateAction<FlowDocument>>;\n /** History-free update channel; falls back to `setDoc` when not provided. */\n setDocTransient?: React.Dispatch<React.SetStateAction<FlowDocument>>;\n selection: SelectionState;\n setSelection: React.Dispatch<React.SetStateAction<SelectionState>>;\n children: React.ReactNode;\n}\n\nconst EMPTY_CANVAS: FlowCanvasData = { nodes: [], edges: [], lines: [] };\n\nexport function FlowProvider({ doc, setDoc, setDocTransient, selection, setSelection, children }: FlowProviderProps) {\n const currentCanvasId = doc.stack[doc.stack.length - 1] ?? ROOT_CANVAS_ID;\n const currentCanvas = doc.canvases[currentCanvasId] ?? EMPTY_CANVAS;\n const transient = setDocTransient ?? setDoc;\n\n const emptySelection: SelectionState = useMemo(() => ({\n nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set(),\n }), []);\n\n const pushCanvas = useMemo(() => (canvasId: string) => {\n setDoc(prev => ({ ...prev, stack: [...prev.stack, canvasId] }));\n setSelection(emptySelection);\n }, [setDoc, setSelection, emptySelection]);\n\n const popCanvas = useMemo(() => () => {\n setDoc(prev => ({\n ...prev,\n stack: prev.stack.length > 1 ? prev.stack.slice(0, -1) : prev.stack,\n }));\n setSelection(emptySelection);\n }, [setDoc, setSelection, emptySelection]);\n\n const value = useMemo<FlowContextValue>(() => ({\n doc,\n setDoc,\n setDocTransient: transient,\n currentCanvasId,\n currentCanvas,\n selection,\n setSelection,\n pushCanvas,\n popCanvas,\n }), [doc, setDoc, transient, currentCanvasId, currentCanvas, selection, setSelection, pushCanvas, popCanvas]);\n\n return <FlowContext.Provider value={value}>{children}</FlowContext.Provider>;\n}\n"],"mappings":";;;;AAwBA,IAAM,IAAc,EAAuC,IAAI;AAE/D,SAAgB,IAAmC;CACjD,IAAM,IAAM,EAAW,CAAW;CAClC,IAAI,CAAC,GAAK,MAAU,MAAM,iDAAiD;CAC3E,OAAO;AACT;AAYA,IAAM,IAA+B;CAAE,OAAO,CAAC;CAAG,OAAO,CAAC;CAAG,OAAO,CAAC;AAAE;AAEvE,SAAgB,EAAa,EAAE,QAAK,WAAQ,oBAAiB,cAAW,iBAAc,eAA+B;CACnH,IAAM,IAAkB,EAAI,MAAM,EAAI,MAAM,SAAS,MAAA,QAC/C,IAAgB,EAAI,SAAS,MAAoB,GACjD,IAAY,KAAmB,GAE/B,IAAiC,SAAe;EACpD,yBAAS,IAAI,IAAI;EAAG,yBAAS,IAAI,IAAI;EAAG,yBAAS,IAAI,IAAI;CAC3D,IAAI,CAAC,CAAC,GAEA,IAAa,SAAe,MAAqB;EAErD,AADA,GAAO,OAAS;GAAE,GAAG;GAAM,OAAO,CAAC,GAAG,EAAK,OAAO,CAAQ;EAAE,EAAE,GAC9D,EAAa,CAAc;CAC7B,GAAG;EAAC;EAAQ;EAAc;CAAc,CAAC,GAEnC,IAAY,cAAoB;EAKpC,AAJA,GAAO,OAAS;GACd,GAAG;GACH,OAAO,EAAK,MAAM,SAAS,IAAI,EAAK,MAAM,MAAM,GAAG,EAAE,IAAI,EAAK;EAChE,EAAE,GACF,EAAa,CAAc;CAC7B,GAAG;EAAC;EAAQ;EAAc;CAAc,CAAC,GAEnC,IAAQ,SAAiC;EAC7C;EACA;EACA,iBAAiB;EACjB;EACA;EACA;EACA;EACA;EACA;CACF,IAAI;EAAC;EAAK;EAAQ;EAAW;EAAiB;EAAe;EAAW;EAAc;EAAY;CAAS,CAAC;CAE5G,OAAO,kBAAC,EAAY,UAAb;EAA6B;EAAQ;CAA+B,CAAA;AAC7E"}
@@ -14,7 +14,7 @@ function u(e) {
14
14
  });
15
15
  }
16
16
  function d(d) {
17
- let { doc: f, setDoc: p } = e(), { showAnchors: m, setShowAnchors: h } = t();
17
+ let { doc: f, setDocTransient: p } = e(), { showAnchors: m, setShowAnchors: h } = t();
18
18
  return l(async () => {
19
19
  let e = i(f);
20
20
  if (e.length === 0) return !1;
@@ -1 +1 @@
1
- {"version":3,"file":"usePdfExport.js","names":[],"sources":["../../../../../src/components/pro/Flow/hooks/usePdfExport.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useFlowContext } from '../context/FlowContext';\nimport { useFlowUI } from '../context/FlowUIContext';\nimport { getDocumentSlides, anchorFocusRect, canvasStackTo } from '../nodes/animAnchors';\nimport { buildPdfFromJpegs, pngDataUrlToJpeg } from '../utils/pdfExport';\nimport { downloadDataURL, safeFileBaseName } from './useFlowImportExport';\nimport type { PixiApp } from '../canvas/PixiApp';\n\n/** Await the next N animation frames (lets Pixi settle after a state change). */\nfunction nextFrames(n: number): Promise<void> {\n return new Promise((resolve) => {\n let left = n;\n const step = () => {\n if (--left <= 0) resolve();\n else requestAnimationFrame(step);\n };\n requestAnimationFrame(step);\n });\n}\n\n/**\n * Exports the document's animation anchors as a single PDF. Each page is cropped\n * exactly to an anchor's world rectangle (not the whole viewport), so the PDF\n * contains only the framed slide content. Pages follow the global anchor order,\n * navigating across sub-canvases as needed.\n *\n * Returns a callback; it no-ops (returns false) when there are no anchors.\n */\nexport function usePdfExport(pixiRef: React.RefObject<PixiApp | null>) {\n const { doc, setDoc } = useFlowContext();\n const { showAnchors, setShowAnchors } = useFlowUI();\n\n return useCallback(async (): Promise<boolean> => {\n const slides = getDocumentSlides(doc);\n if (slides.length === 0) return false;\n\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return false;\n\n // Snapshot state we temporarily change, so we can restore it afterward.\n const originalStack = doc.stack.slice();\n const anchorsWereVisible = showAnchors;\n\n // Hide anchor frames so they don't appear in the exported pages. The region\n // capture drives the world transform directly and restores it each time, so\n // the interactive viewport is untouched.\n setShowAnchors(false);\n await nextFrames(2);\n\n // Render slides at a crisp scale so text/shapes stay sharp in the PDF.\n const CAPTURE_SCALE = 2;\n const pages: Awaited<ReturnType<typeof pngDataUrlToJpeg>>[] = [];\n try {\n for (const slide of slides) {\n // Switch to the slide's canvas if it lives on a nested sub-canvas.\n const stack = canvasStackTo(doc, slide.canvasId);\n if (stack) {\n setDoc((prev) => ({ ...prev, stack }));\n // Canvas swap needs a couple frames to re-render the new node set.\n await nextFrames(3);\n }\n\n const r = anchorFocusRect(slide.node);\n const shot = await pixi.exportRegionPNG(r, {\n scale: CAPTURE_SCALE,\n backgroundColor: 0xffffff,\n });\n if (shot) pages.push(await pngDataUrlToJpeg(shot.dataUrl));\n }\n } finally {\n // Restore prior editor state regardless of success/failure.\n setShowAnchors(anchorsWereVisible);\n setDoc((prev) => ({ ...prev, stack: originalStack }));\n }\n\n if (pages.length === 0) return false;\n const blob = buildPdfFromJpegs(pages);\n const url = URL.createObjectURL(blob);\n downloadDataURL(url, `${safeFileBaseName(doc.title)}.pdf`);\n URL.revokeObjectURL(url);\n return true;\n }, [doc, setDoc, showAnchors, setShowAnchors, pixiRef]);\n}\n"],"mappings":";;;;;;;AASA,SAAS,EAAW,GAA0B;CAC5C,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAI,IAAO,GACL,UAAa;GACjB,AAAI,EAAE,KAAQ,IAAG,EAAQ,IACpB,sBAAsB,CAAI;EACjC;EACA,sBAAsB,CAAI;CAC5B,CAAC;AACH;AAUA,SAAgB,EAAa,GAA0C;CACrE,IAAM,EAAE,QAAK,cAAW,EAAe,GACjC,EAAE,gBAAa,sBAAmB,EAAU;CAElD,OAAO,EAAY,YAA8B;EAC/C,IAAM,IAAS,EAAkB,CAAG;EACpC,IAAI,EAAO,WAAW,GAAG,OAAO;EAEhC,IAAM,IAAO,EAAQ;EACrB,IAAI,CAAC,KAAQ,EAAK,WAAW,OAAO;EAGpC,IAAM,IAAgB,EAAI,MAAM,MAAM,GAChC,IAAqB;EAM3B,AADA,EAAe,EAAK,GACpB,MAAM,EAAW,CAAC;EAGlB,IACM,IAAwD,CAAC;EAC/D,IAAI;GACF,KAAK,IAAM,KAAS,GAAQ;IAE1B,IAAM,IAAQ,EAAc,GAAK,EAAM,QAAQ;IAC/C,AAAI,MACF,GAAQ,OAAU;KAAE,GAAG;KAAM;IAAM,EAAE,GAErC,MAAM,EAAW,CAAC;IAGpB,IAAM,IAAI,EAAgB,EAAM,IAAI,GAC9B,IAAO,MAAM,EAAK,gBAAgB,GAAG;KACzC,OAAO;KACP,iBAAiB;IACnB,CAAC;IACD,AAAI,KAAM,EAAM,KAAK,MAAM,EAAiB,EAAK,OAAO,CAAC;GAC3D;EACF,UAAU;GAGR,AADA,EAAe,CAAkB,GACjC,GAAQ,OAAU;IAAE,GAAG;IAAM,OAAO;GAAc,EAAE;EACtD;EAEA,IAAI,EAAM,WAAW,GAAG,OAAO;EAC/B,IAAM,IAAO,EAAkB,CAAK,GAC9B,IAAM,IAAI,gBAAgB,CAAI;EAGpC,OAFA,EAAgB,GAAK,GAAG,EAAiB,EAAI,KAAK,EAAE,KAAK,GACzD,IAAI,gBAAgB,CAAG,GAChB;CACT,GAAG;EAAC;EAAK;EAAQ;EAAa;EAAgB;CAAO,CAAC;AACxD"}
1
+ {"version":3,"file":"usePdfExport.js","names":[],"sources":["../../../../../src/components/pro/Flow/hooks/usePdfExport.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useFlowContext } from '../context/FlowContext';\nimport { useFlowUI } from '../context/FlowUIContext';\nimport { getDocumentSlides, anchorFocusRect, canvasStackTo } from '../nodes/animAnchors';\nimport { buildPdfFromJpegs, pngDataUrlToJpeg } from '../utils/pdfExport';\nimport { downloadDataURL, safeFileBaseName } from './useFlowImportExport';\nimport type { PixiApp } from '../canvas/PixiApp';\n\n/** Await the next N animation frames (lets Pixi settle after a state change). */\nfunction nextFrames(n: number): Promise<void> {\n return new Promise((resolve) => {\n let left = n;\n const step = () => {\n if (--left <= 0) resolve();\n else requestAnimationFrame(step);\n };\n requestAnimationFrame(step);\n });\n}\n\n/**\n * Exports the document's animation anchors as a single PDF. Each page is cropped\n * exactly to an anchor's world rectangle (not the whole viewport), so the PDF\n * contains only the framed slide content. Pages follow the global anchor order,\n * navigating across sub-canvases as needed.\n *\n * Returns a callback; it no-ops (returns false) when there are no anchors.\n */\nexport function usePdfExport(pixiRef: React.RefObject<PixiApp | null>) {\n const { doc, setDocTransient } = useFlowContext();\n const { showAnchors, setShowAnchors } = useFlowUI();\n\n return useCallback(async (): Promise<boolean> => {\n const slides = getDocumentSlides(doc);\n if (slides.length === 0) return false;\n\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return false;\n\n // Snapshot state we temporarily change, so we can restore it afterward.\n const originalStack = doc.stack.slice();\n const anchorsWereVisible = showAnchors;\n\n // Hide anchor frames so they don't appear in the exported pages. The region\n // capture drives the world transform directly and restores it each time, so\n // the interactive viewport is untouched.\n setShowAnchors(false);\n await nextFrames(2);\n\n // Render slides at a crisp scale so text/shapes stay sharp in the PDF.\n const CAPTURE_SCALE = 2;\n const pages: Awaited<ReturnType<typeof pngDataUrlToJpeg>>[] = [];\n try {\n for (const slide of slides) {\n // Switch to the slide's canvas if it lives on a nested sub-canvas.\n // Transient updates: slide paging must not pollute the undo history.\n const stack = canvasStackTo(doc, slide.canvasId);\n if (stack) {\n setDocTransient((prev) => ({ ...prev, stack }));\n // Canvas swap needs a couple frames to re-render the new node set.\n await nextFrames(3);\n }\n\n const r = anchorFocusRect(slide.node);\n const shot = await pixi.exportRegionPNG(r, {\n scale: CAPTURE_SCALE,\n backgroundColor: 0xffffff,\n });\n if (shot) pages.push(await pngDataUrlToJpeg(shot.dataUrl));\n }\n } finally {\n // Restore prior editor state regardless of success/failure.\n setShowAnchors(anchorsWereVisible);\n setDocTransient((prev) => ({ ...prev, stack: originalStack }));\n }\n\n if (pages.length === 0) return false;\n const blob = buildPdfFromJpegs(pages);\n const url = URL.createObjectURL(blob);\n downloadDataURL(url, `${safeFileBaseName(doc.title)}.pdf`);\n URL.revokeObjectURL(url);\n return true;\n }, [doc, setDocTransient, showAnchors, setShowAnchors, pixiRef]);\n}\n"],"mappings":";;;;;;;AASA,SAAS,EAAW,GAA0B;CAC5C,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAI,IAAO,GACL,UAAa;GACjB,AAAI,EAAE,KAAQ,IAAG,EAAQ,IACpB,sBAAsB,CAAI;EACjC;EACA,sBAAsB,CAAI;CAC5B,CAAC;AACH;AAUA,SAAgB,EAAa,GAA0C;CACrE,IAAM,EAAE,QAAK,uBAAoB,EAAe,GAC1C,EAAE,gBAAa,sBAAmB,EAAU;CAElD,OAAO,EAAY,YAA8B;EAC/C,IAAM,IAAS,EAAkB,CAAG;EACpC,IAAI,EAAO,WAAW,GAAG,OAAO;EAEhC,IAAM,IAAO,EAAQ;EACrB,IAAI,CAAC,KAAQ,EAAK,WAAW,OAAO;EAGpC,IAAM,IAAgB,EAAI,MAAM,MAAM,GAChC,IAAqB;EAM3B,AADA,EAAe,EAAK,GACpB,MAAM,EAAW,CAAC;EAGlB,IACM,IAAwD,CAAC;EAC/D,IAAI;GACF,KAAK,IAAM,KAAS,GAAQ;IAG1B,IAAM,IAAQ,EAAc,GAAK,EAAM,QAAQ;IAC/C,AAAI,MACF,GAAiB,OAAU;KAAE,GAAG;KAAM;IAAM,EAAE,GAE9C,MAAM,EAAW,CAAC;IAGpB,IAAM,IAAI,EAAgB,EAAM,IAAI,GAC9B,IAAO,MAAM,EAAK,gBAAgB,GAAG;KACzC,OAAO;KACP,iBAAiB;IACnB,CAAC;IACD,AAAI,KAAM,EAAM,KAAK,MAAM,EAAiB,EAAK,OAAO,CAAC;GAC3D;EACF,UAAU;GAGR,AADA,EAAe,CAAkB,GACjC,GAAiB,OAAU;IAAE,GAAG;IAAM,OAAO;GAAc,EAAE;EAC/D;EAEA,IAAI,EAAM,WAAW,GAAG,OAAO;EAC/B,IAAM,IAAO,EAAkB,CAAK,GAC9B,IAAM,IAAI,gBAAgB,CAAI;EAGpC,OAFA,EAAgB,GAAK,GAAG,EAAiB,EAAI,KAAK,EAAE,KAAK,GACzD,IAAI,gBAAgB,CAAG,GAChB;CACT,GAAG;EAAC;EAAK;EAAiB;EAAa;EAAgB;CAAO,CAAC;AACjE"}