@uigraph/sdk 1.2.11 → 1.2.13

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/index.mjs CHANGED
@@ -2737,7 +2737,7 @@ function convertC4ToReactFlow(data) {
2737
2737
  sourceHandle: `source-${side.source}`,
2738
2738
  targetHandle: `target-${side.target}`,
2739
2739
  label,
2740
- type: "simplebezier",
2740
+ type: "smoothstep",
2741
2741
  style: {
2742
2742
  stroke: lineColor,
2743
2743
  strokeWidth: (_style$lineWidth = style === null || style === void 0 ? void 0 : style.lineWidth) !== null && _style$lineWidth !== void 0 ? _style$lineWidth : 1.5
@@ -2774,16 +2774,19 @@ const LAYOUT_SPACING = {
2774
2774
  SUBGRAPH_HEADER_HEIGHT: 35,
2775
2775
  SUBGRAPH_PADDING: 8,
2776
2776
  SUBGRAPH_CONTENT_TOP_MARGIN: 10,
2777
- NODE_SEPARATION_HORIZONTAL: 80,
2778
- NODE_SEPARATION_VERTICAL: 100,
2779
- CONTAINER_SEPARATION_HORIZONTAL: 120,
2780
- CONTAINER_SEPARATION_VERTICAL: 160,
2781
- NESTED_SUBGRAPH_SEPARATION_HORIZONTAL: 120,
2782
- NESTED_SUBGRAPH_SEPARATION_VERTICAL: 140,
2777
+ NODE_SEPARATION_HORIZONTAL: 120,
2778
+ NODE_SEPARATION_VERTICAL: 180,
2779
+ CONTAINER_SEPARATION_HORIZONTAL: 180,
2780
+ CONTAINER_SEPARATION_VERTICAL: 280,
2781
+ NESTED_SUBGRAPH_SEPARATION_HORIZONTAL: 160,
2782
+ NESTED_SUBGRAPH_SEPARATION_VERTICAL: 220,
2783
+ MIN_SUBGRAPH_WIDTH_HORIZONTAL: 600,
2784
+ MIN_SUBGRAPH_WIDTH_VERTICAL: 240,
2785
+ MIN_SUBGRAPH_HEIGHT: 200,
2783
2786
  META_GRAPH_MARGIN: 100,
2784
2787
  NESTED_CONTENT_MARGIN: 40,
2785
- MIXED_CONTENT_VERTICAL_SPACING: 100,
2786
- MIXED_CONTENT_HORIZONTAL_SPACING: 120
2788
+ MIXED_CONTENT_VERTICAL_SPACING: 180,
2789
+ MIXED_CONTENT_HORIZONTAL_SPACING: 160
2787
2790
  };
2788
2791
  ({
2789
2792
  NETWORK_SIMPLEX: "network-simplex",
@@ -2846,10 +2849,27 @@ function resolvePortalNodeType(hasImageUrl, tag) {
2846
2849
  if (tag && TAG_TO_NODE_TYPE[tag]) return TAG_TO_NODE_TYPE[tag];
2847
2850
  return "shape";
2848
2851
  }
2852
+ const COMPOUND_SHAPE_DELIMITERS = {
2853
+ circle: {
2854
+ open: "((",
2855
+ close: "))"
2856
+ },
2857
+ stadium: {
2858
+ open: "([",
2859
+ close: "])"
2860
+ },
2861
+ cylinder: {
2862
+ open: "[(",
2863
+ close: ")]"
2864
+ },
2865
+ subroutine: {
2866
+ open: "[[",
2867
+ close: "]]"
2868
+ }
2869
+ };
2849
2870
  function getNodeShape(nodeDefinition) {
2850
2871
  if (nodeDefinition.includes("{") && nodeDefinition.includes("}")) return "diamond";
2851
- if (nodeDefinition.includes("((") && nodeDefinition.includes("))")) return "circle";
2852
- if (nodeDefinition.includes("([") && nodeDefinition.includes("])")) return "stadium";
2872
+ for (const [shape, { open, close }] of Object.entries(COMPOUND_SHAPE_DELIMITERS)) if (nodeDefinition.includes(open) && nodeDefinition.includes(close)) return shape;
2853
2873
  if (nodeDefinition.includes("[") && nodeDefinition.includes("]")) return "rect";
2854
2874
  if (nodeDefinition.includes("(") && nodeDefinition.includes(")")) return "round";
2855
2875
  return "rect";
@@ -2899,15 +2919,35 @@ function parseMermaidCode(code) {
2899
2919
  }
2900
2920
  const lines = cleanCode.split("\n");
2901
2921
  const subgraphStack = [];
2922
+ const SHAPE_DELIMITER_PAIRS = [
2923
+ ["[", "]"],
2924
+ ["(", ")"],
2925
+ ["{", "}"]
2926
+ ];
2927
+ function stripWrappingShapeDelimiters(label) {
2928
+ let result = label;
2929
+ let changed = true;
2930
+ while (changed && result.length >= 2) {
2931
+ changed = false;
2932
+ for (const [open, close] of SHAPE_DELIMITER_PAIRS) if (result[0] === open && result[result.length - 1] === close) {
2933
+ const stripped = result.slice(1, -1).trim().replace(new RegExp("^\"(.*)\"$", "s"), "$1").replace(new RegExp("^'(.*)'$", "s"), "$1").trim();
2934
+ if (!stripped) break;
2935
+ result = stripped;
2936
+ changed = true;
2937
+ break;
2938
+ }
2939
+ }
2940
+ return result;
2941
+ }
2902
2942
  function enhancedCleanLabel(label) {
2903
- return label.replace(/<br\s*\/?>/gi, "\n").replace(/<[^>]*>/g, "").replace(/\\u([0-9a-fA-F]{4})/g, (match, code$1) => {
2943
+ return stripWrappingShapeDelimiters(label.replace(/<br\s*\/?>/gi, "\n").replace(/<[^>]*>/g, "").replace(/\\u([0-9a-fA-F]{4})/g, (match, code$1) => {
2904
2944
  try {
2905
2945
  return String.fromCharCode(parseInt(code$1, 16));
2906
2946
  } catch (_unused) {
2907
2947
  debugLog(`Warning: Could not parse unicode character: ${match}`);
2908
2948
  return match;
2909
2949
  }
2910
- }).replace(/\\n/g, "\n").replace(/\s*\n\s*/g, "\n").trim();
2950
+ }).replace(/\\n/g, "\n").replace(/\s*\n\s*/g, "\n").trim());
2911
2951
  }
2912
2952
  debugLog("Pre-scanning for node definitions...");
2913
2953
  lines.forEach((line, lineIndex) => {
@@ -2953,11 +2993,13 @@ function parseMermaidCode(code) {
2953
2993
  if (shapeDef) {
2954
2994
  const shape = getNodeShape(fullDef);
2955
2995
  let rawLabel = nodeId;
2956
- const labelContentMatch = shapeDef.match(new RegExp("^[\\[\\(\\{](.*)[\\]\\)\\}]$", "s"));
2957
- if (labelContentMatch) {
2958
- rawLabel = labelContentMatch[1];
2959
- rawLabel = rawLabel.replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1");
2996
+ const compoundDelimiters = COMPOUND_SHAPE_DELIMITERS[shape];
2997
+ if (compoundDelimiters && shapeDef.startsWith(compoundDelimiters.open) && shapeDef.endsWith(compoundDelimiters.close)) rawLabel = shapeDef.slice(compoundDelimiters.open.length, shapeDef.length - compoundDelimiters.close.length);
2998
+ else {
2999
+ const labelContentMatch = shapeDef.match(new RegExp("^[\\[\\(\\{](.*)[\\]\\)\\}]$", "s"));
3000
+ if (labelContentMatch) rawLabel = labelContentMatch[1];
2960
3001
  }
3002
+ rawLabel = rawLabel.replace(new RegExp("^\"(.*)\"$", "s"), "$1").replace(new RegExp("^'(.*)'$", "s"), "$1");
2961
3003
  const label = enhancedCleanLabel(rawLabel);
2962
3004
  nodeDefinitions.set(nodeId, {
2963
3005
  label,
@@ -3114,7 +3156,16 @@ function parseMermaidCode(code) {
3114
3156
  const openChar = openCharMatch[1];
3115
3157
  const openPos = idx + rest.indexOf(openChar);
3116
3158
  const closeChar = openChar === "[" ? "]" : openChar === "(" ? ")" : "}";
3117
- const closePos = str.indexOf(closeChar, openPos + 1);
3159
+ let depth = 0;
3160
+ let closePos = -1;
3161
+ for (let pos = openPos; pos < str.length; pos++) if (str[pos] === openChar) depth++;
3162
+ else if (str[pos] === closeChar) {
3163
+ depth--;
3164
+ if (depth === 0) {
3165
+ closePos = pos;
3166
+ break;
3167
+ }
3168
+ }
3118
3169
  if (closePos !== -1) return {
3119
3170
  id,
3120
3171
  full: str.slice(startIndex + idMatch[0].search(/\S/), closePos + 1).trim(),
@@ -3127,101 +3178,106 @@ function parseMermaidCode(code) {
3127
3178
  endIndex: idx
3128
3179
  };
3129
3180
  }
3181
+ const arrowHeads = [
3182
+ "-.->",
3183
+ "-->",
3184
+ "==>",
3185
+ "->>",
3186
+ "<->",
3187
+ "-<>",
3188
+ "<-",
3189
+ "->"
3190
+ ];
3130
3191
  function parseEdge(str) {
3131
3192
  try {
3193
+ const hops = [];
3132
3194
  let i$2 = 0;
3133
- const src = extractToken(str, i$2);
3195
+ let src = extractToken(str, i$2);
3134
3196
  if (!src) return null;
3135
3197
  i$2 = src.endIndex;
3136
- while (i$2 < str.length && /\s/.test(str[i$2])) i$2++;
3137
- const arrowHeads = [
3138
- "-.->",
3139
- "-->",
3140
- "==>",
3141
- "->>",
3142
- "<->",
3143
- "-<>",
3144
- "<-",
3145
- "->"
3146
- ];
3147
- let foundArrowIndex = -1;
3148
- let foundArrow = "";
3149
- for (const ah of arrowHeads) {
3150
- const idx = str.indexOf(ah, i$2);
3151
- if (idx !== -1 && (foundArrowIndex === -1 || idx < foundArrowIndex)) {
3152
- foundArrowIndex = idx;
3153
- foundArrow = ah;
3154
- }
3155
- }
3156
- let op = null;
3157
- let edgeLabel = "";
3158
- if (foundArrowIndex !== -1) {
3159
- const between = str.slice(i$2, foundArrowIndex);
3160
- const prePipeMatch = between.match(/\|(.*?)\|/);
3161
- if (prePipeMatch) edgeLabel = prePipeMatch[1];
3162
- else {
3163
- const inline = between.replace(/^\s*[\-\.=:\~]+\s*/g, "").replace(/\s*[\-\.=:\~]+\s*$/g, "").trim();
3164
- if (inline) edgeLabel = inline;
3165
- }
3166
- op = foundArrow;
3167
- i$2 = foundArrowIndex + foundArrow.length;
3198
+ while (true) {
3168
3199
  while (i$2 < str.length && /\s/.test(str[i$2])) i$2++;
3169
- if (str[i$2] === "|") {
3170
- const next = str.indexOf("|", i$2 + 1);
3171
- if (next !== -1) {
3172
- edgeLabel = str.slice(i$2 + 1, next);
3173
- i$2 = next + 1;
3200
+ let foundArrowIndex = -1;
3201
+ let foundArrow = "";
3202
+ for (const ah of arrowHeads) {
3203
+ const idx = str.indexOf(ah, i$2);
3204
+ if (idx !== -1 && (foundArrowIndex === -1 || idx < foundArrowIndex)) {
3205
+ foundArrowIndex = idx;
3206
+ foundArrow = ah;
3174
3207
  }
3175
3208
  }
3176
- } else {
3177
- for (const o of [
3178
- "---",
3179
- "-.-",
3180
- "::",
3181
- ":-:",
3182
- "...",
3183
- "~",
3184
- "==="
3185
- ].sort((a, b) => b.length - a.length)) if (str.startsWith(o, i$2)) {
3186
- op = o;
3187
- i$2 += o.length;
3188
- break;
3189
- }
3190
- if (!op) return null;
3191
- while (i$2 < str.length && /\s/.test(str[i$2])) i$2++;
3192
- if (str[i$2] === "|") {
3193
- const next = str.indexOf("|", i$2 + 1);
3194
- if (next !== -1) {
3195
- edgeLabel = str.slice(i$2 + 1, next);
3196
- i$2 = next + 1;
3209
+ let op = null;
3210
+ let edgeLabel = "";
3211
+ if (foundArrowIndex !== -1) {
3212
+ const between = str.slice(i$2, foundArrowIndex);
3213
+ const prePipeMatch = between.match(/\|(.*?)\|/);
3214
+ if (prePipeMatch) edgeLabel = prePipeMatch[1];
3215
+ else {
3216
+ const inline = between.replace(/^\s*[\-\.=:\~]+\s*/g, "").replace(/\s*[\-\.=:\~]+\s*$/g, "").trim();
3217
+ if (inline) edgeLabel = inline;
3197
3218
  }
3219
+ op = foundArrow;
3220
+ i$2 = foundArrowIndex + foundArrow.length;
3221
+ while (i$2 < str.length && /\s/.test(str[i$2])) i$2++;
3222
+ if (str[i$2] === "|") {
3223
+ const next = str.indexOf("|", i$2 + 1);
3224
+ if (next !== -1) {
3225
+ edgeLabel = str.slice(i$2 + 1, next);
3226
+ i$2 = next + 1;
3227
+ }
3228
+ }
3229
+ } else if (hops.length === 0) {
3230
+ for (const o of [
3231
+ "---",
3232
+ "-.-",
3233
+ "::",
3234
+ ":-:",
3235
+ "...",
3236
+ "~",
3237
+ "==="
3238
+ ].sort((a, b) => b.length - a.length)) if (str.startsWith(o, i$2)) {
3239
+ op = o;
3240
+ i$2 += o.length;
3241
+ break;
3242
+ }
3243
+ if (!op) return null;
3244
+ while (i$2 < str.length && /\s/.test(str[i$2])) i$2++;
3245
+ if (str[i$2] === "|") {
3246
+ const next = str.indexOf("|", i$2 + 1);
3247
+ if (next !== -1) {
3248
+ edgeLabel = str.slice(i$2 + 1, next);
3249
+ i$2 = next + 1;
3250
+ }
3251
+ }
3252
+ } else break;
3253
+ while (i$2 < str.length && /\s/.test(str[i$2])) i$2++;
3254
+ const tgt = extractToken(str, i$2);
3255
+ if (!tgt) break;
3256
+ const trailing = str.slice(tgt.endIndex).trimStart();
3257
+ if (!edgeLabel && !trailing.startsWith(":::") && !arrowHeads.some((ah) => trailing.includes(ah))) {
3258
+ const colonLabelMatch = trailing.match(/^:\s*(.+)$/);
3259
+ if (colonLabelMatch) edgeLabel = colonLabelMatch[1].trim();
3198
3260
  }
3261
+ const isReverseArrow = op === "<-";
3262
+ hops.push({
3263
+ sourceId: isReverseArrow ? tgt.id : src.id,
3264
+ sourceFull: isReverseArrow ? tgt.full : src.full,
3265
+ targetId: isReverseArrow ? src.id : tgt.id,
3266
+ targetFull: isReverseArrow ? src.full : tgt.full,
3267
+ edgeType: isReverseArrow ? "->" : op,
3268
+ edgeLabel
3269
+ });
3270
+ src = tgt;
3271
+ i$2 = tgt.endIndex;
3199
3272
  }
3200
- while (i$2 < str.length && /\s/.test(str[i$2])) i$2++;
3201
- const tgt = extractToken(str, i$2);
3202
- if (!tgt) return null;
3203
- const trailing = str.slice(tgt.endIndex).trimStart();
3204
- if (!edgeLabel && !trailing.startsWith(":::")) {
3205
- const colonLabelMatch = trailing.match(/^:\s*(.+)$/);
3206
- if (colonLabelMatch) edgeLabel = colonLabelMatch[1].trim();
3207
- }
3208
- const isReverseArrow = op === "<-";
3209
- return {
3210
- sourceId: isReverseArrow ? tgt.id : src.id,
3211
- sourceFull: isReverseArrow ? tgt.full : src.full,
3212
- targetId: isReverseArrow ? src.id : tgt.id,
3213
- targetFull: isReverseArrow ? src.full : tgt.full,
3214
- edgeType: isReverseArrow ? "->" : op,
3215
- edgeLabel
3216
- };
3273
+ return hops.length > 0 ? hops : null;
3217
3274
  } catch (_unused2) {
3218
3275
  return null;
3219
3276
  }
3220
3277
  }
3221
- const parsedEdge = parseEdge(line);
3222
- if (!parsedEdge) debugLog(`Line "${line}" did not match edge pattern - checking for standalone nodes`);
3223
- if (parsedEdge) try {
3224
- const { sourceId, targetId, edgeType, edgeLabel } = parsedEdge;
3278
+ const parsedEdges = parseEdge(line);
3279
+ if (!parsedEdges) debugLog(`Line "${line}" did not match edge pattern - checking for standalone nodes`);
3280
+ if (parsedEdges) for (const { sourceId, targetId, edgeType, edgeLabel } of parsedEdges) try {
3225
3281
  debugLog(`Found edge: ${sourceId} ${edgeType} ${targetId} with label: "${edgeLabel}" in context: ${currentSubgraph || "global"}`);
3226
3282
  const isSourceSubgraph = subgraphMap.has(sourceId);
3227
3283
  const isTargetSubgraph = subgraphMap.has(targetId);
@@ -3241,10 +3297,11 @@ function parseMermaidCode(code) {
3241
3297
  createOrGetNode(targetId, targetSubgraph);
3242
3298
  }
3243
3299
  }
3300
+ const unquotedEdgeLabel = edgeLabel.replace(new RegExp("^\"(.*)\"$", "s"), "$1").replace(new RegExp("^'(.*)'$", "s"), "$1");
3244
3301
  edges.push({
3245
3302
  source: sourceId,
3246
3303
  target: targetId,
3247
- label: enhancedCleanLabel(edgeLabel),
3304
+ label: enhancedCleanLabel(unquotedEdgeLabel),
3248
3305
  type: edgeType,
3249
3306
  isSourceSubgraph,
3250
3307
  isTargetSubgraph
@@ -3300,7 +3357,9 @@ const MERMAID_TO_PORTAL_SHAPE = {
3300
3357
  round: "rounded-rect",
3301
3358
  stadium: "terminator",
3302
3359
  circle: "ellipse",
3303
- diamond: "diamond"
3360
+ diamond: "diamond",
3361
+ cylinder: "cylinder",
3362
+ subroutine: "subroutine"
3304
3363
  };
3305
3364
  const SUBGRAPH_HEADER_HEIGHT = LAYOUT_SPACING.SUBGRAPH_HEADER_HEIGHT;
3306
3365
  const SUBGRAPH_PADDING = LAYOUT_SPACING.SUBGRAPH_PADDING;
@@ -3311,6 +3370,9 @@ const CONTAINER_SEPARATION_HORIZONTAL = LAYOUT_SPACING.CONTAINER_SEPARATION_HORI
3311
3370
  const CONTAINER_SEPARATION_VERTICAL = LAYOUT_SPACING.CONTAINER_SEPARATION_VERTICAL;
3312
3371
  const NESTED_SUBGRAPH_SEPARATION_HORIZONTAL = LAYOUT_SPACING.NESTED_SUBGRAPH_SEPARATION_HORIZONTAL;
3313
3372
  const NESTED_SUBGRAPH_SEPARATION_VERTICAL = LAYOUT_SPACING.NESTED_SUBGRAPH_SEPARATION_VERTICAL;
3373
+ const MIN_SUBGRAPH_WIDTH_HORIZONTAL = LAYOUT_SPACING.MIN_SUBGRAPH_WIDTH_HORIZONTAL;
3374
+ const MIN_SUBGRAPH_WIDTH_VERTICAL = LAYOUT_SPACING.MIN_SUBGRAPH_WIDTH_VERTICAL;
3375
+ const MIN_SUBGRAPH_HEIGHT = LAYOUT_SPACING.MIN_SUBGRAPH_HEIGHT;
3314
3376
  const META_GRAPH_MARGIN = LAYOUT_SPACING.META_GRAPH_MARGIN;
3315
3377
  const NESTED_CONTENT_MARGIN = LAYOUT_SPACING.NESTED_CONTENT_MARGIN;
3316
3378
  const MIXED_CONTENT_VERTICAL_SPACING = LAYOUT_SPACING.MIXED_CONTENT_VERTICAL_SPACING;
@@ -3334,7 +3396,8 @@ function calculateNodeSize(label, shape, isImageNode = false) {
3334
3396
  } catch (_unused) {}
3335
3397
  return text.length * 8;
3336
3398
  }
3337
- const baseWidth = Math.max(...lines.map((line) => Math.ceil(measureLineWidth(line)))) + 30;
3399
+ const maxLineWidth = Math.max(...lines.map((line) => Math.ceil(measureLineWidth(line))));
3400
+ const baseWidth = maxLineWidth + 30;
3338
3401
  const baseHeight = lines.length * 18 + 20;
3339
3402
  const width = Math.max(80, baseWidth + 30);
3340
3403
  const height = Math.max(40, baseHeight + 20);
@@ -3349,6 +3412,27 @@ function calculateNodeSize(label, shape, isImageNode = false) {
3349
3412
  height: size
3350
3413
  };
3351
3414
  }
3415
+ if (shape === "stadium") {
3416
+ const sideInset = Math.max(12, height / 2) * 2;
3417
+ return {
3418
+ width: Math.max(width, maxLineWidth + sideInset + 20),
3419
+ height
3420
+ };
3421
+ }
3422
+ if (shape === "cylinder") {
3423
+ const capInset = Math.max(12, Math.min(height * .18, width * .5) + 8) * 2;
3424
+ return {
3425
+ width,
3426
+ height: Math.max(height, lines.length * 18 + capInset + 10)
3427
+ };
3428
+ }
3429
+ if (shape === "subroutine") {
3430
+ const sideInset = Math.max(24, width * .2);
3431
+ return {
3432
+ width: Math.max(width, maxLineWidth + sideInset + 20),
3433
+ height
3434
+ };
3435
+ }
3352
3436
  return {
3353
3437
  width,
3354
3438
  height
@@ -3397,6 +3481,7 @@ function processSubgraphsInHierarchicalOrder(subgraphs) {
3397
3481
  }
3398
3482
  function layoutSubgraphs(nodes, edges, subgraphs, direction) {
3399
3483
  const subgraphLayouts = /* @__PURE__ */ new Map();
3484
+ const isHorizontal = direction === "LR" || direction === "RL";
3400
3485
  const orderedSubgraphs = processSubgraphsInHierarchicalOrder(subgraphs);
3401
3486
  debugLog(`Laying out ${orderedSubgraphs.length} subgraphs in hierarchical order`);
3402
3487
  orderedSubgraphs.forEach((subgraph) => {
@@ -3469,8 +3554,8 @@ function layoutSubgraphs(nodes, edges, subgraphs, direction) {
3469
3554
  validateNodeSpacing(nodePositions, subgraph.id);
3470
3555
  const baseWidth = maxX - minX + SUBGRAPH_PADDING * 2;
3471
3556
  const baseHeight = maxY - minY + SUBGRAPH_PADDING * 2 + SUBGRAPH_HEADER_HEIGHT + SUBGRAPH_CONTENT_TOP_MARGIN;
3472
- const width = baseWidth + 4;
3473
- const height = baseHeight + 4;
3557
+ const width = Math.max(baseWidth + SUBGRAPH_PADDING * 3, isHorizontal ? MIN_SUBGRAPH_WIDTH_HORIZONTAL : MIN_SUBGRAPH_WIDTH_VERTICAL);
3558
+ const height = Math.max(baseHeight + SUBGRAPH_PADDING * 2, MIN_SUBGRAPH_HEIGHT);
3474
3559
  subgraphLayouts.set(subgraph.id, {
3475
3560
  id: subgraph.id,
3476
3561
  title: subgraph.title,
@@ -3580,8 +3665,8 @@ function adjustParentSizesAfterPositioning(subgraphLayouts, subgraphPositions, o
3580
3665
  const contentMaxBottom = Math.max(maxNodeBottom, maxChildBottom);
3581
3666
  const requiredWidth = contentMaxRight + (isHorizontal ? SUBGRAPH_PADDING * 4 : SUBGRAPH_PADDING * 3);
3582
3667
  const requiredHeight = contentMaxBottom + SUBGRAPH_PADDING * 3;
3583
- const newWidth = Math.max(layout.width, requiredWidth, isHorizontal ? 600 : 240);
3584
- const newHeight = Math.max(layout.height, requiredHeight, 200);
3668
+ const newWidth = Math.max(layout.width, requiredWidth, isHorizontal ? MIN_SUBGRAPH_WIDTH_HORIZONTAL : MIN_SUBGRAPH_WIDTH_VERTICAL);
3669
+ const newHeight = Math.max(layout.height, requiredHeight, MIN_SUBGRAPH_HEIGHT);
3585
3670
  if (newWidth > layout.width || newHeight > layout.height) {
3586
3671
  debugLog(`Post-positioning resize (iter ${iterations}): ${subgraph.id} ${layout.width}x${layout.height} → ${newWidth}x${newHeight}`);
3587
3672
  layout.width = newWidth;
@@ -3616,11 +3701,12 @@ function validateNodeSpacing(nodePositions, subgraphId) {
3616
3701
  if (!hasOverlap) debugLog(`✓ Node spacing validated for subgraph ${subgraphId} - no overlaps detected`);
3617
3702
  }
3618
3703
  function layoutMetaGraph(nodes, edges, subgraphLayouts, direction) {
3704
+ const hasTopLevelSubgraphs = Array.from(subgraphLayouts.values()).some((layout) => !layout.parentId);
3619
3705
  const g = new dagre.graphlib.Graph();
3620
3706
  g.setGraph({
3621
3707
  rankdir: direction,
3622
- nodesep: CONTAINER_SEPARATION_HORIZONTAL,
3623
- ranksep: CONTAINER_SEPARATION_VERTICAL,
3708
+ nodesep: hasTopLevelSubgraphs ? CONTAINER_SEPARATION_HORIZONTAL : NODE_SEPARATION_HORIZONTAL,
3709
+ ranksep: hasTopLevelSubgraphs ? CONTAINER_SEPARATION_VERTICAL : NODE_SEPARATION_VERTICAL,
3624
3710
  marginx: META_GRAPH_MARGIN,
3625
3711
  marginy: META_GRAPH_MARGIN,
3626
3712
  ranker: DAGRE_RANKER
@@ -3865,7 +3951,8 @@ function createReactFlowElements(nodes, edges, subgraphs, subgraphLayouts, subgr
3865
3951
  ];
3866
3952
  return subgraphColors[index % subgraphColors.length];
3867
3953
  }
3868
- processSubgraphsInHierarchicalOrder(subgraphs).forEach((subgraph, index) => {
3954
+ const orderedSubgraphs = processSubgraphsInHierarchicalOrder(subgraphs);
3955
+ orderedSubgraphs.forEach((subgraph, index) => {
3869
3956
  const layout = subgraphLayouts.get(subgraph.id);
3870
3957
  const position = subgraphPositions.get(subgraph.id);
3871
3958
  if (layout && position) {
@@ -4060,11 +4147,42 @@ function createReactFlowElements(nodes, edges, subgraphs, subgraphLayouts, subgr
4060
4147
  zIndex: 1
4061
4148
  });
4062
4149
  });
4150
+ const nodeSubgraphById = new Map(nodes.map((n) => [n.id, n.subgraph]));
4151
+ const meaningfulEdges = edges.filter((edge) => {
4152
+ if (edge.isTargetSubgraph && nodeSubgraphById.get(edge.source) === edge.target) {
4153
+ debugLog(`Dropping edge ${edge.source} -> ${edge.target}: source already lives inside this subgraph`);
4154
+ return false;
4155
+ }
4156
+ if (edge.isSourceSubgraph && nodeSubgraphById.get(edge.target) === edge.source) {
4157
+ debugLog(`Dropping edge ${edge.source} -> ${edge.target}: target already lives inside this subgraph`);
4158
+ return false;
4159
+ }
4160
+ return true;
4161
+ });
4162
+ const nodeAxisPosition = /* @__PURE__ */ new Map();
4163
+ orderedSubgraphs.forEach((subgraph) => {
4164
+ const position = subgraphPositions.get(subgraph.id);
4165
+ if (position) nodeAxisPosition.set(`subgraph-${subgraph.id}`, position);
4166
+ });
4167
+ nodes.forEach((node) => {
4168
+ if (node.subgraph) {
4169
+ const subgraphLayout = subgraphLayouts.get(node.subgraph);
4170
+ const subgraphPosition = subgraphPositions.get(node.subgraph);
4171
+ const nodeLayout = subgraphLayout === null || subgraphLayout === void 0 ? void 0 : subgraphLayout.nodes.get(node.id);
4172
+ if (nodeLayout && subgraphPosition) nodeAxisPosition.set(node.id, {
4173
+ x: subgraphPosition.x + nodeLayout.x,
4174
+ y: subgraphPosition.y + nodeLayout.y
4175
+ });
4176
+ } else {
4177
+ const standalonePos = standalonePositions.get(node.id);
4178
+ if (standalonePos) nodeAxisPosition.set(node.id, standalonePos);
4179
+ }
4180
+ });
4063
4181
  return {
4064
4182
  nodes: reactFlowNodes,
4065
- edges: edges.map((edge, index) => {
4183
+ edges: meaningfulEdges.map((edge, index) => {
4066
4184
  const edgeStyle = { strokeWidth: 2.5 };
4067
- const edgeType = "default";
4185
+ const edgeType = "smoothstep";
4068
4186
  switch (edge.type) {
4069
4187
  case "-->":
4070
4188
  case "->": break;
@@ -4081,6 +4199,22 @@ function createReactFlowElements(nodes, edges, subgraphs, subgraphLayouts, subgr
4081
4199
  }
4082
4200
  const sourceId = edge.isSourceSubgraph ? `subgraph-${edge.source}` : edge.source;
4083
4201
  const targetId = edge.isTargetSubgraph ? `subgraph-${edge.target}` : edge.target;
4202
+ const isHorizontalLayout = direction === "LR" || direction === "RL";
4203
+ let sourceHandle = isHorizontalLayout ? "source-right" : "source-bottom";
4204
+ let targetHandle = isHorizontalLayout ? "target-left" : "target-top";
4205
+ const sourcePoint = nodeAxisPosition.get(sourceId);
4206
+ const targetPoint = nodeAxisPosition.get(targetId);
4207
+ if (sourcePoint && targetPoint) {
4208
+ if (isHorizontalLayout) {
4209
+ if (targetPoint.x < sourcePoint.x) {
4210
+ sourceHandle = "source-left";
4211
+ targetHandle = "target-right";
4212
+ }
4213
+ } else if (targetPoint.y < sourcePoint.y) {
4214
+ sourceHandle = "source-top";
4215
+ targetHandle = "target-bottom";
4216
+ }
4217
+ }
4084
4218
  return {
4085
4219
  id: `edge-${edge.source}-${edge.target}-${index}`,
4086
4220
  source: sourceId,
@@ -4100,8 +4234,8 @@ function createReactFlowElements(nodes, edges, subgraphs, subgraphLayouts, subgr
4100
4234
  width: 20,
4101
4235
  height: 20
4102
4236
  },
4103
- sourceHandle: direction === "LR" || direction === "RL" ? "source-right" : "source-bottom",
4104
- targetHandle: direction === "LR" || direction === "RL" ? "target-left" : "target-top",
4237
+ sourceHandle,
4238
+ targetHandle,
4105
4239
  zIndex: 0
4106
4240
  };
4107
4241
  })
@@ -6888,4 +7022,494 @@ function convertUiGraphToMermaid(input, options) {
6888
7022
  context
6889
7023
  };
6890
7024
  }
6891
- export { AstToSqlGenerator, AstToUiConverter, BasicDetailsSchema, C4_COLORS, C4_LAYOUT, ComponentInputType, DialectIdSchema, DocumentCollectionSchema, DocumentIndexSchema, DynamoAttributeSchema, DynamoEditorSchema, DynamoGsiSchema, EditorSupportedDialectSchema, JsonEditorSchema, MongoCollectionSchema, MongoEditorSchema, MongoIndexFieldSchema, MongoIndexSchema, MongoNestedFieldSchema, NestedFieldSchema, NoSqlFieldSchema, SEQUENCE_LAYOUT, SqlToAstParser, buildMetaData, computeDiagramSyncHash, contextSchema, convertC4MermaidToReactFlow, convertC4ToReactFlow, convertDynamoSchemaToAst, convertJsonSchemaToAst, convertMermaidToReactFlow, convertMermaidToReactFlowWithContext, convertMongoSchemaToAst, convertNoSQLToAst, convertReactFlowToC4Mermaid, convertReactFlowToC4UiGraph, convertReactFlowToSequenceMermaid, convertReactFlowToSequenceUiGraph, convertUiGraphToMermaid, estimateSequenceMessageBoxSize, flattenMetaData, generateTableNodeId, generateUUID, getC4ElementColors, isC4Diagram, isC4ReactFlowDiagram, isSequenceDiagram, parseC4Diagram, sanitizeMermaidLabels, syncBaseData };
7025
+ const SHAPE_IDS = [
7026
+ "rectangle",
7027
+ "rounded-rect",
7028
+ "ellipse",
7029
+ "diamond",
7030
+ "triangle",
7031
+ "parallelogram",
7032
+ "trapezoid",
7033
+ "hexagon",
7034
+ "document",
7035
+ "cylinder",
7036
+ "delay",
7037
+ "off-page-connector",
7038
+ "display",
7039
+ "collate",
7040
+ "sort",
7041
+ "terminator",
7042
+ "or",
7043
+ "database",
7044
+ "multiple-documents",
7045
+ "subroutine",
7046
+ "manual-input",
7047
+ "summing-junction",
7048
+ "internal-storage"
7049
+ ];
7050
+ const STROKE_STYLES = [
7051
+ "solid",
7052
+ "dashed",
7053
+ "dotted"
7054
+ ];
7055
+ function clampNum(value, min, max) {
7056
+ if (value === void 0 || !Number.isFinite(value)) return void 0;
7057
+ return Math.min(max, Math.max(min, value));
7058
+ }
7059
+ function dropUndefined(input) {
7060
+ const output = {};
7061
+ for (const [key, value] of Object.entries(input)) {
7062
+ if (value === void 0) continue;
7063
+ output[key] = value;
7064
+ }
7065
+ return output;
7066
+ }
7067
+ function mapShapeStylePatch(patch) {
7068
+ return dropUndefined({
7069
+ fill: patch.fill,
7070
+ stroke: patch.stroke,
7071
+ strokeWidth: clampNum(patch.strokeWidth, 0, 10),
7072
+ strokeStyle: patch.strokeStyle,
7073
+ cornerRadius: clampNum(patch.cornerRadius, 0, 64),
7074
+ textColor: patch.textColor,
7075
+ textFontSize: clampNum(patch.textFontSize, 8, 48),
7076
+ shape: patch.shape
7077
+ });
7078
+ }
7079
+ function mapCloudStylePatch(patch) {
7080
+ return dropUndefined({
7081
+ fill: patch.fill,
7082
+ stroke: patch.stroke,
7083
+ strokeWidth: clampNum(patch.strokeWidth, 0, 10),
7084
+ strokeStyle: patch.strokeStyle
7085
+ });
7086
+ }
7087
+ function mapTextStylePatch(patch) {
7088
+ return dropUndefined({
7089
+ fill: patch.fill,
7090
+ stroke: patch.stroke,
7091
+ strokeWidth: clampNum(patch.strokeWidth, 0, 10),
7092
+ strokeStyle: patch.strokeStyle,
7093
+ borderRadius: clampNum(patch.cornerRadius, 0, 64),
7094
+ color: patch.textColor,
7095
+ fontSize: clampNum(patch.textFontSize, 8, 48)
7096
+ });
7097
+ }
7098
+ function mapGroupStylePatch(patch) {
7099
+ return dropUndefined({
7100
+ backgroundColor: patch.fill,
7101
+ borderColor: patch.stroke
7102
+ });
7103
+ }
7104
+ function mapC4StylePatch(patch) {
7105
+ return dropUndefined({
7106
+ fill: patch.fill,
7107
+ stroke: patch.stroke,
7108
+ fontColor: patch.textColor
7109
+ });
7110
+ }
7111
+ function mapC4BoundaryStylePatch(patch) {
7112
+ return dropUndefined({
7113
+ backgroundColor: patch.fill,
7114
+ borderColor: patch.stroke,
7115
+ fontColor: patch.textColor
7116
+ });
7117
+ }
7118
+ function mapSequenceParticipantStylePatch(patch) {
7119
+ return dropUndefined({
7120
+ color: patch.stroke,
7121
+ textColor: patch.textColor
7122
+ });
7123
+ }
7124
+ const NODE_TYPE_REGISTRY = {
7125
+ shape: {
7126
+ tag: "shape",
7127
+ diagramTypes: ["flowchart"],
7128
+ isContainer: false,
7129
+ geometryEditable: true,
7130
+ shapes: SHAPE_IDS,
7131
+ mapStylePatch: mapShapeStylePatch
7132
+ },
7133
+ default: {
7134
+ tag: "default",
7135
+ diagramTypes: ["flowchart"],
7136
+ isContainer: false,
7137
+ geometryEditable: true,
7138
+ shapes: SHAPE_IDS,
7139
+ mapStylePatch: mapShapeStylePatch
7140
+ },
7141
+ cloud: {
7142
+ tag: "cloud",
7143
+ diagramTypes: ["flowchart"],
7144
+ isContainer: false,
7145
+ geometryEditable: true,
7146
+ mapStylePatch: mapCloudStylePatch
7147
+ },
7148
+ text: {
7149
+ tag: "text",
7150
+ diagramTypes: ["flowchart"],
7151
+ isContainer: false,
7152
+ geometryEditable: true,
7153
+ mapStylePatch: mapTextStylePatch
7154
+ },
7155
+ group: {
7156
+ tag: "group",
7157
+ diagramTypes: ["flowchart"],
7158
+ isContainer: true,
7159
+ geometryEditable: false,
7160
+ mapStylePatch: mapGroupStylePatch
7161
+ },
7162
+ c4: {
7163
+ tag: "c4",
7164
+ diagramTypes: ["c4"],
7165
+ isContainer: false,
7166
+ geometryEditable: true,
7167
+ mapStylePatch: mapC4StylePatch
7168
+ },
7169
+ c4Boundary: {
7170
+ tag: "c4Boundary",
7171
+ diagramTypes: ["c4"],
7172
+ isContainer: true,
7173
+ geometryEditable: false,
7174
+ mapStylePatch: mapC4BoundaryStylePatch
7175
+ },
7176
+ sequenceParticipant: {
7177
+ tag: "sequenceParticipant",
7178
+ diagramTypes: ["sequence"],
7179
+ isContainer: false,
7180
+ geometryEditable: false,
7181
+ mapStylePatch: mapSequenceParticipantStylePatch
7182
+ }
7183
+ };
7184
+ function getNodeTypeSpec(type) {
7185
+ if (type === void 0) return void 0;
7186
+ return NODE_TYPE_REGISTRY[type];
7187
+ }
7188
+ function buildNodeStyleDataPatch(type, patch) {
7189
+ var _getNodeTypeSpec$mapS, _getNodeTypeSpec;
7190
+ return (_getNodeTypeSpec$mapS = (_getNodeTypeSpec = getNodeTypeSpec(type)) === null || _getNodeTypeSpec === void 0 ? void 0 : _getNodeTypeSpec.mapStylePatch(patch)) !== null && _getNodeTypeSpec$mapS !== void 0 ? _getNodeTypeSpec$mapS : {};
7191
+ }
7192
+ function isGeometryEditableNodeType(type) {
7193
+ var _getNodeTypeSpec$geom, _getNodeTypeSpec2;
7194
+ return (_getNodeTypeSpec$geom = (_getNodeTypeSpec2 = getNodeTypeSpec(type)) === null || _getNodeTypeSpec2 === void 0 ? void 0 : _getNodeTypeSpec2.geometryEditable) !== null && _getNodeTypeSpec$geom !== void 0 ? _getNodeTypeSpec$geom : false;
7195
+ }
7196
+ const THEME_ROLES = [
7197
+ "boundary",
7198
+ "client",
7199
+ "service",
7200
+ "data",
7201
+ "messaging",
7202
+ "neutral"
7203
+ ];
7204
+ const DEFAULT_THEME_ID = "professional";
7205
+ const THEME_REGISTRY = {
7206
+ professional: {
7207
+ id: "professional",
7208
+ label: "Professional",
7209
+ description: "Calm slate-navy palette, the default look",
7210
+ mode: "dark",
7211
+ promptHint: "clean, modern, professional, calm, corporate, default, no specific style requested",
7212
+ nodeText: "#F8FAFC",
7213
+ canvasText: "#93B4E8",
7214
+ roles: {
7215
+ boundary: {
7216
+ fill: "#171B26",
7217
+ stroke: "#3D4759"
7218
+ },
7219
+ client: {
7220
+ fill: "#1C2336",
7221
+ stroke: "#3D5EA8"
7222
+ },
7223
+ service: {
7224
+ fill: "#1C2336",
7225
+ stroke: "#3D5EA8"
7226
+ },
7227
+ data: {
7228
+ fill: "#18242F",
7229
+ stroke: "#3D8A7A"
7230
+ },
7231
+ messaging: {
7232
+ fill: "#241F30",
7233
+ stroke: "#6B5CA8"
7234
+ },
7235
+ neutral: {
7236
+ fill: "#1C2336",
7237
+ stroke: "#3D5EA8"
7238
+ }
7239
+ },
7240
+ edge: {
7241
+ stroke: "#828DA3",
7242
+ strokeWidth: 1.5,
7243
+ labelBackground: "#1E293B",
7244
+ labelText: "#E2E8F0",
7245
+ emphasizedStroke: "#5B9BFF",
7246
+ emphasizedStrokeWidth: 3
7247
+ }
7248
+ },
7249
+ "midnight-bold": {
7250
+ id: "midnight-bold",
7251
+ label: "Midnight Bold",
7252
+ description: "Dark background, saturated high-contrast accents",
7253
+ mode: "dark",
7254
+ promptHint: "dark, bold, saturated, high contrast, vivid, striking",
7255
+ nodeText: "#F8FAFC",
7256
+ canvasText: "#7FB2FF",
7257
+ roles: {
7258
+ boundary: {
7259
+ fill: "#12151F",
7260
+ stroke: "#3D4759"
7261
+ },
7262
+ client: {
7263
+ fill: "#1C2336",
7264
+ stroke: "#5B9BFF"
7265
+ },
7266
+ service: {
7267
+ fill: "#1C2336",
7268
+ stroke: "#38BDF8"
7269
+ },
7270
+ data: {
7271
+ fill: "#0F2D3A",
7272
+ stroke: "#2AD4B3"
7273
+ },
7274
+ messaging: {
7275
+ fill: "#2A2410",
7276
+ stroke: "#E8B93E"
7277
+ },
7278
+ neutral: {
7279
+ fill: "#1C2336",
7280
+ stroke: "#5B9BFF"
7281
+ }
7282
+ },
7283
+ edge: {
7284
+ stroke: "#5B9BFF",
7285
+ strokeWidth: 2.5,
7286
+ labelBackground: "#1E293B",
7287
+ labelText: "#E2E8F0",
7288
+ emphasizedStroke: "#5B9BFF",
7289
+ emphasizedStrokeWidth: 4
7290
+ }
7291
+ },
7292
+ "soft-pastel": {
7293
+ id: "soft-pastel",
7294
+ label: "Soft Pastel",
7295
+ description: "Dark cards, soft muted pastel-hued borders",
7296
+ mode: "dark",
7297
+ promptHint: "soft, pastel, gentle, muted, airy, whimsical",
7298
+ nodeText: "#F1F5F9",
7299
+ canvasText: "#A8C8E8",
7300
+ roles: {
7301
+ boundary: {
7302
+ fill: "#171B24",
7303
+ stroke: "#7C93B8"
7304
+ },
7305
+ client: {
7306
+ fill: "#1A2233",
7307
+ stroke: "#8FD9C4"
7308
+ },
7309
+ service: {
7310
+ fill: "#1A2233",
7311
+ stroke: "#93B8F0"
7312
+ },
7313
+ data: {
7314
+ fill: "#1F1A2E",
7315
+ stroke: "#E3A98C"
7316
+ },
7317
+ messaging: {
7318
+ fill: "#241F14",
7319
+ stroke: "#E8D48A"
7320
+ },
7321
+ neutral: {
7322
+ fill: "#1C2029",
7323
+ stroke: "#A8B3C4"
7324
+ }
7325
+ },
7326
+ edge: {
7327
+ stroke: "#8FA3C4",
7328
+ strokeWidth: 2,
7329
+ labelBackground: "#1E293B",
7330
+ labelText: "#E8EDF5",
7331
+ emphasizedStroke: "#8FD9C4",
7332
+ emphasizedStrokeWidth: 3.5
7333
+ }
7334
+ },
7335
+ monochrome: {
7336
+ id: "monochrome",
7337
+ label: "Monochrome",
7338
+ description: "Grayscale, roles differ by shade rather than hue",
7339
+ mode: "dark",
7340
+ promptHint: "monochrome, grayscale, black and white, minimal, neutral",
7341
+ nodeText: "#F3F4F6",
7342
+ canvasText: "#D1D5DB",
7343
+ roles: {
7344
+ boundary: {
7345
+ fill: "#17191D",
7346
+ stroke: "#4B5563"
7347
+ },
7348
+ client: {
7349
+ fill: "#23262B",
7350
+ stroke: "#9CA3AF"
7351
+ },
7352
+ service: {
7353
+ fill: "#1D2024",
7354
+ stroke: "#6B7280"
7355
+ },
7356
+ data: {
7357
+ fill: "#26292E",
7358
+ stroke: "#D1D5DB"
7359
+ },
7360
+ messaging: {
7361
+ fill: "#202225",
7362
+ stroke: "#4B5563"
7363
+ },
7364
+ neutral: {
7365
+ fill: "#1F2226",
7366
+ stroke: "#6B7280"
7367
+ }
7368
+ },
7369
+ edge: {
7370
+ stroke: "#9CA3AF",
7371
+ strokeWidth: 2,
7372
+ labelBackground: "#111318",
7373
+ labelText: "#E5E7EB",
7374
+ emphasizedStroke: "#F3F4F6",
7375
+ emphasizedStrokeWidth: 3.5
7376
+ }
7377
+ },
7378
+ "high-contrast": {
7379
+ id: "high-contrast",
7380
+ label: "High Contrast",
7381
+ description: "Maximum-contrast palette for accessibility or emphasis",
7382
+ mode: "dark",
7383
+ promptHint: "high contrast, accessible, accessibility, maximum contrast, bright neon",
7384
+ nodeText: "#000000",
7385
+ canvasText: "#FFFFFF",
7386
+ roles: {
7387
+ boundary: {
7388
+ fill: "#000000",
7389
+ stroke: "#FFFFFF"
7390
+ },
7391
+ client: {
7392
+ fill: "#FFD400",
7393
+ stroke: "#000000"
7394
+ },
7395
+ service: {
7396
+ fill: "#00E5FF",
7397
+ stroke: "#000000"
7398
+ },
7399
+ data: {
7400
+ fill: "#00FF85",
7401
+ stroke: "#000000"
7402
+ },
7403
+ messaging: {
7404
+ fill: "#FF6EC7",
7405
+ stroke: "#000000"
7406
+ },
7407
+ neutral: {
7408
+ fill: "#FFFFFF",
7409
+ stroke: "#000000"
7410
+ }
7411
+ },
7412
+ edge: {
7413
+ stroke: "#FFFFFF",
7414
+ strokeWidth: 2.5,
7415
+ labelBackground: "#000000",
7416
+ labelText: "#FFFFFF",
7417
+ emphasizedStroke: "#FFD400",
7418
+ emphasizedStrokeWidth: 4.5
7419
+ }
7420
+ },
7421
+ blueprint: {
7422
+ id: "blueprint",
7423
+ label: "Blueprint",
7424
+ description: "Monochrome technical blueprint — one blue hue, thin uniform lines, near-transparent fills",
7425
+ mode: "dark",
7426
+ promptHint: "blueprint, technical, monochrome blue, schematic, precise, no decorative color, engineering drawing",
7427
+ nodeText: "#CFE3F5",
7428
+ canvasText: "#5B8FBF",
7429
+ roles: {
7430
+ boundary: {
7431
+ fill: "#0B1929",
7432
+ stroke: "#3D6A94"
7433
+ },
7434
+ client: {
7435
+ fill: "#0E1D30",
7436
+ stroke: "#5B8FBF"
7437
+ },
7438
+ service: {
7439
+ fill: "#0E1D30",
7440
+ stroke: "#4A7BAA"
7441
+ },
7442
+ data: {
7443
+ fill: "#0E1D30",
7444
+ stroke: "#6FA8D6"
7445
+ },
7446
+ messaging: {
7447
+ fill: "#0E1D30",
7448
+ stroke: "#3D6A94"
7449
+ },
7450
+ neutral: {
7451
+ fill: "#0E1D30",
7452
+ stroke: "#4A7BAA"
7453
+ }
7454
+ },
7455
+ edge: {
7456
+ stroke: "#3D6A94",
7457
+ strokeWidth: 1,
7458
+ labelBackground: "#0B1929",
7459
+ labelText: "#CFE3F5",
7460
+ emphasizedStroke: "#6FA8D6",
7461
+ emphasizedStrokeWidth: 2
7462
+ }
7463
+ },
7464
+ ocean: {
7465
+ id: "ocean",
7466
+ label: "Ocean",
7467
+ description: "Cool dark blues and teals",
7468
+ mode: "dark",
7469
+ promptHint: "ocean, cool, blue, teal, calm water, deep sea",
7470
+ nodeText: "#EAF6FA",
7471
+ canvasText: "#7FD9EE",
7472
+ roles: {
7473
+ boundary: {
7474
+ fill: "#0B1F2A",
7475
+ stroke: "#2E5A6E"
7476
+ },
7477
+ client: {
7478
+ fill: "#0F2E3D",
7479
+ stroke: "#4FB8D6"
7480
+ },
7481
+ service: {
7482
+ fill: "#0F3A3A",
7483
+ stroke: "#35C7B0"
7484
+ },
7485
+ data: {
7486
+ fill: "#10293F",
7487
+ stroke: "#3B7DD8"
7488
+ },
7489
+ messaging: {
7490
+ fill: "#172B3D",
7491
+ stroke: "#6E93C7"
7492
+ },
7493
+ neutral: {
7494
+ fill: "#10222C",
7495
+ stroke: "#4FB8D6"
7496
+ }
7497
+ },
7498
+ edge: {
7499
+ stroke: "#4FB8D6",
7500
+ strokeWidth: 2,
7501
+ labelBackground: "#0B1F2A",
7502
+ labelText: "#DCEEF5",
7503
+ emphasizedStroke: "#35C7B0",
7504
+ emphasizedStrokeWidth: 3.5
7505
+ }
7506
+ }
7507
+ };
7508
+ function getTheme(themeId) {
7509
+ if (themeId && THEME_REGISTRY[themeId]) return THEME_REGISTRY[themeId];
7510
+ return THEME_REGISTRY[DEFAULT_THEME_ID];
7511
+ }
7512
+ function buildThemeCatalogPromptContext() {
7513
+ return Object.values(THEME_REGISTRY).map((t) => `- "${t.id}" (${t.mode}): ${t.description}. Matches requests like: ${t.promptHint}.`).join("\n");
7514
+ }
7515
+ export { AstToSqlGenerator, AstToUiConverter, BasicDetailsSchema, C4_COLORS, C4_LAYOUT, ComponentInputType, DEFAULT_THEME_ID, DialectIdSchema, DocumentCollectionSchema, DocumentIndexSchema, DynamoAttributeSchema, DynamoEditorSchema, DynamoGsiSchema, EditorSupportedDialectSchema, JsonEditorSchema, MongoCollectionSchema, MongoEditorSchema, MongoIndexFieldSchema, MongoIndexSchema, MongoNestedFieldSchema, NODE_TYPE_REGISTRY, NestedFieldSchema, NoSqlFieldSchema, SEQUENCE_LAYOUT, SHAPE_IDS, STROKE_STYLES, SqlToAstParser, THEME_REGISTRY, THEME_ROLES, buildMetaData, buildNodeStyleDataPatch, buildThemeCatalogPromptContext, computeDiagramSyncHash, contextSchema, convertC4MermaidToReactFlow, convertC4ToReactFlow, convertDynamoSchemaToAst, convertJsonSchemaToAst, convertMermaidToReactFlow, convertMermaidToReactFlowWithContext, convertMongoSchemaToAst, convertNoSQLToAst, convertReactFlowToC4Mermaid, convertReactFlowToC4UiGraph, convertReactFlowToSequenceMermaid, convertReactFlowToSequenceUiGraph, convertUiGraphToMermaid, estimateSequenceMessageBoxSize, flattenMetaData, generateTableNodeId, generateUUID, getC4ElementColors, getNodeTypeSpec, getTheme, isC4Diagram, isC4ReactFlowDiagram, isGeometryEditableNodeType, isSequenceDiagram, parseC4Diagram, sanitizeMermaidLabels, syncBaseData };