@dilipod/ui 0.4.34 → 0.4.35

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.
@@ -4,6 +4,7 @@ export interface UploadedFile {
4
4
  type: string;
5
5
  size: number;
6
6
  url?: string;
7
+ processing?: boolean;
7
8
  }
8
9
  export interface FilePreviewProps {
9
10
  files: UploadedFile[];
@@ -1 +1 @@
1
- {"version":3,"file":"file-preview.d.ts","sourceRoot":"","sources":["../../src/components/file-preview.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACvD;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAgDD,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAwB,EACxB,YAAY,EACZ,QAAe,EACf,YAAkC,EACnC,EAAE,gBAAgB,2CAuQlB"}
1
+ {"version":3,"file":"file-preview.d.ts","sourceRoot":"","sources":["../../src/components/file-preview.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACvD;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAgDD,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAwB,EACxB,YAAY,EACZ,QAAe,EACf,YAAkC,EACnC,EAAE,gBAAgB,2CAoRlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"flowchart-diagram.d.ts","sourceRoot":"","sources":["../../src/components/flowchart-diagram.tsx"],"names":[],"mappings":"AAoRA,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,qBAAqB,2CAmC7E"}
1
+ {"version":3,"file":"flowchart-diagram.d.ts","sourceRoot":"","sources":["../../src/components/flowchart-diagram.tsx"],"names":[],"mappings":"AAmfA,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,qBAAqB,2CA0C7E"}
package/dist/index.js CHANGED
@@ -3991,7 +3991,8 @@ function FilePreview({
3991
3991
  const FileIcon = getFileIcon(file.type);
3992
3992
  const typeLabel = getTypeLabel(file.type);
3993
3993
  const sizeLabel = formatSize(file.size);
3994
- const isPreviewable = canPreview(file);
3994
+ const isProcessing = file.processing === true;
3995
+ const isPreviewable = !isProcessing && canPreview(file);
3995
3996
  const previewType = getPreviewType(file);
3996
3997
  return /* @__PURE__ */ jsxRuntime.jsxs(
3997
3998
  "div",
@@ -4001,20 +4002,20 @@ function FilePreview({
4001
4002
  children: [
4002
4003
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
4003
4004
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [
4004
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-sm bg-white border border-gray-200 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { className: "w-5 h-5 text-[var(--cyan)]", weight: "fill" }) }),
4005
- previewType === "video" && /* @__PURE__ */ jsxRuntime.jsx(react_star.Play, { className: "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 text-[var(--cyan)] bg-white rounded-full", weight: "fill" })
4005
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-sm bg-white border border-gray-200 flex items-center justify-center", children: isProcessing ? /* @__PURE__ */ jsxRuntime.jsx(react_star.CircleNotch, { className: "w-5 h-5 text-[var(--cyan)] animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { className: "w-5 h-5 text-[var(--cyan)]", weight: "fill" }) }),
4006
+ !isProcessing && previewType === "video" && /* @__PURE__ */ jsxRuntime.jsx(react_star.Play, { className: "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 text-[var(--cyan)] bg-white rounded-full", weight: "fill" })
4006
4007
  ] }),
4007
4008
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
4008
4009
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-[var(--black)] truncate", children: file.filename }),
4009
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
4010
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: isProcessing ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-amber-600", children: "Processing video \u2014 this takes about a minute" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4010
4011
  typeLabel,
4011
4012
  " \xB7 ",
4012
4013
  sizeLabel,
4013
4014
  isPreviewable && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--cyan)] ml-1", children: "\xB7 Click to preview" })
4014
- ] })
4015
+ ] }) })
4015
4016
  ] })
4016
4017
  ] }),
4017
- /* @__PURE__ */ jsxRuntime.jsx(
4018
+ !isProcessing && /* @__PURE__ */ jsxRuntime.jsx(
4018
4019
  "button",
4019
4020
  {
4020
4021
  onClick: (e) => handleDownload(e, file),
@@ -6287,190 +6288,383 @@ function WorkflowViewer({
6287
6288
  ] })
6288
6289
  ] });
6289
6290
  }
6290
- function parseMermaidFlowchart(mermaid) {
6291
- const nodes = /* @__PURE__ */ new Map();
6292
- const edges = [];
6293
- const lines = mermaid.split(/\\n|\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith("flowchart") && !l.startsWith("graph"));
6294
- function parseNodeDef(str) {
6295
- const decisionMatch = str.match(/^([A-Za-z0-9_]+)\{(.+?)\}$/);
6296
- if (decisionMatch) return { id: decisionMatch[1], label: decisionMatch[2], type: "decision" };
6297
- const bracketMatch = str.match(/^([A-Za-z0-9_]+)\[?\(?\[?(.+?)\]?\)?\]?$/);
6298
- if (bracketMatch) {
6299
- const label = bracketMatch[2];
6300
- const isTerminal = /^(start|end|begin|finish|done)$/i.test(label);
6301
- return { id: bracketMatch[1], label, type: isTerminal ? "terminal" : "action" };
6291
+ var NODE_WIDTH = 180;
6292
+ var NODE_HEIGHT = 44;
6293
+ var DIAMOND_SIZE = 72;
6294
+ var X_GAP = 50;
6295
+ var Y_GAP = 64;
6296
+ var PADDING = 40;
6297
+ var FONT_SIZE = 11;
6298
+ var CHAR_WIDTH = 6.2;
6299
+ var LINE_HEIGHT = 14;
6300
+ function stripQuotes(s) {
6301
+ const t = s.trim();
6302
+ if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'")) {
6303
+ return t.slice(1, -1);
6304
+ }
6305
+ return t;
6306
+ }
6307
+ function parseNodeRef(raw) {
6308
+ const s = raw.trim();
6309
+ const decision = s.match(/^([A-Za-z0-9_]+)\{(.+)\}$/);
6310
+ if (decision) return { id: decision[1], label: stripQuotes(decision[2]), type: "decision" };
6311
+ const stadium = s.match(/^([A-Za-z0-9_]+)\(\[(.+)\]\)$/);
6312
+ if (stadium) return { id: stadium[1], label: stripQuotes(stadium[2]), type: "terminal" };
6313
+ const circle = s.match(/^([A-Za-z0-9_]+)\(\((.+)\)\)$/);
6314
+ if (circle) return { id: circle[1], label: stripQuotes(circle[2]), type: "terminal" };
6315
+ const rounded = s.match(/^([A-Za-z0-9_]+)\(([^[(].+?)\)$/);
6316
+ if (rounded) return { id: rounded[1], label: stripQuotes(rounded[2]), type: "action" };
6317
+ const rect = s.match(/^([A-Za-z0-9_]+)\[([^(].+?)\]$/);
6318
+ if (rect) {
6319
+ const label = stripQuotes(rect[2]);
6320
+ const isTerminal = /^(start|end|begin|finish|done|stop)$/i.test(label);
6321
+ return { id: rect[1], label, type: isTerminal ? "terminal" : "action" };
6322
+ }
6323
+ const bareId = s.match(/^([A-Za-z0-9_]+)$/);
6324
+ if (bareId) return { id: bareId[1] };
6325
+ return { id: s };
6326
+ }
6327
+ function registerNode(map, ref) {
6328
+ if (!ref.id) return;
6329
+ const existing = map.get(ref.id);
6330
+ if (existing) {
6331
+ if (ref.label && existing.label === existing.id) {
6332
+ existing.label = ref.label;
6302
6333
  }
6303
- return { id: str.trim() };
6334
+ if (ref.type && ref.type !== "action" && existing.type === "action") {
6335
+ existing.type = ref.type;
6336
+ }
6337
+ return;
6304
6338
  }
6339
+ map.set(ref.id, {
6340
+ id: ref.id,
6341
+ label: ref.label || ref.id,
6342
+ type: ref.type || "action"
6343
+ });
6344
+ }
6345
+ function parseMermaidFlowchart(mermaid) {
6346
+ const nodeMap = /* @__PURE__ */ new Map();
6347
+ const edges = [];
6348
+ const lines = mermaid.split(/\\n|\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith("%%"));
6305
6349
  for (const line of lines) {
6306
- const edgeMatch = line.match(/^(.+?)\s*-->(?:\|(.+?)\|)?\s*(.+)$/);
6307
- if (!edgeMatch) continue;
6308
- const leftRaw = edgeMatch[1].trim();
6309
- const edgeLabel = edgeMatch[2]?.trim();
6310
- const rightRaw = edgeMatch[3].trim();
6311
- const left = parseNodeDef(leftRaw);
6312
- const right = parseNodeDef(rightRaw);
6313
- if (left.label && !nodes.has(left.id)) {
6314
- nodes.set(left.id, { id: left.id, label: left.label, type: left.type || "action" });
6350
+ if (/^(flowchart|graph|subgraph|end|style|classDef|class|click|linkStyle)\b/i.test(line)) continue;
6351
+ const edgeMatch = line.match(
6352
+ /^(.+?)\s*(?:-->|==>|-\.->|---)\s*(?:\|([^|]*)\|)?\s*(.+)$/
6353
+ );
6354
+ if (edgeMatch) {
6355
+ const leftNode = parseNodeRef(edgeMatch[1].trim());
6356
+ const edgeLabel = edgeMatch[2]?.trim() || void 0;
6357
+ const rightNode = parseNodeRef(edgeMatch[3].trim());
6358
+ registerNode(nodeMap, leftNode);
6359
+ registerNode(nodeMap, rightNode);
6360
+ edges.push({ from: leftNode.id, to: rightNode.id, label: edgeLabel });
6361
+ continue;
6315
6362
  }
6316
- if (right.label && !nodes.has(right.id)) {
6317
- nodes.set(right.id, { id: right.id, label: right.label, type: right.type || "action" });
6363
+ const nodeDef = parseNodeRef(line);
6364
+ if (nodeDef.label) {
6365
+ registerNode(nodeMap, nodeDef);
6318
6366
  }
6319
- if (!nodes.has(left.id)) {
6320
- nodes.set(left.id, { id: left.id, label: left.id, type: "action" });
6367
+ }
6368
+ return { nodes: Array.from(nodeMap.values()), edges };
6369
+ }
6370
+ function computeLayout(nodes, edges) {
6371
+ if (nodes.length === 0) return { layoutNodes: [], svgWidth: 0, svgHeight: 0 };
6372
+ const forward = /* @__PURE__ */ new Map();
6373
+ const backward = /* @__PURE__ */ new Map();
6374
+ for (const e of edges) {
6375
+ if (!forward.has(e.from)) forward.set(e.from, []);
6376
+ forward.get(e.from).push(e.to);
6377
+ if (!backward.has(e.to)) backward.set(e.to, []);
6378
+ backward.get(e.to).push(e.from);
6379
+ }
6380
+ const roots = nodes.filter((n) => !backward.has(n.id) || backward.get(n.id).length === 0);
6381
+ if (roots.length === 0) roots.push(nodes[0]);
6382
+ const layers = /* @__PURE__ */ new Map();
6383
+ const queue = [];
6384
+ for (const r of roots) {
6385
+ layers.set(r.id, 0);
6386
+ queue.push(r.id);
6387
+ }
6388
+ const visited = /* @__PURE__ */ new Set();
6389
+ while (queue.length > 0) {
6390
+ const id = queue.shift();
6391
+ if (visited.has(id)) continue;
6392
+ visited.add(id);
6393
+ const myLayer = layers.get(id) || 0;
6394
+ for (const child of forward.get(id) || []) {
6395
+ const childLayer = layers.get(child);
6396
+ if (childLayer === void 0 || myLayer + 1 > childLayer) {
6397
+ layers.set(child, myLayer + 1);
6398
+ }
6399
+ if (!visited.has(child)) queue.push(child);
6321
6400
  }
6322
- if (!nodes.has(right.id)) {
6323
- nodes.set(right.id, { id: right.id, label: right.id, type: "action" });
6401
+ }
6402
+ const maxLayer = Math.max(0, ...Array.from(layers.values()));
6403
+ for (const n of nodes) {
6404
+ if (!layers.has(n.id)) layers.set(n.id, maxLayer + 1);
6405
+ }
6406
+ const nodesByLayer = /* @__PURE__ */ new Map();
6407
+ for (const n of nodes) {
6408
+ const layer = layers.get(n.id);
6409
+ if (!nodesByLayer.has(layer)) nodesByLayer.set(layer, []);
6410
+ nodesByLayer.get(layer).push(n);
6411
+ }
6412
+ const sortedLayers = Array.from(nodesByLayer.keys()).sort((a, b) => a - b);
6413
+ const posInLayer = /* @__PURE__ */ new Map();
6414
+ for (let li = 0; li < sortedLayers.length; li++) {
6415
+ const layer = sortedLayers[li];
6416
+ const nodesInLayer = nodesByLayer.get(layer);
6417
+ if (li > 0) {
6418
+ nodesInLayer.sort((a, b) => {
6419
+ const parentsA = backward.get(a.id) || [];
6420
+ const parentsB = backward.get(b.id) || [];
6421
+ const avgA = parentsA.length > 0 ? parentsA.reduce((s, p) => s + (posInLayer.get(p) ?? 0), 0) / parentsA.length : 0;
6422
+ const avgB = parentsB.length > 0 ? parentsB.reduce((s, p) => s + (posInLayer.get(p) ?? 0), 0) / parentsB.length : 0;
6423
+ return avgA - avgB;
6424
+ });
6324
6425
  }
6325
- edges.push({ from: left.id, to: right.id, label: edgeLabel });
6426
+ nodesInLayer.forEach((n, i) => posInLayer.set(n.id, i));
6427
+ }
6428
+ const layoutNodes = [];
6429
+ for (const layer of sortedLayers) {
6430
+ const nodesInLayer = nodesByLayer.get(layer);
6431
+ const widths = nodesInLayer.map((n) => nodeWidth(n));
6432
+ const heights = nodesInLayer.map((n) => nodeHeight(n));
6433
+ const totalWidth = widths.reduce((s, w) => s + w, 0) + (nodesInLayer.length - 1) * X_GAP;
6434
+ let startX = -totalWidth / 2;
6435
+ nodesInLayer.forEach((n, i) => {
6436
+ layoutNodes.push({
6437
+ id: n.id,
6438
+ x: startX + widths[i] / 2,
6439
+ y: layer * (NODE_HEIGHT + Y_GAP),
6440
+ width: widths[i],
6441
+ height: heights[i],
6442
+ layer,
6443
+ node: n
6444
+ });
6445
+ startX += widths[i] + X_GAP;
6446
+ });
6326
6447
  }
6327
- return { nodes: Array.from(nodes.values()), edges };
6448
+ const minX = Math.min(...layoutNodes.map((n) => n.x - n.width / 2));
6449
+ const minY = Math.min(...layoutNodes.map((n) => n.y - n.height / 2));
6450
+ const offsetX = PADDING - minX;
6451
+ const offsetY = PADDING - minY;
6452
+ for (const n of layoutNodes) {
6453
+ n.x += offsetX;
6454
+ n.y += offsetY;
6455
+ }
6456
+ const svgWidth = Math.max(...layoutNodes.map((n) => n.x + n.width / 2)) + PADDING;
6457
+ const svgHeight = Math.max(...layoutNodes.map((n) => n.y + n.height / 2)) + PADDING;
6458
+ return { layoutNodes, svgWidth, svgHeight };
6459
+ }
6460
+ function nodeWidth(n) {
6461
+ if (n.type === "decision") return Math.max(DIAMOND_SIZE * 1.4, 100);
6462
+ const textWidth = n.label.length * CHAR_WIDTH + 32;
6463
+ return Math.max(100, Math.min(NODE_WIDTH, textWidth));
6328
6464
  }
6329
- function findMergePoint(branchStarts, outgoing) {
6330
- const reachable = /* @__PURE__ */ new Map();
6331
- for (const start of branchStarts) {
6332
- const q2 = [start];
6333
- const seen2 = /* @__PURE__ */ new Set();
6334
- while (q2.length > 0) {
6335
- const id = q2.shift();
6336
- if (seen2.has(id)) continue;
6337
- seen2.add(id);
6338
- if (!reachable.has(id)) reachable.set(id, /* @__PURE__ */ new Set());
6339
- reachable.get(id).add(start);
6340
- const outs = outgoing.get(id) || [];
6341
- for (const e of outs) q2.push(e.to);
6465
+ function nodeHeight(n) {
6466
+ if (n.type === "decision") return DIAMOND_SIZE;
6467
+ const w = nodeWidth(n);
6468
+ const lines = wrapText(n.label, w - 24);
6469
+ return Math.max(NODE_HEIGHT, lines.length * LINE_HEIGHT + 16);
6470
+ }
6471
+ function wrapText(text, maxPixelWidth) {
6472
+ const charsPerLine = Math.max(8, Math.floor(maxPixelWidth / CHAR_WIDTH));
6473
+ if (text.length <= charsPerLine) return [text];
6474
+ const words = text.split(" ");
6475
+ const lines = [];
6476
+ let cur = "";
6477
+ for (const word of words) {
6478
+ const test = cur ? `${cur} ${word}` : word;
6479
+ if (test.length > charsPerLine && cur) {
6480
+ lines.push(cur);
6481
+ cur = word;
6482
+ } else {
6483
+ cur = test;
6342
6484
  }
6343
6485
  }
6344
- const allBranches = new Set(branchStarts);
6345
- const q = [branchStarts[0]];
6346
- const seen = /* @__PURE__ */ new Set();
6347
- while (q.length > 0) {
6348
- const id = q.shift();
6349
- if (seen.has(id)) continue;
6350
- seen.add(id);
6351
- if (!allBranches.has(id) && reachable.get(id)?.size === branchStarts.length) {
6352
- return id;
6486
+ if (cur) lines.push(cur);
6487
+ if (lines.length > 3) {
6488
+ lines.length = 3;
6489
+ lines[2] = lines[2].slice(0, -1) + "\u2026";
6490
+ }
6491
+ return lines;
6492
+ }
6493
+ function computeEdgePath(from, to) {
6494
+ let startX = from.x;
6495
+ let startY = from.y + from.height / 2;
6496
+ if (from.node.type === "decision") {
6497
+ const dx = to.x - from.x;
6498
+ const halfDiamond = DIAMOND_SIZE / 2;
6499
+ if (Math.abs(dx) > halfDiamond) {
6500
+ startX = from.x + (dx > 0 ? halfDiamond : -halfDiamond);
6501
+ startY = from.y;
6353
6502
  }
6354
- const outs = outgoing.get(id) || [];
6355
- for (const e of outs) q.push(e.to);
6356
6503
  }
6357
- return null;
6504
+ const endX = to.x;
6505
+ const endY = to.y - to.height / 2;
6506
+ const midY = (startY + endY) / 2;
6507
+ return `M ${startX} ${startY} C ${startX} ${midY}, ${endX} ${midY}, ${endX} ${endY}`;
6358
6508
  }
6359
- function buildLayout(startId, outgoing, incoming, nodeMap, visited) {
6360
- const items = [];
6361
- let currentId = startId;
6362
- while (currentId) {
6363
- if (visited.has(currentId)) break;
6364
- const node = nodeMap.get(currentId);
6365
- if (!node) break;
6366
- const outs = outgoing.get(currentId) || [];
6367
- if (outs.length <= 1) {
6368
- visited.add(currentId);
6369
- items.push({ type: "node", nodeId: currentId });
6370
- if (outs.length === 1) {
6371
- const nextId = outs[0].to;
6372
- if (visited.has(nextId)) break;
6373
- items.push({ type: "arrow", label: outs[0].label });
6374
- currentId = nextId;
6375
- } else {
6376
- currentId = null;
6377
- }
6378
- } else {
6379
- visited.add(currentId);
6380
- items.push({ type: "node", nodeId: currentId });
6381
- const branchStarts = outs.map((e) => e.to);
6382
- const mergeId = findMergePoint(branchStarts, outgoing);
6383
- const branches = [];
6384
- for (const edge of outs) {
6385
- if (visited.has(edge.to) && edge.to !== mergeId) {
6386
- branches.push({ label: edge.label, items: [] });
6387
- continue;
6388
- }
6389
- const branchItems = buildLayout(edge.to, outgoing, incoming, nodeMap, visited);
6390
- branches.push({ label: edge.label, items: branchItems });
6391
- }
6392
- items.push({ type: "branch", decision: currentId, branches, mergeId });
6393
- if (mergeId && !visited.has(mergeId)) {
6394
- items.push({ type: "arrow" });
6395
- currentId = mergeId;
6396
- } else {
6397
- currentId = null;
6509
+ function SvgDefs() {
6510
+ return /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
6511
+ /* @__PURE__ */ jsxRuntime.jsx(
6512
+ "marker",
6513
+ {
6514
+ id: "fc-arrowhead",
6515
+ viewBox: "0 0 10 7",
6516
+ refX: "10",
6517
+ refY: "3.5",
6518
+ markerWidth: "8",
6519
+ markerHeight: "6",
6520
+ orient: "auto-start-reverse",
6521
+ children: /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "#D1D5DB" })
6398
6522
  }
6523
+ ),
6524
+ /* @__PURE__ */ jsxRuntime.jsx("filter", { id: "fc-shadow", x: "-4%", y: "-4%", width: "108%", height: "116%", children: /* @__PURE__ */ jsxRuntime.jsx("feDropShadow", { dx: "0", dy: "1", stdDeviation: "1.5", floodOpacity: "0.07" }) })
6525
+ ] });
6526
+ }
6527
+ function TextBlock({ lines, x, y, fill, fontSize }) {
6528
+ const startY = y - (lines.length - 1) * LINE_HEIGHT / 2;
6529
+ return /* @__PURE__ */ jsxRuntime.jsx(
6530
+ "text",
6531
+ {
6532
+ x,
6533
+ textAnchor: "middle",
6534
+ fill,
6535
+ style: { fontSize: `${fontSize}px`, fontFamily: "var(--font-outfit, system-ui, sans-serif)", fontWeight: 500 },
6536
+ children: lines.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx("tspan", { x, y: startY + i * LINE_HEIGHT, children: line }, i))
6399
6537
  }
6400
- }
6401
- return items;
6538
+ );
6402
6539
  }
6403
- function FlowArrow({ label }) {
6404
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
6405
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-purple-600 bg-purple-50 px-1.5 py-0.5 rounded mb-0.5", children: label }),
6406
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-gray-300" }),
6407
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-0 h-0 border-l-[4px] border-r-[4px] border-t-[5px] border-l-transparent border-r-transparent border-t-gray-300" })
6540
+ function ActionNodeSvg({ n }) {
6541
+ const lines = wrapText(n.node.label, n.width - 24);
6542
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6543
+ /* @__PURE__ */ jsxRuntime.jsx(
6544
+ "rect",
6545
+ {
6546
+ x: n.x - n.width / 2,
6547
+ y: n.y - n.height / 2,
6548
+ width: n.width,
6549
+ height: n.height,
6550
+ rx: 3,
6551
+ fill: "white",
6552
+ stroke: "#E5E7EB",
6553
+ strokeWidth: 1,
6554
+ filter: "url(#fc-shadow)"
6555
+ }
6556
+ ),
6557
+ /* @__PURE__ */ jsxRuntime.jsx(TextBlock, { lines, x: n.x, y: n.y, fill: "#0A0A0A", fontSize: FONT_SIZE })
6408
6558
  ] });
6409
6559
  }
6410
- function FlowNodeBox({ node }) {
6411
- if (node.type === "decision") {
6412
- return /* @__PURE__ */ jsxRuntime.jsxs(
6413
- "div",
6560
+ function DecisionNodeSvg({ n }) {
6561
+ const half = DIAMOND_SIZE / 2;
6562
+ const points = `${n.x},${n.y - half} ${n.x + half},${n.y} ${n.x},${n.y + half} ${n.x - half},${n.y}`;
6563
+ const lines = wrapText(n.node.label, DIAMOND_SIZE - 16);
6564
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6565
+ /* @__PURE__ */ jsxRuntime.jsx(
6566
+ "polygon",
6414
6567
  {
6415
- className: "bg-amber-50 border-2 border-amber-300 rounded-lg px-4 py-2.5 text-xs font-medium text-amber-800 text-center my-1",
6416
- style: { minWidth: "120px" },
6417
- children: [
6418
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-amber-400 mr-1", children: "\u25C7" }),
6419
- node.label
6420
- ]
6568
+ points,
6569
+ fill: "#FFFBEB",
6570
+ stroke: "#FCD34D",
6571
+ strokeWidth: 2
6421
6572
  }
6422
- );
6423
- }
6424
- if (node.type === "terminal") {
6425
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-gray-100 border border-gray-200 rounded-full px-5 py-1.5 text-xs font-medium text-gray-500 text-center my-1", children: node.label });
6426
- }
6427
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white border border-gray-200 rounded-sm px-4 py-2 text-xs font-medium text-[var(--black)] text-center shadow-sm my-1 max-w-[220px]", children: node.label });
6573
+ ),
6574
+ /* @__PURE__ */ jsxRuntime.jsx(TextBlock, { lines, x: n.x, y: n.y, fill: "#92400E", fontSize: 10 })
6575
+ ] });
6428
6576
  }
6429
- function RenderLayoutItems({ items, nodeMap }) {
6430
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: items.map((item, i) => {
6431
- if (item.type === "node") {
6432
- const node = nodeMap.get(item.nodeId);
6433
- if (!node) return null;
6434
- return /* @__PURE__ */ jsxRuntime.jsx(FlowNodeBox, { node }, `node-${item.nodeId}`);
6435
- }
6436
- if (item.type === "arrow") {
6437
- return /* @__PURE__ */ jsxRuntime.jsx(FlowArrow, { label: item.label }, `arrow-${i}`);
6438
- }
6439
- if (item.type === "branch") {
6440
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center w-full", children: [
6441
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-3 bg-gray-300" }),
6442
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-center gap-6 w-full", children: item.branches.map((branch, j) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center min-w-[100px]", children: [
6443
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
6444
- branch.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-purple-600 bg-purple-50 px-1.5 py-0.5 rounded mb-1", children: branch.label }),
6445
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-0 h-0 border-l-[4px] border-r-[4px] border-t-[5px] border-l-transparent border-r-transparent border-t-gray-300" })
6446
- ] }),
6447
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center", children: /* @__PURE__ */ jsxRuntime.jsx(RenderLayoutItems, { items: branch.items, nodeMap }) })
6448
- ] }, j)) }),
6449
- item.mergeId && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-3 bg-gray-300" })
6450
- ] }, `branch-${item.decision}-${i}`);
6451
- }
6452
- return null;
6453
- }) });
6577
+ function TerminalNodeSvg({ n }) {
6578
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6579
+ /* @__PURE__ */ jsxRuntime.jsx(
6580
+ "rect",
6581
+ {
6582
+ x: n.x - n.width / 2,
6583
+ y: n.y - n.height / 2,
6584
+ width: n.width,
6585
+ height: n.height,
6586
+ rx: n.height / 2,
6587
+ fill: "#F3F4F6",
6588
+ stroke: "#E5E7EB",
6589
+ strokeWidth: 1
6590
+ }
6591
+ ),
6592
+ /* @__PURE__ */ jsxRuntime.jsx(TextBlock, { lines: [n.node.label], x: n.x, y: n.y, fill: "#6B7280", fontSize: FONT_SIZE })
6593
+ ] });
6594
+ }
6595
+ function EdgeSvg({ from, to, label }) {
6596
+ const path = computeEdgePath(from, to);
6597
+ const midX = (from.x + to.x) / 2;
6598
+ const midY = (from.y + from.height / 2 + to.y - to.height / 2) / 2;
6599
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6600
+ /* @__PURE__ */ jsxRuntime.jsx(
6601
+ "path",
6602
+ {
6603
+ d: path,
6604
+ fill: "none",
6605
+ stroke: "#D1D5DB",
6606
+ strokeWidth: 1.5,
6607
+ markerEnd: "url(#fc-arrowhead)"
6608
+ }
6609
+ ),
6610
+ label && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6611
+ /* @__PURE__ */ jsxRuntime.jsx(
6612
+ "rect",
6613
+ {
6614
+ x: midX - label.length * CHAR_WIDTH / 2 - 6,
6615
+ y: midY - 9,
6616
+ width: label.length * CHAR_WIDTH + 12,
6617
+ height: 18,
6618
+ rx: 9,
6619
+ fill: "#F5F3FF"
6620
+ }
6621
+ ),
6622
+ /* @__PURE__ */ jsxRuntime.jsx(
6623
+ "text",
6624
+ {
6625
+ x: midX,
6626
+ y: midY + 1,
6627
+ textAnchor: "middle",
6628
+ dominantBaseline: "central",
6629
+ fill: "#7C3AED",
6630
+ style: { fontSize: "10px", fontFamily: "var(--font-outfit, system-ui, sans-serif)", fontWeight: 500 },
6631
+ children: label
6632
+ }
6633
+ )
6634
+ ] })
6635
+ ] });
6454
6636
  }
6455
6637
  function FlowchartDiagram({ mermaid, className }) {
6456
6638
  const { nodes, edges } = parseMermaidFlowchart(mermaid);
6457
6639
  if (nodes.length === 0) {
6458
6640
  return /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-white border border-gray-100 rounded-sm p-3 overflow-x-auto whitespace-pre-wrap", children: mermaid });
6459
6641
  }
6460
- const outgoing = /* @__PURE__ */ new Map();
6461
- const incoming = /* @__PURE__ */ new Map();
6462
- for (const edge of edges) {
6463
- if (!outgoing.has(edge.from)) outgoing.set(edge.from, []);
6464
- outgoing.get(edge.from).push(edge);
6465
- if (!incoming.has(edge.to)) incoming.set(edge.to, []);
6466
- incoming.get(edge.to).push(edge);
6467
- }
6468
- const nodeMap = new Map(nodes.map((n) => [n.id, n]));
6469
- const roots = nodes.filter((n) => !incoming.has(n.id) || incoming.get(n.id).length === 0);
6470
- const startId = roots.length > 0 ? roots[0].id : nodes[0].id;
6471
- const visited = /* @__PURE__ */ new Set();
6472
- const layout = buildLayout(startId, outgoing, incoming, nodeMap, visited);
6473
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center py-2", children: /* @__PURE__ */ jsxRuntime.jsx(RenderLayoutItems, { items: layout, nodeMap }) }) });
6642
+ const { layoutNodes, svgWidth, svgHeight } = computeLayout(nodes, edges);
6643
+ const nodeById = new Map(layoutNodes.map((n) => [n.id, n]));
6644
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(
6645
+ "svg",
6646
+ {
6647
+ width: svgWidth,
6648
+ height: svgHeight,
6649
+ viewBox: `0 0 ${svgWidth} ${svgHeight}`,
6650
+ xmlns: "http://www.w3.org/2000/svg",
6651
+ className: "block",
6652
+ children: [
6653
+ /* @__PURE__ */ jsxRuntime.jsx(SvgDefs, {}),
6654
+ edges.map((e, i) => {
6655
+ const fromNode = nodeById.get(e.from);
6656
+ const toNode = nodeById.get(e.to);
6657
+ if (!fromNode || !toNode) return null;
6658
+ return /* @__PURE__ */ jsxRuntime.jsx(EdgeSvg, { from: fromNode, to: toNode, label: e.label }, `e-${i}`);
6659
+ }),
6660
+ layoutNodes.map((n) => {
6661
+ if (n.node.type === "decision") return /* @__PURE__ */ jsxRuntime.jsx(DecisionNodeSvg, { n }, n.id);
6662
+ if (n.node.type === "terminal") return /* @__PURE__ */ jsxRuntime.jsx(TerminalNodeSvg, { n }, n.id);
6663
+ return /* @__PURE__ */ jsxRuntime.jsx(ActionNodeSvg, { n }, n.id);
6664
+ })
6665
+ ]
6666
+ }
6667
+ ) }) });
6474
6668
  }
6475
6669
  var frequencyLabels = {
6476
6670
  multiple_daily: "occurrence",