@synergenius/flow-weaver 0.4.0 → 0.4.2

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.
@@ -59713,6 +59713,8 @@ function buildDiagramGraph(ast, options = {}) {
59713
59713
  }
59714
59714
  }
59715
59715
  }
59716
+ let originX = 0;
59717
+ let originY = 0;
59716
59718
  let normalizedMaxY = maxY - minY + padding * 2;
59717
59719
  let normalizedMaxX = maxX - minX + padding * 2;
59718
59720
  const allConns = [...connections];
@@ -59723,11 +59725,15 @@ function buildDiagramGraph(ast, options = {}) {
59723
59725
  const extent = pathExtent(conn.path);
59724
59726
  if (extent.maxY + padding > normalizedMaxY) normalizedMaxY = extent.maxY + padding;
59725
59727
  if (extent.maxX + padding > normalizedMaxX) normalizedMaxX = extent.maxX + padding;
59728
+ if (extent.minY - padding < originY) originY = extent.minY - padding;
59729
+ if (extent.minX - padding < originX) originX = extent.minX - padding;
59726
59730
  }
59731
+ normalizedMaxX -= originX;
59732
+ normalizedMaxY -= originY;
59727
59733
  return {
59728
59734
  nodes,
59729
59735
  connections,
59730
- bounds: { width: normalizedMaxX, height: normalizedMaxY },
59736
+ bounds: { width: normalizedMaxX, height: normalizedMaxY, originX, originY },
59731
59737
  workflowName: ast.name
59732
59738
  };
59733
59739
  }
@@ -59765,15 +59771,19 @@ function resolveDefaultIcon(nt) {
59765
59771
  return "code";
59766
59772
  }
59767
59773
  function pathExtent(path38) {
59768
- let maxX = -Infinity;
59769
- let maxY = -Infinity;
59774
+ let minX = Infinity, minY = Infinity;
59775
+ let maxX = -Infinity, maxY = -Infinity;
59770
59776
  const pattern = /(-?[\d.]+),(-?[\d.]+)/g;
59771
59777
  let m;
59772
59778
  while ((m = pattern.exec(path38)) !== null) {
59773
- maxX = Math.max(maxX, parseFloat(m[1]));
59774
- maxY = Math.max(maxY, parseFloat(m[2]));
59779
+ const x = parseFloat(m[1]);
59780
+ const y = parseFloat(m[2]);
59781
+ minX = Math.min(minX, x);
59782
+ minY = Math.min(minY, y);
59783
+ maxX = Math.max(maxX, x);
59784
+ maxY = Math.max(maxY, y);
59775
59785
  }
59776
- return { maxX, maxY };
59786
+ return { minX, minY, maxX, maxY };
59777
59787
  }
59778
59788
  function maxPortLabelExtent(ports) {
59779
59789
  if (ports.length === 0) return 0;
@@ -59804,7 +59814,9 @@ function renderSVG(graph, options = {}) {
59804
59814
  const themeName = options.theme ?? "dark";
59805
59815
  const theme = getTheme(themeName);
59806
59816
  const showPortLabels = options.showPortLabels ?? true;
59807
- let { width: vbWidth, height: vbHeight } = graph.bounds;
59817
+ let { width: vbWidth, height: vbHeight, originX: vbX, originY: vbY } = graph.bounds;
59818
+ vbX = vbX ?? 0;
59819
+ vbY = vbY ?? 0;
59808
59820
  vbWidth = Math.max(vbWidth, 200);
59809
59821
  vbHeight = Math.max(vbHeight, 100);
59810
59822
  const svgWidth = options.width || vbWidth;
@@ -59812,7 +59824,7 @@ function renderSVG(graph, options = {}) {
59812
59824
  const allConnections = collectAllConnections(graph);
59813
59825
  const parts2 = [];
59814
59826
  parts2.push(
59815
- `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${vbWidth} ${vbHeight}" width="${svgWidth}" height="${svgHeight}">`
59827
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${vbX} ${vbY} ${vbWidth} ${vbHeight}" width="${svgWidth}" height="${svgHeight}">`
59816
59828
  );
59817
59829
  parts2.push(`<style>`);
59818
59830
  parts2.push(` text { font-family: Montserrat, 'Segoe UI', Roboto, sans-serif; }`);
@@ -60065,7 +60077,7 @@ body {
60065
60077
  body.node-active .connections path.dimmed { opacity: 0.15; }
60066
60078
 
60067
60079
  /* Node hover glow */
60068
- .nodes > g:hover rect:first-of-type { filter: brightness(1.08); }
60080
+ .nodes g[data-node-id]:hover > rect:first-of-type { filter: brightness(1.08); }
60069
60081
 
60070
60082
  /* Zoom controls */
60071
60083
  #controls {
@@ -60260,27 +60272,38 @@ body.node-active .connections path.dimmed { opacity: 0.15; }
60260
60272
 
60261
60273
  // ---- Port label visibility via JS (since CSS sibling selectors can't reach .labels group) ----
60262
60274
  var labelEls = content.querySelectorAll('.labels g[data-port-label]');
60263
- var nodeEls = content.querySelectorAll('.nodes > g[data-node-id]');
60275
+ var nodeEls = content.querySelectorAll('.nodes g[data-node-id]');
60276
+
60277
+ function showLabelsFor(id) {
60278
+ labelEls.forEach(function(lbl) {
60279
+ var portId = lbl.getAttribute('data-port-label') || '';
60280
+ if (portId.indexOf(id + '.') === 0) {
60281
+ lbl.style.opacity = '1';
60282
+ lbl.style.pointerEvents = 'auto';
60283
+ }
60284
+ });
60285
+ }
60286
+ function hideLabelsFor(id) {
60287
+ labelEls.forEach(function(lbl) {
60288
+ var portId = lbl.getAttribute('data-port-label') || '';
60289
+ if (portId.indexOf(id + '.') === 0) {
60290
+ lbl.style.opacity = '0';
60291
+ lbl.style.pointerEvents = 'none';
60292
+ }
60293
+ });
60294
+ }
60264
60295
 
60265
60296
  nodeEls.forEach(function(nodeG) {
60266
60297
  var nodeId = nodeG.getAttribute('data-node-id');
60298
+ var parentNodeG = nodeG.parentElement ? nodeG.parentElement.closest('g[data-node-id]') : null;
60299
+ var parentId = parentNodeG ? parentNodeG.getAttribute('data-node-id') : null;
60267
60300
  nodeG.addEventListener('mouseenter', function() {
60268
- labelEls.forEach(function(lbl) {
60269
- var portId = lbl.getAttribute('data-port-label') || '';
60270
- if (portId.indexOf(nodeId + '.') === 0) {
60271
- lbl.style.opacity = '1';
60272
- lbl.style.pointerEvents = 'auto';
60273
- }
60274
- });
60301
+ if (parentId) hideLabelsFor(parentId);
60302
+ showLabelsFor(nodeId);
60275
60303
  });
60276
60304
  nodeG.addEventListener('mouseleave', function() {
60277
- labelEls.forEach(function(lbl) {
60278
- var portId = lbl.getAttribute('data-port-label') || '';
60279
- if (portId.indexOf(nodeId + '.') === 0) {
60280
- lbl.style.opacity = '0';
60281
- lbl.style.pointerEvents = 'none';
60282
- }
60283
- });
60305
+ hideLabelsFor(nodeId);
60306
+ if (parentId) showLabelsFor(parentId);
60284
60307
  });
60285
60308
  });
60286
60309
 
@@ -94412,7 +94435,7 @@ function displayInstalledPackage(pkg) {
94412
94435
  }
94413
94436
 
94414
94437
  // src/cli/index.ts
94415
- var version2 = true ? "0.4.0" : "0.0.0-dev";
94438
+ var version2 = true ? "0.4.2" : "0.0.0-dev";
94416
94439
  var program2 = new Command();
94417
94440
  program2.name("flow-weaver").description("Flow Weaver Annotations - Compile and validate workflow files").version(version2, "-v, --version", "Output the current version");
94418
94441
  program2.configureOutput({
@@ -982,7 +982,9 @@ export function buildDiagramGraph(ast, options = {}) {
982
982
  }
983
983
  }
984
984
  }
985
- // Extend bounds to include connection paths (orthogonal routes can go outside node area)
985
+ // Extend bounds to include connection paths (routes can go outside node area)
986
+ let originX = 0;
987
+ let originY = 0;
986
988
  let normalizedMaxY = (maxY - minY) + padding * 2;
987
989
  let normalizedMaxX = (maxX - minX) + padding * 2;
988
990
  const allConns = [...connections];
@@ -996,11 +998,18 @@ export function buildDiagramGraph(ast, options = {}) {
996
998
  normalizedMaxY = extent.maxY + padding;
997
999
  if (extent.maxX + padding > normalizedMaxX)
998
1000
  normalizedMaxX = extent.maxX + padding;
1001
+ if (extent.minY - padding < originY)
1002
+ originY = extent.minY - padding;
1003
+ if (extent.minX - padding < originX)
1004
+ originX = extent.minX - padding;
999
1005
  }
1006
+ // Expand dimensions to cover the shifted origin
1007
+ normalizedMaxX -= originX;
1008
+ normalizedMaxY -= originY;
1000
1009
  return {
1001
1010
  nodes,
1002
1011
  connections,
1003
- bounds: { width: normalizedMaxX, height: normalizedMaxY },
1012
+ bounds: { width: normalizedMaxX, height: normalizedMaxY, originX, originY },
1004
1013
  workflowName: ast.name,
1005
1014
  };
1006
1015
  }
@@ -1052,17 +1061,21 @@ function resolveDefaultIcon(nt) {
1052
1061
  return 'flow';
1053
1062
  return 'code';
1054
1063
  }
1055
- /** Extract max X/Y extent from an SVG path string (for bounds calculation) */
1064
+ /** Extract min/max X/Y extent from an SVG path string (for bounds calculation) */
1056
1065
  function pathExtent(path) {
1057
- let maxX = -Infinity;
1058
- let maxY = -Infinity;
1066
+ let minX = Infinity, minY = Infinity;
1067
+ let maxX = -Infinity, maxY = -Infinity;
1059
1068
  const pattern = /(-?[\d.]+),(-?[\d.]+)/g;
1060
1069
  let m;
1061
1070
  while ((m = pattern.exec(path)) !== null) {
1062
- maxX = Math.max(maxX, parseFloat(m[1]));
1063
- maxY = Math.max(maxY, parseFloat(m[2]));
1071
+ const x = parseFloat(m[1]);
1072
+ const y = parseFloat(m[2]);
1073
+ minX = Math.min(minX, x);
1074
+ minY = Math.min(minY, y);
1075
+ maxX = Math.max(maxX, x);
1076
+ maxY = Math.max(maxY, y);
1064
1077
  }
1065
- return { maxX, maxY };
1078
+ return { minX, minY, maxX, maxY };
1066
1079
  }
1067
1080
  /** Estimate the maximum port label badge extent beyond the node edge */
1068
1081
  function maxPortLabelExtent(ports) {
@@ -73,7 +73,7 @@ body {
73
73
  body.node-active .connections path.dimmed { opacity: 0.15; }
74
74
 
75
75
  /* Node hover glow */
76
- .nodes > g:hover rect:first-of-type { filter: brightness(1.08); }
76
+ .nodes g[data-node-id]:hover > rect:first-of-type { filter: brightness(1.08); }
77
77
 
78
78
  /* Zoom controls */
79
79
  #controls {
@@ -268,27 +268,38 @@ body.node-active .connections path.dimmed { opacity: 0.15; }
268
268
 
269
269
  // ---- Port label visibility via JS (since CSS sibling selectors can't reach .labels group) ----
270
270
  var labelEls = content.querySelectorAll('.labels g[data-port-label]');
271
- var nodeEls = content.querySelectorAll('.nodes > g[data-node-id]');
271
+ var nodeEls = content.querySelectorAll('.nodes g[data-node-id]');
272
+
273
+ function showLabelsFor(id) {
274
+ labelEls.forEach(function(lbl) {
275
+ var portId = lbl.getAttribute('data-port-label') || '';
276
+ if (portId.indexOf(id + '.') === 0) {
277
+ lbl.style.opacity = '1';
278
+ lbl.style.pointerEvents = 'auto';
279
+ }
280
+ });
281
+ }
282
+ function hideLabelsFor(id) {
283
+ labelEls.forEach(function(lbl) {
284
+ var portId = lbl.getAttribute('data-port-label') || '';
285
+ if (portId.indexOf(id + '.') === 0) {
286
+ lbl.style.opacity = '0';
287
+ lbl.style.pointerEvents = 'none';
288
+ }
289
+ });
290
+ }
272
291
 
273
292
  nodeEls.forEach(function(nodeG) {
274
293
  var nodeId = nodeG.getAttribute('data-node-id');
294
+ var parentNodeG = nodeG.parentElement ? nodeG.parentElement.closest('g[data-node-id]') : null;
295
+ var parentId = parentNodeG ? parentNodeG.getAttribute('data-node-id') : null;
275
296
  nodeG.addEventListener('mouseenter', function() {
276
- labelEls.forEach(function(lbl) {
277
- var portId = lbl.getAttribute('data-port-label') || '';
278
- if (portId.indexOf(nodeId + '.') === 0) {
279
- lbl.style.opacity = '1';
280
- lbl.style.pointerEvents = 'auto';
281
- }
282
- });
297
+ if (parentId) hideLabelsFor(parentId);
298
+ showLabelsFor(nodeId);
283
299
  });
284
300
  nodeG.addEventListener('mouseleave', function() {
285
- labelEls.forEach(function(lbl) {
286
- var portId = lbl.getAttribute('data-port-label') || '';
287
- if (portId.indexOf(nodeId + '.') === 0) {
288
- lbl.style.opacity = '0';
289
- lbl.style.pointerEvents = 'none';
290
- }
291
- });
301
+ hideLabelsFor(nodeId);
302
+ if (parentId) showLabelsFor(parentId);
292
303
  });
293
304
  });
294
305
 
@@ -17,7 +17,9 @@ export function renderSVG(graph, options = {}) {
17
17
  const themeName = options.theme ?? 'dark';
18
18
  const theme = getTheme(themeName);
19
19
  const showPortLabels = options.showPortLabels ?? true;
20
- let { width: vbWidth, height: vbHeight } = graph.bounds;
20
+ let { width: vbWidth, height: vbHeight, originX: vbX, originY: vbY } = graph.bounds;
21
+ vbX = vbX ?? 0;
22
+ vbY = vbY ?? 0;
21
23
  // Ensure minimum bounds
22
24
  vbWidth = Math.max(vbWidth, 200);
23
25
  vbHeight = Math.max(vbHeight, 100);
@@ -27,7 +29,7 @@ export function renderSVG(graph, options = {}) {
27
29
  const allConnections = collectAllConnections(graph);
28
30
  const parts = [];
29
31
  // SVG open
30
- parts.push(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${vbWidth} ${vbHeight}" width="${svgWidth}" height="${svgHeight}">`);
32
+ parts.push(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${vbX} ${vbY} ${vbWidth} ${vbHeight}" width="${svgWidth}" height="${svgHeight}">`);
31
33
  // Styles
32
34
  parts.push(`<style>`);
33
35
  parts.push(` text { font-family: Montserrat, 'Segoe UI', Roboto, sans-serif; }`);
@@ -52,6 +52,8 @@ export interface DiagramGraph {
52
52
  bounds: {
53
53
  width: number;
54
54
  height: number;
55
+ originX?: number;
56
+ originY?: number;
55
57
  };
56
58
  workflowName: string;
57
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flow-weaver",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Deterministic workflow compiler for AI agents. Compiles to standalone TypeScript, no runtime dependencies.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -30,6 +30,42 @@
30
30
  "./doc-metadata": {
31
31
  "types": "./dist/doc-metadata/index.d.ts",
32
32
  "default": "./dist/doc-metadata/index.js"
33
+ },
34
+ "./ast": {
35
+ "types": "./dist/ast/index.d.ts",
36
+ "default": "./dist/ast/index.js"
37
+ },
38
+ "./api": {
39
+ "types": "./dist/api/index.d.ts",
40
+ "default": "./dist/api/index.js"
41
+ },
42
+ "./diff": {
43
+ "types": "./dist/diff/index.d.ts",
44
+ "default": "./dist/diff/index.js"
45
+ },
46
+ "./editor": {
47
+ "types": "./dist/editor-completions/index.d.ts",
48
+ "default": "./dist/editor-completions/index.js"
49
+ },
50
+ "./browser": {
51
+ "types": "./dist/jsdoc-port-sync/index.d.ts",
52
+ "default": "./dist/jsdoc-port-sync/index.js"
53
+ },
54
+ "./generated-branding": {
55
+ "types": "./dist/generated-branding.d.ts",
56
+ "default": "./dist/generated-branding.js"
57
+ },
58
+ "./npm-packages": {
59
+ "types": "./dist/npm-packages.d.ts",
60
+ "default": "./dist/npm-packages.js"
61
+ },
62
+ "./deployment": {
63
+ "types": "./dist/deployment/index.d.ts",
64
+ "default": "./dist/deployment/index.js"
65
+ },
66
+ "./marketplace": {
67
+ "types": "./dist/marketplace/index.d.ts",
68
+ "default": "./dist/marketplace/index.js"
33
69
  }
34
70
  },
35
71
  "bin": {
@@ -59,8 +95,8 @@
59
95
  "typecheck": "tsc --noEmit -p tsconfig.build.json",
60
96
  "docs": "typedoc && tsx scripts/generate-grammar-docs.ts",
61
97
  "docs:serve": "npm run docs && npx http-server docs/api -c-1 -o",
62
- "prepublishOnly": "npm run build",
63
- "cli": "ts-node src/cli/index.ts"
98
+ "prepare": "npm run build",
99
+ "cli": "tsx src/cli/index.ts"
64
100
  },
65
101
  "keywords": [
66
102
  "flow-weaver",