@statelyai/layout 0.1.3 → 0.3.0

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.
Files changed (85) hide show
  1. package/NOTICE.md +43 -0
  2. package/README.md +153 -6
  3. package/dist/elkjs/index.cjs +9 -0
  4. package/dist/elkjs/index.d.cts +155 -0
  5. package/dist/elkjs/index.d.mts +51 -39
  6. package/dist/elkjs/index.mjs +3 -1484
  7. package/dist/elkjs/main.cjs +17 -0
  8. package/dist/elkjs/main.d.cts +10 -0
  9. package/dist/elkjs/main.d.mts +11 -0
  10. package/dist/elkjs/main.mjs +17 -0
  11. package/dist/elkjs/worker-api.cjs +3 -0
  12. package/dist/elkjs/worker-api.d.cts +3 -0
  13. package/dist/elkjs/worker-api.d.mts +3 -0
  14. package/dist/elkjs/worker-api.mjs +3 -0
  15. package/dist/elkjs/worker.cjs +86 -0
  16. package/dist/elkjs/worker.d.cts +17 -0
  17. package/dist/elkjs/worker.d.mts +17 -0
  18. package/dist/elkjs/worker.mjs +86 -0
  19. package/dist/elkjs-DaHMISnQ.mjs +1677 -0
  20. package/dist/elkjs-dMghiiWW.cjs +1706 -0
  21. package/dist/index-BEA_pzeT.d.cts +72 -0
  22. package/dist/{index-8xYkohbz.d.mts → index-D9dhxrRl.d.cts} +111 -5
  23. package/dist/index-DNTLRsDl.d.mts +72 -0
  24. package/dist/index-DNixtE3h.d.mts +1318 -0
  25. package/dist/index.cjs +215 -0
  26. package/dist/index.d.cts +78 -0
  27. package/dist/index.d.mts +4 -3
  28. package/dist/index.mjs +25 -25
  29. package/dist/layered/index.cjs +38 -0
  30. package/dist/layered/index.d.cts +3 -0
  31. package/dist/layered/index.d.mts +3 -2
  32. package/dist/layered/index.mjs +1 -1
  33. package/dist/layered-B2buJqMf.cjs +12009 -0
  34. package/dist/{layered-CoeH9LRO.mjs → layered-DGFTeQSl.mjs} +2323 -149
  35. package/dist/{spore-BtTSZbb6.mjs → layout-engine-Cs5tatA6.mjs} +159 -5
  36. package/dist/layout-engine-Dn1PiFwP.cjs +712 -0
  37. package/dist/public-types-9NCPoqbp.d.mts +109 -0
  38. package/dist/public-types-BcRZoJE3.d.cts +109 -0
  39. package/dist/routing/index.cjs +28 -0
  40. package/dist/routing/index.d.cts +3 -0
  41. package/dist/routing/index.d.mts +3 -0
  42. package/dist/routing/index.mjs +3 -0
  43. package/dist/routing-A2hrK9MP.mjs +2396 -0
  44. package/dist/routing-ujEP7Qh6.cjs +2606 -0
  45. package/dist/types-CT2akdK0.d.mts +133 -0
  46. package/dist/types-uxPlGRof.d.cts +133 -0
  47. package/dist/worker-client-BNjwT1AJ.mjs +92 -0
  48. package/dist/worker-client-BwGGRD5y.d.mts +19 -0
  49. package/dist/worker-client-D4oEvhAl.cjs +98 -0
  50. package/dist/worker-client-D4zNyPEI.d.cts +19 -0
  51. package/package.json +45 -10
  52. package/src/authoring/coordinates.ts +114 -0
  53. package/src/authoring/partial.ts +584 -0
  54. package/src/authoring/routing.ts +211 -0
  55. package/src/box.ts +22 -0
  56. package/src/constraints.ts +222 -0
  57. package/src/elkjs/index.ts +104 -39
  58. package/src/elkjs/main.ts +19 -0
  59. package/src/elkjs/public-types.ts +125 -0
  60. package/src/elkjs/routes.ts +147 -0
  61. package/src/elkjs/worker-api.ts +29 -0
  62. package/src/elkjs/worker-client.ts +138 -0
  63. package/src/elkjs/worker.ts +117 -0
  64. package/src/index.ts +19 -0
  65. package/src/internal/elkjs-compatibility.ts +17 -0
  66. package/src/internal/layout-engine.ts +126 -0
  67. package/src/layered/compound.ts +417 -0
  68. package/src/layered/index.ts +58 -105
  69. package/src/layered/types.ts +21 -0
  70. package/src/layout.ts +35 -28
  71. package/src/packing.ts +22 -0
  72. package/src/random.ts +75 -3
  73. package/src/routing/adapters.ts +111 -0
  74. package/src/routing/algorithms.ts +676 -0
  75. package/src/routing/coordination.ts +86 -0
  76. package/src/routing/engine.ts +473 -0
  77. package/src/routing/index.ts +68 -0
  78. package/src/routing/layout-cache.ts +65 -0
  79. package/src/routing/model.ts +218 -0
  80. package/src/routing/path.ts +324 -0
  81. package/src/routing/persistent.ts +117 -0
  82. package/src/routing/search.ts +276 -0
  83. package/src/routing/spatial.ts +78 -0
  84. package/src/routing/types.ts +146 -0
  85. package/src/types.ts +17 -2
@@ -1,4 +1,4 @@
1
- import { F as placePorts, O as getPolylineMidpoint, z as JavaRandom } from "./layered-CoeH9LRO.mjs";
1
+ import { B as JavaRandom, I as placePorts, k as getPolylineMidpoint, n as layeredAlgorithm } from "./layered-DGFTeQSl.mjs";
2
2
  import { getNodeSize } from "@statelyai/graph/layout";
3
3
 
4
4
  //#region src/fixed.ts
@@ -68,6 +68,14 @@ const fixedAlgorithm = {
68
68
  }
69
69
  };
70
70
 
71
+ //#endregion
72
+ //#region src/internal/elkjs-compatibility.ts
73
+ const elkjs0111ResultPolicy = Symbol("elkjs0111ResultPolicy");
74
+ function setElkjs0111ResultPolicy(graph, policy) {
75
+ Object.defineProperty(graph, elkjs0111ResultPolicy, { value: policy });
76
+ return graph;
77
+ }
78
+
71
79
  //#endregion
72
80
  //#region src/box.ts
73
81
  function getPadding$3(value) {
@@ -193,6 +201,25 @@ const boxAlgorithm = {
193
201
  return getBoxLayout(graph, options ?? {});
194
202
  }
195
203
  };
204
+ /** Pinned behavior used only by the elkjs 0.11.1 compatibility adapter. */
205
+ const elkjs0111BoxAlgorithm = {
206
+ ...boxAlgorithm,
207
+ layout(graph, options = {}) {
208
+ const result = getBoxLayout(graph, options);
209
+ const padding = getPadding$3(options.padding);
210
+ return setElkjs0111ResultPolicy(result, {
211
+ providerBounds: result.nodes.length === 0 ? {
212
+ width: 0,
213
+ height: 0
214
+ } : {
215
+ width: Math.max(...result.nodes.map((node) => node.x + node.width)) + padding.right,
216
+ height: Math.max(...result.nodes.map((node) => node.y + node.height)) + padding.bottom
217
+ },
218
+ preserveEdgeSections: true,
219
+ skipBoundsNormalization: true
220
+ });
221
+ }
222
+ };
196
223
 
197
224
  //#endregion
198
225
  //#region src/packing.ts
@@ -259,9 +286,36 @@ const rectanglePackingAlgorithm = {
259
286
  return getRectanglePackingLayout(graph, options ?? {});
260
287
  }
261
288
  };
289
+ /** Pinned output policy used only by the elkjs 0.11.1 compatibility adapter. */
290
+ const elkjs0111RectanglePackingAlgorithm = {
291
+ ...rectanglePackingAlgorithm,
292
+ layout(graph, options = {}) {
293
+ const result = getRectanglePackingLayout(graph, options);
294
+ const padding = getPadding$2(options.padding);
295
+ return setElkjs0111ResultPolicy(result, {
296
+ providerBounds: result.nodes.length === 0 ? {
297
+ width: 0,
298
+ height: 0
299
+ } : {
300
+ width: Math.max(...result.nodes.map((node) => node.x + node.width)) + padding.right,
301
+ height: Math.max(...result.nodes.map((node) => node.y + node.height)) + padding.bottom
302
+ },
303
+ preserveEdgeSections: true,
304
+ skipBoundsNormalization: true
305
+ });
306
+ }
307
+ };
262
308
 
263
309
  //#endregion
264
310
  //#region src/random.ts
311
+ const nativeBehavior = {
312
+ elkjs0111EdgeTargetBug: false,
313
+ preserveProviderBounds: false
314
+ };
315
+ const elkjs0111Behavior = {
316
+ elkjs0111EdgeTargetBug: true,
317
+ preserveProviderBounds: true
318
+ };
265
319
  function getPadding$1(value) {
266
320
  if (typeof value === "number") return {
267
321
  top: value,
@@ -299,6 +353,9 @@ function borderPoint(source, target) {
299
353
  }
300
354
  /** Seeded random distribution using Java's 48-bit `Random` sequence. */
301
355
  function getRandomLayout(graph, options = {}) {
356
+ return getRandomLayoutWithBehavior(graph, options, nativeBehavior);
357
+ }
358
+ function getRandomLayoutWithBehavior(graph, options, behavior) {
302
359
  if (graph.nodes.length === 0) return getFixedLayout(graph, options);
303
360
  const random = new JavaRandom(options.seed && options.seed !== 0 ? options.seed : Date.now());
304
361
  const aspectRatio = Math.fround(options.aspectRatio ?? 1.6);
@@ -328,10 +385,49 @@ function getRandomLayout(graph, options = {}) {
328
385
  const nodeById = new Map(nodes.map((node) => [node.id, node]));
329
386
  const totalWidth = drawWidth + padding.left + padding.right;
330
387
  const totalHeight = drawHeight + padding.top + padding.bottom;
331
- const edges = graph.edges.map((edge) => {
388
+ const layoutEdge = (edge) => {
332
389
  const source = nodeById.get(edge.sourceId);
333
390
  const target = nodeById.get(edge.targetId);
334
391
  if (!source || !target) return edge;
392
+ if (behavior.elkjs0111EdgeTargetBug) {
393
+ const start$1 = {
394
+ x: source.x + source.width,
395
+ y: source.y + source.height / 2
396
+ };
397
+ const end$1 = {
398
+ x: source.x + source.width / 2,
399
+ y: source.y + source.height
400
+ };
401
+ const bendCount$1 = random.nextInt(5) + 1;
402
+ const xDifference = end$1.x - start$1.x;
403
+ const yDifference = end$1.y - start$1.y;
404
+ const maximumDeviation$1 = Math.hypot(xDifference, yDifference) * Math.fround(.2);
405
+ const xIncrement = xDifference / (bendCount$1 + 1);
406
+ const yIncrement = yDifference / (bendCount$1 + 1);
407
+ let x = start$1.x;
408
+ let y = start$1.y;
409
+ const points$1 = [start$1];
410
+ for (let index = 0; index < bendCount$1; index++) {
411
+ x += xIncrement;
412
+ y += yIncrement;
413
+ let randomX = x + random.nextFloat() * maximumDeviation$1 - maximumDeviation$1 / 2;
414
+ if (randomX < 0) randomX = 1;
415
+ else if (randomX > totalWidth) randomX = totalWidth - 1;
416
+ let randomY = y + random.nextFloat() * maximumDeviation$1 - maximumDeviation$1 / 2;
417
+ if (randomY < 0) randomY = 1;
418
+ else if (randomY > totalHeight) randomY = totalHeight - 1;
419
+ points$1.push({
420
+ x: randomX,
421
+ y: randomY
422
+ });
423
+ }
424
+ points$1.push(end$1);
425
+ return {
426
+ ...edge,
427
+ points: points$1,
428
+ routing: "polyline"
429
+ };
430
+ }
335
431
  const start = borderPoint(source, target);
336
432
  const end = borderPoint(target, source);
337
433
  const bendCount = random.nextInt(5) + (source === target ? 1 : 0);
@@ -350,12 +446,18 @@ function getRandomLayout(graph, options = {}) {
350
446
  points,
351
447
  routing: "polyline"
352
448
  };
353
- });
354
- return getFixedLayout({
449
+ };
450
+ const edges = behavior.elkjs0111EdgeTargetBug ? graph.nodes.flatMap((node) => graph.edges.filter((edge) => edge.sourceId === node.id).map(layoutEdge)) : graph.edges.map(layoutEdge);
451
+ const result = getFixedLayout({
355
452
  ...graph,
356
453
  nodes,
357
454
  edges
358
455
  }, { direction: options.direction ?? graph.direction });
456
+ if (behavior.preserveProviderBounds) setElkjs0111ResultPolicy(result, { providerBounds: {
457
+ width: drawWidth + 2 * (padding.left + padding.right),
458
+ height: drawHeight + 2 * (padding.top + padding.bottom)
459
+ } });
460
+ return result;
359
461
  }
360
462
  const randomAlgorithm = {
361
463
  id: "random",
@@ -371,6 +473,13 @@ const randomAlgorithm = {
371
473
  return getRandomLayout(graph, options ?? {});
372
474
  }
373
475
  };
476
+ /** Pinned behavior used only by the elkjs 0.11.1 compatibility adapter. */
477
+ const elkjs0111RandomAlgorithm = {
478
+ ...randomAlgorithm,
479
+ layout(graph, options) {
480
+ return getRandomLayoutWithBehavior(graph, options ?? {}, elkjs0111Behavior);
481
+ }
482
+ };
374
483
 
375
484
  //#endregion
376
485
  //#region src/spore.ts
@@ -454,4 +563,49 @@ const sporeCompactionAlgorithm = algorithm("sporeCompaction", true);
454
563
  const sporeOverlapRemovalAlgorithm = algorithm("sporeOverlap", false);
455
564
 
456
565
  //#endregion
457
- export { getRandomLayout as a, rectanglePackingAlgorithm as c, fixedAlgorithm as d, getFixedLayout as f, sporeOverlapRemovalAlgorithm as i, boxAlgorithm as l, getSporeOverlapRemovalLayout as n, randomAlgorithm as o, sporeCompactionAlgorithm as r, getRectanglePackingLayout as s, getSporeCompactionLayout as t, getBoxLayout as u };
566
+ //#region src/internal/layout-engine.ts
567
+ const builtInLayoutAlgorithms = {
568
+ box: boxAlgorithm,
569
+ fixed: fixedAlgorithm,
570
+ layered: layeredAlgorithm,
571
+ random: randomAlgorithm,
572
+ rectpacking: rectanglePackingAlgorithm,
573
+ sporeCompaction: sporeCompactionAlgorithm,
574
+ sporeOverlap: sporeOverlapRemovalAlgorithm
575
+ };
576
+ const elkjs0111LayoutAlgorithms = {
577
+ ...builtInLayoutAlgorithms,
578
+ box: elkjs0111BoxAlgorithm,
579
+ random: elkjs0111RandomAlgorithm,
580
+ rectpacking: elkjs0111RectanglePackingAlgorithm
581
+ };
582
+ function getBuiltInLayoutAlgorithm(id) {
583
+ if (!Object.hasOwn(builtInLayoutAlgorithms, id)) return void 0;
584
+ return builtInLayoutAlgorithms[id];
585
+ }
586
+ /** Execute one algorithm through the shared engine seam. */
587
+ function executeLayoutAlgorithm({ algorithm: algorithm$1, graph, options, context }) {
588
+ return algorithm$1.layout(graph, options, context);
589
+ }
590
+ function createDirectExecutionContext() {
591
+ return {
592
+ scope: { mode: "full" },
593
+ diagnostics: [],
594
+ measurePhase(_id, run) {
595
+ return run();
596
+ },
597
+ throwIfAborted() {}
598
+ };
599
+ }
600
+ /** Execute through the pinned elkjs 0.11.1 compatibility policy. */
601
+ function executeElkjs0111Layout({ algorithm: algorithm$1, graph, options }) {
602
+ return executeLayoutAlgorithm({
603
+ algorithm: elkjs0111LayoutAlgorithms[algorithm$1],
604
+ graph,
605
+ options,
606
+ context: createDirectExecutionContext()
607
+ });
608
+ }
609
+
610
+ //#endregion
611
+ export { getFixedLayout as _, getSporeCompactionLayout as a, sporeOverlapRemovalAlgorithm as c, getRectanglePackingLayout as d, rectanglePackingAlgorithm as f, fixedAlgorithm as g, elkjs0111ResultPolicy as h, getBuiltInLayoutAlgorithm as i, getRandomLayout as l, getBoxLayout as m, executeElkjs0111Layout as n, getSporeOverlapRemovalLayout as o, boxAlgorithm as p, executeLayoutAlgorithm as r, sporeCompactionAlgorithm as s, builtInLayoutAlgorithms as t, randomAlgorithm as u };