dishui 0.0.104 → 0.0.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.release-verified.json +2 -2
- package/dist/components/ChoicePicker/index.js +8 -6
- package/dist/components/ChoicePicker/index.js.map +1 -1
- package/dist/components/Column/index.d.ts +3 -2
- package/dist/components/Column/index.js +5 -17
- package/dist/components/Column/index.js.map +1 -1
- package/dist/components/ConfirmDialog/index.d.ts +20 -0
- package/dist/components/ConfirmDialog/index.js +84 -0
- package/dist/components/ConfirmDialog/index.js.map +1 -0
- package/dist/components/DateTimeInput/index.js +28 -26
- package/dist/components/DateTimeInput/index.js.map +1 -1
- package/dist/components/Input/index.js +1 -1
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/MultipleChoice/index.js +2 -1
- package/dist/components/MultipleChoice/index.js.map +1 -1
- package/dist/components/Row/index.d.ts +3 -2
- package/dist/components/Row/index.js +5 -17
- package/dist/components/Row/index.js.map +1 -1
- package/dist/components/Tab/index.js +80 -0
- package/dist/components/Tab/index.js.map +1 -0
- package/dist/components/Tabs/index.js +28 -33
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tabs/tabNavigation.d.ts +2 -0
- package/dist/components/Tabs/tabNavigation.js +14 -0
- package/dist/components/Tabs/tabNavigation.js.map +1 -0
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.d.ts +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +25 -26
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js +8 -11
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +184 -182
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/archify/convert.js +26 -26
- package/dist/components/pro/Flow/archify/convert.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js +13 -11
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.d.ts +2 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js +15 -15
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js +8 -7
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js +73 -83
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +73 -49
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js +12 -14
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js +113 -113
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/css.d.ts +1 -0
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +113 -111
- package/dist/layouts/Sidebar.js +201 -107
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/utils/flexLayout.d.ts +5 -0
- package/dist/utils/flexLayout.js +19 -0
- package/dist/utils/flexLayout.js.map +1 -0
- package/package.json +63 -57
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.js","names":[],"sources":["../../../../../src/components/pro/Flow/archify/convert.ts"],"sourcesContent":["/**\n * Convert an Archify spec into a native Flow `FlowDocument`.\n *\n * One converter per diagram type reproduces Archify's fixed layout geometry\n * (constants copied from the reference renderers) so the imported diagram\n * matches the reference artifact, then emits editable Flow nodes/edges/lines.\n *\n * When `meta.animation === \"trace\"`, edges are marked `animated` so the Flow\n * presentation / preview mode plays the traveling gradient pulse.\n */\n\nimport type { FlowDocument, FlowNode, FlowEdge, FlowLine } from '../types';\nimport { ROOT_CANVAS_ID } from '../constants';\nimport type {\n ArchifySpec,\n ArchifyArchitectureSpec,\n ArchifyWorkflowSpec,\n ArchifySequenceSpec,\n ArchifyDataflowSpec,\n ArchifyLifecycleSpec,\n} from './spec';\nimport {\n ARCHIFY_LANE_STROKE,\n ARCHIFY_TEXT_MUTED,\n componentStyle,\n stateStyle,\n variantEdgeStyle,\n messageEdgeStyle,\n} from './palette';\nimport { card, frame, edge, sideHandle, uid } from './build';\n\nfunction isTrace(spec: ArchifySpec): boolean {\n return spec.meta?.animation === 'trace';\n}\n\n/* ========================================================================== */\n/* Architecture */\n/* ========================================================================== */\n\nconst ARCH_GRID = { origin: [40, 80], cols: 4, gapX: 30, gapY: 40, cellW: 130, cellH: 64 };\n\nfunction convertArchitecture(spec: ArchifyArchitectureSpec): FlowDocument {\n const trace = isTrace(spec);\n const grid = { ...ARCH_GRID, ...spec.layout };\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const rect = new Map<string, { x: number; y: number; w: number; h: number }>();\n\n for (const c of spec.components) {\n let x: number;\n let y: number;\n if (Array.isArray(c.pos)) {\n [x, y] = c.pos;\n } else if (Number.isInteger(c.row) && Number.isInteger(c.col)) {\n const stepX = grid.cellW + grid.gapX;\n const stepY = grid.cellH + grid.gapY;\n x = grid.origin[0] + (c.col ?? 0) * stepX;\n y = grid.origin[1] + (c.row ?? 0) * stepY;\n } else {\n x = grid.origin[0];\n y = grid.origin[1];\n }\n const w = c.size?.[0] ?? grid.cellW;\n const h = c.size?.[1] ?? grid.cellH;\n rect.set(c.id, { x, y, w, h });\n const style = componentStyle(c.type);\n nodes.push(\n card({\n id: c.id,\n x,\n y,\n width: w,\n height: h,\n label: c.label,\n sublabel: c.sublabel,\n tag: c.tag,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n }),\n );\n }\n\n // Boundaries wrap their member components with padding, rendered behind.\n for (const [i, b] of (spec.boundaries ?? []).entries()) {\n const members = b.wraps.map((id) => rect.get(id)).filter(Boolean) as Array<{\n x: number;\n y: number;\n w: number;\n h: number;\n }>;\n if (members.length === 0) continue;\n const pad = b.pad ?? 26;\n const minX = Math.min(...members.map((m) => m.x)) - pad;\n const minY = Math.min(...members.map((m) => m.y)) - pad - 14;\n const maxX = Math.max(...members.map((m) => m.x + m.w)) + pad;\n const maxY = Math.max(...members.map((m) => m.y + m.h)) + pad;\n nodes.push(\n frame({\n id: `boundary_${i}_${uid('b')}`,\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n label: b.label,\n stroke: b.kind === 'security-group' ? '#fb7185' : ARCHIFY_LANE_STROKE,\n borderStyle: 'dashed',\n labelColor: b.kind === 'security-group' ? '#fb7185' : ARCHIFY_TEXT_MUTED,\n zIndex: -10 + i,\n }),\n );\n }\n\n for (const conn of spec.connections ?? []) {\n const style = variantEdgeStyle(conn.variant);\n edges.push(\n edge({\n id: conn.id,\n source: conn.from,\n target: conn.to,\n sourceHandle: sideHandle(conn.fromSide),\n targetHandle: sideHandle(conn.toSide),\n label: conn.label,\n color: style.color,\n width: conn.width ?? style.width,\n lineStyle: style.lineStyle,\n animated: trace,\n waypoints: conn.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Workflow */\n/* ========================================================================== */\n\nconst WF = {\n laneX: 40,\n laneY: 52,\n laneW: 640,\n laneH: 104,\n laneGap: 20,\n laneTitleH: 30,\n colXs: [88, 220, 300, 430, 500, 625],\n nodeW: 92,\n nodeH: 52,\n};\n\nfunction convertWorkflow(spec: ArchifyWorkflowSpec): FlowDocument {\n const trace = isTrace(spec);\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const laneIndex = new Map(spec.lanes.map((l, i) => [l.id, i]));\n const laneTop = (id: string) =>\n WF.laneY + (laneIndex.get(id) ?? 0) * (WF.laneH + WF.laneGap);\n\n // Lane frames (behind everything).\n for (const lane of spec.lanes) {\n const top = laneTop(lane.id);\n nodes.push(\n frame({\n id: `lane_${lane.id}`,\n x: WF.laneX,\n y: top,\n width: WF.laneW,\n height: WF.laneH,\n label: lane.label,\n stroke: lane.variant === 'exception' ? '#fb7185' : ARCHIFY_LANE_STROKE,\n labelColor: lane.variant === 'exception' ? '#fb7185' : ARCHIFY_TEXT_MUTED,\n zIndex: -20,\n }),\n );\n }\n\n // Phase bands (thin frames spanning columns, drawn just above lanes).\n for (const [i, phase] of (spec.phases ?? []).entries()) {\n const x0 = WF.colXs[phase.fromCol] - WF.nodeW / 2 - 12;\n const x1 = WF.colXs[phase.toCol] + WF.nodeW / 2 + 12;\n nodes.push(\n frame({\n id: `phase_${phase.id}`,\n x: x0,\n y: WF.laneY - 34,\n width: x1 - x0,\n height: 26,\n label: phase.label,\n stroke: variantEdgeStyle(phase.variant).color,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'none',\n zIndex: -15 + i,\n }),\n );\n }\n\n // Workflow groups (nested emphasis frames inside a lane).\n for (const [i, g] of (spec.groups ?? []).entries()) {\n const top = laneTop(g.lane);\n const x0 = WF.colXs[g.fromCol] - WF.nodeW / 2 - 8;\n const x1 = WF.colXs[g.toCol] + WF.nodeW / 2 + 8;\n nodes.push(\n frame({\n id: `wfgroup_${g.id}`,\n x: x0,\n y: top + WF.laneTitleH - 6,\n width: x1 - x0,\n height: WF.laneH - WF.laneTitleH,\n label: g.label,\n stroke: variantEdgeStyle(g.variant).color,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -12 + i,\n }),\n );\n }\n\n for (const n of spec.nodes) {\n const width = n.width ?? WF.nodeW;\n const height = n.height ?? (n.tag ? 68 : WF.nodeH);\n const cx = WF.colXs[n.col] ?? WF.colXs[WF.colXs.length - 1];\n const contentH = WF.laneH - WF.laneTitleH;\n const y = laneTop(n.lane) + WF.laneTitleH + (contentH - height) / 2 + (n.yOffset ?? 0);\n const style = componentStyle(n.type);\n nodes.push(\n card({\n id: n.id,\n x: cx - width / 2,\n y,\n width,\n height,\n label: n.label,\n sublabel: n.sublabel,\n tag: n.tag,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 12,\n }),\n );\n }\n\n const mainPath = new Set<string>();\n const mp = spec.mainPath ?? [];\n for (let i = 0; i < mp.length - 1; i++) mainPath.add(`${mp[i]}->${mp[i + 1]}`);\n\n for (const e of spec.edges) {\n const onMain = mainPath.has(`${e.from}->${e.to}`);\n const style = variantEdgeStyle(e.variant ?? (onMain ? 'emphasis' : 'default'));\n edges.push(\n edge({\n id: e.id,\n source: e.from,\n target: e.to,\n sourceHandle: sideHandle(e.fromSide),\n targetHandle: sideHandle(e.toSide),\n label: e.label,\n color: e.role === 'error' ? '#fb7185' : style.color,\n width: e.width ?? style.width,\n lineStyle: e.role === 'error' ? 'dashed' : style.lineStyle,\n animated: trace && onMain,\n waypoints: e.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Sequence */\n/* ========================================================================== */\n\nfunction convertSequence(spec: ArchifySequenceSpec): FlowDocument {\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n const lines: FlowLine[] = [];\n\n const viewBox = spec.meta.viewBox ?? [920, 760];\n const sideMargin = 62;\n const participantW = 86;\n const colGap = 108;\n const topY = 72;\n const participantH = 54;\n const lifelineTop = 142;\n const lifelineBottom = viewBox[1] - 65;\n\n const cx = (i: number) => sideMargin + i * colGap;\n const partX = new Map<string, number>();\n\n spec.participants.forEach((p, i) => {\n const x = cx(i);\n partX.set(p.id, x);\n const style = componentStyle(p.type);\n nodes.push(\n card({\n id: p.id,\n x: x - participantW / 2,\n y: topY,\n width: participantW,\n height: participantH,\n label: p.label,\n sublabel: p.sublabel,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 11,\n zIndex: 5,\n }),\n );\n // Lifeline (dashed vertical guide beneath each participant).\n lines.push({\n id: `lifeline_${p.id}`,\n type: 'straight',\n points: [\n { x, y: lifelineTop },\n { x, y: lifelineBottom },\n ],\n strokeColor: ARCHIFY_LANE_STROKE,\n strokeWidth: 1,\n lineStyle: 'dashed',\n markerEnd: 'none',\n zIndex: -5,\n });\n });\n\n // Segment frames (labelled bands over ranges of the timeline).\n for (const [i, seg] of (spec.segments ?? []).entries()) {\n nodes.push(\n frame({\n id: `segment_${i}`,\n x: 48,\n y: seg.from,\n width: viewBox[0] - 96,\n height: seg.to - seg.from,\n label: seg.label,\n stroke: ARCHIFY_LANE_STROKE,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -10,\n }),\n );\n }\n\n // Activation bars (thin vertical rects on a participant lifeline).\n for (const [i, act] of (spec.activations ?? []).entries()) {\n const x = partX.get(act.participant);\n if (x === undefined) continue;\n const style = componentStyle(act.type ?? 'backend');\n nodes.push({\n id: `activation_${i}_${act.participant}`,\n type: 'shapeRect',\n position: { x: x - 5, y: act.from },\n width: 10,\n height: Math.max(6, act.to - act.from),\n zIndex: 1,\n data: {\n label: '',\n fill: style.fill,\n stroke: style.stroke,\n strokeWidth: 1,\n color: style.text,\n fontSize: 10,\n borderStyle: 'solid',\n attributes: [],\n },\n });\n }\n\n // Messages become horizontal arrow lines at their y with a label above.\n for (const m of spec.messages) {\n const fromX = partX.get(m.from);\n const toX = partX.get(m.to);\n if (fromX === undefined || toX === undefined) continue;\n const dir = toX > fromX ? 1 : -1;\n const start = fromX + dir * 7;\n const end = toX - dir * 7;\n const style = messageEdgeStyle(m.variant);\n lines.push({\n id: m.id ?? uid('msg'),\n type: 'arrow',\n points: [\n { x: start, y: m.y },\n { x: end, y: m.y },\n ],\n strokeColor: style.color,\n strokeWidth: style.width,\n lineStyle: style.lineStyle,\n markerEnd: m.variant === 'return' ? 'arrow' : 'arrowclosed',\n zIndex: 3,\n });\n // Label as a tiny transparent text node centered above the arrow.\n nodes.push({\n id: `mlabel_${m.id ?? uid('m')}`,\n type: 'textLabel',\n position: { x: (start + end) / 2 - 70, y: m.y - 22 },\n width: 140,\n height: 16,\n zIndex: 4,\n data: {\n label: m.label,\n fill: 'transparent',\n stroke: 'transparent',\n strokeWidth: 0,\n color: style.color,\n labelColor: style.color,\n fontSize: 11,\n attributes: [],\n },\n });\n }\n\n return wrap(nodes, edges, lines, spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Dataflow */\n/* ========================================================================== */\n\nconst DF = {\n stageY: 46,\n stageH: 36,\n stageBottomPad: 74,\n leftX: 100,\n colGap: 215,\n stageW: 168,\n nodeW: 112,\n nodeH: 58,\n rowYs: [128, 242, 356, 470, 584],\n};\n\nfunction convertDataflow(spec: ArchifyDataflowSpec): FlowDocument {\n const trace = isTrace(spec);\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const viewBox = spec.meta.viewBox ?? [940, 720];\n const stageX = (i: number) => DF.leftX + i * DF.colGap;\n\n // Stage frames (tall vertical bands).\n for (const [i, stage] of spec.stages.entries()) {\n nodes.push(\n frame({\n id: `stage_${i}`,\n x: stageX(i) - DF.stageW / 2,\n y: DF.stageY,\n width: DF.stageW,\n height: viewBox[1] - DF.stageY - DF.stageBottomPad,\n label: stage.label,\n stroke: ARCHIFY_LANE_STROKE,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -10,\n }),\n );\n }\n\n for (const n of spec.nodes) {\n const width = n.width ?? DF.nodeW;\n const height = n.height ?? DF.nodeH;\n const cx = stageX(n.stage);\n const y = (DF.rowYs[n.row] ?? DF.rowYs[DF.rowYs.length - 1]) + (n.yOffset ?? 0);\n const style = componentStyle(n.type);\n nodes.push(\n card({\n id: n.id,\n x: cx - width / 2,\n y,\n width,\n height,\n label: n.label,\n sublabel: n.sublabel,\n tag: n.tag,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 12,\n }),\n );\n }\n\n for (const f of spec.flows) {\n const style = variantEdgeStyle(f.variant);\n edges.push(\n edge({\n id: f.id,\n source: f.from,\n target: f.to,\n sourceHandle: sideHandle(f.fromSide),\n targetHandle: sideHandle(f.toSide),\n label: f.label,\n color: style.color,\n width: f.width ?? style.width,\n lineStyle: style.lineStyle,\n animated: trace && f.variant === 'emphasis',\n waypoints: f.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Lifecycle */\n/* ========================================================================== */\n\nconst LC = {\n phaseY: 126,\n eventY: 278,\n outcomeY: 450,\n phaseW: 118,\n phaseH: 62,\n eventW: 126,\n eventH: 58,\n outcomeW: 118,\n outcomeH: 58,\n phaseXs: [94, 248, 402, 556, 710],\n eventXs: [402, 556, 710],\n outcomeXs: [402, 556, 710],\n};\n\nfunction lifecycleBand(lane: string): 'phase' | 'event' | 'outcome' {\n if (lane === 'main') return 'phase';\n if (lane === 'terminal') return 'outcome';\n return 'event';\n}\n\nfunction convertLifecycle(spec: ArchifyLifecycleSpec): FlowDocument {\n const trace = isTrace(spec);\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const viewBox = spec.meta.viewBox ?? [980, 660];\n\n // Band frames give the three horizontal groupings some structure.\n const laneLabel = new Map(spec.lanes.map((l) => [l.id, l.label]));\n const bandRows: Array<{ band: 'phase' | 'event' | 'outcome'; y: number; h: number; label: string }> = [\n { band: 'phase', y: LC.phaseY - 26, h: LC.phaseH + 40, label: laneLabel.get('main') ?? 'Lifecycle phases' },\n { band: 'event', y: LC.eventY - 26, h: LC.eventH + 40, label: 'Interruptions + Recovery' },\n { band: 'outcome', y: LC.outcomeY - 26, h: LC.outcomeH + 40, label: laneLabel.get('terminal') ?? 'Terminal exits' },\n ];\n for (const [i, b] of bandRows.entries()) {\n nodes.push(\n frame({\n id: `band_${b.band}`,\n x: 40,\n y: b.y,\n width: viewBox[0] - 80,\n height: b.h,\n label: `0${i + 1} / ${b.label}`,\n stroke: ARCHIFY_LANE_STROKE,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -10,\n }),\n );\n }\n\n for (const s of spec.states) {\n const band = lifecycleBand(s.lane);\n const isPhase = band === 'phase';\n const isOutcome = band === 'outcome';\n const width = s.width ?? (isPhase ? LC.phaseW : isOutcome ? LC.outcomeW : LC.eventW);\n const height = s.height ?? (isPhase ? LC.phaseH : isOutcome ? LC.outcomeH : LC.eventH);\n const xs = isPhase ? LC.phaseXs : isOutcome ? LC.outcomeXs : LC.eventXs;\n const cx = xs[s.col] ?? xs[xs.length - 1];\n const y = (isPhase ? LC.phaseY : isOutcome ? LC.outcomeY : LC.eventY) + (s.yOffset ?? 0);\n const style = stateStyle(s.type);\n nodes.push(\n card({\n id: s.id,\n x: cx - width / 2,\n y,\n width,\n height,\n label: s.label,\n sublabel: s.sublabel,\n tag: s.tag ?? s.step,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 12,\n }),\n );\n }\n\n // Order states along the main lane to build the primary rail. Archify draws\n // this rail decoratively (not as explicit transitions), so synthesize edges\n // between consecutive phase states, connecting right-to-left across columns.\n const mainStates = spec.states\n .filter((s) => s.lane === 'main')\n .sort((a, b) => a.col - b.col);\n const explicitPairs = new Set(spec.transitions.map((t) => `${t.from}->${t.to}`));\n for (let i = 0; i < mainStates.length - 1; i++) {\n const from = mainStates[i];\n const to = mainStates[i + 1];\n // Skip if the author already provided this exact transition.\n if (explicitPairs.has(`${from.id}->${to.id}`)) continue;\n edges.push(\n edge({\n id: `mainrail_${from.id}_${to.id}`,\n source: from.id,\n target: to.id,\n sourceHandle: sideHandle('right'),\n targetHandle: sideHandle('left'),\n label: undefined,\n color: variantEdgeStyle('emphasis').color,\n width: 2.2,\n lineStyle: 'solid',\n animated: trace,\n }),\n );\n }\n\n const mainPairs = new Set<string>();\n for (let i = 0; i < mainStates.length - 1; i++) {\n mainPairs.add(`${mainStates[i].id}->${mainStates[i + 1].id}`);\n }\n\n for (const t of spec.transitions) {\n const style = variantEdgeStyle(t.variant);\n const onMain = mainPairs.has(`${t.from}->${t.to}`);\n edges.push(\n edge({\n id: t.id,\n source: t.from,\n target: t.to,\n sourceHandle: sideHandle(t.fromSide),\n targetHandle: sideHandle(t.toSide),\n label: t.label,\n color: style.color,\n width: t.width ?? style.width,\n lineStyle: style.lineStyle,\n animated: trace && onMain,\n waypoints: t.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n\nfunction wrap(\n nodes: FlowNode[],\n edges: FlowEdge[],\n lines: FlowLine[],\n title?: string,\n): FlowDocument {\n return {\n canvases: {\n [ROOT_CANVAS_ID]: { nodes, edges, lines },\n },\n stack: [ROOT_CANVAS_ID],\n title,\n };\n}\n\n/** Convert any supported Archify spec into a Flow document. */\nexport function archifyToFlowDocument(spec: ArchifySpec): FlowDocument {\n switch (spec.diagram_type) {\n case 'architecture':\n return convertArchitecture(spec);\n case 'workflow':\n return convertWorkflow(spec);\n case 'sequence':\n return convertSequence(spec);\n case 'dataflow':\n return convertDataflow(spec);\n case 'lifecycle':\n return convertLifecycle(spec);\n default:\n return wrap([], [], []);\n }\n}\n"],"mappings":";;;;AA+BA,SAAS,EAAQ,GAA4B;CAC3C,OAAO,EAAK,MAAM,cAAc;AAClC;AAMA,IAAM,IAAY;CAAE,QAAQ,CAAC,IAAI,EAAE;CAAG,MAAM;CAAG,MAAM;CAAI,MAAM;CAAI,OAAO;CAAK,OAAO;AAAG;AAEzF,SAAS,EAAoB,GAA6C;CACxE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAO;EAAE,GAAG;EAAW,GAAG,EAAK;CAAO,GACtC,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,oBAAO,IAAI,IAA4D;CAE7E,KAAK,IAAM,KAAK,EAAK,YAAY;EAC/B,IAAI,GACA;EACJ,IAAI,MAAM,QAAQ,EAAE,GAAG,GACrB,CAAC,GAAG,KAAK,EAAE;OACN,IAAI,OAAO,UAAU,EAAE,GAAG,KAAK,OAAO,UAAU,EAAE,GAAG,GAAG;GAC7D,IAAM,IAAQ,EAAK,QAAQ,EAAK,MAC1B,IAAQ,EAAK,QAAQ,EAAK;GAEhC,AADA,IAAI,EAAK,OAAO,MAAM,EAAE,OAAO,KAAK,GACpC,IAAI,EAAK,OAAO,MAAM,EAAE,OAAO,KAAK;EACtC,OAEE,AADA,IAAI,EAAK,OAAO,IAChB,IAAI,EAAK,OAAO;EAElB,IAAM,IAAI,EAAE,OAAO,MAAM,EAAK,OACxB,IAAI,EAAE,OAAO,MAAM,EAAK;EAC9B,EAAK,IAAI,EAAE,IAAI;GAAE;GAAG;GAAG;GAAG;EAAE,CAAC;EAC7B,IAAM,IAAQ,EAAe,EAAE,IAAI;EACnC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN;GACA;GACA,OAAO;GACP,QAAQ;GACR,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE;GACP,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;EACb,CAAC,CACH;CACF;CAGA,KAAK,IAAM,CAAC,GAAG,OAAO,EAAK,cAAc,CAAC,EAAA,CAAG,QAAQ,GAAG;EACtD,IAAM,IAAU,EAAE,MAAM,KAAK,MAAO,EAAK,IAAI,CAAE,CAAC,CAAC,CAAC,OAAO,OAAO;EAMhE,IAAI,EAAQ,WAAW,GAAG;EAC1B,IAAM,IAAM,EAAE,OAAO,IACf,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,CAAC,CAAC,IAAI,GAC9C,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,CAAC,CAAC,IAAI,IAAM,IACpD,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,GACpD,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;EAC1D,EAAM,KACJ,EAAM;GACJ,IAAI,YAAY,EAAE,GAAG,EAAI,GAAG;GAC5B,GAAG;GACH,GAAG;GACH,OAAO,IAAO;GACd,QAAQ,IAAO;GACf,OAAO,EAAE;GACT,QAAQ,EAAE,SAAS,mBAAmB,YAAY;GAClD,aAAa;GACb,YAAY,EAAE,SAAS,mBAAmB,YAAY;GACtD,QAAQ,MAAM;EAChB,CAAC,CACH;CACF;CAEA,KAAK,IAAM,KAAQ,EAAK,eAAe,CAAC,GAAG;EACzC,IAAM,IAAQ,EAAiB,EAAK,OAAO;EAC3C,EAAM,KACJ,EAAK;GACH,IAAI,EAAK;GACT,QAAQ,EAAK;GACb,QAAQ,EAAK;GACb,cAAc,EAAW,EAAK,QAAQ;GACtC,cAAc,EAAW,EAAK,MAAM;GACpC,OAAO,EAAK;GACZ,OAAO,EAAM;GACb,OAAO,EAAK,SAAS,EAAM;GAC3B,WAAW,EAAM;GACjB,UAAU;GACV,WAAW,EAAK,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EACjD,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAMA,IAAM,IAAK;CACT,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;CACZ,OAAO;EAAC;EAAI;EAAK;EAAK;EAAK;EAAK;CAAG;CACnC,OAAO;CACP,OAAO;AACT;AAEA,SAAS,EAAgB,GAAyC;CAChE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAY,IAAI,IAAI,EAAK,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GACvD,KAAW,MACf,EAAG,SAAS,EAAU,IAAI,CAAE,KAAK,MAAM,EAAG,QAAQ,EAAG;CAGvD,KAAK,IAAM,KAAQ,EAAK,OAAO;EAC7B,IAAM,IAAM,EAAQ,EAAK,EAAE;EAC3B,EAAM,KACJ,EAAM;GACJ,IAAI,QAAQ,EAAK;GACjB,GAAG,EAAG;GACN,GAAG;GACH,OAAO,EAAG;GACV,QAAQ,EAAG;GACX,OAAO,EAAK;GACZ,QAAQ,EAAK,YAAY,cAAc,YAAY;GACnD,YAAY,EAAK,YAAY,cAAc,YAAY;GACvD,QAAQ;EACV,CAAC,CACH;CACF;CAGA,KAAK,IAAM,CAAC,GAAG,OAAW,EAAK,UAAU,CAAC,EAAA,CAAG,QAAQ,GAAG;EACtD,IAAM,IAAK,EAAG,MAAM,EAAM,WAAW,EAAG,QAAQ,IAAI,IAC9C,IAAK,EAAG,MAAM,EAAM,SAAS,EAAG,QAAQ,IAAI;EAClD,EAAM,KACJ,EAAM;GACJ,IAAI,SAAS,EAAM;GACnB,GAAG;GACH,GAAG,EAAG,QAAQ;GACd,OAAO,IAAK;GACZ,QAAQ;GACR,OAAO,EAAM;GACb,QAAQ,EAAiB,EAAM,OAAO,CAAC,CAAC;GACxC,YAAY;GACZ,aAAa;GACb,QAAQ,MAAM;EAChB,CAAC,CACH;CACF;CAGA,KAAK,IAAM,CAAC,GAAG,OAAO,EAAK,UAAU,CAAC,EAAA,CAAG,QAAQ,GAAG;EAClD,IAAM,IAAM,EAAQ,EAAE,IAAI,GACpB,IAAK,EAAG,MAAM,EAAE,WAAW,EAAG,QAAQ,IAAI,GAC1C,IAAK,EAAG,MAAM,EAAE,SAAS,EAAG,QAAQ,IAAI;EAC9C,EAAM,KACJ,EAAM;GACJ,IAAI,WAAW,EAAE;GACjB,GAAG;GACH,GAAG,IAAM,EAAG,aAAa;GACzB,OAAO,IAAK;GACZ,QAAQ,EAAG,QAAQ,EAAG;GACtB,OAAO,EAAE;GACT,QAAQ,EAAiB,EAAE,OAAO,CAAC,CAAC;GACpC,YAAY;GACZ,aAAa;GACb,QAAQ,MAAM;EAChB,CAAC,CACH;CACF;CAEA,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAQ,EAAE,SAAS,EAAG,OACtB,IAAS,EAAE,WAAW,EAAE,MAAM,KAAK,EAAG,QACtC,IAAK,EAAG,MAAM,EAAE,QAAQ,EAAG,MAAM,EAAG,MAAM,SAAS,IACnD,IAAW,EAAG,QAAQ,EAAG,YACzB,IAAI,EAAQ,EAAE,IAAI,IAAI,EAAG,cAAc,IAAW,KAAU,KAAK,EAAE,WAAW,IAC9E,IAAQ,EAAe,EAAE,IAAI;EACnC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAK,IAAQ;GAChB;GACA;GACA;GACA,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE;GACP,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAEA,IAAM,oBAAW,IAAI,IAAY,GAC3B,IAAK,EAAK,YAAY,CAAC;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAG,SAAS,GAAG,KAAK,EAAS,IAAI,GAAG,EAAG,GAAG,IAAI,EAAG,IAAI,IAAI;CAE7E,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAS,EAAS,IAAI,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI,GAC1C,IAAQ,EAAiB,EAAE,YAAY,IAAS,aAAa,UAAU;EAC7E,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,QAAQ,EAAE;GACV,QAAQ,EAAE;GACV,cAAc,EAAW,EAAE,QAAQ;GACnC,cAAc,EAAW,EAAE,MAAM;GACjC,OAAO,EAAE;GACT,OAAO,EAAE,SAAS,UAAU,YAAY,EAAM;GAC9C,OAAO,EAAE,SAAS,EAAM;GACxB,WAAW,EAAE,SAAS,UAAU,WAAW,EAAM;GACjD,UAAU,KAAS;GACnB,WAAW,EAAE,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EAC9C,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAMA,SAAS,EAAgB,GAAyC;CAChE,IAAM,IAAoB,CAAC,GACrB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAU,EAAK,KAAK,WAAW,CAAC,KAAK,GAAG,GAOxC,IAAiB,EAAQ,KAAK,IAE9B,KAAM,MAAc,KAAa,IAAI,KACrC,oBAAQ,IAAI,IAAoB;CAEtC,EAAK,aAAa,SAAS,GAAG,MAAM;EAClC,IAAM,IAAI,EAAG,CAAC;EACd,EAAM,IAAI,EAAE,IAAI,CAAC;EACjB,IAAM,IAAQ,EAAe,EAAE,IAAI;EAmBnC,AAlBA,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAI;GACP,GAAG;GACH,OAAO;GACP,QAAQ;GACR,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;GACV,QAAQ;EACV,CAAC,CACH,GAEA,EAAM,KAAK;GACT,IAAI,YAAY,EAAE;GAClB,MAAM;GACN,QAAQ,CACN;IAAE;IAAG,GAAG;GAAY,GACpB;IAAE;IAAG,GAAG;GAAe,CACzB;GACA,aAAa;GACb,aAAa;GACb,WAAW;GACX,WAAW;GACX,QAAQ;EACV,CAAC;CACH,CAAC;CAGD,KAAK,IAAM,CAAC,GAAG,OAAS,EAAK,YAAY,CAAC,EAAA,CAAG,QAAQ,GACnD,EAAM,KACJ,EAAM;EACJ,IAAI,WAAW;EACf,GAAG;EACH,GAAG,EAAI;EACP,OAAO,EAAQ,KAAK;EACpB,QAAQ,EAAI,KAAK,EAAI;EACrB,OAAO,EAAI;EACX,QAAQ;EACR,YAAY;EACZ,aAAa;EACb,QAAQ;CACV,CAAC,CACH;CAIF,KAAK,IAAM,CAAC,GAAG,OAAS,EAAK,eAAe,CAAC,EAAA,CAAG,QAAQ,GAAG;EACzD,IAAM,IAAI,EAAM,IAAI,EAAI,WAAW;EACnC,IAAI,MAAM,KAAA,GAAW;EACrB,IAAM,IAAQ,EAAe,EAAI,QAAQ,SAAS;EAClD,EAAM,KAAK;GACT,IAAI,cAAc,EAAE,GAAG,EAAI;GAC3B,MAAM;GACN,UAAU;IAAE,GAAG,IAAI;IAAG,GAAG,EAAI;GAAK;GAClC,OAAO;GACP,QAAQ,KAAK,IAAI,GAAG,EAAI,KAAK,EAAI,IAAI;GACrC,QAAQ;GACR,MAAM;IACJ,OAAO;IACP,MAAM,EAAM;IACZ,QAAQ,EAAM;IACd,aAAa;IACb,OAAO,EAAM;IACb,UAAU;IACV,aAAa;IACb,YAAY,CAAC;GACf;EACF,CAAC;CACH;CAGA,KAAK,IAAM,KAAK,EAAK,UAAU;EAC7B,IAAM,IAAQ,EAAM,IAAI,EAAE,IAAI,GACxB,IAAM,EAAM,IAAI,EAAE,EAAE;EAC1B,IAAI,MAAU,KAAA,KAAa,MAAQ,KAAA,GAAW;EAC9C,IAAM,IAAM,IAAM,IAAQ,IAAI,IACxB,IAAQ,IAAQ,IAAM,GACtB,IAAM,IAAM,IAAM,GAClB,IAAQ,EAAiB,EAAE,OAAO;EAexC,AAdA,EAAM,KAAK;GACT,IAAI,EAAE,MAAM,EAAI,KAAK;GACrB,MAAM;GACN,QAAQ,CACN;IAAE,GAAG;IAAO,GAAG,EAAE;GAAE,GACnB;IAAE,GAAG;IAAK,GAAG,EAAE;GAAE,CACnB;GACA,aAAa,EAAM;GACnB,aAAa,EAAM;GACnB,WAAW,EAAM;GACjB,WAAW,EAAE,YAAY,WAAW,UAAU;GAC9C,QAAQ;EACV,CAAC,GAED,EAAM,KAAK;GACT,IAAI,UAAU,EAAE,MAAM,EAAI,GAAG;GAC7B,MAAM;GACN,UAAU;IAAE,IAAI,IAAQ,KAAO,IAAI;IAAI,GAAG,EAAE,IAAI;GAAG;GACnD,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,MAAM;IACJ,OAAO,EAAE;IACT,MAAM;IACN,QAAQ;IACR,aAAa;IACb,OAAO,EAAM;IACb,YAAY,EAAM;IAClB,UAAU;IACV,YAAY,CAAC;GACf;EACF,CAAC;CACH;CAEA,OAAO,EAAK,GAAO,GAAO,GAAO,EAAK,KAAK,KAAK;AAClD;AAMA,IAAM,IAAK;CACT,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACP,OAAO;EAAC;EAAK;EAAK;EAAK;EAAK;CAAG;AACjC;AAEA,SAAS,EAAgB,GAAyC;CAChE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAU,EAAK,KAAK,WAAW,CAAC,KAAK,GAAG,GACxC,KAAU,MAAc,EAAG,QAAQ,IAAI,EAAG;CAGhD,KAAK,IAAM,CAAC,GAAG,MAAU,EAAK,OAAO,QAAQ,GAC3C,EAAM,KACJ,EAAM;EACJ,IAAI,SAAS;EACb,GAAG,EAAO,CAAC,IAAI,EAAG,SAAS;EAC3B,GAAG,EAAG;EACN,OAAO,EAAG;EACV,QAAQ,EAAQ,KAAK,EAAG,SAAS,EAAG;EACpC,OAAO,EAAM;EACb,QAAQ;EACR,YAAY;EACZ,aAAa;EACb,QAAQ;CACV,CAAC,CACH;CAGF,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAQ,EAAE,SAAS,EAAG,OACtB,IAAS,EAAE,UAAU,EAAG,OACxB,IAAK,EAAO,EAAE,KAAK,GACnB,KAAK,EAAG,MAAM,EAAE,QAAQ,EAAG,MAAM,EAAG,MAAM,SAAS,OAAO,EAAE,WAAW,IACvE,IAAQ,EAAe,EAAE,IAAI;EACnC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAK,IAAQ;GAChB;GACA;GACA;GACA,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE;GACP,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAEA,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAQ,EAAiB,EAAE,OAAO;EACxC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,QAAQ,EAAE;GACV,QAAQ,EAAE;GACV,cAAc,EAAW,EAAE,QAAQ;GACnC,cAAc,EAAW,EAAE,MAAM;GACjC,OAAO,EAAE;GACT,OAAO,EAAM;GACb,OAAO,EAAE,SAAS,EAAM;GACxB,WAAW,EAAM;GACjB,UAAU,KAAS,EAAE,YAAY;GACjC,WAAW,EAAE,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EAC9C,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAMA,IAAM,IAAK;CACT,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,UAAU;CACV,SAAS;EAAC;EAAI;EAAK;EAAK;EAAK;CAAG;CAChC,SAAS;EAAC;EAAK;EAAK;CAAG;CACvB,WAAW;EAAC;EAAK;EAAK;CAAG;AAC3B;AAEA,SAAS,EAAc,GAA6C;CAGlE,OAFI,MAAS,SAAe,UACxB,MAAS,aAAmB,YACzB;AACT;AAEA,SAAS,EAAiB,GAA0C;CAClE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAU,EAAK,KAAK,WAAW,CAAC,KAAK,GAAG,GAGxC,IAAY,IAAI,IAAI,EAAK,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,GAC1D,IAAgG;EACpG;GAAE,MAAM;GAAS,GAAG,EAAG,SAAS;GAAI,GAAG,EAAG,SAAS;GAAI,OAAO,EAAU,IAAI,MAAM,KAAK;EAAmB;EAC1G;GAAE,MAAM;GAAS,GAAG,EAAG,SAAS;GAAI,GAAG,EAAG,SAAS;GAAI,OAAO;EAA2B;EACzF;GAAE,MAAM;GAAW,GAAG,EAAG,WAAW;GAAI,GAAG,EAAG,WAAW;GAAI,OAAO,EAAU,IAAI,UAAU,KAAK;EAAiB;CACpH;CACA,KAAK,IAAM,CAAC,GAAG,MAAM,EAAS,QAAQ,GACpC,EAAM,KACJ,EAAM;EACJ,IAAI,QAAQ,EAAE;EACd,GAAG;EACH,GAAG,EAAE;EACL,OAAO,EAAQ,KAAK;EACpB,QAAQ,EAAE;EACV,OAAO,IAAI,IAAI,EAAE,KAAK,EAAE;EACxB,QAAQ;EACR,YAAY;EACZ,aAAa;EACb,QAAQ;CACV,CAAC,CACH;CAGF,KAAK,IAAM,KAAK,EAAK,QAAQ;EAC3B,IAAM,IAAO,EAAc,EAAE,IAAI,GAC3B,IAAU,MAAS,SACnB,IAAY,MAAS,WACrB,IAAQ,EAAE,UAAU,IAAU,EAAG,SAAS,IAAY,EAAG,WAAW,EAAG,SACvE,IAAS,EAAE,WAAW,IAAU,EAAG,SAAS,IAAY,EAAG,WAAW,EAAG,SACzE,IAAK,IAAU,EAAG,UAAU,IAAY,EAAG,YAAY,EAAG,SAC1D,IAAK,EAAG,EAAE,QAAQ,EAAG,EAAG,SAAS,IACjC,KAAK,IAAU,EAAG,SAAS,IAAY,EAAG,WAAW,EAAG,WAAW,EAAE,WAAW,IAChF,IAAQ,EAAW,EAAE,IAAI;EAC/B,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAK,IAAQ;GAChB;GACA;GACA;GACA,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE,OAAO,EAAE;GAChB,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAKA,IAAM,IAAa,EAAK,OACrB,QAAQ,MAAM,EAAE,SAAS,MAAM,CAAC,CAChC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,GACzB,IAAgB,IAAI,IAAI,EAAK,YAAY,KAAK,MAAM,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI,CAAC;CAC/E,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,SAAS,GAAG,KAAK;EAC9C,IAAM,IAAO,EAAW,IAClB,IAAK,EAAW,IAAI;EAEtB,EAAc,IAAI,GAAG,EAAK,GAAG,IAAI,EAAG,IAAI,KAC5C,EAAM,KACJ,EAAK;GACH,IAAI,YAAY,EAAK,GAAG,GAAG,EAAG;GAC9B,QAAQ,EAAK;GACb,QAAQ,EAAG;GACX,cAAc,EAAW,OAAO;GAChC,cAAc,EAAW,MAAM;GAC/B,OAAO,KAAA;GACP,OAAO,EAAiB,UAAU,CAAC,CAAC;GACpC,OAAO;GACP,WAAW;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAEA,IAAM,oBAAY,IAAI,IAAY;CAClC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,SAAS,GAAG,KACzC,EAAU,IAAI,GAAG,EAAW,EAAE,CAAC,GAAG,IAAI,EAAW,IAAI,EAAE,CAAC,IAAI;CAG9D,KAAK,IAAM,KAAK,EAAK,aAAa;EAChC,IAAM,IAAQ,EAAiB,EAAE,OAAO,GAClC,IAAS,EAAU,IAAI,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI;EACjD,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,QAAQ,EAAE;GACV,QAAQ,EAAE;GACV,cAAc,EAAW,EAAE,QAAQ;GACnC,cAAc,EAAW,EAAE,MAAM;GACjC,OAAO,EAAE;GACT,OAAO,EAAM;GACb,OAAO,EAAE,SAAS,EAAM;GACxB,WAAW,EAAM;GACjB,UAAU,KAAS;GACnB,WAAW,EAAE,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EAC9C,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAIA,SAAS,EACP,GACA,GACA,GACA,GACc;CACd,OAAO;EACL,UAAU,GACP,IAAiB;GAAE;GAAO;GAAO;EAAM,EAC1C;EACA,OAAO,CAAC,CAAc;EACtB;CACF;AACF;AAGA,SAAgB,EAAsB,GAAiC;CACrE,QAAQ,EAAK,cAAb;EACE,KAAK,gBACH,OAAO,EAAoB,CAAI;EACjC,KAAK,YACH,OAAO,EAAgB,CAAI;EAC7B,KAAK,YACH,OAAO,EAAgB,CAAI;EAC7B,KAAK,YACH,OAAO,EAAgB,CAAI;EAC7B,KAAK,aACH,OAAO,EAAiB,CAAI;EAC9B,SACE,OAAO,EAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC1B;AACF"}
|
|
1
|
+
{"version":3,"file":"convert.js","names":[],"sources":["../../../../../src/components/pro/Flow/archify/convert.ts"],"sourcesContent":["/**\n * Convert an Archify spec into a native Flow `FlowDocument`.\n *\n * One converter per diagram type reproduces Archify's fixed layout geometry\n * (constants copied from the reference renderers) so the imported diagram\n * matches the reference artifact, then emits editable Flow nodes/edges/lines.\n *\n * When `meta.animation === \"trace\"`, edges are marked `animated` so the Flow\n * presentation / preview mode plays the traveling gradient pulse.\n */\n\nimport type { FlowDocument, FlowNode, FlowEdge, FlowLine } from '../types';\nimport { ROOT_CANVAS_ID } from '../constants';\nimport type {\n ArchifySpec,\n ArchifyArchitectureSpec,\n ArchifyWorkflowSpec,\n ArchifySequenceSpec,\n ArchifyDataflowSpec,\n ArchifyLifecycleSpec,\n} from './spec';\nimport {\n ARCHIFY_LANE_STROKE,\n ARCHIFY_TEXT_MUTED,\n componentStyle,\n stateStyle,\n variantEdgeStyle,\n messageEdgeStyle,\n} from './palette';\nimport { card, frame, edge, sideHandle, uid } from './build';\n\nfunction isTrace(spec: ArchifySpec): boolean {\n return spec.meta?.animation === 'trace';\n}\n\n/* ========================================================================== */\n/* Architecture */\n/* ========================================================================== */\n\nconst ARCH_GRID = { origin: [40, 80], cols: 4, gapX: 30, gapY: 40, cellW: 130, cellH: 64 };\n\nfunction convertArchitecture(spec: ArchifyArchitectureSpec): FlowDocument {\n const trace = isTrace(spec);\n const grid = { ...ARCH_GRID, ...spec.layout };\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const rect = new Map<string, { x: number; y: number; w: number; h: number }>();\n\n for (const c of spec.components) {\n let x: number;\n let y: number;\n if (Array.isArray(c.pos)) {\n [x, y] = c.pos;\n } else if (Number.isInteger(c.row) && Number.isInteger(c.col)) {\n const stepX = grid.cellW + grid.gapX;\n const stepY = grid.cellH + grid.gapY;\n x = grid.origin[0] + (c.col ?? 0) * stepX;\n y = grid.origin[1] + (c.row ?? 0) * stepY;\n } else {\n x = grid.origin[0];\n y = grid.origin[1];\n }\n const w = c.size?.[0] ?? grid.cellW;\n const h = c.size?.[1] ?? grid.cellH;\n rect.set(c.id, { x, y, w, h });\n const style = componentStyle(c.type);\n nodes.push(\n card({\n id: c.id,\n x,\n y,\n width: w,\n height: h,\n label: c.label,\n sublabel: c.sublabel,\n tag: c.tag,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n }),\n );\n }\n\n // Boundaries wrap their member components with padding, rendered behind.\n for (const [i, b] of (spec.boundaries ?? []).entries()) {\n const members = b.wraps.map((id) => rect.get(id)).filter(Boolean) as Array<{\n x: number;\n y: number;\n w: number;\n h: number;\n }>;\n if (members.length === 0) continue;\n const pad = b.pad ?? 26;\n const minX = Math.min(...members.map((m) => m.x)) - pad;\n const minY = Math.min(...members.map((m) => m.y)) - pad - 14;\n const maxX = Math.max(...members.map((m) => m.x + m.w)) + pad;\n const maxY = Math.max(...members.map((m) => m.y + m.h)) + pad;\n nodes.push(\n frame({\n id: `boundary_${i}_${uid('b')}`,\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n label: b.label,\n stroke: b.kind === 'security-group' ? '#fb7185' : ARCHIFY_LANE_STROKE,\n borderStyle: 'dashed',\n labelColor: b.kind === 'security-group' ? '#fb7185' : ARCHIFY_TEXT_MUTED,\n zIndex: -10 + i,\n }),\n );\n }\n\n for (const conn of spec.connections ?? []) {\n const style = variantEdgeStyle(conn.variant);\n edges.push(\n edge({\n id: conn.id,\n source: conn.from,\n target: conn.to,\n sourceHandle: sideHandle(conn.fromSide),\n targetHandle: sideHandle(conn.toSide),\n label: conn.label,\n color: style.color,\n width: conn.width ?? style.width,\n lineStyle: style.lineStyle,\n animated: trace,\n waypoints: conn.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Workflow */\n/* ========================================================================== */\n\nconst WF = {\n laneX: 40,\n laneY: 52,\n laneW: 640,\n laneH: 104,\n laneGap: 20,\n laneTitleH: 30,\n colXs: [88, 220, 300, 430, 500, 625],\n nodeW: 92,\n nodeH: 52,\n};\n\nfunction convertWorkflow(spec: ArchifyWorkflowSpec): FlowDocument {\n const trace = isTrace(spec);\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const laneIndex = new Map(spec.lanes.map((l, i) => [l.id, i]));\n const laneTop = (id: string) =>\n WF.laneY + (laneIndex.get(id) ?? 0) * (WF.laneH + WF.laneGap);\n\n // Lane frames (behind everything).\n for (const lane of spec.lanes) {\n const top = laneTop(lane.id);\n nodes.push(\n frame({\n id: `lane_${lane.id}`,\n x: WF.laneX,\n y: top,\n width: WF.laneW,\n height: WF.laneH,\n label: lane.label,\n stroke: lane.variant === 'exception' ? '#fb7185' : ARCHIFY_LANE_STROKE,\n labelColor: lane.variant === 'exception' ? '#fb7185' : ARCHIFY_TEXT_MUTED,\n zIndex: -20,\n }),\n );\n }\n\n // Phase bands (thin frames spanning columns, drawn just above lanes).\n for (const [i, phase] of (spec.phases ?? []).entries()) {\n const x0 = WF.colXs[phase.fromCol] - WF.nodeW / 2 - 12;\n const x1 = WF.colXs[phase.toCol] + WF.nodeW / 2 + 12;\n nodes.push(\n frame({\n id: `phase_${phase.id}`,\n x: x0,\n y: WF.laneY - 34,\n width: x1 - x0,\n height: 26,\n label: phase.label,\n stroke: variantEdgeStyle(phase.variant).color,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'none',\n zIndex: -15 + i,\n }),\n );\n }\n\n // Workflow groups (nested emphasis frames inside a lane).\n for (const [i, g] of (spec.groups ?? []).entries()) {\n const top = laneTop(g.lane);\n const x0 = WF.colXs[g.fromCol] - WF.nodeW / 2 - 8;\n const x1 = WF.colXs[g.toCol] + WF.nodeW / 2 + 8;\n nodes.push(\n frame({\n id: `wfgroup_${g.id}`,\n x: x0,\n y: top + WF.laneTitleH - 6,\n width: x1 - x0,\n height: WF.laneH - WF.laneTitleH,\n label: g.label,\n stroke: variantEdgeStyle(g.variant).color,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -12 + i,\n }),\n );\n }\n\n for (const n of spec.nodes) {\n const width = n.width ?? WF.nodeW;\n const height = n.height ?? (n.tag ? 68 : WF.nodeH);\n const cx = WF.colXs[n.col] ?? WF.colXs[WF.colXs.length - 1];\n const contentH = WF.laneH - WF.laneTitleH;\n const y = laneTop(n.lane) + WF.laneTitleH + (contentH - height) / 2 + (n.yOffset ?? 0);\n const style = componentStyle(n.type);\n nodes.push(\n card({\n id: n.id,\n x: cx - width / 2,\n y,\n width,\n height,\n label: n.label,\n sublabel: n.sublabel,\n tag: n.tag,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 12,\n }),\n );\n }\n\n const mainPath = new Set<string>();\n const mp = spec.mainPath ?? [];\n for (let i = 0; i < mp.length - 1; i++) mainPath.add(`${mp[i]}->${mp[i + 1]}`);\n\n for (const e of spec.edges) {\n const onMain = mainPath.has(`${e.from}->${e.to}`);\n const style = variantEdgeStyle(e.variant ?? (onMain ? 'emphasis' : 'default'));\n edges.push(\n edge({\n id: e.id,\n source: e.from,\n target: e.to,\n sourceHandle: sideHandle(e.fromSide),\n targetHandle: sideHandle(e.toSide),\n label: e.label,\n color: e.role === 'error' ? '#fb7185' : style.color,\n width: e.width ?? style.width,\n lineStyle: e.role === 'error' ? 'dashed' : style.lineStyle,\n animated: trace && onMain,\n waypoints: e.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Sequence */\n/* ========================================================================== */\n\nfunction convertSequence(spec: ArchifySequenceSpec): FlowDocument {\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n const lines: FlowLine[] = [];\n\n const viewBox = spec.meta.viewBox ?? [920, 760];\n const sideMargin = 62;\n const participantW = 86;\n const colGap = 108;\n const topY = 72;\n const participantH = 54;\n const lifelineTop = 142;\n const lifelineBottom = viewBox[1] - 65;\n\n const cx = (i: number) => sideMargin + i * colGap;\n const partX = new Map<string, number>();\n\n spec.participants.forEach((p, i) => {\n const x = cx(i);\n partX.set(p.id, x);\n const style = componentStyle(p.type);\n nodes.push(\n card({\n id: p.id,\n x: x - participantW / 2,\n y: topY,\n width: participantW,\n height: participantH,\n label: p.label,\n sublabel: p.sublabel,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 11,\n zIndex: 5,\n }),\n );\n // Lifeline (dashed vertical guide beneath each participant).\n lines.push({\n id: `lifeline_${p.id}`,\n type: 'straight',\n points: [\n { x, y: lifelineTop },\n { x, y: lifelineBottom },\n ],\n strokeColor: ARCHIFY_LANE_STROKE,\n strokeWidth: 1,\n lineStyle: 'dashed',\n markerEnd: 'none',\n zIndex: -5,\n });\n });\n\n // Segment frames (labelled bands over ranges of the timeline).\n for (const [i, seg] of (spec.segments ?? []).entries()) {\n nodes.push(\n frame({\n id: `segment_${i}`,\n x: 48,\n y: seg.from,\n width: viewBox[0] - 96,\n height: seg.to - seg.from,\n label: seg.label,\n stroke: ARCHIFY_LANE_STROKE,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -10,\n }),\n );\n }\n\n // Activation bars (thin vertical rects on a participant lifeline).\n for (const [i, act] of (spec.activations ?? []).entries()) {\n const x = partX.get(act.participant);\n if (x === undefined) continue;\n const style = componentStyle(act.type ?? 'backend');\n nodes.push({\n id: `activation_${i}_${act.participant}`,\n type: 'shapeRect',\n position: { x: x - 5, y: act.from },\n width: 10,\n height: Math.max(6, act.to - act.from),\n zIndex: 1,\n data: {\n label: '',\n fill: style.fill,\n stroke: style.stroke,\n strokeWidth: 1,\n color: style.text,\n fontSize: 10,\n borderStyle: 'solid',\n attributes: [],\n },\n });\n }\n\n // Messages become horizontal arrow lines at their y with a label above.\n for (const m of spec.messages) {\n const fromX = partX.get(m.from);\n const toX = partX.get(m.to);\n if (fromX === undefined || toX === undefined) continue;\n const dir = toX > fromX ? 1 : -1;\n const start = fromX + dir * 7;\n const end = toX - dir * 7;\n const style = messageEdgeStyle(m.variant);\n lines.push({\n id: m.id ?? uid('msg'),\n type: 'arrow',\n points: [\n { x: start, y: m.y },\n { x: end, y: m.y },\n ],\n strokeColor: style.color,\n strokeWidth: style.width,\n lineStyle: style.lineStyle,\n markerEnd: m.variant === 'return' ? 'arrow' : 'arrowclosed',\n zIndex: 3,\n });\n // Label as a tiny transparent text node centered above the arrow.\n nodes.push({\n id: `mlabel_${m.id ?? uid('m')}`,\n type: 'textLabel',\n position: { x: (start + end) / 2 - 70, y: m.y - 22 },\n width: 140,\n height: 16,\n zIndex: 4,\n data: {\n label: m.label,\n fill: 'transparent',\n stroke: 'transparent',\n strokeWidth: 0,\n color: style.color,\n labelColor: style.color,\n fontSize: 11,\n attributes: [],\n },\n });\n }\n\n return wrap(nodes, edges, lines, spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Dataflow */\n/* ========================================================================== */\n\nconst DF = {\n stageY: 46,\n stageH: 36,\n stageBottomPad: 74,\n leftX: 100,\n colGap: 215,\n stageW: 168,\n nodeW: 112,\n nodeH: 58,\n rowYs: [128, 242, 356, 470, 584],\n};\n\nconst stageX = (i: number) => DF.leftX + i * DF.colGap;\n\nfunction convertDataflow(spec: ArchifyDataflowSpec): FlowDocument {\n const trace = isTrace(spec);\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const viewBox = spec.meta.viewBox ?? [940, 720];\n\n // Stage frames (tall vertical bands).\n for (const [i, stage] of spec.stages.entries()) {\n nodes.push(\n frame({\n id: `stage_${i}`,\n x: stageX(i) - DF.stageW / 2,\n y: DF.stageY,\n width: DF.stageW,\n height: viewBox[1] - DF.stageY - DF.stageBottomPad,\n label: stage.label,\n stroke: ARCHIFY_LANE_STROKE,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -10,\n }),\n );\n }\n\n for (const n of spec.nodes) {\n const width = n.width ?? DF.nodeW;\n const height = n.height ?? DF.nodeH;\n const cx = stageX(n.stage);\n const y = (DF.rowYs[n.row] ?? DF.rowYs[DF.rowYs.length - 1]) + (n.yOffset ?? 0);\n const style = componentStyle(n.type);\n nodes.push(\n card({\n id: n.id,\n x: cx - width / 2,\n y,\n width,\n height,\n label: n.label,\n sublabel: n.sublabel,\n tag: n.tag,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 12,\n }),\n );\n }\n\n for (const f of spec.flows) {\n const style = variantEdgeStyle(f.variant);\n edges.push(\n edge({\n id: f.id,\n source: f.from,\n target: f.to,\n sourceHandle: sideHandle(f.fromSide),\n targetHandle: sideHandle(f.toSide),\n label: f.label,\n color: style.color,\n width: f.width ?? style.width,\n lineStyle: style.lineStyle,\n animated: trace && f.variant === 'emphasis',\n waypoints: f.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n/* Lifecycle */\n/* ========================================================================== */\n\nconst LC = {\n phaseY: 126,\n eventY: 278,\n outcomeY: 450,\n phaseW: 118,\n phaseH: 62,\n eventW: 126,\n eventH: 58,\n outcomeW: 118,\n outcomeH: 58,\n phaseXs: [94, 248, 402, 556, 710],\n eventXs: [402, 556, 710],\n outcomeXs: [402, 556, 710],\n};\n\nfunction lifecycleBand(lane: string): 'phase' | 'event' | 'outcome' {\n if (lane === 'main') return 'phase';\n if (lane === 'terminal') return 'outcome';\n return 'event';\n}\n\nfunction convertLifecycle(spec: ArchifyLifecycleSpec): FlowDocument {\n const trace = isTrace(spec);\n const nodes: FlowNode[] = [];\n const edges: FlowEdge[] = [];\n\n const viewBox = spec.meta.viewBox ?? [980, 660];\n\n // Band frames give the three horizontal groupings some structure.\n const laneLabel = new Map(spec.lanes.map((l) => [l.id, l.label]));\n const bandRows: Array<{ band: 'phase' | 'event' | 'outcome'; y: number; h: number; label: string }> = [\n { band: 'phase', y: LC.phaseY - 26, h: LC.phaseH + 40, label: laneLabel.get('main') ?? 'Lifecycle phases' },\n { band: 'event', y: LC.eventY - 26, h: LC.eventH + 40, label: 'Interruptions + Recovery' },\n { band: 'outcome', y: LC.outcomeY - 26, h: LC.outcomeH + 40, label: laneLabel.get('terminal') ?? 'Terminal exits' },\n ];\n for (const [i, b] of bandRows.entries()) {\n nodes.push(\n frame({\n id: `band_${b.band}`,\n x: 40,\n y: b.y,\n width: viewBox[0] - 80,\n height: b.h,\n label: `0${i + 1} / ${b.label}`,\n stroke: ARCHIFY_LANE_STROKE,\n labelColor: ARCHIFY_TEXT_MUTED,\n borderStyle: 'dashed',\n zIndex: -10,\n }),\n );\n }\n\n for (const s of spec.states) {\n const band = lifecycleBand(s.lane);\n const isPhase = band === 'phase';\n const isOutcome = band === 'outcome';\n const width = s.width ?? (isPhase ? LC.phaseW : isOutcome ? LC.outcomeW : LC.eventW);\n const height = s.height ?? (isPhase ? LC.phaseH : isOutcome ? LC.outcomeH : LC.eventH);\n const xs = isPhase ? LC.phaseXs : isOutcome ? LC.outcomeXs : LC.eventXs;\n const cx = xs[s.col] ?? xs[xs.length - 1];\n const y = (isPhase ? LC.phaseY : isOutcome ? LC.outcomeY : LC.eventY) + (s.yOffset ?? 0);\n const style = stateStyle(s.type);\n nodes.push(\n card({\n id: s.id,\n x: cx - width / 2,\n y,\n width,\n height,\n label: s.label,\n sublabel: s.sublabel,\n tag: s.tag ?? s.step,\n fill: style.fill,\n stroke: style.stroke,\n text: style.text,\n sub: style.sub,\n fontSize: 12,\n }),\n );\n }\n\n // Order states along the main lane to build the primary rail. Archify draws\n // this rail decoratively (not as explicit transitions), so synthesize edges\n // between consecutive phase states, connecting right-to-left across columns.\n const mainStates = spec.states\n .filter((s) => s.lane === 'main')\n .sort((a, b) => a.col - b.col);\n const explicitPairs = new Set(spec.transitions.map((t) => `${t.from}->${t.to}`));\n for (let i = 0; i < mainStates.length - 1; i++) {\n const from = mainStates[i];\n const to = mainStates[i + 1];\n // Skip if the author already provided this exact transition.\n if (explicitPairs.has(`${from.id}->${to.id}`)) continue;\n edges.push(\n edge({\n id: `mainrail_${from.id}_${to.id}`,\n source: from.id,\n target: to.id,\n sourceHandle: sideHandle('right'),\n targetHandle: sideHandle('left'),\n label: undefined,\n color: variantEdgeStyle('emphasis').color,\n width: 2.2,\n lineStyle: 'solid',\n animated: trace,\n }),\n );\n }\n\n const mainPairs = new Set<string>();\n for (let i = 0; i < mainStates.length - 1; i++) {\n mainPairs.add(`${mainStates[i].id}->${mainStates[i + 1].id}`);\n }\n\n for (const t of spec.transitions) {\n const style = variantEdgeStyle(t.variant);\n const onMain = mainPairs.has(`${t.from}->${t.to}`);\n edges.push(\n edge({\n id: t.id,\n source: t.from,\n target: t.to,\n sourceHandle: sideHandle(t.fromSide),\n targetHandle: sideHandle(t.toSide),\n label: t.label,\n color: style.color,\n width: t.width ?? style.width,\n lineStyle: style.lineStyle,\n animated: trace && onMain,\n waypoints: t.via?.map(([x, y]) => ({ x, y })),\n }),\n );\n }\n\n return wrap(nodes, edges, [], spec.meta.title);\n}\n\n/* ========================================================================== */\n\nfunction wrap(\n nodes: FlowNode[],\n edges: FlowEdge[],\n lines: FlowLine[],\n title?: string,\n): FlowDocument {\n return {\n canvases: {\n [ROOT_CANVAS_ID]: { nodes, edges, lines },\n },\n stack: [ROOT_CANVAS_ID],\n title,\n };\n}\n\n/** Convert any supported Archify spec into a Flow document. */\nexport function archifyToFlowDocument(spec: ArchifySpec): FlowDocument {\n switch (spec.diagram_type) {\n case 'architecture':\n return convertArchitecture(spec);\n case 'workflow':\n return convertWorkflow(spec);\n case 'sequence':\n return convertSequence(spec);\n case 'dataflow':\n return convertDataflow(spec);\n case 'lifecycle':\n return convertLifecycle(spec);\n default:\n return wrap([], [], []);\n }\n}\n"],"mappings":";;;;AA+BA,SAAS,EAAQ,GAA4B;CAC3C,OAAO,EAAK,MAAM,cAAc;AAClC;AAMA,IAAM,IAAY;CAAE,QAAQ,CAAC,IAAI,EAAE;CAAG,MAAM;CAAG,MAAM;CAAI,MAAM;CAAI,OAAO;CAAK,OAAO;AAAG;AAEzF,SAAS,EAAoB,GAA6C;CACxE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAO;EAAE,GAAG;EAAW,GAAG,EAAK;CAAO,GACtC,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,oBAAO,IAAI,IAA4D;CAE7E,KAAK,IAAM,KAAK,EAAK,YAAY;EAC/B,IAAI,GACA;EACJ,IAAI,MAAM,QAAQ,EAAE,GAAG,GACrB,CAAC,GAAG,KAAK,EAAE;OACN,IAAI,OAAO,UAAU,EAAE,GAAG,KAAK,OAAO,UAAU,EAAE,GAAG,GAAG;GAC7D,IAAM,IAAQ,EAAK,QAAQ,EAAK,MAC1B,IAAQ,EAAK,QAAQ,EAAK;GAEhC,AADA,IAAI,EAAK,OAAO,MAAM,EAAE,OAAO,KAAK,GACpC,IAAI,EAAK,OAAO,MAAM,EAAE,OAAO,KAAK;EACtC,OAEE,AADA,IAAI,EAAK,OAAO,IAChB,IAAI,EAAK,OAAO;EAElB,IAAM,IAAI,EAAE,OAAO,MAAM,EAAK,OACxB,IAAI,EAAE,OAAO,MAAM,EAAK;EAC9B,EAAK,IAAI,EAAE,IAAI;GAAE;GAAG;GAAG;GAAG;EAAE,CAAC;EAC7B,IAAM,IAAQ,EAAe,EAAE,IAAI;EACnC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN;GACA;GACA,OAAO;GACP,QAAQ;GACR,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE;GACP,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;EACb,CAAC,CACH;CACF;CAGA,KAAK,IAAM,CAAC,GAAG,OAAO,EAAK,cAAc,CAAC,EAAA,CAAG,QAAQ,GAAG;EACtD,IAAM,IAAU,EAAE,MAAM,KAAK,MAAO,EAAK,IAAI,CAAE,CAAC,CAAC,CAAC,OAAO,OAAO;EAMhE,IAAI,EAAQ,WAAW,GAAG;EAC1B,IAAM,IAAM,EAAE,OAAO,IACf,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,CAAC,CAAC,IAAI,GAC9C,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,CAAC,CAAC,IAAI,IAAM,IACpD,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,GACpD,IAAO,KAAK,IAAI,GAAG,EAAQ,KAAK,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;EAC1D,EAAM,KACJ,EAAM;GACJ,IAAI,YAAY,EAAE,GAAG,EAAI,GAAG;GAC5B,GAAG;GACH,GAAG;GACH,OAAO,IAAO;GACd,QAAQ,IAAO;GACf,OAAO,EAAE;GACT,QAAQ,EAAE,SAAS,mBAAmB,YAAY;GAClD,aAAa;GACb,YAAY,EAAE,SAAS,mBAAmB,YAAY;GACtD,QAAQ,MAAM;EAChB,CAAC,CACH;CACF;CAEA,KAAK,IAAM,KAAQ,EAAK,eAAe,CAAC,GAAG;EACzC,IAAM,IAAQ,EAAiB,EAAK,OAAO;EAC3C,EAAM,KACJ,EAAK;GACH,IAAI,EAAK;GACT,QAAQ,EAAK;GACb,QAAQ,EAAK;GACb,cAAc,EAAW,EAAK,QAAQ;GACtC,cAAc,EAAW,EAAK,MAAM;GACpC,OAAO,EAAK;GACZ,OAAO,EAAM;GACb,OAAO,EAAK,SAAS,EAAM;GAC3B,WAAW,EAAM;GACjB,UAAU;GACV,WAAW,EAAK,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EACjD,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAMA,IAAM,IAAK;CACT,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;CACZ,OAAO;EAAC;EAAI;EAAK;EAAK;EAAK;EAAK;CAAG;CACnC,OAAO;CACP,OAAO;AACT;AAEA,SAAS,EAAgB,GAAyC;CAChE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAY,IAAI,IAAI,EAAK,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GACvD,KAAW,MACf,EAAG,SAAS,EAAU,IAAI,CAAE,KAAK,MAAM,EAAG,QAAQ,EAAG;CAGvD,KAAK,IAAM,KAAQ,EAAK,OAAO;EAC7B,IAAM,IAAM,EAAQ,EAAK,EAAE;EAC3B,EAAM,KACJ,EAAM;GACJ,IAAI,QAAQ,EAAK;GACjB,GAAG,EAAG;GACN,GAAG;GACH,OAAO,EAAG;GACV,QAAQ,EAAG;GACX,OAAO,EAAK;GACZ,QAAQ,EAAK,YAAY,cAAc,YAAY;GACnD,YAAY,EAAK,YAAY,cAAc,YAAY;GACvD,QAAQ;EACV,CAAC,CACH;CACF;CAGA,KAAK,IAAM,CAAC,GAAG,OAAW,EAAK,UAAU,CAAC,EAAA,CAAG,QAAQ,GAAG;EACtD,IAAM,IAAK,EAAG,MAAM,EAAM,WAAW,EAAG,QAAQ,IAAI,IAC9C,IAAK,EAAG,MAAM,EAAM,SAAS,EAAG,QAAQ,IAAI;EAClD,EAAM,KACJ,EAAM;GACJ,IAAI,SAAS,EAAM;GACnB,GAAG;GACH,GAAG,EAAG,QAAQ;GACd,OAAO,IAAK;GACZ,QAAQ;GACR,OAAO,EAAM;GACb,QAAQ,EAAiB,EAAM,OAAO,CAAC,CAAC;GACxC,YAAY;GACZ,aAAa;GACb,QAAQ,MAAM;EAChB,CAAC,CACH;CACF;CAGA,KAAK,IAAM,CAAC,GAAG,OAAO,EAAK,UAAU,CAAC,EAAA,CAAG,QAAQ,GAAG;EAClD,IAAM,IAAM,EAAQ,EAAE,IAAI,GACpB,IAAK,EAAG,MAAM,EAAE,WAAW,EAAG,QAAQ,IAAI,GAC1C,IAAK,EAAG,MAAM,EAAE,SAAS,EAAG,QAAQ,IAAI;EAC9C,EAAM,KACJ,EAAM;GACJ,IAAI,WAAW,EAAE;GACjB,GAAG;GACH,GAAG,IAAM,EAAG,aAAa;GACzB,OAAO,IAAK;GACZ,QAAQ,EAAG,QAAQ,EAAG;GACtB,OAAO,EAAE;GACT,QAAQ,EAAiB,EAAE,OAAO,CAAC,CAAC;GACpC,YAAY;GACZ,aAAa;GACb,QAAQ,MAAM;EAChB,CAAC,CACH;CACF;CAEA,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAQ,EAAE,SAAS,EAAG,OACtB,IAAS,EAAE,WAAW,EAAE,MAAM,KAAK,EAAG,QACtC,IAAK,EAAG,MAAM,EAAE,QAAQ,EAAG,MAAM,EAAG,MAAM,SAAS,IACnD,IAAW,EAAG,QAAQ,EAAG,YACzB,IAAI,EAAQ,EAAE,IAAI,IAAI,EAAG,cAAc,IAAW,KAAU,KAAK,EAAE,WAAW,IAC9E,IAAQ,EAAe,EAAE,IAAI;EACnC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAK,IAAQ;GAChB;GACA;GACA;GACA,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE;GACP,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAEA,IAAM,oBAAW,IAAI,IAAY,GAC3B,IAAK,EAAK,YAAY,CAAC;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAG,SAAS,GAAG,KAAK,EAAS,IAAI,GAAG,EAAG,GAAG,IAAI,EAAG,IAAI,IAAI;CAE7E,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAS,EAAS,IAAI,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI,GAC1C,IAAQ,EAAiB,EAAE,YAAY,IAAS,aAAa,UAAU;EAC7E,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,QAAQ,EAAE;GACV,QAAQ,EAAE;GACV,cAAc,EAAW,EAAE,QAAQ;GACnC,cAAc,EAAW,EAAE,MAAM;GACjC,OAAO,EAAE;GACT,OAAO,EAAE,SAAS,UAAU,YAAY,EAAM;GAC9C,OAAO,EAAE,SAAS,EAAM;GACxB,WAAW,EAAE,SAAS,UAAU,WAAW,EAAM;GACjD,UAAU,KAAS;GACnB,WAAW,EAAE,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EAC9C,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAMA,SAAS,EAAgB,GAAyC;CAChE,IAAM,IAAoB,CAAC,GACrB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAU,EAAK,KAAK,WAAW,CAAC,KAAK,GAAG,GAOxC,IAAiB,EAAQ,KAAK,IAE9B,KAAM,MAAc,KAAa,IAAI,KACrC,oBAAQ,IAAI,IAAoB;CAEtC,EAAK,aAAa,SAAS,GAAG,MAAM;EAClC,IAAM,IAAI,EAAG,CAAC;EACd,EAAM,IAAI,EAAE,IAAI,CAAC;EACjB,IAAM,IAAQ,EAAe,EAAE,IAAI;EAmBnC,AAlBA,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAI;GACP,GAAG;GACH,OAAO;GACP,QAAQ;GACR,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;GACV,QAAQ;EACV,CAAC,CACH,GAEA,EAAM,KAAK;GACT,IAAI,YAAY,EAAE;GAClB,MAAM;GACN,QAAQ,CACN;IAAE;IAAG,GAAG;GAAY,GACpB;IAAE;IAAG,GAAG;GAAe,CACzB;GACA,aAAa;GACb,aAAa;GACb,WAAW;GACX,WAAW;GACX,QAAQ;EACV,CAAC;CACH,CAAC;CAGD,KAAK,IAAM,CAAC,GAAG,OAAS,EAAK,YAAY,CAAC,EAAA,CAAG,QAAQ,GACnD,EAAM,KACJ,EAAM;EACJ,IAAI,WAAW;EACf,GAAG;EACH,GAAG,EAAI;EACP,OAAO,EAAQ,KAAK;EACpB,QAAQ,EAAI,KAAK,EAAI;EACrB,OAAO,EAAI;EACX,QAAQ;EACR,YAAY;EACZ,aAAa;EACb,QAAQ;CACV,CAAC,CACH;CAIF,KAAK,IAAM,CAAC,GAAG,OAAS,EAAK,eAAe,CAAC,EAAA,CAAG,QAAQ,GAAG;EACzD,IAAM,IAAI,EAAM,IAAI,EAAI,WAAW;EACnC,IAAI,MAAM,KAAA,GAAW;EACrB,IAAM,IAAQ,EAAe,EAAI,QAAQ,SAAS;EAClD,EAAM,KAAK;GACT,IAAI,cAAc,EAAE,GAAG,EAAI;GAC3B,MAAM;GACN,UAAU;IAAE,GAAG,IAAI;IAAG,GAAG,EAAI;GAAK;GAClC,OAAO;GACP,QAAQ,KAAK,IAAI,GAAG,EAAI,KAAK,EAAI,IAAI;GACrC,QAAQ;GACR,MAAM;IACJ,OAAO;IACP,MAAM,EAAM;IACZ,QAAQ,EAAM;IACd,aAAa;IACb,OAAO,EAAM;IACb,UAAU;IACV,aAAa;IACb,YAAY,CAAC;GACf;EACF,CAAC;CACH;CAGA,KAAK,IAAM,KAAK,EAAK,UAAU;EAC7B,IAAM,IAAQ,EAAM,IAAI,EAAE,IAAI,GACxB,IAAM,EAAM,IAAI,EAAE,EAAE;EAC1B,IAAI,MAAU,KAAA,KAAa,MAAQ,KAAA,GAAW;EAC9C,IAAM,IAAM,IAAM,IAAQ,IAAI,IACxB,IAAQ,IAAQ,IAAM,GACtB,IAAM,IAAM,IAAM,GAClB,IAAQ,EAAiB,EAAE,OAAO;EAexC,AAdA,EAAM,KAAK;GACT,IAAI,EAAE,MAAM,EAAI,KAAK;GACrB,MAAM;GACN,QAAQ,CACN;IAAE,GAAG;IAAO,GAAG,EAAE;GAAE,GACnB;IAAE,GAAG;IAAK,GAAG,EAAE;GAAE,CACnB;GACA,aAAa,EAAM;GACnB,aAAa,EAAM;GACnB,WAAW,EAAM;GACjB,WAAW,EAAE,YAAY,WAAW,UAAU;GAC9C,QAAQ;EACV,CAAC,GAED,EAAM,KAAK;GACT,IAAI,UAAU,EAAE,MAAM,EAAI,GAAG;GAC7B,MAAM;GACN,UAAU;IAAE,IAAI,IAAQ,KAAO,IAAI;IAAI,GAAG,EAAE,IAAI;GAAG;GACnD,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,MAAM;IACJ,OAAO,EAAE;IACT,MAAM;IACN,QAAQ;IACR,aAAa;IACb,OAAO,EAAM;IACb,YAAY,EAAM;IAClB,UAAU;IACV,YAAY,CAAC;GACf;EACF,CAAC;CACH;CAEA,OAAO,EAAK,GAAO,GAAO,GAAO,EAAK,KAAK,KAAK;AAClD;AAMA,IAAM,IAAK;CACT,QAAQ;CACR,QAAQ;CACR,gBAAgB;CAChB,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACP,OAAO;EAAC;EAAK;EAAK;EAAK;EAAK;CAAG;AACjC,GAEM,KAAU,MAAc,EAAG,QAAQ,IAAI,EAAG;AAEhD,SAAS,EAAgB,GAAyC;CAChE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAU,EAAK,KAAK,WAAW,CAAC,KAAK,GAAG;CAG9C,KAAK,IAAM,CAAC,GAAG,MAAU,EAAK,OAAO,QAAQ,GAC3C,EAAM,KACJ,EAAM;EACJ,IAAI,SAAS;EACb,GAAG,EAAO,CAAC,IAAI,EAAG,SAAS;EAC3B,GAAG,EAAG;EACN,OAAO,EAAG;EACV,QAAQ,EAAQ,KAAK,EAAG,SAAS,EAAG;EACpC,OAAO,EAAM;EACb,QAAQ;EACR,YAAY;EACZ,aAAa;EACb,QAAQ;CACV,CAAC,CACH;CAGF,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAQ,EAAE,SAAS,EAAG,OACtB,IAAS,EAAE,UAAU,EAAG,OACxB,IAAK,EAAO,EAAE,KAAK,GACnB,KAAK,EAAG,MAAM,EAAE,QAAQ,EAAG,MAAM,EAAG,MAAM,SAAS,OAAO,EAAE,WAAW,IACvE,IAAQ,EAAe,EAAE,IAAI;EACnC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAK,IAAQ;GAChB;GACA;GACA;GACA,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE;GACP,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAEA,KAAK,IAAM,KAAK,EAAK,OAAO;EAC1B,IAAM,IAAQ,EAAiB,EAAE,OAAO;EACxC,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,QAAQ,EAAE;GACV,QAAQ,EAAE;GACV,cAAc,EAAW,EAAE,QAAQ;GACnC,cAAc,EAAW,EAAE,MAAM;GACjC,OAAO,EAAE;GACT,OAAO,EAAM;GACb,OAAO,EAAE,SAAS,EAAM;GACxB,WAAW,EAAM;GACjB,UAAU,KAAS,EAAE,YAAY;GACjC,WAAW,EAAE,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EAC9C,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAMA,IAAM,IAAK;CACT,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,UAAU;CACV,SAAS;EAAC;EAAI;EAAK;EAAK;EAAK;CAAG;CAChC,SAAS;EAAC;EAAK;EAAK;CAAG;CACvB,WAAW;EAAC;EAAK;EAAK;CAAG;AAC3B;AAEA,SAAS,EAAc,GAA6C;CAGlE,OAFI,MAAS,SAAe,UACxB,MAAS,aAAmB,YACzB;AACT;AAEA,SAAS,EAAiB,GAA0C;CAClE,IAAM,IAAQ,EAAQ,CAAI,GACpB,IAAoB,CAAC,GACrB,IAAoB,CAAC,GAErB,IAAU,EAAK,KAAK,WAAW,CAAC,KAAK,GAAG,GAGxC,IAAY,IAAI,IAAI,EAAK,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,GAC1D,IAAgG;EACpG;GAAE,MAAM;GAAS,GAAG,EAAG,SAAS;GAAI,GAAG,EAAG,SAAS;GAAI,OAAO,EAAU,IAAI,MAAM,KAAK;EAAmB;EAC1G;GAAE,MAAM;GAAS,GAAG,EAAG,SAAS;GAAI,GAAG,EAAG,SAAS;GAAI,OAAO;EAA2B;EACzF;GAAE,MAAM;GAAW,GAAG,EAAG,WAAW;GAAI,GAAG,EAAG,WAAW;GAAI,OAAO,EAAU,IAAI,UAAU,KAAK;EAAiB;CACpH;CACA,KAAK,IAAM,CAAC,GAAG,MAAM,EAAS,QAAQ,GACpC,EAAM,KACJ,EAAM;EACJ,IAAI,QAAQ,EAAE;EACd,GAAG;EACH,GAAG,EAAE;EACL,OAAO,EAAQ,KAAK;EACpB,QAAQ,EAAE;EACV,OAAO,IAAI,IAAI,EAAE,KAAK,EAAE;EACxB,QAAQ;EACR,YAAY;EACZ,aAAa;EACb,QAAQ;CACV,CAAC,CACH;CAGF,KAAK,IAAM,KAAK,EAAK,QAAQ;EAC3B,IAAM,IAAO,EAAc,EAAE,IAAI,GAC3B,IAAU,MAAS,SACnB,IAAY,MAAS,WACrB,IAAQ,EAAE,UAAU,IAAU,EAAG,SAAS,IAAY,EAAG,WAAW,EAAG,SACvE,IAAS,EAAE,WAAW,IAAU,EAAG,SAAS,IAAY,EAAG,WAAW,EAAG,SACzE,IAAK,IAAU,EAAG,UAAU,IAAY,EAAG,YAAY,EAAG,SAC1D,IAAK,EAAG,EAAE,QAAQ,EAAG,EAAG,SAAS,IACjC,KAAK,IAAU,EAAG,SAAS,IAAY,EAAG,WAAW,EAAG,WAAW,EAAE,WAAW,IAChF,IAAQ,EAAW,EAAE,IAAI;EAC/B,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,GAAG,IAAK,IAAQ;GAChB;GACA;GACA;GACA,OAAO,EAAE;GACT,UAAU,EAAE;GACZ,KAAK,EAAE,OAAO,EAAE;GAChB,MAAM,EAAM;GACZ,QAAQ,EAAM;GACd,MAAM,EAAM;GACZ,KAAK,EAAM;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAKA,IAAM,IAAa,EAAK,OACrB,QAAQ,MAAM,EAAE,SAAS,MAAM,CAAC,CAChC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,GACzB,IAAgB,IAAI,IAAI,EAAK,YAAY,KAAK,MAAM,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI,CAAC;CAC/E,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,SAAS,GAAG,KAAK;EAC9C,IAAM,IAAO,EAAW,IAClB,IAAK,EAAW,IAAI;EAEtB,EAAc,IAAI,GAAG,EAAK,GAAG,IAAI,EAAG,IAAI,KAC5C,EAAM,KACJ,EAAK;GACH,IAAI,YAAY,EAAK,GAAG,GAAG,EAAG;GAC9B,QAAQ,EAAK;GACb,QAAQ,EAAG;GACX,cAAc,EAAW,OAAO;GAChC,cAAc,EAAW,MAAM;GAC/B,OAAO,KAAA;GACP,OAAO,EAAiB,UAAU,CAAC,CAAC;GACpC,OAAO;GACP,WAAW;GACX,UAAU;EACZ,CAAC,CACH;CACF;CAEA,IAAM,oBAAY,IAAI,IAAY;CAClC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,SAAS,GAAG,KACzC,EAAU,IAAI,GAAG,EAAW,EAAE,CAAC,GAAG,IAAI,EAAW,IAAI,EAAE,CAAC,IAAI;CAG9D,KAAK,IAAM,KAAK,EAAK,aAAa;EAChC,IAAM,IAAQ,EAAiB,EAAE,OAAO,GAClC,IAAS,EAAU,IAAI,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI;EACjD,EAAM,KACJ,EAAK;GACH,IAAI,EAAE;GACN,QAAQ,EAAE;GACV,QAAQ,EAAE;GACV,cAAc,EAAW,EAAE,QAAQ;GACnC,cAAc,EAAW,EAAE,MAAM;GACjC,OAAO,EAAE;GACT,OAAO,EAAM;GACb,OAAO,EAAE,SAAS,EAAM;GACxB,WAAW,EAAM;GACjB,UAAU,KAAS;GACnB,WAAW,EAAE,KAAK,KAAK,CAAC,GAAG,QAAQ;IAAE;IAAG;GAAE,EAAE;EAC9C,CAAC,CACH;CACF;CAEA,OAAO,EAAK,GAAO,GAAO,CAAC,GAAG,EAAK,KAAK,KAAK;AAC/C;AAIA,SAAS,EACP,GACA,GACA,GACA,GACc;CACd,OAAO;EACL,UAAU,GACP,IAAiB;GAAE;GAAO;GAAO;EAAM,EAC1C;EACA,OAAO,CAAC,CAAc;EACtB;CACF;AACF;AAGA,SAAgB,EAAsB,GAAiC;CACrE,QAAQ,EAAK,cAAb;EACE,KAAK,gBACH,OAAO,EAAoB,CAAI;EACjC,KAAK,YACH,OAAO,EAAgB,CAAI;EAC7B,KAAK,YACH,OAAO,EAAgB,CAAI;EAC7B,KAAK,YACH,OAAO,EAAgB,CAAI;EAC7B,KAAK,aACH,OAAO,EAAiB,CAAI;EAC9B,SACE,OAAO,EAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC1B;AACF"}
|
|
@@ -140,23 +140,25 @@ function n() {
|
|
|
140
140
|
]),
|
|
141
141
|
changeZIndex: t((e) => {
|
|
142
142
|
let t = i.nodeIds, a = i.lineIds;
|
|
143
|
-
(t.size
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
let
|
|
143
|
+
if (t.size === 0 && a.size === 0) return;
|
|
144
|
+
let o = (t, n, r) => e === "front" ? n + 1 : e === "back" ? r - 1 : e === "up" ? t + 1 : t - 1;
|
|
145
|
+
n((e) => {
|
|
146
|
+
let n = e.canvases[r];
|
|
147
|
+
if (!n) return e;
|
|
148
|
+
let i = n.nodes.map((e) => e.zIndex ?? 0), s = i.length > 0 ? Math.max(...i) : 0, c = i.length > 0 ? Math.min(...i) : 0, l = n.lines.map((e) => e.zIndex ?? 0), u = l.length > 0 ? Math.max(...l) : 0, d = l.length > 0 ? Math.min(...l) : 0;
|
|
147
149
|
return {
|
|
148
|
-
...
|
|
150
|
+
...e,
|
|
149
151
|
canvases: {
|
|
150
|
-
...
|
|
152
|
+
...e.canvases,
|
|
151
153
|
[r]: {
|
|
152
|
-
...
|
|
153
|
-
nodes:
|
|
154
|
+
...n,
|
|
155
|
+
nodes: n.nodes.map((e) => t.has(e.id) ? {
|
|
154
156
|
...e,
|
|
155
|
-
zIndex:
|
|
157
|
+
zIndex: o(e.zIndex ?? 0, s, c)
|
|
156
158
|
} : e),
|
|
157
|
-
lines:
|
|
159
|
+
lines: n.lines.map((e) => a.has(e.id) ? {
|
|
158
160
|
...e,
|
|
159
|
-
zIndex:
|
|
161
|
+
zIndex: o(e.zIndex ?? 0, u, d)
|
|
160
162
|
} : e)
|
|
161
163
|
}
|
|
162
164
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLayoutActions.js","names":[],"sources":["../../../../../src/components/pro/Flow/hooks/useLayoutActions.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useFlowContext } from '../context/FlowContext';\nimport type { FlowNode } from '../types';\n\ntype Align = 'left' | 'center-h' | 'right' | 'top' | 'center-v' | 'bottom';\ntype Distribute = 'horizontal' | 'vertical';\ntype LayerMode = 'front' | 'back' | 'up' | 'down';\n\nexport function useLayoutActions() {\n const { setDoc, currentCanvasId, selection, currentCanvas } = useFlowContext();\n\n const align = useCallback(\n (direction: Align) => {\n const ids = selection.nodeIds;\n if (ids.size < 2) return;\n const nodes = currentCanvas.nodes.filter(n => ids.has(n.id));\n if (nodes.length < 2) return;\n\n let target: number;\n switch (direction) {\n case 'left':\n target = Math.min(...nodes.map(n => n.position.x));\n break;\n case 'right':\n target = Math.max(...nodes.map(n => n.position.x + n.width));\n break;\n case 'center-h':\n target = nodes.reduce((s, n) => s + n.position.x + n.width / 2, 0) / nodes.length;\n break;\n case 'top':\n target = Math.min(...nodes.map(n => n.position.y));\n break;\n case 'bottom':\n target = Math.max(...nodes.map(n => n.position.y + n.height));\n break;\n case 'center-v':\n target = nodes.reduce((s, n) => s + n.position.y + n.height / 2, 0) / nodes.length;\n break;\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]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n if (!ids.has(n.id)) return n;\n let newX = n.position.x;\n let newY = n.position.y;\n switch (direction) {\n case 'left': newX = target; break;\n case 'right': newX = target - n.width; break;\n case 'center-h': newX = target - n.width / 2; break;\n case 'top': newY = target; break;\n case 'bottom': newY = target - n.height; break;\n case 'center-v': newY = target - n.height / 2; break;\n }\n return { ...n, position: { x: newX, y: newY } };\n }),\n },\n },\n };\n });\n },\n [setDoc, currentCanvasId, selection, currentCanvas],\n );\n\n const distribute = useCallback(\n (direction: Distribute) => {\n const ids = selection.nodeIds;\n if (ids.size < 3) return;\n const nodes = currentCanvas.nodes.filter(n => ids.has(n.id));\n if (nodes.length < 3) return;\n\n const sorted = [...nodes].sort((a, b) =>\n direction === 'horizontal'\n ? a.position.x - b.position.x\n : a.position.y - b.position.y,\n );\n\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n\n if (direction === 'horizontal') {\n const totalWidth = sorted.reduce((s, n) => s + n.width, 0);\n const totalSpace = (last.position.x + last.width) - first.position.x - totalWidth;\n const gap = totalSpace / (sorted.length - 1);\n let x = first.position.x;\n\n const posMap = new Map<string, number>();\n for (const n of sorted) {\n posMap.set(n.id, x);\n x += n.width + gap;\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]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n const newX = posMap.get(n.id);\n return newX !== undefined ? { ...n, position: { ...n.position, x: newX } } : n;\n }),\n },\n },\n };\n });\n } else {\n const totalHeight = sorted.reduce((s, n) => s + n.height, 0);\n const totalSpace = (last.position.y + last.height) - first.position.y - totalHeight;\n const gap = totalSpace / (sorted.length - 1);\n let y = first.position.y;\n\n const posMap = new Map<string, number>();\n for (const n of sorted) {\n posMap.set(n.id, y);\n y += n.height + gap;\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]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n const newY = posMap.get(n.id);\n return newY !== undefined ? { ...n, position: { ...n.position, y: newY } } : n;\n }),\n },\n },\n };\n });\n }\n },\n [setDoc, currentCanvasId, selection, currentCanvas],\n );\n\n const changeZIndex = useCallback(\n (mode: LayerMode) => {\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: {\n ...prev.canvases,\n [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 });\n },\n [setDoc, currentCanvasId, selection],\n );\n\n return { align, distribute, changeZIndex };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useLayoutActions.js","names":[],"sources":["../../../../../src/components/pro/Flow/hooks/useLayoutActions.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useFlowContext } from '../context/FlowContext';\nimport type { FlowNode } from '../types';\n\ntype Align = 'left' | 'center-h' | 'right' | 'top' | 'center-v' | 'bottom';\ntype Distribute = 'horizontal' | 'vertical';\ntype LayerMode = 'front' | 'back' | 'up' | 'down';\n\nexport function useLayoutActions() {\n const { setDoc, currentCanvasId, selection, currentCanvas } = useFlowContext();\n\n const align = useCallback(\n (direction: Align) => {\n const ids = selection.nodeIds;\n if (ids.size < 2) return;\n const nodes = currentCanvas.nodes.filter(n => ids.has(n.id));\n if (nodes.length < 2) return;\n\n let target: number;\n switch (direction) {\n case 'left':\n target = Math.min(...nodes.map(n => n.position.x));\n break;\n case 'right':\n target = Math.max(...nodes.map(n => n.position.x + n.width));\n break;\n case 'center-h':\n target = nodes.reduce((s, n) => s + n.position.x + n.width / 2, 0) / nodes.length;\n break;\n case 'top':\n target = Math.min(...nodes.map(n => n.position.y));\n break;\n case 'bottom':\n target = Math.max(...nodes.map(n => n.position.y + n.height));\n break;\n case 'center-v':\n target = nodes.reduce((s, n) => s + n.position.y + n.height / 2, 0) / nodes.length;\n break;\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]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n if (!ids.has(n.id)) return n;\n let newX = n.position.x;\n let newY = n.position.y;\n switch (direction) {\n case 'left': newX = target; break;\n case 'right': newX = target - n.width; break;\n case 'center-h': newX = target - n.width / 2; break;\n case 'top': newY = target; break;\n case 'bottom': newY = target - n.height; break;\n case 'center-v': newY = target - n.height / 2; break;\n }\n return { ...n, position: { x: newX, y: newY } };\n }),\n },\n },\n };\n });\n },\n [setDoc, currentCanvasId, selection, currentCanvas],\n );\n\n const distribute = useCallback(\n (direction: Distribute) => {\n const ids = selection.nodeIds;\n if (ids.size < 3) return;\n const nodes = currentCanvas.nodes.filter(n => ids.has(n.id));\n if (nodes.length < 3) return;\n\n const sorted = [...nodes].sort((a, b) =>\n direction === 'horizontal'\n ? a.position.x - b.position.x\n : a.position.y - b.position.y,\n );\n\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n\n if (direction === 'horizontal') {\n const totalWidth = sorted.reduce((s, n) => s + n.width, 0);\n const totalSpace = (last.position.x + last.width) - first.position.x - totalWidth;\n const gap = totalSpace / (sorted.length - 1);\n let x = first.position.x;\n\n const posMap = new Map<string, number>();\n for (const n of sorted) {\n posMap.set(n.id, x);\n x += n.width + gap;\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]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n const newX = posMap.get(n.id);\n return newX !== undefined ? { ...n, position: { ...n.position, x: newX } } : n;\n }),\n },\n },\n };\n });\n } else {\n const totalHeight = sorted.reduce((s, n) => s + n.height, 0);\n const totalSpace = (last.position.y + last.height) - first.position.y - totalHeight;\n const gap = totalSpace / (sorted.length - 1);\n let y = first.position.y;\n\n const posMap = new Map<string, number>();\n for (const n of sorted) {\n posMap.set(n.id, y);\n y += n.height + gap;\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]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n const newY = posMap.get(n.id);\n return newY !== undefined ? { ...n, position: { ...n.position, y: newY } } : n;\n }),\n },\n },\n };\n });\n }\n },\n [setDoc, currentCanvasId, selection, currentCanvas],\n );\n\n const changeZIndex = useCallback(\n (mode: LayerMode) => {\n const nodeIds = selection.nodeIds;\n const lineIds = selection.lineIds;\n if (nodeIds.size === 0 && lineIds.size === 0) return;\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 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 return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [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 });\n },\n [setDoc, currentCanvasId, selection],\n );\n\n return { align, distribute, changeZIndex };\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { FlowNode, FlowAIConfig } from '../types';
|
|
3
3
|
/** Dispatches to the correct renderer for the node's media kind. */
|
|
4
|
-
export declare function MediaContent({ node, interactive, aiConfig }: {
|
|
4
|
+
export declare function MediaContent({ node, interactive, aiConfig, useSharedAIConfig }: {
|
|
5
5
|
node: FlowNode;
|
|
6
6
|
interactive: boolean;
|
|
7
7
|
aiConfig?: FlowAIConfig;
|
|
8
|
+
useSharedAIConfig?: boolean;
|
|
8
9
|
}): React.JSX.Element | null;
|
|
@@ -194,43 +194,43 @@ function x({ node: t, config: n, interactive: i, color: a }) {
|
|
|
194
194
|
]
|
|
195
195
|
});
|
|
196
196
|
}
|
|
197
|
-
function S({ node: r, interactive: a, aiConfig: o }) {
|
|
198
|
-
let
|
|
199
|
-
switch (
|
|
197
|
+
function S({ node: r, interactive: a, aiConfig: o, useSharedAIConfig: s = !1 }) {
|
|
198
|
+
let c = r.data.mediaKind ?? "markdown", l = r.data.mediaContent ?? "", d = n(r.data.labelColor ?? r.data.color, "#111827");
|
|
199
|
+
switch (c) {
|
|
200
200
|
case "markdown": return /* @__PURE__ */ u("div", {
|
|
201
201
|
className: "flow-media-markdown",
|
|
202
202
|
style: {
|
|
203
|
-
color:
|
|
203
|
+
color: d,
|
|
204
204
|
fontSize: r.data.fontSize
|
|
205
205
|
},
|
|
206
|
-
children: /* @__PURE__ */ u(e, { content:
|
|
206
|
+
children: /* @__PURE__ */ u(e, { content: l })
|
|
207
207
|
});
|
|
208
208
|
case "html": return /* @__PURE__ */ u(y, {
|
|
209
|
-
content:
|
|
209
|
+
content: l,
|
|
210
210
|
interactive: a,
|
|
211
211
|
color: t(r.data.labelColor ?? r.data.color, "#111827"),
|
|
212
212
|
fontSize: r.data.fontSize
|
|
213
213
|
});
|
|
214
214
|
case "mermaid": return /* @__PURE__ */ u(_, {
|
|
215
|
-
content:
|
|
216
|
-
color:
|
|
215
|
+
content: l,
|
|
216
|
+
color: d
|
|
217
217
|
});
|
|
218
218
|
case "math": return /* @__PURE__ */ u(v, {
|
|
219
|
-
content:
|
|
220
|
-
color:
|
|
219
|
+
content: l,
|
|
220
|
+
color: d,
|
|
221
221
|
fontSize: r.data.fontSize
|
|
222
222
|
});
|
|
223
|
-
case "image": return /* @__PURE__ */ u(b, { content:
|
|
223
|
+
case "image": return /* @__PURE__ */ u(b, { content: l });
|
|
224
224
|
case "model3d": return /* @__PURE__ */ u(i, {
|
|
225
|
-
content:
|
|
225
|
+
content: l,
|
|
226
226
|
format: r.data.modelFormat ?? "stl",
|
|
227
227
|
interactive: a
|
|
228
228
|
});
|
|
229
229
|
case "ai": return /* @__PURE__ */ u(x, {
|
|
230
230
|
node: r,
|
|
231
|
-
config: o
|
|
231
|
+
config: s ? o : r.data.aiConfig,
|
|
232
232
|
interactive: a,
|
|
233
|
-
color:
|
|
233
|
+
color: d
|
|
234
234
|
});
|
|
235
235
|
case "data": return /* @__PURE__ */ u("div", {
|
|
236
236
|
className: "flow-media-data",
|
|
@@ -242,7 +242,7 @@ function S({ node: r, interactive: a, aiConfig: o }) {
|
|
|
242
242
|
view: "table"
|
|
243
243
|
},
|
|
244
244
|
surfaceColor: r.data.fill === "transparent" ? void 0 : n(r.data.fill, ""),
|
|
245
|
-
textColor:
|
|
245
|
+
textColor: d,
|
|
246
246
|
primaryColor: n(r.data.color, "")
|
|
247
247
|
})
|
|
248
248
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaContent.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/MediaContent.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport katex from 'katex';\nimport mermaid from 'mermaid';\nimport Markdown from '../../../Markdown';\nimport type { FlowNode, FlowAIConfig } from '../types';\nimport { streamAIChat, type AIChatMessage } from './aiClient';\nimport { resolveThemeColorCss, resolveThemeColor } from '../utils/themeColor';\nimport 'katex/dist/katex.min.css';\nimport { Model3DView } from './Model3DView';\n\n// Data-node view pulls in DataTable + Chart; lazy-load so it only enters the\n// bundle when a data node actually renders.\nconst DataNodeView = React.lazy(() =>\n import('./DataNodeView').then((m) => ({ default: m.DataNodeView })),\n);\n\nlet mermaidReady = false;\nfunction ensureMermaid() {\n if (mermaidReady) return;\n mermaid.initialize({ startOnLoad: false, theme: 'default', securityLevel: 'loose', fontFamily: 'inherit' });\n mermaidReady = true;\n}\n\n/** Renders a Mermaid diagram from source into an inline SVG. */\nfunction MermaidView({ content, color }: { content: string; color?: string }) {\n const [svg, setSvg] = useState('');\n const [error, setError] = useState<string | null>(null);\n const idRef = useRef(`flow-mermaid-${Math.random().toString(36).slice(2)}`);\n\n useEffect(() => {\n let cancelled = false;\n ensureMermaid();\n const src = content.trim();\n if (!src) { setSvg(''); setError(null); return; }\n mermaid\n .render(idRef.current, src)\n .then(({ svg }) => { if (!cancelled) { setSvg(svg); setError(null); } })\n .catch((e) => { if (!cancelled) setError(e?.message ?? 'Mermaid error'); });\n return () => { cancelled = true; };\n }, [content]);\n\n if (error) return <div className=\"flow-media-error\">{error}</div>;\n return <div className=\"flow-media-mermaid\" style={{ color }} dangerouslySetInnerHTML={{ __html: svg }} />;\n}\n\n/** Renders a LaTeX formula (display mode) via KaTeX. */\nfunction MathView({ content, color, fontSize }: { content: string; color?: string; fontSize?: number }) {\n const html = useMemo(() => {\n try {\n return katex.renderToString(content.trim() || '\\\\;', { displayMode: true, throwOnError: false });\n } catch (e: any) {\n return `<span class=\"flow-media-error\">${e?.message ?? 'KaTeX error'}</span>`;\n }\n }, [content]);\n return <div className=\"flow-media-math\" style={{ color, fontSize }} dangerouslySetInnerHTML={{ __html: html }} />;\n}\n\n/** Renders raw HTML in a sandboxed iframe (isolated from the host document).\n * A base stylesheet is injected so the fragment inherits the node's themed\n * text color / font size and a transparent background, keeping it readable on\n * any theme without the author having to set colors.\n * Content is always untrusted: scripts can drive the preview, but the opaque\n * sandbox origin prevents host DOM/storage access. Do not add allow-same-origin\n * alongside allow-scripts; interactive only controls pointer input. */\nfunction HtmlView({ content, interactive, color, fontSize }: { content: string; interactive: boolean; color?: string; fontSize?: number }) {\n const srcDoc = useMemo(() => {\n const base = `<!doctype html><html><head><meta charset=\"utf-8\"><style>\n :root { color-scheme: light dark; }\n html, body { margin: 0; background: transparent; }\n body {\n color: ${color ?? '#111827'};\n font-size: ${fontSize ?? 13}px;\n font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n line-height: 1.5;\n padding: 0;\n }\n a { color: inherit; }\n </style></head><body>${content}</body></html>`;\n return base;\n }, [content, color, fontSize]);\n return (\n <iframe\n title=\"html-media\"\n className=\"flow-media-iframe\"\n style={{ pointerEvents: interactive ? 'auto' : 'none' }}\n sandbox=\"allow-scripts\"\n srcDoc={srcDoc}\n />\n );\n}\n\nfunction ImageView({ content }: { content: string }) {\n const src = content.trim();\n if (!src) {\n return <div className=\"flow-media-image-empty\">输入图片链接,或直接粘贴图片</div>;\n }\n return (\n <img\n className=\"flow-media-image\"\n src={src}\n alt=\"\"\n draggable={false}\n referrerPolicy=\"no-referrer\"\n />\n );\n}\n\n/** Interactive AI chat backed by an OpenAI/Anthropic-compatible endpoint. */\nfunction AIView({ node, config, interactive, color }: { node: FlowNode; config?: FlowAIConfig; interactive: boolean; color?: string }) {\n const [messages, setMessages] = useState<AIChatMessage[]>([]);\n const [input, setInput] = useState('');\n const [streaming, setStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight });\n }, [messages, streaming]);\n\n useEffect(() => () => abortRef.current?.abort(), []);\n\n const canSend = !!config?.gateway && !!config?.model && !streaming;\n\n const send = async () => {\n const text = input.trim();\n if (!text || !config?.gateway) return;\n setError(null);\n // Only keep non-empty assistant messages in history; an aborted/errored\n // request can leave an empty assistant placeholder behind, which the API\n // then rejects (\"assistant message must not be empty\").\n const history = messages.filter(\n (m) => !(m.role === 'assistant' && m.content.trim() === ''),\n );\n const next: AIChatMessage[] = [...history, { role: 'user', content: text }];\n setMessages(next);\n setInput('');\n setStreaming(true);\n const ac = new AbortController();\n abortRef.current = ac;\n let acc = '';\n setMessages((m) => [...m, { role: 'assistant', content: '' }]);\n try {\n for await (const delta of streamAIChat(config, next, ac.signal)) {\n acc += delta;\n setMessages((m) => {\n const copy = m.slice();\n copy[copy.length - 1] = { role: 'assistant', content: acc };\n return copy;\n });\n }\n } catch (e: any) {\n if (e?.name !== 'AbortError') setError(e?.message ?? 'Request failed');\n } finally {\n // Drop the trailing assistant placeholder if nothing streamed in.\n setMessages((m) => {\n const last = m[m.length - 1];\n if (last && last.role === 'assistant' && last.content.trim() === '') {\n return m.slice(0, -1);\n }\n return m;\n });\n setStreaming(false);\n abortRef.current = null;\n }\n };\n\n return (\n <div className=\"flow-media-ai\" style={{ color }}>\n <div className=\"flow-media-ai-header\">\n {config?.model ? `AI · ${config.model}` : (node.data.label || 'AI')}\n </div>\n <div className=\"flow-media-ai-log\" ref={scrollRef}>\n {messages.length === 0 && (\n <div className=\"flow-media-ai-empty\">\n {config?.gateway ? '开始对话…' : '请先配置 AI 接口'}\n </div>\n )}\n {messages.map((m, i) => (\n <div key={i} className={`flow-media-ai-msg flow-media-ai-msg--${m.role}`}>\n {m.role === 'assistant'\n ? <Markdown content={m.content || '…'} enableMermaid={false} enableMarkmap={false} />\n : <span>{m.content}</span>}\n </div>\n ))}\n {error && <div className=\"flow-media-error\">{error}</div>}\n </div>\n <div className=\"flow-media-ai-input\" style={{ pointerEvents: interactive ? 'auto' : 'none' }}>\n <textarea\n value={input}\n placeholder=\"输入消息,Enter 发送\"\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); if (canSend) send(); }\n }}\n onPointerDown={(e) => e.stopPropagation()}\n />\n {streaming ? (\n <button type=\"button\" onClick={() => abortRef.current?.abort()}>停止</button>\n ) : (\n <button type=\"button\" disabled={!canSend || !input.trim()} onClick={send}>发送</button>\n )}\n </div>\n </div>\n );\n}\n\n/** Dispatches to the correct renderer for the node's media kind. */\nexport function MediaContent({ node, interactive, aiConfig }: { node: FlowNode; interactive: boolean; aiConfig?: FlowAIConfig }) {\n const kind = node.data.mediaKind ?? 'markdown';\n const content = node.data.mediaContent ?? '';\n const textColor = resolveThemeColorCss(node.data.labelColor ?? node.data.color, '#111827');\n\n switch (kind) {\n case 'markdown':\n return (\n <div className=\"flow-media-markdown\" style={{ color: textColor, fontSize: node.data.fontSize }}>\n <Markdown content={content} />\n </div>\n );\n case 'html':\n // The iframe is an isolated document with no access to the parent's CSS\n // variables, so pass a concrete resolved color instead of a var().\n return (\n <HtmlView\n content={content}\n interactive={interactive}\n color={resolveThemeColor(node.data.labelColor ?? node.data.color, '#111827')}\n fontSize={node.data.fontSize}\n />\n );\n case 'mermaid':\n return <MermaidView content={content} color={textColor} />;\n case 'math':\n return <MathView content={content} color={textColor} fontSize={node.data.fontSize} />;\n case 'image':\n return <ImageView content={content} />;\n case 'model3d':\n return (\n <Model3DView\n content={content}\n format={node.data.modelFormat ?? 'stl'}\n interactive={interactive}\n />\n );\n case 'ai':\n return <AIView node={node} config={aiConfig ?? node.data.aiConfig} interactive={interactive} color={textColor} />;\n case 'data':\n return (\n <div className=\"flow-media-data\" style={{ pointerEvents: interactive ? 'auto' : 'none' }}>\n <DataNodeView\n config={node.data.dataConfig ?? { columns: [], rows: [], view: 'table' }}\n surfaceColor={node.data.fill === 'transparent' ? undefined : resolveThemeColorCss(node.data.fill, '')}\n textColor={textColor}\n primaryColor={resolveThemeColorCss(node.data.color, '')}\n />\n </div>\n );\n default:\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;AAYA,IAAM,IAAe,EAAM,WACzB,OAAO,oBAAiB,CAAC,MAAM,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CACpE,GAEI,IAAe;AACnB,SAAS,IAAgB;CACnB,AAEJ,OADA,EAAQ,WAAW;EAAE,aAAa;EAAO,OAAO;EAAW,eAAe;EAAS,YAAY;CAAU,CAAC,GAC3F;AACjB;AAGA,SAAS,EAAY,EAAE,YAAS,YAA8C;CAC5E,IAAM,CAAC,GAAK,KAAU,EAAS,EAAE,GAC3B,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,IAAQ,EAAO,gBAAgB,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG;CAe1E,OAbA,QAAgB;EACd,IAAI,IAAY;EAChB,EAAc;EACd,IAAM,IAAM,EAAQ,KAAK;EACzB,IAAI,CAAC,GAAK;GAAc,AAAZ,EAAO,EAAE,GAAG,EAAS,IAAI;GAAG;EAAQ;EAKhD,OAJA,EACG,OAAO,EAAM,SAAS,CAAG,CAAC,CAC1B,MAAM,EAAE,aAAU;GAAE,AAAK,MAAa,EAAO,CAAG,GAAG,EAAS,IAAI;EAAK,CAAC,CAAC,CACvE,OAAO,MAAM;GAAE,AAAK,KAAW,EAAS,GAAG,WAAW,eAAe;EAAG,CAAC,SAC/D;GAAE,IAAY;EAAM;CACnC,GAAG,CAAC,CAAO,CAAC,GAER,IAAc,kBAAC,OAAD;EAAK,WAAU;EAAoB,UAAA;CAAW,CAAA,IACzD,kBAAC,OAAD;EAAK,WAAU;EAAqB,OAAO,EAAE,SAAM;EAAG,yBAAyB,EAAE,QAAQ,EAAI;CAAI,CAAA;AAC1G;AAGA,SAAS,EAAS,EAAE,YAAS,UAAO,eAAoE;CACtG,IAAM,IAAO,QAAc;EACzB,IAAI;GACF,OAAO,EAAM,eAAe,EAAQ,KAAK,KAAK,OAAO;IAAE,aAAa;IAAM,cAAc;GAAM,CAAC;EACjG,SAAS,GAAQ;GACf,OAAO,kCAAkC,GAAG,WAAW,cAAc;EACvE;CACF,GAAG,CAAC,CAAO,CAAC;CACZ,OAAO,kBAAC,OAAD;EAAK,WAAU;EAAkB,OAAO;GAAE;GAAO;EAAS;EAAG,yBAAyB,EAAE,QAAQ,EAAK;CAAI,CAAA;AAClH;AASA,SAAS,EAAS,EAAE,YAAS,gBAAa,UAAO,eAA0F;CACzI,IAAM,IAAS,QAaN;;;;iBARM,KAAS,UAAU;qBACf,KAAY,GAAG;;;;;;2BAMT,EAAQ,iBAE9B;EAAC;EAAS;EAAO;CAAQ,CAAC;CAC7B,OACE,kBAAC,UAAD;EACE,OAAM;EACN,WAAU;EACV,OAAO,EAAE,eAAe,IAAc,SAAS,OAAO;EACtD,SAAQ;EACA;CACT,CAAA;AAEL;AAEA,SAAS,EAAU,EAAE,cAAgC;CACnD,IAAM,IAAM,EAAQ,KAAK;CAIzB,OAHK,IAIH,kBAAC,OAAD;EACE,WAAU;EACL;EACL,KAAI;EACJ,WAAW;EACX,gBAAe;CAChB,CAAA,IATM,kBAAC,OAAD;EAAK,WAAU;EAAyB,UAAA;CAAmB,CAAA;AAWtE;AAGA,SAAS,EAAO,EAAE,SAAM,WAAQ,gBAAa,YAA0F;CACrI,IAAM,CAAC,GAAU,KAAe,EAA0B,CAAC,CAAC,GACtD,CAAC,GAAO,KAAY,EAAS,EAAE,GAC/B,CAAC,GAAW,KAAgB,EAAS,EAAK,GAC1C,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,IAAW,EAA+B,IAAI,GAC9C,IAAY,EAAuB,IAAI;CAM7C,AAJA,QAAgB;EACd,EAAU,SAAS,SAAS,EAAE,KAAK,EAAU,QAAQ,aAAa,CAAC;CACrE,GAAG,CAAC,GAAU,CAAS,CAAC,GAExB,cAAsB,EAAS,SAAS,MAAM,GAAG,CAAC,CAAC;CAEnD,IAAM,IAAU,CAAC,CAAC,GAAQ,WAAW,CAAC,CAAC,GAAQ,SAAS,CAAC,GAEnD,IAAO,YAAY;EACvB,IAAM,IAAO,EAAM,KAAK;EACxB,IAAI,CAAC,KAAQ,CAAC,GAAQ,SAAS;EAC/B,EAAS,IAAI;EAOb,IAAM,IAAwB,CAAC,GAHf,EAAS,QACtB,MAAQ,EAAE,SAAS,eAAe,EAAE,QAAQ,KAAK,MAAM,EAExB,GAAS;GAAE,MAAM;GAAQ,SAAS;EAAK,CAAC;EAG1E,AAFA,EAAY,CAAI,GAChB,EAAS,EAAE,GACX,EAAa,EAAI;EACjB,IAAM,IAAK,IAAI,gBAAgB;EAC/B,EAAS,UAAU;EACnB,IAAI,IAAM;EACV,GAAa,MAAM,CAAC,GAAG,GAAG;GAAE,MAAM;GAAa,SAAS;EAAG,CAAC,CAAC;EAC7D,IAAI;GACF,WAAW,IAAM,KAAS,EAAa,GAAQ,GAAM,EAAG,MAAM,GAE5D,AADA,KAAO,GACP,GAAa,MAAM;IACjB,IAAM,IAAO,EAAE,MAAM;IAErB,OADA,EAAK,EAAK,SAAS,KAAK;KAAE,MAAM;KAAa,SAAS;IAAI,GACnD;GACT,CAAC;EAEL,SAAS,GAAQ;GACf,AAAI,GAAG,SAAS,gBAAc,EAAS,GAAG,WAAW,gBAAgB;EACvE,UAAU;GAUR,AARA,GAAa,MAAM;IACjB,IAAM,IAAO,EAAE,EAAE,SAAS;IAI1B,OAHI,KAAQ,EAAK,SAAS,eAAe,EAAK,QAAQ,KAAK,MAAM,KACxD,EAAE,MAAM,GAAG,EAAE,IAEf;GACT,CAAC,GACD,EAAa,EAAK,GAClB,EAAS,UAAU;EACrB;CACF;CAEA,OACE,kBAAC,OAAD;EAAK,WAAU;EAAgB,OAAO,EAAE,SAAM;EAA9C,UAAA;GACE,kBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,GAAQ,QAAQ,QAAQ,EAAO,UAAW,EAAK,KAAK,SAAS;GAC3D,CAAA;GACL,kBAAC,OAAD;IAAK,WAAU;IAAoB,KAAK;IAAxC,UAAA;KACG,EAAS,WAAW,KACnB,kBAAC,OAAD;MAAK,WAAU;MACZ,UAAA,GAAQ,UAAU,UAAU;KAC1B,CAAA;KAEN,EAAS,KAAK,GAAG,MAChB,kBAAC,OAAD;MAAa,WAAW,wCAAwC,EAAE;MAC/D,UAAA,EAAE,SAAS,cACR,kBAAC,GAAD;OAAU,SAAS,EAAE,WAAW;OAAK,eAAe;OAAO,eAAe;MAAQ,CAAA,IAClF,kBAAC,QAAD,EAAA,UAAO,EAAE,QAAc,CAAA;KACxB,GAJK,CAIL,CACN;KACA,KAAS,kBAAC,OAAD;MAAK,WAAU;MAAoB,UAAA;KAAW,CAAA;IACrD;;GACL,kBAAC,OAAD;IAAK,WAAU;IAAsB,OAAO,EAAE,eAAe,IAAc,SAAS,OAAO;IAA3F,UAAA,CACE,kBAAC,YAAD;KACE,OAAO;KACP,aAAY;KACZ,WAAW,MAAM,EAAS,EAAE,OAAO,KAAK;KACxC,YAAY,MAAM;MAChB,AAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,aAAY,EAAE,eAAe,GAAO,KAAS,EAAK;KAChF;KACA,gBAAgB,MAAM,EAAE,gBAAgB;IACzC,CAAA,GACA,IACC,kBAAC,UAAD;KAAQ,MAAK;KAAS,eAAe,EAAS,SAAS,MAAM;KAAG,UAAA;IAAU,CAAA,IAE1E,kBAAC,UAAD;KAAQ,MAAK;KAAS,UAAU,CAAC,KAAW,CAAC,EAAM,KAAK;KAAG,SAAS;KAAM,UAAA;IAAU,CAAA,CAEnF;;EACF;;AAET;AAGA,SAAgB,EAAa,EAAE,SAAM,gBAAa,eAA+E;CAC/H,IAAM,IAAO,EAAK,KAAK,aAAa,YAC9B,IAAU,EAAK,KAAK,gBAAgB,IACpC,IAAY,EAAqB,EAAK,KAAK,cAAc,EAAK,KAAK,OAAO,SAAS;CAEzF,QAAQ,GAAR;EACE,KAAK,YACH,OACE,kBAAC,OAAD;GAAK,WAAU;GAAsB,OAAO;IAAE,OAAO;IAAW,UAAU,EAAK,KAAK;GAAS;GAC3F,UAAA,kBAAC,GAAD,EAAmB,WAAU,CAAA;EAC1B,CAAA;EAET,KAAK,QAGH,OACE,kBAAC,GAAD;GACW;GACI;GACb,OAAO,EAAkB,EAAK,KAAK,cAAc,EAAK,KAAK,OAAO,SAAS;GAC3E,UAAU,EAAK,KAAK;EACrB,CAAA;EAEL,KAAK,WACH,OAAO,kBAAC,GAAD;GAAsB;GAAS,OAAO;EAAY,CAAA;EAC3D,KAAK,QACH,OAAO,kBAAC,GAAD;GAAmB;GAAS,OAAO;GAAW,UAAU,EAAK,KAAK;EAAW,CAAA;EACtF,KAAK,SACH,OAAO,kBAAC,GAAD,EAAoB,WAAU,CAAA;EACvC,KAAK,WACH,OACE,kBAAC,GAAD;GACW;GACT,QAAQ,EAAK,KAAK,eAAe;GACpB;EACd,CAAA;EAEL,KAAK,MACH,OAAO,kBAAC,GAAD;GAAc;GAAM,QAAQ,KAAY,EAAK,KAAK;GAAuB;GAAa,OAAO;EAAY,CAAA;EAClH,KAAK,QACH,OACE,kBAAC,OAAD;GAAK,WAAU;GAAkB,OAAO,EAAE,eAAe,IAAc,SAAS,OAAO;GACrF,UAAA,kBAAC,GAAD;IACE,QAAQ,EAAK,KAAK,cAAc;KAAE,SAAS,CAAC;KAAG,MAAM,CAAC;KAAG,MAAM;IAAQ;IACvE,cAAc,EAAK,KAAK,SAAS,gBAAgB,KAAA,IAAY,EAAqB,EAAK,KAAK,MAAM,EAAE;IACzF;IACX,cAAc,EAAqB,EAAK,KAAK,OAAO,EAAE;GACvD,CAAA;EACE,CAAA;EAET,SACE,OAAO;CACX;AACF"}
|
|
1
|
+
{"version":3,"file":"MediaContent.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/MediaContent.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport katex from 'katex';\nimport mermaid from 'mermaid';\nimport Markdown from '../../../Markdown';\nimport type { FlowNode, FlowAIConfig } from '../types';\nimport { streamAIChat, type AIChatMessage } from './aiClient';\nimport { resolveThemeColorCss, resolveThemeColor } from '../utils/themeColor';\nimport 'katex/dist/katex.min.css';\nimport { Model3DView } from './Model3DView';\n\n// Data-node view pulls in DataTable + Chart; lazy-load so it only enters the\n// bundle when a data node actually renders.\nconst DataNodeView = React.lazy(() =>\n import('./DataNodeView').then((m) => ({ default: m.DataNodeView })),\n);\n\nlet mermaidReady = false;\nfunction ensureMermaid() {\n if (mermaidReady) return;\n mermaid.initialize({ startOnLoad: false, theme: 'default', securityLevel: 'loose', fontFamily: 'inherit' });\n mermaidReady = true;\n}\n\n/** Renders a Mermaid diagram from source into an inline SVG. */\nfunction MermaidView({ content, color }: { content: string; color?: string }) {\n const [svg, setSvg] = useState('');\n const [error, setError] = useState<string | null>(null);\n const idRef = useRef(`flow-mermaid-${Math.random().toString(36).slice(2)}`);\n\n useEffect(() => {\n let cancelled = false;\n ensureMermaid();\n const src = content.trim();\n if (!src) { setSvg(''); setError(null); return; }\n mermaid\n .render(idRef.current, src)\n .then(({ svg }) => { if (!cancelled) { setSvg(svg); setError(null); } })\n .catch((e) => { if (!cancelled) setError(e?.message ?? 'Mermaid error'); });\n return () => { cancelled = true; };\n }, [content]);\n\n if (error) return <div className=\"flow-media-error\">{error}</div>;\n return <div className=\"flow-media-mermaid\" style={{ color }} dangerouslySetInnerHTML={{ __html: svg }} />;\n}\n\n/** Renders a LaTeX formula (display mode) via KaTeX. */\nfunction MathView({ content, color, fontSize }: { content: string; color?: string; fontSize?: number }) {\n const html = useMemo(() => {\n try {\n return katex.renderToString(content.trim() || '\\\\;', { displayMode: true, throwOnError: false });\n } catch (e: any) {\n return `<span class=\"flow-media-error\">${e?.message ?? 'KaTeX error'}</span>`;\n }\n }, [content]);\n return <div className=\"flow-media-math\" style={{ color, fontSize }} dangerouslySetInnerHTML={{ __html: html }} />;\n}\n\n/** Renders raw HTML in a sandboxed iframe (isolated from the host document).\n * A base stylesheet is injected so the fragment inherits the node's themed\n * text color / font size and a transparent background, keeping it readable on\n * any theme without the author having to set colors.\n * Content is always untrusted: scripts can drive the preview, but the opaque\n * sandbox origin prevents host DOM/storage access. Do not add allow-same-origin\n * alongside allow-scripts; interactive only controls pointer input. */\nfunction HtmlView({ content, interactive, color, fontSize }: { content: string; interactive: boolean; color?: string; fontSize?: number }) {\n const srcDoc = useMemo(() => {\n const base = `<!doctype html><html><head><meta charset=\"utf-8\"><style>\n :root { color-scheme: light dark; }\n html, body { margin: 0; background: transparent; }\n body {\n color: ${color ?? '#111827'};\n font-size: ${fontSize ?? 13}px;\n font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n line-height: 1.5;\n padding: 0;\n }\n a { color: inherit; }\n </style></head><body>${content}</body></html>`;\n return base;\n }, [content, color, fontSize]);\n return (\n <iframe\n title=\"html-media\"\n className=\"flow-media-iframe\"\n style={{ pointerEvents: interactive ? 'auto' : 'none' }}\n sandbox=\"allow-scripts\"\n srcDoc={srcDoc}\n />\n );\n}\n\nfunction ImageView({ content }: { content: string }) {\n const src = content.trim();\n if (!src) {\n return <div className=\"flow-media-image-empty\">输入图片链接,或直接粘贴图片</div>;\n }\n return (\n <img\n className=\"flow-media-image\"\n src={src}\n alt=\"\"\n draggable={false}\n referrerPolicy=\"no-referrer\"\n />\n );\n}\n\n/** Interactive AI chat backed by an OpenAI/Anthropic-compatible endpoint. */\nfunction AIView({ node, config, interactive, color }: { node: FlowNode; config?: FlowAIConfig; interactive: boolean; color?: string }) {\n const [messages, setMessages] = useState<AIChatMessage[]>([]);\n const [input, setInput] = useState('');\n const [streaming, setStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight });\n }, [messages, streaming]);\n\n useEffect(() => () => abortRef.current?.abort(), []);\n\n const canSend = !!config?.gateway && !!config?.model && !streaming;\n\n const send = async () => {\n const text = input.trim();\n if (!text || !config?.gateway) return;\n setError(null);\n // Only keep non-empty assistant messages in history; an aborted/errored\n // request can leave an empty assistant placeholder behind, which the API\n // then rejects (\"assistant message must not be empty\").\n const history = messages.filter(\n (m) => !(m.role === 'assistant' && m.content.trim() === ''),\n );\n const next: AIChatMessage[] = [...history, { role: 'user', content: text }];\n setMessages(next);\n setInput('');\n setStreaming(true);\n const ac = new AbortController();\n abortRef.current = ac;\n let acc = '';\n setMessages((m) => [...m, { role: 'assistant', content: '' }]);\n try {\n for await (const delta of streamAIChat(config, next, ac.signal)) {\n acc += delta;\n setMessages((m) => {\n const copy = m.slice();\n copy[copy.length - 1] = { role: 'assistant', content: acc };\n return copy;\n });\n }\n } catch (e: any) {\n if (e?.name !== 'AbortError') setError(e?.message ?? 'Request failed');\n } finally {\n // Drop the trailing assistant placeholder if nothing streamed in.\n setMessages((m) => {\n const last = m[m.length - 1];\n if (last && last.role === 'assistant' && last.content.trim() === '') {\n return m.slice(0, -1);\n }\n return m;\n });\n setStreaming(false);\n abortRef.current = null;\n }\n };\n\n return (\n <div className=\"flow-media-ai\" style={{ color }}>\n <div className=\"flow-media-ai-header\">\n {config?.model ? `AI · ${config.model}` : (node.data.label || 'AI')}\n </div>\n <div className=\"flow-media-ai-log\" ref={scrollRef}>\n {messages.length === 0 && (\n <div className=\"flow-media-ai-empty\">\n {config?.gateway ? '开始对话…' : '请先配置 AI 接口'}\n </div>\n )}\n {messages.map((m, i) => (\n <div key={i} className={`flow-media-ai-msg flow-media-ai-msg--${m.role}`}>\n {m.role === 'assistant'\n ? <Markdown content={m.content || '…'} enableMermaid={false} enableMarkmap={false} />\n : <span>{m.content}</span>}\n </div>\n ))}\n {error && <div className=\"flow-media-error\">{error}</div>}\n </div>\n <div className=\"flow-media-ai-input\" style={{ pointerEvents: interactive ? 'auto' : 'none' }}>\n <textarea\n value={input}\n placeholder=\"输入消息,Enter 发送\"\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); if (canSend) send(); }\n }}\n onPointerDown={(e) => e.stopPropagation()}\n />\n {streaming ? (\n <button type=\"button\" onClick={() => abortRef.current?.abort()}>停止</button>\n ) : (\n <button type=\"button\" disabled={!canSend || !input.trim()} onClick={send}>发送</button>\n )}\n </div>\n </div>\n );\n}\n\n/** Dispatches to the correct renderer for the node's media kind. */\nexport function MediaContent({ node, interactive, aiConfig, useSharedAIConfig = false }: { node: FlowNode; interactive: boolean; aiConfig?: FlowAIConfig; useSharedAIConfig?: boolean }) {\n const kind = node.data.mediaKind ?? 'markdown';\n const content = node.data.mediaContent ?? '';\n const textColor = resolveThemeColorCss(node.data.labelColor ?? node.data.color, '#111827');\n\n switch (kind) {\n case 'markdown':\n return (\n <div className=\"flow-media-markdown\" style={{ color: textColor, fontSize: node.data.fontSize }}>\n <Markdown content={content} />\n </div>\n );\n case 'html':\n // The iframe is an isolated document with no access to the parent's CSS\n // variables, so pass a concrete resolved color instead of a var().\n return (\n <HtmlView\n content={content}\n interactive={interactive}\n color={resolveThemeColor(node.data.labelColor ?? node.data.color, '#111827')}\n fontSize={node.data.fontSize}\n />\n );\n case 'mermaid':\n return <MermaidView content={content} color={textColor} />;\n case 'math':\n return <MathView content={content} color={textColor} fontSize={node.data.fontSize} />;\n case 'image':\n return <ImageView content={content} />;\n case 'model3d':\n return (\n <Model3DView\n content={content}\n format={node.data.modelFormat ?? 'stl'}\n interactive={interactive}\n />\n );\n case 'ai':\n return <AIView node={node} config={useSharedAIConfig ? aiConfig : node.data.aiConfig} interactive={interactive} color={textColor} />;\n case 'data':\n return (\n <div className=\"flow-media-data\" style={{ pointerEvents: interactive ? 'auto' : 'none' }}>\n <DataNodeView\n config={node.data.dataConfig ?? { columns: [], rows: [], view: 'table' }}\n surfaceColor={node.data.fill === 'transparent' ? undefined : resolveThemeColorCss(node.data.fill, '')}\n textColor={textColor}\n primaryColor={resolveThemeColorCss(node.data.color, '')}\n />\n </div>\n );\n default:\n return null;\n }\n}\n"],"mappings":"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"}
|
|
@@ -20,13 +20,13 @@ var c = i.memo(i.lazy(() => import("./MediaContent.js").then((e) => ({ default:
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
function u() {
|
|
23
|
-
let { currentCanvas: i, selection: u } = e(), { viewport: d, isNodeDragging: f } = t(), { aiConfig:
|
|
24
|
-
if (
|
|
25
|
-
let { x:
|
|
23
|
+
let { currentCanvas: i, selection: u } = e(), { viewport: d, isNodeDragging: f, readOnly: p } = t(), { aiConfig: m, hasSharedConfig: h } = n(), g = o(() => i.nodes.filter((e) => e.type === "mediaNode"), [i.nodes]);
|
|
24
|
+
if (g.length === 0) return null;
|
|
25
|
+
let { x: _, y: v, zoom: y } = d;
|
|
26
26
|
return /* @__PURE__ */ s("div", {
|
|
27
27
|
className: "flow-media-layer",
|
|
28
|
-
children:
|
|
29
|
-
let t = e.position.x *
|
|
28
|
+
children: g.map((e) => {
|
|
29
|
+
let t = e.position.x * y + _, n = e.position.y * y + v, i = (u.nodeIds.has(e.id) || p && e.data.mediaKind === "ai") && !f, o = e.data.fill === "transparent" ? "transparent" : r(e.data.fill, "transparent"), d = r(e.data.labelColor ?? e.data.color, "#111827");
|
|
30
30
|
return /* @__PURE__ */ s("div", {
|
|
31
31
|
className: "flow-media-node",
|
|
32
32
|
"data-media-node": e.id,
|
|
@@ -36,7 +36,7 @@ function u() {
|
|
|
36
36
|
top: n,
|
|
37
37
|
width: e.width,
|
|
38
38
|
height: e.height,
|
|
39
|
-
transform: `scale(${
|
|
39
|
+
transform: `scale(${y})`,
|
|
40
40
|
transformOrigin: "top left",
|
|
41
41
|
pointerEvents: "none"
|
|
42
42
|
},
|
|
@@ -55,7 +55,8 @@ function u() {
|
|
|
55
55
|
children: /* @__PURE__ */ s(l, { children: /* @__PURE__ */ s(c, {
|
|
56
56
|
node: e,
|
|
57
57
|
interactive: i,
|
|
58
|
-
aiConfig:
|
|
58
|
+
aiConfig: m,
|
|
59
|
+
useSharedAIConfig: h
|
|
59
60
|
}) })
|
|
60
61
|
})
|
|
61
62
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaOverlay.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/MediaOverlay.tsx"],"sourcesContent":["import React, { useMemo, Suspense } from 'react';\nimport { useFlowContext } from '../context/FlowContext';\nimport { useFlowUI } from '../context/FlowUIContext';\nimport { useFlowAI } from '../context/FlowAIContext';\nimport { resolveThemeColorCss } from '../utils/themeColor';\n\n// Lazy-load the media renderers so the heavy optional deps they pull in\n// (react-markdown, mermaid, katex, markmap, …) are only fetched when a media\n// node actually needs to render. This keeps the base `dishui/flow` bundle\n// lightweight and avoids loading that stack for diagrams without media nodes.\n// Viewport-only updates move the outer box, not the live media subtree. Keep\n// nodes mounted offscreen so iframe/AI state and model camera state survive.\nconst MediaContent = React.memo(React.lazy(() =>\n import('./MediaContent').then((m) => ({ default: m.MediaContent })),\n));\n\n/** Isolates media render/load failures so one bad node never blanks the editor. */\nclass MediaErrorBoundary extends React.Component<\n { children: React.ReactNode },\n { error: Error | null }\n> {\n constructor(props: { children: React.ReactNode }) {\n super(props);\n this.state = { error: null };\n }\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n render() {\n if (this.state.error) {\n return <div className=\"flow-media-error\">{this.state.error.message}</div>;\n }\n return this.props.children;\n }\n}\n\n/**\n * DOM overlay for media nodes. PixiJS draws the frame; this layer renders the\n * live content (markdown/html/mermaid/math/AI) on top, synced to the viewport\n * so it pans and zooms with the canvas.\n *\n * Event model: a media surface is `pointer-events: none` by default so the\n * canvas underneath can be clicked to select/drag the node's frame. The\n * surface only becomes interactive while its node is selected (so AI chat can\n * be typed into, HTML can be scrolled). This also stops an always-interactive\n * iframe/AI box from swallowing pointer gestures and leaving the drag stuck.\n */\nexport function MediaOverlay() {\n const { currentCanvas, selection } = useFlowContext();\n const { viewport, isNodeDragging } = useFlowUI();\n const { aiConfig } = useFlowAI();\n\n const mediaNodes = useMemo(\n () => currentCanvas.nodes.filter((n) => n.type === 'mediaNode'),\n [currentCanvas.nodes],\n );\n\n if (mediaNodes.length === 0) return null;\n\n const { x: vx, y: vy, zoom } = viewport;\n\n return (\n <div className=\"flow-media-layer\">\n {mediaNodes.map((node) => {\n // World → screen (CSS px, matching ViewportManager.worldToScreen).\n const left = node.position.x * zoom + vx;\n const top = node.position.y * zoom + vy;\n // Interactive only while selected, so the canvas stays draggable.\n // Suppress entirely during a drag: an interactive iframe would swallow\n // the pointer and the canvas would never receive pointerup (stuck drag).\n const interactive = selection.nodeIds.has(node.id) && !isNodeDragging;\n // Drive the overlay's background / text from the node's own color data.\n // Theme tokens (`theme:*`) resolve to CSS variables so the media content\n // follows theme switches natively; literal colors are used as-is. This\n // keeps html / ai / data (which render opaque content) in sync with the\n // fill/color chosen in the inspector, matching the PixiJS frame drawn\n // underneath. The border is owned by the Pixi frame (also what PNG/PDF\n // export captures), so we don't redraw it here.\n const fillCss = node.data.fill === 'transparent'\n ? 'transparent'\n : resolveThemeColorCss(node.data.fill, 'transparent');\n const textColor = resolveThemeColorCss(node.data.labelColor ?? node.data.color, '#111827');\n return (\n <div\n key={node.id}\n className=\"flow-media-node\"\n data-media-node={node.id}\n style={{\n position: 'absolute',\n left,\n top,\n width: node.width,\n height: node.height,\n // Scale the fixed-size content box to match zoom without\n // reflowing text on every zoom step.\n transform: `scale(${zoom})`,\n transformOrigin: 'top left',\n // Below the frame's selection outline but above the canvas.\n pointerEvents: 'none',\n }}\n >\n <div\n className=\"flow-media-surface\"\n onWheel={(e) => e.stopPropagation()}\n style={{\n background: fillCss,\n color: textColor,\n }}\n >\n <Suspense fallback={<div className=\"flow-media-loading\">…</div>}>\n <MediaErrorBoundary>\n <MediaContent node={node} interactive={interactive} aiConfig={aiConfig} />\n </MediaErrorBoundary>\n </Suspense>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAYA,IAAM,IAAe,EAAM,KAAK,EAAM,WACpC,OAAO,oBAAiB,CAAC,MAAM,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CACpE,CAAC,GAGK,IAAN,cAAiC,EAAM,UAGrC;CACA,YAAY,GAAsC;EAEhD,AADA,MAAM,CAAK,GACX,KAAK,QAAQ,EAAE,OAAO,KAAK;CAC7B;CACA,OAAO,yBAAyB,GAAc;EAC5C,OAAO,EAAE,SAAM;CACjB;CACA,SAAS;EAIP,OAHI,KAAK,MAAM,QACN,kBAAC,OAAD;GAAK,WAAU;GAAoB,UAAA,KAAK,MAAM,MAAM;EAAa,CAAA,IAEnE,KAAK,MAAM;CACpB;AACF;AAaA,SAAgB,IAAe;CAC7B,IAAM,EAAE,kBAAe,iBAAc,EAAe,GAC9C,EAAE,aAAU,
|
|
1
|
+
{"version":3,"file":"MediaOverlay.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/MediaOverlay.tsx"],"sourcesContent":["import React, { useMemo, Suspense } from 'react';\nimport { useFlowContext } from '../context/FlowContext';\nimport { useFlowUI } from '../context/FlowUIContext';\nimport { useFlowAI } from '../context/FlowAIContext';\nimport { resolveThemeColorCss } from '../utils/themeColor';\n\n// Lazy-load the media renderers so the heavy optional deps they pull in\n// (react-markdown, mermaid, katex, markmap, …) are only fetched when a media\n// node actually needs to render. This keeps the base `dishui/flow` bundle\n// lightweight and avoids loading that stack for diagrams without media nodes.\n// Viewport-only updates move the outer box, not the live media subtree. Keep\n// nodes mounted offscreen so iframe/AI state and model camera state survive.\nconst MediaContent = React.memo(React.lazy(() =>\n import('./MediaContent').then((m) => ({ default: m.MediaContent })),\n));\n\n/** Isolates media render/load failures so one bad node never blanks the editor. */\nclass MediaErrorBoundary extends React.Component<\n { children: React.ReactNode },\n { error: Error | null }\n> {\n constructor(props: { children: React.ReactNode }) {\n super(props);\n this.state = { error: null };\n }\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n render() {\n if (this.state.error) {\n return <div className=\"flow-media-error\">{this.state.error.message}</div>;\n }\n return this.props.children;\n }\n}\n\n/**\n * DOM overlay for media nodes. PixiJS draws the frame; this layer renders the\n * live content (markdown/html/mermaid/math/AI) on top, synced to the viewport\n * so it pans and zooms with the canvas.\n *\n * Event model: a media surface is `pointer-events: none` by default so the\n * canvas underneath can be clicked to select/drag the node's frame. The\n * surface only becomes interactive while its node is selected (so AI chat can\n * be typed into, HTML can be scrolled). This also stops an always-interactive\n * iframe/AI box from swallowing pointer gestures and leaving the drag stuck.\n */\nexport function MediaOverlay() {\n const { currentCanvas, selection } = useFlowContext();\n const { viewport, isNodeDragging, readOnly } = useFlowUI();\n const { aiConfig, hasSharedConfig } = useFlowAI();\n\n const mediaNodes = useMemo(\n () => currentCanvas.nodes.filter((n) => n.type === 'mediaNode'),\n [currentCanvas.nodes],\n );\n\n if (mediaNodes.length === 0) return null;\n\n const { x: vx, y: vy, zoom } = viewport;\n\n return (\n <div className=\"flow-media-layer\">\n {mediaNodes.map((node) => {\n // World → screen (CSS px, matching ViewportManager.worldToScreen).\n const left = node.position.x * zoom + vx;\n const top = node.position.y * zoom + vy;\n // Interactive only while selected, so the canvas stays draggable.\n // Suppress entirely during a drag: an interactive iframe would swallow\n // the pointer and the canvas would never receive pointerup (stuck drag).\n const interactive = (selection.nodeIds.has(node.id) || (readOnly && node.data.mediaKind === 'ai')) && !isNodeDragging;\n // Drive the overlay's background / text from the node's own color data.\n // Theme tokens (`theme:*`) resolve to CSS variables so the media content\n // follows theme switches natively; literal colors are used as-is. This\n // keeps html / ai / data (which render opaque content) in sync with the\n // fill/color chosen in the inspector, matching the PixiJS frame drawn\n // underneath. The border is owned by the Pixi frame (also what PNG/PDF\n // export captures), so we don't redraw it here.\n const fillCss = node.data.fill === 'transparent'\n ? 'transparent'\n : resolveThemeColorCss(node.data.fill, 'transparent');\n const textColor = resolveThemeColorCss(node.data.labelColor ?? node.data.color, '#111827');\n return (\n <div\n key={node.id}\n className=\"flow-media-node\"\n data-media-node={node.id}\n style={{\n position: 'absolute',\n left,\n top,\n width: node.width,\n height: node.height,\n // Scale the fixed-size content box to match zoom without\n // reflowing text on every zoom step.\n transform: `scale(${zoom})`,\n transformOrigin: 'top left',\n // Below the frame's selection outline but above the canvas.\n pointerEvents: 'none',\n }}\n >\n <div\n className=\"flow-media-surface\"\n onWheel={(e) => e.stopPropagation()}\n style={{\n background: fillCss,\n color: textColor,\n }}\n >\n <Suspense fallback={<div className=\"flow-media-loading\">…</div>}>\n <MediaErrorBoundary>\n <MediaContent node={node} interactive={interactive} aiConfig={aiConfig} useSharedAIConfig={hasSharedConfig} />\n </MediaErrorBoundary>\n </Suspense>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAYA,IAAM,IAAe,EAAM,KAAK,EAAM,WACpC,OAAO,oBAAiB,CAAC,MAAM,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CACpE,CAAC,GAGK,IAAN,cAAiC,EAAM,UAGrC;CACA,YAAY,GAAsC;EAEhD,AADA,MAAM,CAAK,GACX,KAAK,QAAQ,EAAE,OAAO,KAAK;CAC7B;CACA,OAAO,yBAAyB,GAAc;EAC5C,OAAO,EAAE,SAAM;CACjB;CACA,SAAS;EAIP,OAHI,KAAK,MAAM,QACN,kBAAC,OAAD;GAAK,WAAU;GAAoB,UAAA,KAAK,MAAM,MAAM;EAAa,CAAA,IAEnE,KAAK,MAAM;CACpB;AACF;AAaA,SAAgB,IAAe;CAC7B,IAAM,EAAE,kBAAe,iBAAc,EAAe,GAC9C,EAAE,aAAU,mBAAgB,gBAAa,EAAU,GACnD,EAAE,aAAU,uBAAoB,EAAU,GAE1C,IAAa,QACX,EAAc,MAAM,QAAQ,MAAM,EAAE,SAAS,WAAW,GAC9D,CAAC,EAAc,KAAK,CACtB;CAEA,IAAI,EAAW,WAAW,GAAG,OAAO;CAEpC,IAAM,EAAE,GAAG,GAAI,GAAG,GAAI,YAAS;CAE/B,OACE,kBAAC,OAAD;EAAK,WAAU;EACZ,UAAA,EAAW,KAAK,MAAS;GAExB,IAAM,IAAO,EAAK,SAAS,IAAI,IAAO,GAChC,IAAM,EAAK,SAAS,IAAI,IAAO,GAI/B,KAAe,EAAU,QAAQ,IAAI,EAAK,EAAE,KAAM,KAAY,EAAK,KAAK,cAAc,SAAU,CAAC,GAQjG,IAAU,EAAK,KAAK,SAAS,gBAC/B,gBACA,EAAqB,EAAK,KAAK,MAAM,aAAa,GAChD,IAAY,EAAqB,EAAK,KAAK,cAAc,EAAK,KAAK,OAAO,SAAS;GACzF,OACE,kBAAC,OAAD;IAEE,WAAU;IACV,mBAAiB,EAAK;IACtB,OAAO;KACL,UAAU;KACV;KACA;KACA,OAAO,EAAK;KACZ,QAAQ,EAAK;KAGb,WAAW,SAAS,EAAK;KACzB,iBAAiB;KAEjB,eAAe;IACjB;IAEA,UAAA,kBAAC,OAAD;KACE,WAAU;KACV,UAAU,MAAM,EAAE,gBAAgB;KAClC,OAAO;MACL,YAAY;MACZ,OAAO;KACT;KAEA,UAAA,kBAAC,GAAD;MAAU,UAAU,kBAAC,OAAD;OAAK,WAAU;OAAqB,UAAA;MAAM,CAAA;MAC5D,UAAA,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAoB;OAAmB;OAAuB;OAAU,mBAAmB;MAAkB,CAAA,EAC3F,CAAA;KACZ,CAAA;IACP,CAAA;GACF,GA/BE,EAAK,EA+BP;EAET,CAAC;CACE,CAAA;AAET"}
|