@html-graph/html-graph 0.0.44 → 0.0.46
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/README.md +2 -2
- package/dist/main.d.ts +11 -11
- package/dist/main.js +220 -220
- package/dist/main.umd.cjs +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -33,9 +33,9 @@ npm i @html-graph/html-graph
|
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
```typescript
|
|
36
|
-
import { MarkPortRequest,
|
|
36
|
+
import { MarkPortRequest, HtmlGraphBuilder } from "@html-graph/html-graph";
|
|
37
37
|
|
|
38
|
-
const canvas = new
|
|
38
|
+
const canvas = new HtmlGraphBuilder()
|
|
39
39
|
.setOptions({
|
|
40
40
|
background: { type: "dots" },
|
|
41
41
|
connections: { hasTargetArrow: true },
|
package/dist/main.d.ts
CHANGED
|
@@ -179,17 +179,6 @@ export declare interface Canvas {
|
|
|
179
179
|
destroy(): void;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
export declare class CanvasBuilder {
|
|
183
|
-
private coreOptions;
|
|
184
|
-
private transformOptions;
|
|
185
|
-
private isDraggable;
|
|
186
|
-
private isTransformable;
|
|
187
|
-
setOptions(options: CoreOptions): CanvasBuilder;
|
|
188
|
-
setDraggableNodes(): CanvasBuilder;
|
|
189
|
-
setTransformableCanvas(options?: TransformOptions): CanvasBuilder;
|
|
190
|
-
build(): Canvas;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
182
|
/**
|
|
194
183
|
* Provides core API for acting on graph
|
|
195
184
|
*/
|
|
@@ -391,6 +380,17 @@ declare class GraphStore {
|
|
|
391
380
|
clear(): void;
|
|
392
381
|
}
|
|
393
382
|
|
|
383
|
+
export declare class HtmlGraphBuilder {
|
|
384
|
+
private coreOptions;
|
|
385
|
+
private transformOptions;
|
|
386
|
+
private isDraggable;
|
|
387
|
+
private isTransformable;
|
|
388
|
+
setOptions(options: CoreOptions): HtmlGraphBuilder;
|
|
389
|
+
setDraggableNodes(): HtmlGraphBuilder;
|
|
390
|
+
setTransformableCanvas(options?: TransformOptions): HtmlGraphBuilder;
|
|
391
|
+
build(): Canvas;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
394
|
declare type LayersMode = "connections-on-top" | "nodes-on-top" | "connections-follow-node";
|
|
395
395
|
|
|
396
396
|
export declare type MarkPortRequest = HTMLElement | {
|
package/dist/main.js
CHANGED
|
@@ -290,6 +290,213 @@ class D {
|
|
|
290
290
|
return this.transformer.getAbsScale();
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
|
+
class R {
|
|
294
|
+
constructor() {
|
|
295
|
+
r(this, "nodes", /* @__PURE__ */ Object.create(null));
|
|
296
|
+
r(this, "ports", /* @__PURE__ */ Object.create(null));
|
|
297
|
+
r(this, "nodePorts", /* @__PURE__ */ Object.create(null));
|
|
298
|
+
r(this, "portNodeId", /* @__PURE__ */ Object.create(null));
|
|
299
|
+
r(this, "connections", /* @__PURE__ */ Object.create(null));
|
|
300
|
+
r(this, "incommingConnections", /* @__PURE__ */ Object.create(null));
|
|
301
|
+
r(this, "outcommingConnections", /* @__PURE__ */ Object.create(null));
|
|
302
|
+
r(this, "cycleConnections", /* @__PURE__ */ Object.create(null));
|
|
303
|
+
}
|
|
304
|
+
getAllNodes() {
|
|
305
|
+
return Object.keys(this.nodes);
|
|
306
|
+
}
|
|
307
|
+
getAllPorts() {
|
|
308
|
+
return Object.keys(this.ports);
|
|
309
|
+
}
|
|
310
|
+
getAllConnections() {
|
|
311
|
+
return Object.keys(this.connections);
|
|
312
|
+
}
|
|
313
|
+
addNode(t, e, o, s, i) {
|
|
314
|
+
this.nodes[t] = { element: e, x: o, y: s, centerFn: i }, this.nodePorts[t] = /* @__PURE__ */ Object.create(null);
|
|
315
|
+
}
|
|
316
|
+
hasNode(t) {
|
|
317
|
+
return this.nodes[t] !== void 0;
|
|
318
|
+
}
|
|
319
|
+
getNode(t) {
|
|
320
|
+
return this.nodes[t];
|
|
321
|
+
}
|
|
322
|
+
updateNodeCoords(t, e, o) {
|
|
323
|
+
this.nodes[t].x = e, this.nodes[t].y = o;
|
|
324
|
+
}
|
|
325
|
+
updateConnectionController(t, e) {
|
|
326
|
+
this.connections[t].controller = e;
|
|
327
|
+
}
|
|
328
|
+
removeNode(t) {
|
|
329
|
+
this.getNodeAdjacentConnections(t).forEach((s) => {
|
|
330
|
+
this.removeConnection(s);
|
|
331
|
+
}), delete this.nodes[t];
|
|
332
|
+
const o = this.nodePorts[t];
|
|
333
|
+
Object.keys(o).forEach((s) => {
|
|
334
|
+
delete this.portNodeId[s];
|
|
335
|
+
}), delete this.nodePorts[t];
|
|
336
|
+
}
|
|
337
|
+
addPort(t, e, o, s, i) {
|
|
338
|
+
this.ports[t] = { element: e, centerFn: s, direction: i }, this.cycleConnections[t] = {}, this.incommingConnections[t] = {}, this.outcommingConnections[t] = {}, this.portNodeId[t] = o;
|
|
339
|
+
const c = this.nodePorts[o];
|
|
340
|
+
c !== void 0 && (c[t] = e);
|
|
341
|
+
}
|
|
342
|
+
getPort(t) {
|
|
343
|
+
return this.ports[t];
|
|
344
|
+
}
|
|
345
|
+
getPortNode(t) {
|
|
346
|
+
return this.portNodeId[t];
|
|
347
|
+
}
|
|
348
|
+
hasPort(t) {
|
|
349
|
+
return this.portNodeId[t] !== void 0;
|
|
350
|
+
}
|
|
351
|
+
removePort(t) {
|
|
352
|
+
Object.keys(this.cycleConnections[t]).forEach((s) => {
|
|
353
|
+
this.removeConnection(s);
|
|
354
|
+
}), delete this.cycleConnections[t], Object.keys(this.incommingConnections[t]).forEach((s) => {
|
|
355
|
+
this.removeConnection(s);
|
|
356
|
+
}), delete this.incommingConnections[t], Object.keys(this.outcommingConnections[t]).forEach((s) => {
|
|
357
|
+
this.removeConnection(s);
|
|
358
|
+
}), delete this.outcommingConnections[t];
|
|
359
|
+
const e = this.portNodeId[t];
|
|
360
|
+
delete this.portNodeId[t];
|
|
361
|
+
const o = this.nodePorts[e];
|
|
362
|
+
delete o[t], delete this.ports[t];
|
|
363
|
+
}
|
|
364
|
+
addConnection(t, e, o, s) {
|
|
365
|
+
this.connections[t] = {
|
|
366
|
+
from: e,
|
|
367
|
+
to: o,
|
|
368
|
+
controller: s
|
|
369
|
+
}, e !== o ? (this.outcommingConnections[e][t] = !0, this.incommingConnections[o][t] = !0) : this.cycleConnections[e][t] = !0;
|
|
370
|
+
}
|
|
371
|
+
getConnection(t) {
|
|
372
|
+
return this.connections[t];
|
|
373
|
+
}
|
|
374
|
+
hasConnection(t) {
|
|
375
|
+
return this.connections[t] !== void 0;
|
|
376
|
+
}
|
|
377
|
+
removeConnection(t) {
|
|
378
|
+
const e = this.connections[t], o = e.from, s = e.to;
|
|
379
|
+
delete this.cycleConnections[o][t], delete this.cycleConnections[s][t], delete this.incommingConnections[o][t], delete this.incommingConnections[s][t], delete this.outcommingConnections[o][t], delete this.outcommingConnections[s][t], delete this.connections[t];
|
|
380
|
+
}
|
|
381
|
+
getPortIncomingConnections(t) {
|
|
382
|
+
return Object.keys(this.incommingConnections[t] ?? {});
|
|
383
|
+
}
|
|
384
|
+
getPortOutcomingConnections(t) {
|
|
385
|
+
return Object.keys(this.outcommingConnections[t] ?? {});
|
|
386
|
+
}
|
|
387
|
+
getPortCycleConnections(t) {
|
|
388
|
+
return Object.keys(this.cycleConnections[t] ?? {});
|
|
389
|
+
}
|
|
390
|
+
getPortAdjacentConnections(t) {
|
|
391
|
+
return [
|
|
392
|
+
...this.getPortIncomingConnections(t),
|
|
393
|
+
...this.getPortOutcomingConnections(t),
|
|
394
|
+
...this.getPortCycleConnections(t)
|
|
395
|
+
];
|
|
396
|
+
}
|
|
397
|
+
getNodeIncomingConnections(t) {
|
|
398
|
+
const e = Object.keys(this.nodePorts[t]);
|
|
399
|
+
let o = [];
|
|
400
|
+
return e.forEach((s) => {
|
|
401
|
+
o = [...o, ...this.getPortIncomingConnections(s)];
|
|
402
|
+
}), o;
|
|
403
|
+
}
|
|
404
|
+
getNodeOutcomingConnections(t) {
|
|
405
|
+
const e = Object.keys(this.nodePorts[t]);
|
|
406
|
+
let o = [];
|
|
407
|
+
return e.forEach((s) => {
|
|
408
|
+
o = [...o, ...this.getPortOutcomingConnections(s)];
|
|
409
|
+
}), o;
|
|
410
|
+
}
|
|
411
|
+
getNodeCycleConnections(t) {
|
|
412
|
+
const e = Object.keys(this.nodePorts[t]);
|
|
413
|
+
let o = [];
|
|
414
|
+
return e.forEach((s) => {
|
|
415
|
+
o = [...o, ...this.getPortCycleConnections(s)];
|
|
416
|
+
}), o;
|
|
417
|
+
}
|
|
418
|
+
getNodeAdjacentConnections(t) {
|
|
419
|
+
return [
|
|
420
|
+
...this.getNodeIncomingConnections(t),
|
|
421
|
+
...this.getNodeOutcomingConnections(t),
|
|
422
|
+
...this.getNodeCycleConnections(t)
|
|
423
|
+
];
|
|
424
|
+
}
|
|
425
|
+
clear() {
|
|
426
|
+
this.nodes = /* @__PURE__ */ Object.create(null), this.ports = /* @__PURE__ */ Object.create(null), this.nodePorts = /* @__PURE__ */ Object.create(null), this.portNodeId = /* @__PURE__ */ Object.create(null), this.connections = /* @__PURE__ */ Object.create(null), this.incommingConnections = /* @__PURE__ */ Object.create(null), this.outcommingConnections = /* @__PURE__ */ Object.create(null), this.cycleConnections = /* @__PURE__ */ Object.create(null);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
class z {
|
|
430
|
+
constructor(t) {
|
|
431
|
+
this.graphStore = t;
|
|
432
|
+
}
|
|
433
|
+
getNode(t) {
|
|
434
|
+
const e = this.graphStore.getNode(t);
|
|
435
|
+
return e === void 0 ? null : { x: e.x, y: e.y };
|
|
436
|
+
}
|
|
437
|
+
getPort(t) {
|
|
438
|
+
const e = this.graphStore.getPortNode(t);
|
|
439
|
+
return e === void 0 ? null : { nodeId: e };
|
|
440
|
+
}
|
|
441
|
+
getConnection(t) {
|
|
442
|
+
const e = this.graphStore.getConnection(t);
|
|
443
|
+
return e === void 0 ? null : { from: e.from, to: e.to };
|
|
444
|
+
}
|
|
445
|
+
getAllNodes() {
|
|
446
|
+
return this.graphStore.getAllNodes();
|
|
447
|
+
}
|
|
448
|
+
getAllPorts() {
|
|
449
|
+
return this.graphStore.getAllPorts();
|
|
450
|
+
}
|
|
451
|
+
getAllConnections() {
|
|
452
|
+
return this.graphStore.getAllConnections();
|
|
453
|
+
}
|
|
454
|
+
hasNode(t) {
|
|
455
|
+
return this.graphStore.hasNode(t);
|
|
456
|
+
}
|
|
457
|
+
hasPort(t) {
|
|
458
|
+
return this.graphStore.hasPort(t);
|
|
459
|
+
}
|
|
460
|
+
hasConnection(t) {
|
|
461
|
+
return this.graphStore.hasConnection(t);
|
|
462
|
+
}
|
|
463
|
+
getPortIncomingConnections(t) {
|
|
464
|
+
return this.graphStore.getPortIncomingConnections(t);
|
|
465
|
+
}
|
|
466
|
+
getPortOutcomingConnections(t) {
|
|
467
|
+
return this.graphStore.getPortOutcomingConnections(t);
|
|
468
|
+
}
|
|
469
|
+
getPortCycleConnections(t) {
|
|
470
|
+
return this.graphStore.getPortCycleConnections(t);
|
|
471
|
+
}
|
|
472
|
+
getPortAdjacentConnections(t) {
|
|
473
|
+
return this.graphStore.getPortAdjacentConnections(t);
|
|
474
|
+
}
|
|
475
|
+
getNodeIncomingConnections(t) {
|
|
476
|
+
return this.graphStore.getNodeIncomingConnections(t);
|
|
477
|
+
}
|
|
478
|
+
getNodeOutcomingConnections(t) {
|
|
479
|
+
return this.graphStore.getNodeOutcomingConnections(t);
|
|
480
|
+
}
|
|
481
|
+
getNodeCycleConnections(t) {
|
|
482
|
+
return this.graphStore.getNodeCycleConnections(t);
|
|
483
|
+
}
|
|
484
|
+
getNodeAdjacentConnections(t) {
|
|
485
|
+
return this.graphStore.getNodeAdjacentConnections(t);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
class A {
|
|
489
|
+
constructor() {
|
|
490
|
+
r(this, "counter", 0);
|
|
491
|
+
}
|
|
492
|
+
next() {
|
|
493
|
+
const t = `${this.counter}`;
|
|
494
|
+
return this.counter++, t;
|
|
495
|
+
}
|
|
496
|
+
reset() {
|
|
497
|
+
this.counter = 0;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
293
500
|
class C {
|
|
294
501
|
static getPortCenter(t) {
|
|
295
502
|
const { top: e, left: o, width: s, height: i } = t.element.getBoundingClientRect(), c = t.centerFn(s, i);
|
|
@@ -320,7 +527,7 @@ class C {
|
|
|
320
527
|
return `M ${a[0][0]} ${a[0][1]} L ${a[1][0]} ${a[1][1]}`;
|
|
321
528
|
}
|
|
322
529
|
}
|
|
323
|
-
class
|
|
530
|
+
class G {
|
|
324
531
|
constructor(t, e, o, s, i, c, a) {
|
|
325
532
|
r(this, "svg");
|
|
326
533
|
r(this, "group");
|
|
@@ -384,7 +591,7 @@ class R {
|
|
|
384
591
|
}
|
|
385
592
|
}
|
|
386
593
|
}
|
|
387
|
-
const
|
|
594
|
+
const B = (n) => () => new G(
|
|
388
595
|
n.color ?? "#5c5c5c",
|
|
389
596
|
n.width ?? 1,
|
|
390
597
|
n.curvature ?? 90,
|
|
@@ -393,7 +600,7 @@ const z = (n) => () => new R(
|
|
|
393
600
|
n.hasSourceArrow ?? !1,
|
|
394
601
|
n.hasTargetArrow ?? !1
|
|
395
602
|
);
|
|
396
|
-
class
|
|
603
|
+
class Y {
|
|
397
604
|
constructor(t, e, o, s, i, c, a) {
|
|
398
605
|
r(this, "svg");
|
|
399
606
|
r(this, "group");
|
|
@@ -463,7 +670,7 @@ class G {
|
|
|
463
670
|
}
|
|
464
671
|
}
|
|
465
672
|
}
|
|
466
|
-
const
|
|
673
|
+
const X = (n) => () => new Y(
|
|
467
674
|
n.color,
|
|
468
675
|
n.width,
|
|
469
676
|
n.arrowLength,
|
|
@@ -473,7 +680,7 @@ const B = (n) => () => new G(
|
|
|
473
680
|
n.hasTargetArrow
|
|
474
681
|
);
|
|
475
682
|
var $ = /* @__PURE__ */ ((n) => (n.Regular = "regular", n.Cycle = "cycle", n))($ || {});
|
|
476
|
-
class
|
|
683
|
+
class Z {
|
|
477
684
|
constructor(t) {
|
|
478
685
|
this.di = t;
|
|
479
686
|
}
|
|
@@ -610,213 +817,6 @@ class Y {
|
|
|
610
817
|
this.di.htmlController.destroy();
|
|
611
818
|
}
|
|
612
819
|
}
|
|
613
|
-
class X {
|
|
614
|
-
constructor() {
|
|
615
|
-
r(this, "nodes", /* @__PURE__ */ Object.create(null));
|
|
616
|
-
r(this, "ports", /* @__PURE__ */ Object.create(null));
|
|
617
|
-
r(this, "nodePorts", /* @__PURE__ */ Object.create(null));
|
|
618
|
-
r(this, "portNodeId", /* @__PURE__ */ Object.create(null));
|
|
619
|
-
r(this, "connections", /* @__PURE__ */ Object.create(null));
|
|
620
|
-
r(this, "incommingConnections", /* @__PURE__ */ Object.create(null));
|
|
621
|
-
r(this, "outcommingConnections", /* @__PURE__ */ Object.create(null));
|
|
622
|
-
r(this, "cycleConnections", /* @__PURE__ */ Object.create(null));
|
|
623
|
-
}
|
|
624
|
-
getAllNodes() {
|
|
625
|
-
return Object.keys(this.nodes);
|
|
626
|
-
}
|
|
627
|
-
getAllPorts() {
|
|
628
|
-
return Object.keys(this.ports);
|
|
629
|
-
}
|
|
630
|
-
getAllConnections() {
|
|
631
|
-
return Object.keys(this.connections);
|
|
632
|
-
}
|
|
633
|
-
addNode(t, e, o, s, i) {
|
|
634
|
-
this.nodes[t] = { element: e, x: o, y: s, centerFn: i }, this.nodePorts[t] = /* @__PURE__ */ Object.create(null);
|
|
635
|
-
}
|
|
636
|
-
hasNode(t) {
|
|
637
|
-
return this.nodes[t] !== void 0;
|
|
638
|
-
}
|
|
639
|
-
getNode(t) {
|
|
640
|
-
return this.nodes[t];
|
|
641
|
-
}
|
|
642
|
-
updateNodeCoords(t, e, o) {
|
|
643
|
-
this.nodes[t].x = e, this.nodes[t].y = o;
|
|
644
|
-
}
|
|
645
|
-
updateConnectionController(t, e) {
|
|
646
|
-
this.connections[t].controller = e;
|
|
647
|
-
}
|
|
648
|
-
removeNode(t) {
|
|
649
|
-
this.getNodeAdjacentConnections(t).forEach((s) => {
|
|
650
|
-
this.removeConnection(s);
|
|
651
|
-
}), delete this.nodes[t];
|
|
652
|
-
const o = this.nodePorts[t];
|
|
653
|
-
Object.keys(o).forEach((s) => {
|
|
654
|
-
delete this.portNodeId[s];
|
|
655
|
-
}), delete this.nodePorts[t];
|
|
656
|
-
}
|
|
657
|
-
addPort(t, e, o, s, i) {
|
|
658
|
-
this.ports[t] = { element: e, centerFn: s, direction: i }, this.cycleConnections[t] = {}, this.incommingConnections[t] = {}, this.outcommingConnections[t] = {}, this.portNodeId[t] = o;
|
|
659
|
-
const c = this.nodePorts[o];
|
|
660
|
-
c !== void 0 && (c[t] = e);
|
|
661
|
-
}
|
|
662
|
-
getPort(t) {
|
|
663
|
-
return this.ports[t];
|
|
664
|
-
}
|
|
665
|
-
getPortNode(t) {
|
|
666
|
-
return this.portNodeId[t];
|
|
667
|
-
}
|
|
668
|
-
hasPort(t) {
|
|
669
|
-
return this.portNodeId[t] !== void 0;
|
|
670
|
-
}
|
|
671
|
-
removePort(t) {
|
|
672
|
-
Object.keys(this.cycleConnections[t]).forEach((s) => {
|
|
673
|
-
this.removeConnection(s);
|
|
674
|
-
}), delete this.cycleConnections[t], Object.keys(this.incommingConnections[t]).forEach((s) => {
|
|
675
|
-
this.removeConnection(s);
|
|
676
|
-
}), delete this.incommingConnections[t], Object.keys(this.outcommingConnections[t]).forEach((s) => {
|
|
677
|
-
this.removeConnection(s);
|
|
678
|
-
}), delete this.outcommingConnections[t];
|
|
679
|
-
const e = this.portNodeId[t];
|
|
680
|
-
delete this.portNodeId[t];
|
|
681
|
-
const o = this.nodePorts[e];
|
|
682
|
-
delete o[t], delete this.ports[t];
|
|
683
|
-
}
|
|
684
|
-
addConnection(t, e, o, s) {
|
|
685
|
-
this.connections[t] = {
|
|
686
|
-
from: e,
|
|
687
|
-
to: o,
|
|
688
|
-
controller: s
|
|
689
|
-
}, e !== o ? (this.outcommingConnections[e][t] = !0, this.incommingConnections[o][t] = !0) : this.cycleConnections[e][t] = !0;
|
|
690
|
-
}
|
|
691
|
-
getConnection(t) {
|
|
692
|
-
return this.connections[t];
|
|
693
|
-
}
|
|
694
|
-
hasConnection(t) {
|
|
695
|
-
return this.connections[t] !== void 0;
|
|
696
|
-
}
|
|
697
|
-
removeConnection(t) {
|
|
698
|
-
const e = this.connections[t], o = e.from, s = e.to;
|
|
699
|
-
delete this.cycleConnections[o][t], delete this.cycleConnections[s][t], delete this.incommingConnections[o][t], delete this.incommingConnections[s][t], delete this.outcommingConnections[o][t], delete this.outcommingConnections[s][t], delete this.connections[t];
|
|
700
|
-
}
|
|
701
|
-
getPortIncomingConnections(t) {
|
|
702
|
-
return Object.keys(this.incommingConnections[t] ?? {});
|
|
703
|
-
}
|
|
704
|
-
getPortOutcomingConnections(t) {
|
|
705
|
-
return Object.keys(this.outcommingConnections[t] ?? {});
|
|
706
|
-
}
|
|
707
|
-
getPortCycleConnections(t) {
|
|
708
|
-
return Object.keys(this.cycleConnections[t] ?? {});
|
|
709
|
-
}
|
|
710
|
-
getPortAdjacentConnections(t) {
|
|
711
|
-
return [
|
|
712
|
-
...this.getPortIncomingConnections(t),
|
|
713
|
-
...this.getPortOutcomingConnections(t),
|
|
714
|
-
...this.getPortCycleConnections(t)
|
|
715
|
-
];
|
|
716
|
-
}
|
|
717
|
-
getNodeIncomingConnections(t) {
|
|
718
|
-
const e = Object.keys(this.nodePorts[t]);
|
|
719
|
-
let o = [];
|
|
720
|
-
return e.forEach((s) => {
|
|
721
|
-
o = [...o, ...this.getPortIncomingConnections(s)];
|
|
722
|
-
}), o;
|
|
723
|
-
}
|
|
724
|
-
getNodeOutcomingConnections(t) {
|
|
725
|
-
const e = Object.keys(this.nodePorts[t]);
|
|
726
|
-
let o = [];
|
|
727
|
-
return e.forEach((s) => {
|
|
728
|
-
o = [...o, ...this.getPortOutcomingConnections(s)];
|
|
729
|
-
}), o;
|
|
730
|
-
}
|
|
731
|
-
getNodeCycleConnections(t) {
|
|
732
|
-
const e = Object.keys(this.nodePorts[t]);
|
|
733
|
-
let o = [];
|
|
734
|
-
return e.forEach((s) => {
|
|
735
|
-
o = [...o, ...this.getPortCycleConnections(s)];
|
|
736
|
-
}), o;
|
|
737
|
-
}
|
|
738
|
-
getNodeAdjacentConnections(t) {
|
|
739
|
-
return [
|
|
740
|
-
...this.getNodeIncomingConnections(t),
|
|
741
|
-
...this.getNodeOutcomingConnections(t),
|
|
742
|
-
...this.getNodeCycleConnections(t)
|
|
743
|
-
];
|
|
744
|
-
}
|
|
745
|
-
clear() {
|
|
746
|
-
this.nodes = /* @__PURE__ */ Object.create(null), this.ports = /* @__PURE__ */ Object.create(null), this.nodePorts = /* @__PURE__ */ Object.create(null), this.portNodeId = /* @__PURE__ */ Object.create(null), this.connections = /* @__PURE__ */ Object.create(null), this.incommingConnections = /* @__PURE__ */ Object.create(null), this.outcommingConnections = /* @__PURE__ */ Object.create(null), this.cycleConnections = /* @__PURE__ */ Object.create(null);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
class Z {
|
|
750
|
-
constructor(t) {
|
|
751
|
-
this.graphStore = t;
|
|
752
|
-
}
|
|
753
|
-
getNode(t) {
|
|
754
|
-
const e = this.graphStore.getNode(t);
|
|
755
|
-
return e === void 0 ? null : { x: e.x, y: e.y };
|
|
756
|
-
}
|
|
757
|
-
getPort(t) {
|
|
758
|
-
const e = this.graphStore.getPortNode(t);
|
|
759
|
-
return e === void 0 ? null : { nodeId: e };
|
|
760
|
-
}
|
|
761
|
-
getConnection(t) {
|
|
762
|
-
const e = this.graphStore.getConnection(t);
|
|
763
|
-
return e === void 0 ? null : { from: e.from, to: e.to };
|
|
764
|
-
}
|
|
765
|
-
getAllNodes() {
|
|
766
|
-
return this.graphStore.getAllNodes();
|
|
767
|
-
}
|
|
768
|
-
getAllPorts() {
|
|
769
|
-
return this.graphStore.getAllPorts();
|
|
770
|
-
}
|
|
771
|
-
getAllConnections() {
|
|
772
|
-
return this.graphStore.getAllConnections();
|
|
773
|
-
}
|
|
774
|
-
hasNode(t) {
|
|
775
|
-
return this.graphStore.hasNode(t);
|
|
776
|
-
}
|
|
777
|
-
hasPort(t) {
|
|
778
|
-
return this.graphStore.hasPort(t);
|
|
779
|
-
}
|
|
780
|
-
hasConnection(t) {
|
|
781
|
-
return this.graphStore.hasConnection(t);
|
|
782
|
-
}
|
|
783
|
-
getPortIncomingConnections(t) {
|
|
784
|
-
return this.graphStore.getPortIncomingConnections(t);
|
|
785
|
-
}
|
|
786
|
-
getPortOutcomingConnections(t) {
|
|
787
|
-
return this.graphStore.getPortOutcomingConnections(t);
|
|
788
|
-
}
|
|
789
|
-
getPortCycleConnections(t) {
|
|
790
|
-
return this.graphStore.getPortCycleConnections(t);
|
|
791
|
-
}
|
|
792
|
-
getPortAdjacentConnections(t) {
|
|
793
|
-
return this.graphStore.getPortAdjacentConnections(t);
|
|
794
|
-
}
|
|
795
|
-
getNodeIncomingConnections(t) {
|
|
796
|
-
return this.graphStore.getNodeIncomingConnections(t);
|
|
797
|
-
}
|
|
798
|
-
getNodeOutcomingConnections(t) {
|
|
799
|
-
return this.graphStore.getNodeOutcomingConnections(t);
|
|
800
|
-
}
|
|
801
|
-
getNodeCycleConnections(t) {
|
|
802
|
-
return this.graphStore.getNodeCycleConnections(t);
|
|
803
|
-
}
|
|
804
|
-
getNodeAdjacentConnections(t) {
|
|
805
|
-
return this.graphStore.getNodeAdjacentConnections(t);
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
class A {
|
|
809
|
-
constructor() {
|
|
810
|
-
r(this, "counter", 0);
|
|
811
|
-
}
|
|
812
|
-
next() {
|
|
813
|
-
const t = `${this.counter}`;
|
|
814
|
-
return this.counter++, t;
|
|
815
|
-
}
|
|
816
|
-
reset() {
|
|
817
|
-
this.counter = 0;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
820
|
class H {
|
|
821
821
|
constructor(t) {
|
|
822
822
|
r(this, "htmlController");
|
|
@@ -830,7 +830,7 @@ class H {
|
|
|
830
830
|
r(this, "connectionIdGenerator");
|
|
831
831
|
this.options = t, this.htmlController = new F(this), this.viewportTransformer = new W(), this.publicViewportTransformer = new D(
|
|
832
832
|
this.viewportTransformer
|
|
833
|
-
), this.controller = new
|
|
833
|
+
), this.controller = new Z(this), this.graphStore = new R(), this.publicGraphStore = new z(this.graphStore), this.nodeIdGenerator = new A(), this.portIdGenerator = new A(), this.connectionIdGenerator = new A();
|
|
834
834
|
}
|
|
835
835
|
}
|
|
836
836
|
const P = (n, t) => [
|
|
@@ -883,7 +883,7 @@ const P = (n, t) => [
|
|
|
883
883
|
case "custom":
|
|
884
884
|
return n.controllerFactory;
|
|
885
885
|
case "straight":
|
|
886
|
-
return
|
|
886
|
+
return X({
|
|
887
887
|
color: n.color ?? "#5c5c5c",
|
|
888
888
|
width: n.width ?? 1,
|
|
889
889
|
arrowLength: n.arrowLength ?? 15,
|
|
@@ -893,7 +893,7 @@ const P = (n, t) => [
|
|
|
893
893
|
hasTargetArrow: n.hasTargetArrow ?? !1
|
|
894
894
|
});
|
|
895
895
|
default:
|
|
896
|
-
return
|
|
896
|
+
return B({
|
|
897
897
|
color: n.color ?? "#5c5c5c",
|
|
898
898
|
width: n.width ?? 1,
|
|
899
899
|
curvature: n.curvature ?? 90,
|
|
@@ -1296,13 +1296,13 @@ class st {
|
|
|
1296
1296
|
}
|
|
1297
1297
|
}
|
|
1298
1298
|
export {
|
|
1299
|
-
|
|
1300
|
-
st as CanvasBuilder,
|
|
1299
|
+
G as BezierConnectionController,
|
|
1301
1300
|
tt as CanvasCore,
|
|
1302
1301
|
C as ConnectionUtils,
|
|
1303
1302
|
et as DraggableNodesCanvas,
|
|
1304
|
-
|
|
1303
|
+
st as HtmlGraphBuilder,
|
|
1304
|
+
Y as StraightConnectionController,
|
|
1305
1305
|
ot as TransformableCanvas,
|
|
1306
|
-
|
|
1307
|
-
|
|
1306
|
+
B as createBezierConnectionControllerFactory,
|
|
1307
|
+
X as createStraightConnectionControllerFactory
|
|
1308
1308
|
};
|
package/dist/main.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(p,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(p=typeof globalThis<"u"?globalThis:p||self,w(p.HTMLGraph={}))})(this,function(p){"use strict";var nt=Object.defineProperty;var st=(p,w,P)=>w in p?nt(p,w,{enumerable:!0,configurable:!0,writable:!0,value:P}):p[w]=P;var r=(p,w,P)=>st(p,typeof w!="symbol"?w+"":w,P);class w{constructor(t){r(this,"canvasWrapper",null);r(this,"host");r(this,"nodesContainer");r(this,"connectionsContainer");r(this,"canvas");r(this,"canvasCtx");r(this,"hostResizeObserver");r(this,"nodesResizeObserver");r(this,"nodeElementToIdMap",new Map);r(this,"nodeWrapperElementToIdMap",new Map);r(this,"nodeIdToWrapperElementMap",new Map);r(this,"connectionIdToElementMap",new Map);r(this,"currentZIndex",0);r(this,"layers",{"connections-on-top":{create:()=>{this.host.appendChild(this.nodesContainer),this.host.appendChild(this.connectionsContainer)},update:(t,e,o)=>{this.nodesContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`,this.connectionsContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`},moveOnTop:t=>{this.currentZIndex+=1;const e=this.nodeIdToWrapperElementMap.get(t);e.style.zIndex=`${this.currentZIndex}`}},"connections-follow-node":{create:()=>{this.host.appendChild(this.nodesContainer),this.connectionsContainer=this.nodesContainer},update:(t,e,o)=>{this.nodesContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`},moveOnTop:t=>{const e=this.nodeIdToWrapperElementMap.get(t);this.currentZIndex+=2,e.style.zIndex=`${this.currentZIndex}`,this.di.graphStore.getNodeAdjacentConnections(t).forEach(s=>{this.connectionIdToElementMap.get(s).style.zIndex=`${this.currentZIndex-1}`})}},"nodes-on-top":{create:()=>{this.host.appendChild(this.connectionsContainer),this.host.appendChild(this.nodesContainer)},update:(t,e,o)=>{this.nodesContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`,this.connectionsContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`},moveOnTop:t=>{this.currentZIndex+=1;const e=this.nodeIdToWrapperElementMap.get(t);e.style.zIndex=`${this.currentZIndex}`}}});this.di=t,this.host=this.createHost(),this.canvas=this.createCanvas(),this.nodesContainer=this.createNodesContainer(),this.connectionsContainer=this.createConnectionsContainer();const e=this.canvas.getContext("2d");if(e===null)throw new Error("unable to get canvas context");this.canvasCtx=e,this.host.appendChild(this.canvas);const o=this.di.options.layers.mode;this.layers[o].create(),this.hostResizeObserver=this.createHostResizeObserver(),this.hostResizeObserver.observe(this.host),this.nodesResizeObserver=this.createNodesResizeObserver()}clear(){Array.from(this.connectionIdToElementMap.keys()).forEach(t=>{this.detachConnection(t)}),Array.from(this.nodeElementToIdMap.values()).forEach(t=>{this.detachNode(t)})}attach(t){this.canvasWrapper=t,this.canvasWrapper.appendChild(this.host)}detach(){this.canvasWrapper!==null&&this.canvasWrapper.removeChild(this.host)}destroy(){this.hostResizeObserver.disconnect(),this.nodesResizeObserver.disconnect(),this.host.removeChild(this.canvas),this.host.removeChild(this.connectionsContainer),this.host.removeChild(this.nodesContainer),this.canvasWrapper!==null&&this.canvasWrapper.removeChild(this.host)}applyTransform(){this.canvasCtx.clearRect(0,0,this.canvasCtx.canvas.width,this.canvasCtx.canvas.height),this.canvasCtx.save(),this.di.options.background.drawingFn(this.canvasCtx,this.di.publicViewportTransformer),this.canvasCtx.restore();const[t,e]=this.di.viewportTransformer.getViewCoords(0,0),o=this.di.viewportTransformer.getViewScale();this.layers[this.di.options.layers.mode].update(o,t,e)}attachNode(t){const e=this.di.graphStore.getNode(t),o=document.createElement("div");o.appendChild(e.element),o.style.position="absolute",o.style.top="0",o.style.left="0",o.style.zIndex=`${this.currentZIndex}`,this.currentZIndex+=1,o.style.visibility="hidden",this.nodesContainer.appendChild(o),this.nodeElementToIdMap.set(e.element,t),this.nodeWrapperElementToIdMap.set(o,t),this.nodeIdToWrapperElementMap.set(t,o),this.updateNodeCoords(t,e.x,e.y),this.nodesResizeObserver.observe(o),o.style.visibility="visible"}detachNode(t){const e=this.di.graphStore.getNode(t);this.nodesResizeObserver.unobserve(e.element),this.nodesContainer.removeChild(e.element);const o=this.nodeIdToWrapperElementMap.get(t);o.removeChild(e.element),this.nodeElementToIdMap.delete(e.element),this.nodeWrapperElementToIdMap.delete(o),this.nodeIdToWrapperElementMap.delete(t)}attachConnection(t){const o=this.di.graphStore.getConnection(t).controller.svg;o.style.transformOrigin="50% 50%",o.style.position="absolute",o.style.top="0",o.style.left="0",o.style.zIndex=`${this.currentZIndex}`,this.currentZIndex+=1,this.connectionIdToElementMap.set(t,o),this.updateConnectionCoords(t),this.connectionsContainer.appendChild(o)}detachConnection(t){const e=this.connectionIdToElementMap.get(t);this.connectionIdToElementMap.delete(t),this.connectionsContainer.removeChild(e)}moveNodeOnTop(t){this.layers[this.di.options.layers.mode].moveOnTop(t)}updateNodePosition(t){const e=this.di.graphStore.getNode(t),o=this.di.graphStore.getNodeAdjacentConnections(t);this.updateNodeCoords(t,e.x,e.y),o.forEach(s=>{this.updateConnectionCoords(s)})}updatePortConnections(t){this.di.graphStore.getPortAdjacentConnections(t).forEach(o=>{this.updateConnectionCoords(o)})}getViewportDimensions(){const t=this.host.getBoundingClientRect();return[t.width,t.height]}createHost(){const t=document.createElement("div");return t.style.width="100%",t.style.height="100%",t.style.position="relative",t.style.overflow="hidden",t}createCanvas(){const t=document.createElement("canvas");return t.style.position="absolute",t.style.inset="0",t}createNodesContainer(){const t=document.createElement("div");return t.style.position="absolute",t.style.top="0",t.style.left="0",t.style.width="0",t.style.height="0",t}createConnectionsContainer(){const t=document.createElement("div");return t.style.position="absolute",t.style.pointerEvents="none",t.style.top="0",t.style.left="0",t.style.width="0",t.style.height="0",t}createHostResizeObserver(){return new ResizeObserver(()=>{this.updateCanvasDimensions(),this.applyTransform()})}createNodesResizeObserver(){return new ResizeObserver(t=>{t.forEach(e=>{const o=e.target,s=this.nodeWrapperElementToIdMap.get(o),i=this.di.graphStore.getNode(s);this.updateNodeCoords(s,i.x,i.y),this.di.graphStore.getNodeAdjacentConnections(s).forEach(a=>{this.updateConnectionCoords(a)})})})}updateCanvasDimensions(){const{width:t,height:e}=this.host.getBoundingClientRect();this.canvas.width=t,this.canvas.height=e}updateNodeCoords(t,e,o){const s=this.nodeIdToWrapperElementMap.get(t),{width:i,height:c}=s.getBoundingClientRect(),a=this.di.viewportTransformer.getAbsScale(),h=this.di.graphStore.getNode(t),[l,m]=h.centerFn(i,c);s.style.transform=`matrix(1, 0, 0, 1, ${e-a*l}, ${o-a*m})`}updateConnectionCoords(t){const e=this.di.graphStore.getConnection(t),o=this.di.graphStore.getPort(e.from),s=this.di.graphStore.getPort(e.to),i=o.element.getBoundingClientRect(),c=s.element.getBoundingClientRect(),a=this.host.getBoundingClientRect(),[h,l]=this.di.viewportTransformer.getAbsCoords(i.left-a.left,i.top-a.top),[m,d]=this.di.viewportTransformer.getAbsCoords(c.left-a.left,c.top-a.top),g=this.di.viewportTransformer.getAbsScale(),[u,C]=o.centerFn(i.width*g,i.height*g),[b,S]=s.centerFn(c.width*g,c.height*g),T=u+h,N=C+l,E=b+m,f=S+d,y=Math.min(T,E),A=Math.min(N,f),$=Math.abs(E-T),I=Math.abs(f-N),tt=this.connectionIdToElementMap.get(t),et=T<=E,ot=N<=f;tt.style.transform=`matrix(${et?1:-1}, 0, 0, ${ot?1:-1}, ${y}, ${A})`,e.controller.update(y,A,$,I,o,s)}}class P{constructor(){r(this,"state",{scale:1,x:0,y:0})}applyShift(t,e){this.state={scale:this.state.scale,x:this.state.scale*t+this.state.x,y:this.state.scale*e+this.state.y}}applyScale(t,e,o){this.state={scale:this.state.scale*t,x:this.state.scale*(1-t)*e+this.state.x,y:this.state.scale*(1-t)*o+this.state.y}}getViewCoords(t,e){return[(t-this.state.x)/this.state.scale,(e-this.state.y)/this.state.scale]}getViewScale(){return 1/this.state.scale}getAbsCoords(t,e){return[t*this.state.scale+this.state.x,e*this.state.scale+this.state.y]}getAbsScale(){return this.state.scale}patchState(t,e,o){this.state={scale:t??this.state.scale,x:e??this.state.x,y:o??this.state.y}}}class z{constructor(t){this.transformer=t}getViewCoords(t,e){return this.transformer.getViewCoords(t,e)}getViewScale(){return this.transformer.getViewScale()}getAbsCoords(t,e){return this.transformer.getAbsCoords(t,e)}getAbsScale(){return this.transformer.getAbsScale()}}class v{static getPortCenter(t){const{top:e,left:o,width:s,height:i}=t.element.getBoundingClientRect(),c=t.centerFn(s,i);return[o+c[0],e+c[1]]}static rotate(t,e,o){return[e[0]*t[0]-e[1]*t[1]+((1-e[0])*o[0]+e[1]*o[1]),e[1]*t[0]+e[0]*t[1]+((1-e[0])*o[1]-e[1]*o[0])]}static getDirectionVector(t,e,o){return[e*Math.cos(t??0),o*Math.sin(t??0)]}static getArrowPath(t,e,o,s,i){const a=[[0,0],[s,i],[s,-i]].map(d=>this.rotate(d,t,[0,0])).map(d=>[d[0]+e,d[1]+o]),h=`M ${a[0][0]} ${a[0][1]}`,l=`L ${a[1][0]} ${a[1][1]}`,m=`L ${a[2][0]} ${a[2][1]}`;return`${h} ${l} ${m}`}static getArrowOffsetPath(t,e,o,s,i){const a=[[s,0],[s+i,0]].map(h=>this.rotate(h,t,[0,0])).map(h=>[h[0]+e,h[1]+o]);return`M ${a[0][0]} ${a[0][1]} L ${a[1][0]} ${a[1][1]}`}}class x{constructor(t,e,o,s,i,c,a){r(this,"svg");r(this,"group");r(this,"line");r(this,"sourceArrow",null);r(this,"targetArrow",null);this.color=t,this.width=e,this.curvature=o,this.arrowLength=s,this.arrowWidth=i,this.hasSourceArrow=c,this.hasTargetArrow=a,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.pointerEvents="none",this.group=document.createElementNS("http://www.w3.org/2000/svg","g"),this.svg.appendChild(this.group),this.line=document.createElementNS("http://www.w3.org/2000/svg","path"),this.line.setAttribute("stroke",this.color),this.line.setAttribute("stroke-width",`${this.width}`),this.line.setAttribute("fill","none"),this.group.appendChild(this.line),this.group.style.transformOrigin="50% 50%",this.hasSourceArrow&&(this.sourceArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.sourceArrow.setAttribute("fill",this.color),this.group.appendChild(this.sourceArrow)),this.hasTargetArrow&&(this.targetArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.targetArrow.setAttribute("fill",this.color),this.group.appendChild(this.targetArrow)),this.svg.style.overflow="visible"}update(t,e,o,s,i,c){this.svg.style.width=`${o}px`,this.svg.style.height=`${s}px`;const a=v.getPortCenter(i),h=v.getPortCenter(c),l=a[0]<=h[0]?1:-1,m=a[1]<=h[1]?1:-1;this.svg.style.transform=`translate(${t}px, ${e}px)`,this.group.style.transform=`scale(${l}, ${m})`;const d=v.getDirectionVector(i.direction,l,m),g=v.getDirectionVector(c.direction,l,m),u=v.rotate([this.arrowLength,0],d,[0,0]),C=v.rotate([o-this.arrowLength,s],g,[o,s]),b=[u[0]+d[0]*this.curvature,u[1]+d[1]*this.curvature],S=[C[0]-g[0]*this.curvature,C[1]-g[1]*this.curvature],T=`M ${u[0]} ${u[1]}`,N=`C ${b[0]} ${b[1]}, ${S[0]} ${S[1]}, ${C[0]} ${C[1]}`,E=`M 0 0 L ${u[0]} ${u[1]} `,f=` M ${C[0]} ${C[1]} L ${o} ${s}`,y=`${this.sourceArrow?"":E}${T} ${N}${this.targetArrow?"":f}`;if(this.line.setAttribute("d",y),this.sourceArrow){const A=v.getArrowPath(d,0,0,this.arrowLength,this.arrowWidth);this.sourceArrow.setAttribute("d",A)}if(this.targetArrow){const A=v.getArrowPath(g,o,s,-this.arrowLength,this.arrowWidth);this.targetArrow.setAttribute("d",A)}}}const M=n=>()=>new x(n.color??"#5c5c5c",n.width??1,n.curvature??90,n.arrowLength??15,n.arrowWidth??4,n.hasSourceArrow??!1,n.hasTargetArrow??!1);class L{constructor(t,e,o,s,i,c,a){r(this,"svg");r(this,"group");r(this,"line");r(this,"sourceArrow",null);r(this,"targetArrow",null);this.color=t,this.width=e,this.arrowLength=o,this.arrowWidth=s,this.minPortOffset=i,this.hasSourceArrow=c,this.hasTargetArrow=a,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.pointerEvents="none",this.group=document.createElementNS("http://www.w3.org/2000/svg","g"),this.svg.appendChild(this.group),this.line=document.createElementNS("http://www.w3.org/2000/svg","path"),this.line.setAttribute("stroke",this.color),this.line.setAttribute("stroke-width",`${this.width}`),this.line.setAttribute("fill","none"),this.group.appendChild(this.line),this.group.style.transformOrigin="50% 50%",this.hasSourceArrow&&(this.sourceArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.sourceArrow.setAttribute("fill",this.color),this.group.appendChild(this.sourceArrow)),this.hasTargetArrow&&(this.targetArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.targetArrow.setAttribute("fill",this.color),this.group.appendChild(this.targetArrow)),this.svg.style.overflow="visible"}update(t,e,o,s,i,c){this.svg.style.width=`${o}px`,this.svg.style.height=`${s}px`;const a=v.getPortCenter(i),h=v.getPortCenter(c),l=a[0]<=h[0]?1:-1,m=a[1]<=h[1]?1:-1;this.svg.style.transform=`translate(${t}px, ${e}px)`,this.group.style.transform=`scale(${l}, ${m})`;const d=v.getDirectionVector(i.direction,l,m),g=v.getDirectionVector(c.direction,l,m),u=v.rotate([this.arrowLength+this.minPortOffset,0],d,[0,0]),C=v.rotate([o-this.arrowLength-this.minPortOffset,s],g,[o,s]),[b,S]=[o/2,s/2],T=l*(C[0]-u[0])>0?`M ${u[0]} ${u[1]} L ${b} ${u[1]} L ${b} ${C[1]} L ${C[0]} ${C[1]}`:`M ${u[0]} ${u[1]} L ${u[0]} ${S} L ${C[0]} ${S} L ${C[0]} ${C[1]}`,N=`M 0 0 L ${u[0]} ${u[1]} `,E=` M ${C[0]} ${C[1]} L ${o} ${s}`,f=v.getArrowOffsetPath(d,0,0,this.arrowLength,this.minPortOffset),y=v.getArrowOffsetPath(g,o,s,-this.arrowLength,-this.minPortOffset),A=`${this.sourceArrow?f:N}${T}${this.targetArrow?y:E}`;if(this.line.setAttribute("d",A),this.sourceArrow){const $=v.getArrowPath(d,0,0,this.arrowLength,this.arrowWidth);this.sourceArrow.setAttribute("d",$)}if(this.targetArrow){const $=v.getArrowPath(g,o,s,-this.arrowLength,this.arrowWidth);this.targetArrow.setAttribute("d",$)}}}const V=n=>()=>new L(n.color,n.width,n.arrowLength,n.arrowWidth,n.minPortOffset,n.hasSourceArrow,n.hasTargetArrow);var j=(n=>(n.Regular="regular",n.Cycle="cycle",n))(j||{});class G{constructor(t){this.di=t}moveNodeOnTop(t){if(!this.di.graphStore.hasNode(t))throw new Error("failed to move on top nonexisting node");this.di.htmlController.moveNodeOnTop(t)}dragNode(t,e,o){if(!this.di.graphStore.hasNode(t))throw new Error("failed to drag nonexisting node");const s=this.di.graphStore.getNode(t),[i,c]=this.di.viewportTransformer.getViewCoords(s.x,s.y),a=i+e,h=c+o,[l,m]=this.di.viewportTransformer.getAbsCoords(a,h);this.di.graphStore.updateNodeCoords(t,l,m),this.di.htmlController.updateNodePosition(t)}addNode(t,e,o,s,i,c){if(t===void 0)do t=this.di.nodeIdGenerator.next();while(this.di.graphStore.hasNode(t));if(this.di.graphStore.hasNode(t))throw new Error("failed to add node with existing id");this.di.graphStore.addNode(t,e,o,s,c??this.di.options.nodes.centerFn),this.di.htmlController.attachNode(t),i!==void 0&&Object.entries(i).forEach(([a,h])=>{h instanceof HTMLElement?this.di.controller.markPort(a,h,t,this.di.options.ports.centerFn,null):this.di.controller.markPort(a,h.element,t,h.centerFn??this.di.options.ports.centerFn,h.direction??null)})}markPort(t,e,o,s,i){if(t===void 0)do t=this.di.portIdGenerator.next();while(this.di.graphStore.hasPort(t));if(!this.di.graphStore.hasNode(o))throw new Error("failed to set port on nonexisting node");if(this.di.graphStore.hasPort(t))throw new Error("failed to add port with existing id");this.di.graphStore.addPort(t,e,o,s??this.di.options.ports.centerFn,i??null)}updatePortConnections(t){if(!this.di.graphStore.hasPort(t))throw new Error("failed to unset nonexisting port");this.di.htmlController.updatePortConnections(t)}unmarkPort(t){if(!this.di.graphStore.hasPort(t))throw new Error("failed to unset nonexisting port");this.di.graphStore.getPortAdjacentConnections(t).forEach(e=>{this.removeConnection(e)}),this.di.graphStore.removePort(t)}addConnection(t,e,o,s){if(t===void 0)do t=this.di.connectionIdGenerator.next();while(this.di.graphStore.hasConnection(t));if(!this.di.graphStore.hasPort(e))throw new Error("failed to add connection from nonexisting port");if(!this.di.graphStore.hasPort(o))throw new Error("failed to add connection to nonexisting port");this.di.graphStore.addConnection(t,e,o,s(j.Regular)),this.di.htmlController.attachConnection(t)}removeConnection(t){if(!this.di.graphStore.hasConnection(t))throw new Error("failed to remove nonexisting connection");this.di.htmlController.detachConnection(t),this.di.graphStore.removeConnection(t)}removeNode(t){if(!this.di.graphStore.hasNode(t))throw new Error("failed to remove nonexisting node");this.di.htmlController.detachNode(t),this.di.graphStore.removeNode(t)}patchViewportTransform(t,e,o){this.di.viewportTransformer.patchState(t,e,o),this.di.htmlController.applyTransform()}moveContent(t,e){this.di.viewportTransformer.applyShift(-t,-e),this.di.htmlController.applyTransform()}scaleContent(t,e,o){this.di.viewportTransformer.applyScale(1/t,e,o),this.di.htmlController.applyTransform()}moveToNodes(t){if(t.length===0)return;const e=t.map(g=>this.di.graphStore.getNode(g)).filter(g=>g!==void 0);if(e.length<t.length)throw new Error("failed to move to nonexisting node");const[o,s]=e.reduce((g,u)=>[g[0]+u.x,g[1]+u.y],[0,0]),i=o/e.length,c=s/e.length,[a,h]=this.di.htmlController.getViewportDimensions(),l=this.di.viewportTransformer.getAbsScale(),m=i-l*a/2,d=c-l*h/2;this.patchViewportTransform(null,m,d)}updateNodeCoords(t,e,o){if(!this.di.graphStore.hasNode(t))throw new Error("failed to update coordinates of nonexisting node");this.di.graphStore.updateNodeCoords(t,e,o),this.di.htmlController.updateNodePosition(t)}updateConnectionOptions(t,e){if(!this.di.graphStore.hasConnection(t))throw new Error("failed to update nonexisting connection");this.di.htmlController.detachConnection(t),this.di.graphStore.updateConnectionController(t,e),this.di.htmlController.attachConnection(t)}clear(){this.di.htmlController.clear(),this.di.graphStore.clear(),this.di.nodeIdGenerator.reset(),this.di.portIdGenerator.reset(),this.di.connectionIdGenerator.reset()}destroy(){this.di.htmlController.destroy()}}class B{constructor(){r(this,"nodes",Object.create(null));r(this,"ports",Object.create(null));r(this,"nodePorts",Object.create(null));r(this,"portNodeId",Object.create(null));r(this,"connections",Object.create(null));r(this,"incommingConnections",Object.create(null));r(this,"outcommingConnections",Object.create(null));r(this,"cycleConnections",Object.create(null))}getAllNodes(){return Object.keys(this.nodes)}getAllPorts(){return Object.keys(this.ports)}getAllConnections(){return Object.keys(this.connections)}addNode(t,e,o,s,i){this.nodes[t]={element:e,x:o,y:s,centerFn:i},this.nodePorts[t]=Object.create(null)}hasNode(t){return this.nodes[t]!==void 0}getNode(t){return this.nodes[t]}updateNodeCoords(t,e,o){this.nodes[t].x=e,this.nodes[t].y=o}updateConnectionController(t,e){this.connections[t].controller=e}removeNode(t){this.getNodeAdjacentConnections(t).forEach(s=>{this.removeConnection(s)}),delete this.nodes[t];const o=this.nodePorts[t];Object.keys(o).forEach(s=>{delete this.portNodeId[s]}),delete this.nodePorts[t]}addPort(t,e,o,s,i){this.ports[t]={element:e,centerFn:s,direction:i},this.cycleConnections[t]={},this.incommingConnections[t]={},this.outcommingConnections[t]={},this.portNodeId[t]=o;const c=this.nodePorts[o];c!==void 0&&(c[t]=e)}getPort(t){return this.ports[t]}getPortNode(t){return this.portNodeId[t]}hasPort(t){return this.portNodeId[t]!==void 0}removePort(t){Object.keys(this.cycleConnections[t]).forEach(s=>{this.removeConnection(s)}),delete this.cycleConnections[t],Object.keys(this.incommingConnections[t]).forEach(s=>{this.removeConnection(s)}),delete this.incommingConnections[t],Object.keys(this.outcommingConnections[t]).forEach(s=>{this.removeConnection(s)}),delete this.outcommingConnections[t];const e=this.portNodeId[t];delete this.portNodeId[t];const o=this.nodePorts[e];delete o[t],delete this.ports[t]}addConnection(t,e,o,s){this.connections[t]={from:e,to:o,controller:s},e!==o?(this.outcommingConnections[e][t]=!0,this.incommingConnections[o][t]=!0):this.cycleConnections[e][t]=!0}getConnection(t){return this.connections[t]}hasConnection(t){return this.connections[t]!==void 0}removeConnection(t){const e=this.connections[t],o=e.from,s=e.to;delete this.cycleConnections[o][t],delete this.cycleConnections[s][t],delete this.incommingConnections[o][t],delete this.incommingConnections[s][t],delete this.outcommingConnections[o][t],delete this.outcommingConnections[s][t],delete this.connections[t]}getPortIncomingConnections(t){return Object.keys(this.incommingConnections[t]??{})}getPortOutcomingConnections(t){return Object.keys(this.outcommingConnections[t]??{})}getPortCycleConnections(t){return Object.keys(this.cycleConnections[t]??{})}getPortAdjacentConnections(t){return[...this.getPortIncomingConnections(t),...this.getPortOutcomingConnections(t),...this.getPortCycleConnections(t)]}getNodeIncomingConnections(t){const e=Object.keys(this.nodePorts[t]);let o=[];return e.forEach(s=>{o=[...o,...this.getPortIncomingConnections(s)]}),o}getNodeOutcomingConnections(t){const e=Object.keys(this.nodePorts[t]);let o=[];return e.forEach(s=>{o=[...o,...this.getPortOutcomingConnections(s)]}),o}getNodeCycleConnections(t){const e=Object.keys(this.nodePorts[t]);let o=[];return e.forEach(s=>{o=[...o,...this.getPortCycleConnections(s)]}),o}getNodeAdjacentConnections(t){return[...this.getNodeIncomingConnections(t),...this.getNodeOutcomingConnections(t),...this.getNodeCycleConnections(t)]}clear(){this.nodes=Object.create(null),this.ports=Object.create(null),this.nodePorts=Object.create(null),this.portNodeId=Object.create(null),this.connections=Object.create(null),this.incommingConnections=Object.create(null),this.outcommingConnections=Object.create(null),this.cycleConnections=Object.create(null)}}class Y{constructor(t){this.graphStore=t}getNode(t){const e=this.graphStore.getNode(t);return e===void 0?null:{x:e.x,y:e.y}}getPort(t){const e=this.graphStore.getPortNode(t);return e===void 0?null:{nodeId:e}}getConnection(t){const e=this.graphStore.getConnection(t);return e===void 0?null:{from:e.from,to:e.to}}getAllNodes(){return this.graphStore.getAllNodes()}getAllPorts(){return this.graphStore.getAllPorts()}getAllConnections(){return this.graphStore.getAllConnections()}hasNode(t){return this.graphStore.hasNode(t)}hasPort(t){return this.graphStore.hasPort(t)}hasConnection(t){return this.graphStore.hasConnection(t)}getPortIncomingConnections(t){return this.graphStore.getPortIncomingConnections(t)}getPortOutcomingConnections(t){return this.graphStore.getPortOutcomingConnections(t)}getPortCycleConnections(t){return this.graphStore.getPortCycleConnections(t)}getPortAdjacentConnections(t){return this.graphStore.getPortAdjacentConnections(t)}getNodeIncomingConnections(t){return this.graphStore.getNodeIncomingConnections(t)}getNodeOutcomingConnections(t){return this.graphStore.getNodeOutcomingConnections(t)}getNodeCycleConnections(t){return this.graphStore.getNodeCycleConnections(t)}getNodeAdjacentConnections(t){return this.graphStore.getNodeAdjacentConnections(t)}}class O{constructor(){r(this,"counter",0)}next(){const t=`${this.counter}`;return this.counter++,t}reset(){this.counter=0}}class X{constructor(t){r(this,"htmlController");r(this,"viewportTransformer");r(this,"publicViewportTransformer");r(this,"controller");r(this,"graphStore");r(this,"publicGraphStore");r(this,"nodeIdGenerator");r(this,"portIdGenerator");r(this,"connectionIdGenerator");this.options=t,this.htmlController=new w(this),this.viewportTransformer=new P,this.publicViewportTransformer=new z(this.viewportTransformer),this.controller=new G(this),this.graphStore=new B,this.publicGraphStore=new Y(this.graphStore),this.nodeIdGenerator=new O,this.portIdGenerator=new O,this.connectionIdGenerator=new O}}const k=(n,t)=>[n/2,t/2],Z=()=>()=>{},H=(n,t,e,o,s,i)=>{n.fillStyle=i,n.fillRect(0,0,n.canvas.width,n.canvas.height);const c=t.getViewCoords(0,0),a=t.getViewScale(),h=o*a;let l=0,m=0,d=h/2;do d*=2,l=n.canvas.width/d,m=n.canvas.height/d;while(l*m>1e4);const g=c[0]-Math.floor(c[0]/d)*d,u=c[1]-Math.floor(c[1]/d)*d,C=s*a,b=2*Math.PI,S=g-d,T=u-d,N=n.canvas.width+g,E=n.canvas.height+u;n.fillStyle=e;for(let f=S;f<=N;f+=d)for(let y=T;y<=E;y+=d)n.beginPath(),n.arc(f,y,C,0,b),n.closePath(),n.fill()},U=(n,t,e,o)=>(s,i)=>{H(s,i,n,t,e,o)},q=(n,t)=>{n.fillStyle=t,n.fillRect(0,0,n.canvas.width,n.canvas.height)},J=n=>t=>{q(t,n)},K=n=>{switch(n==null?void 0:n.type){case"custom":return n.drawingFn;case"dots":return U(n.dotColor??"#d8d8d8",n.dotGap??25,n.dotRadius??1.5,n.color??"#ffffff");case"color":return J(n.color??"#ffffff");default:return Z()}},F=n=>{switch(n==null?void 0:n.type){case"custom":return n.controllerFactory;case"straight":return V({color:n.color??"#5c5c5c",width:n.width??1,arrowLength:n.arrowLength??15,arrowWidth:n.arrowWidth??4,minPortOffset:n.minPortOffset??15,hasSourceArrow:n.hasSourceArrow??!1,hasTargetArrow:n.hasTargetArrow??!1});default:return M({color:n.color??"#5c5c5c",width:n.width??1,curvature:n.curvature??90,arrowLength:n.arrowLength??15,arrowWidth:n.arrowWidth??4,hasSourceArrow:n.hasSourceArrow??!1,hasTargetArrow:n.hasTargetArrow??!1})}},Q=n=>{var t,e,o;return{background:{drawingFn:K(n.background??{type:"none"})},nodes:{centerFn:((t=n.nodes)==null?void 0:t.centerFn)??k},ports:{centerFn:((e=n.ports)==null?void 0:e.centerFn)??k},connections:{controllerFactory:F(n.connections??{})},layers:{mode:((o=n.layers)==null?void 0:o.mode)??"connections-follow-node"}}};class W{constructor(t){r(this,"transformation");r(this,"model");r(this,"options");r(this,"di");this.apiOptions=t,this.options=Q(this.apiOptions??{}),this.di=new X(this.options),this.transformation=this.di.publicViewportTransformer,this.model=this.di.publicGraphStore}addNode(t){return this.di.controller.addNode(t.id,t.element,t.x,t.y,t.ports,t.centerFn),this}moveNodeOnTop(t){return this.di.controller.moveNodeOnTop(t),this}removeNode(t){return this.di.controller.removeNode(t),this}markPort(t){return this.di.controller.markPort(t.id,t.element,t.nodeId,t.centerFn,t.direction),this}updatePortConnections(t){return this.di.controller.updatePortConnections(t),this}unmarkPort(t){return this.di.controller.unmarkPort(t),this}addConnection(t){const e=t.options!==void 0?F(t.options):this.di.options.connections.controllerFactory;return this.di.controller.addConnection(t.id,t.from,t.to,e),this}removeConnection(t){return this.di.controller.removeConnection(t),this}patchViewportTransform(t){return this.di.controller.patchViewportTransform(t.scale??null,t.x??null,t.y??null),this}moveContent(t){return this.di.controller.moveContent(t.x??0,t.y??0),this}scaleContent(t){return this.di.controller.scaleContent(t.scale,t.x??0,t.y??0),this}moveToNodes(t){return this.di.controller.moveToNodes(t),this}updateNodeCoords(t,e,o){return this.di.controller.updateNodeCoords(t,e,o),this}updateConnectionController(t,e){return this.di.controller.updateConnectionOptions(t,e),this}dragNode(t,e,o){return this.di.controller.dragNode(t,e,o),this}clear(){return this.di.controller.clear(),this}attach(t){return this.di.htmlController.attach(t),this}detach(){return this.di.htmlController.detach(),this}destroy(){this.di.controller.destroy()}}class D{constructor(t){r(this,"transformation");r(this,"model");r(this,"nodes",new Map);r(this,"grabbedNodeId",null);r(this,"nodeIdGenerator",new O);r(this,"element",null);r(this,"onCanvasMouseUp",()=>{this.setCursor(null),this.grabbedNodeId=null});r(this,"onCanvasMouseMove",t=>{this.grabbedNodeId!==null&&(t.stopPropagation(),this.canvas.dragNode(this.grabbedNodeId,t.movementX,t.movementY))});r(this,"onCanvasTouchStart",t=>{this.previousTouchCoords=[t.touches[0].clientX,t.touches[0].clientY]});r(this,"onCanvasTouchMove",t=>{if(this.grabbedNodeId===null||t.touches.length!==1||this.previousTouchCoords===null)return;t.stopImmediatePropagation();const[e,o]=[t.touches[0].clientX-this.previousTouchCoords[0],t.touches[0].clientY-this.previousTouchCoords[1]];this.canvas.dragNode(this.grabbedNodeId,e,o),this.previousTouchCoords=[t.touches[0].clientX,t.touches[0].clientY]});r(this,"onCanvasTouchEnd",()=>{this.previousTouchCoords=null,this.grabbedNodeId=null});r(this,"previousTouchCoords",null);this.canvas=t,this.transformation=this.canvas.transformation,this.model=this.canvas.model}addNode(t){let e=t.id;if(e===void 0)do e=this.nodeIdGenerator.next();while(this.nodes.has(e));this.canvas.addNode(t);const o=i=>{i.stopImmediatePropagation(),this.grabbedNodeId=e,this.setCursor("grab"),this.canvas.moveNodeOnTop(e)},s=i=>{i.touches.length===1&&(this.grabbedNodeId=e,this.canvas.moveNodeOnTop(e))};return this.nodes.set(e,{el:t.element,onMouseDown:o,onTouchStart:s}),t.element.addEventListener("mousedown",o),t.element.addEventListener("touchstart",s),this}removeNode(t){const e=this.nodes.get(t);return e!==void 0&&(e.el.removeEventListener("mousedown",e.onMouseDown),e.el.removeEventListener("touchstart",e.onTouchStart)),this.canvas.removeNode(t),this.nodes.delete(t),this}markPort(t){return this.canvas.markPort(t),this}updatePortConnections(t){return this.canvas.updatePortConnections(t),this}unmarkPort(t){return this.canvas.unmarkPort(t),this}addConnection(t){return this.canvas.addConnection(t),this}removeConnection(t){return this.canvas.removeConnection(t),this}patchViewportTransform(t){return this.canvas.patchViewportTransform(t),this}moveContent(t){return this.canvas.moveContent(t),this}scaleContent(t){return this.canvas.scaleContent(t),this}moveToNodes(t){return this.canvas.moveToNodes(t),this}updateNodeCoords(t,e,o){return this.canvas.updateNodeCoords(t,e,o),this}updateConnectionController(t,e){return this.canvas.updateConnectionController(t,e),this}dragNode(t,e,o){return this.canvas.dragNode(t,e,o),this}moveNodeOnTop(t){return this.canvas.moveNodeOnTop(t),this}clear(){return this.canvas.clear(),this.nodes.forEach(t=>{t.el.removeEventListener("mousedown",t.onMouseDown),t.el.removeEventListener("touchstart",t.onTouchStart)}),this.nodes.clear(),this}attach(t){return this.canvas.attach(t),this.element=t,t.addEventListener("mouseup",this.onCanvasMouseUp),t.addEventListener("mousemove",this.onCanvasMouseMove),t.addEventListener("touchstart",this.onCanvasTouchStart),t.addEventListener("touchmove",this.onCanvasTouchMove),t.addEventListener("touchend",this.onCanvasTouchEnd),t.addEventListener("touchcancel",this.onCanvasTouchEnd),this}detach(){return this.canvas.detach(),this.element!==null&&(this.element.removeEventListener("mouseup",this.onCanvasMouseUp),this.element.removeEventListener("mousemove",this.onCanvasMouseMove),this.element.removeEventListener("touchstart",this.onCanvasTouchStart),this.element.removeEventListener("touchmove",this.onCanvasTouchMove),this.element.removeEventListener("touchend",this.onCanvasTouchEnd),this.element.removeEventListener("touchcancel",this.onCanvasTouchEnd),this.element=null),this}destroy(){this.detach(),this.nodes.forEach(t=>{t.el.removeEventListener("mousedown",t.onMouseDown),t.el.removeEventListener("touchstart",t.onTouchStart)}),this.canvas.destroy()}setCursor(t){this.element!==null&&(t!==null?this.element.style.cursor=t:this.element.style.removeProperty("cursor"))}}class R{constructor(t,e){r(this,"transformation");r(this,"model");r(this,"element",null);r(this,"isMoving",!1);r(this,"prevTouches",null);r(this,"isScalable");r(this,"isShiftable");r(this,"minContentScale");r(this,"maxContentScale");r(this,"wheelSensitivity");r(this,"onMouseDown",()=>{this.setCursor("grab"),this.isMoving=!0});r(this,"onMouseMove",t=>{!this.isMoving||!this.isShiftable||this.canvas.moveContent({x:t.movementX,y:t.movementY})});r(this,"onMouseUp",()=>{this.setCursor(null),this.isMoving=!1});r(this,"onWheelScroll",t=>{if(this.element===null||this.isScalable===!1)return;t.preventDefault();const{left:e,top:o}=this.element.getBoundingClientRect(),s=t.clientX-e,i=t.clientY-o,c=t.deltaY<0?this.wheelSensitivity:1/this.wheelSensitivity,a=this.canvas.transformation.getViewScale()*c;this.checkNextScaleValid(a)&&this.canvas.scaleContent({scale:c,x:s,y:i})});r(this,"onTouchStart",t=>{this.prevTouches=this.getAverageTouch(t)});r(this,"onTouchMove",t=>{if(this.prevTouches===null||this.element===null||!this.isShiftable)return;const e=this.getAverageTouch(t);if((e.touchesCnt===1||e.touchesCnt===2)&&this.canvas.moveContent({x:e.x-this.prevTouches.x,y:e.y-this.prevTouches.y}),e.touchesCnt===2&&this.isScalable){const{left:o,top:s}=this.element.getBoundingClientRect(),i=this.prevTouches.x-o,c=this.prevTouches.y-s,a=e.scale/this.prevTouches.scale,h=this.canvas.transformation.getViewScale()*a;this.checkNextScaleValid(h)&&this.canvas.scaleContent({scale:a,x:i,y:c})}this.prevTouches=e,t.preventDefault()});r(this,"onTouchEnd",()=>{this.prevTouches=null});var s,i,c,a,h,l,m,d,g,u;this.canvas=t,this.options=e,this.transformation=this.canvas.transformation,this.model=this.canvas.model,this.isScalable=((i=(s=this.options)==null?void 0:s.scale)==null?void 0:i.enabled)!==!1,this.minContentScale=((a=(c=this.options)==null?void 0:c.scale)==null?void 0:a.minContent)??null,this.maxContentScale=((l=(h=this.options)==null?void 0:h.scale)==null?void 0:l.maxContent)??null,this.isShiftable=((d=(m=this.options)==null?void 0:m.shift)==null?void 0:d.enabled)!==!1;const o=(u=(g=this.options)==null?void 0:g.scale)==null?void 0:u.wheelSensitivity;this.wheelSensitivity=o!==void 0?o:1.2}addNode(t){return this.canvas.addNode(t),this}removeNode(t){return this.canvas.removeNode(t),this}markPort(t){return this.canvas.markPort(t),this}updatePortConnections(t){return this.canvas.updatePortConnections(t),this}unmarkPort(t){return this.canvas.unmarkPort(t),this}addConnection(t){return this.canvas.addConnection(t),this}removeConnection(t){return this.canvas.removeConnection(t),this}patchViewportTransform(t){return this.canvas.patchViewportTransform(t),this}moveContent(t){return this.canvas.moveContent(t),this}scaleContent(t){return this.canvas.scaleContent(t),this}moveToNodes(t){return this.canvas.moveToNodes(t),this}updateNodeCoords(t,e,o){return this.canvas.updateNodeCoords(t,e,o),this}updateConnectionController(t,e){return this.canvas.updateConnectionController(t,e),this}dragNode(t,e,o){return this.canvas.dragNode(t,e,o),this}moveNodeOnTop(t){return this.canvas.moveNodeOnTop(t),this}clear(){return this.canvas.clear(),this}attach(t){return this.canvas.attach(t),this.element=t,t.addEventListener("mousedown",this.onMouseDown),t.addEventListener("mousemove",this.onMouseMove),t.addEventListener("mouseup",this.onMouseUp),t.addEventListener("wheel",this.onWheelScroll),t.addEventListener("touchstart",this.onTouchStart),t.addEventListener("touchmove",this.onTouchMove),t.addEventListener("touchend",this.onTouchEnd),t.addEventListener("touchcancel",this.onTouchEnd),this}detach(){return this.canvas.detach(),this.element!==null&&(this.element.removeEventListener("mousedown",this.onMouseDown),this.element.removeEventListener("mousemove",this.onMouseMove),this.element.removeEventListener("mouseup",this.onMouseUp),this.element.removeEventListener("wheel",this.onWheelScroll),this.element.removeEventListener("touchstart",this.onTouchStart),this.element.removeEventListener("touchmove",this.onTouchMove),this.element.removeEventListener("touchend",this.onTouchEnd),this.element.removeEventListener("touchcancel",this.onTouchEnd)),this.element=null,this}destroy(){this.detach(),this.canvas.destroy()}getAverageTouch(t){const e=[],o=t.touches.length;for(let h=0;h<o;h++)e.push([t.touches[h].clientX,t.touches[h].clientY]);const s=e.reduce((h,l)=>[h[0]+l[0],h[1]+l[1]],[0,0]),i=[s[0]/o,s[1]/o],a=e.map(h=>[h[0]-i[0],h[1]-i[1]]).reduce((h,l)=>h+Math.sqrt(l[0]*l[0]+l[1]*l[1]),0);return{x:i[0],y:i[1],scale:a/o,touchesCnt:o}}checkNextScaleValid(t){const e=this.canvas.transformation.getViewScale();return!(this.maxContentScale!==null&&t>this.maxContentScale&&t>e||this.minContentScale!==null&&t<this.minContentScale&&t<e)}setCursor(t){this.element!==null&&(t!==null?this.element.style.cursor=t:this.element.style.removeProperty("cursor"))}}class _{constructor(){r(this,"coreOptions");r(this,"transformOptions");r(this,"isDraggable",!1);r(this,"isTransformable",!1)}setOptions(t){return this.coreOptions=t,this}setDraggableNodes(){return this.isDraggable=!0,this}setTransformableCanvas(t){return this.isTransformable=!0,this.transformOptions=t,this}build(){let t=new W(this.coreOptions);return this.isDraggable&&(t=new D(t)),this.isTransformable&&(t=new R(t,this.transformOptions)),t}}p.BezierConnectionController=x,p.CanvasBuilder=_,p.CanvasCore=W,p.ConnectionUtils=v,p.DraggableNodesCanvas=D,p.StraightConnectionController=L,p.TransformableCanvas=R,p.createBezierConnectionControllerFactory=M,p.createStraightConnectionControllerFactory=V,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(p,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(p=typeof globalThis<"u"?globalThis:p||self,w(p.HTMLGraph={}))})(this,function(p){"use strict";var nt=Object.defineProperty;var st=(p,w,P)=>w in p?nt(p,w,{enumerable:!0,configurable:!0,writable:!0,value:P}):p[w]=P;var r=(p,w,P)=>st(p,typeof w!="symbol"?w+"":w,P);class w{constructor(t){r(this,"canvasWrapper",null);r(this,"host");r(this,"nodesContainer");r(this,"connectionsContainer");r(this,"canvas");r(this,"canvasCtx");r(this,"hostResizeObserver");r(this,"nodesResizeObserver");r(this,"nodeElementToIdMap",new Map);r(this,"nodeWrapperElementToIdMap",new Map);r(this,"nodeIdToWrapperElementMap",new Map);r(this,"connectionIdToElementMap",new Map);r(this,"currentZIndex",0);r(this,"layers",{"connections-on-top":{create:()=>{this.host.appendChild(this.nodesContainer),this.host.appendChild(this.connectionsContainer)},update:(t,e,o)=>{this.nodesContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`,this.connectionsContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`},moveOnTop:t=>{this.currentZIndex+=1;const e=this.nodeIdToWrapperElementMap.get(t);e.style.zIndex=`${this.currentZIndex}`}},"connections-follow-node":{create:()=>{this.host.appendChild(this.nodesContainer),this.connectionsContainer=this.nodesContainer},update:(t,e,o)=>{this.nodesContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`},moveOnTop:t=>{const e=this.nodeIdToWrapperElementMap.get(t);this.currentZIndex+=2,e.style.zIndex=`${this.currentZIndex}`,this.di.graphStore.getNodeAdjacentConnections(t).forEach(s=>{this.connectionIdToElementMap.get(s).style.zIndex=`${this.currentZIndex-1}`})}},"nodes-on-top":{create:()=>{this.host.appendChild(this.connectionsContainer),this.host.appendChild(this.nodesContainer)},update:(t,e,o)=>{this.nodesContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`,this.connectionsContainer.style.transform=`matrix(${t}, 0, 0, ${t}, ${e}, ${o})`},moveOnTop:t=>{this.currentZIndex+=1;const e=this.nodeIdToWrapperElementMap.get(t);e.style.zIndex=`${this.currentZIndex}`}}});this.di=t,this.host=this.createHost(),this.canvas=this.createCanvas(),this.nodesContainer=this.createNodesContainer(),this.connectionsContainer=this.createConnectionsContainer();const e=this.canvas.getContext("2d");if(e===null)throw new Error("unable to get canvas context");this.canvasCtx=e,this.host.appendChild(this.canvas);const o=this.di.options.layers.mode;this.layers[o].create(),this.hostResizeObserver=this.createHostResizeObserver(),this.hostResizeObserver.observe(this.host),this.nodesResizeObserver=this.createNodesResizeObserver()}clear(){Array.from(this.connectionIdToElementMap.keys()).forEach(t=>{this.detachConnection(t)}),Array.from(this.nodeElementToIdMap.values()).forEach(t=>{this.detachNode(t)})}attach(t){this.canvasWrapper=t,this.canvasWrapper.appendChild(this.host)}detach(){this.canvasWrapper!==null&&this.canvasWrapper.removeChild(this.host)}destroy(){this.hostResizeObserver.disconnect(),this.nodesResizeObserver.disconnect(),this.host.removeChild(this.canvas),this.host.removeChild(this.connectionsContainer),this.host.removeChild(this.nodesContainer),this.canvasWrapper!==null&&this.canvasWrapper.removeChild(this.host)}applyTransform(){this.canvasCtx.clearRect(0,0,this.canvasCtx.canvas.width,this.canvasCtx.canvas.height),this.canvasCtx.save(),this.di.options.background.drawingFn(this.canvasCtx,this.di.publicViewportTransformer),this.canvasCtx.restore();const[t,e]=this.di.viewportTransformer.getViewCoords(0,0),o=this.di.viewportTransformer.getViewScale();this.layers[this.di.options.layers.mode].update(o,t,e)}attachNode(t){const e=this.di.graphStore.getNode(t),o=document.createElement("div");o.appendChild(e.element),o.style.position="absolute",o.style.top="0",o.style.left="0",o.style.zIndex=`${this.currentZIndex}`,this.currentZIndex+=1,o.style.visibility="hidden",this.nodesContainer.appendChild(o),this.nodeElementToIdMap.set(e.element,t),this.nodeWrapperElementToIdMap.set(o,t),this.nodeIdToWrapperElementMap.set(t,o),this.updateNodeCoords(t,e.x,e.y),this.nodesResizeObserver.observe(o),o.style.visibility="visible"}detachNode(t){const e=this.di.graphStore.getNode(t);this.nodesResizeObserver.unobserve(e.element),this.nodesContainer.removeChild(e.element);const o=this.nodeIdToWrapperElementMap.get(t);o.removeChild(e.element),this.nodeElementToIdMap.delete(e.element),this.nodeWrapperElementToIdMap.delete(o),this.nodeIdToWrapperElementMap.delete(t)}attachConnection(t){const o=this.di.graphStore.getConnection(t).controller.svg;o.style.transformOrigin="50% 50%",o.style.position="absolute",o.style.top="0",o.style.left="0",o.style.zIndex=`${this.currentZIndex}`,this.currentZIndex+=1,this.connectionIdToElementMap.set(t,o),this.updateConnectionCoords(t),this.connectionsContainer.appendChild(o)}detachConnection(t){const e=this.connectionIdToElementMap.get(t);this.connectionIdToElementMap.delete(t),this.connectionsContainer.removeChild(e)}moveNodeOnTop(t){this.layers[this.di.options.layers.mode].moveOnTop(t)}updateNodePosition(t){const e=this.di.graphStore.getNode(t),o=this.di.graphStore.getNodeAdjacentConnections(t);this.updateNodeCoords(t,e.x,e.y),o.forEach(s=>{this.updateConnectionCoords(s)})}updatePortConnections(t){this.di.graphStore.getPortAdjacentConnections(t).forEach(o=>{this.updateConnectionCoords(o)})}getViewportDimensions(){const t=this.host.getBoundingClientRect();return[t.width,t.height]}createHost(){const t=document.createElement("div");return t.style.width="100%",t.style.height="100%",t.style.position="relative",t.style.overflow="hidden",t}createCanvas(){const t=document.createElement("canvas");return t.style.position="absolute",t.style.inset="0",t}createNodesContainer(){const t=document.createElement("div");return t.style.position="absolute",t.style.top="0",t.style.left="0",t.style.width="0",t.style.height="0",t}createConnectionsContainer(){const t=document.createElement("div");return t.style.position="absolute",t.style.pointerEvents="none",t.style.top="0",t.style.left="0",t.style.width="0",t.style.height="0",t}createHostResizeObserver(){return new ResizeObserver(()=>{this.updateCanvasDimensions(),this.applyTransform()})}createNodesResizeObserver(){return new ResizeObserver(t=>{t.forEach(e=>{const o=e.target,s=this.nodeWrapperElementToIdMap.get(o),i=this.di.graphStore.getNode(s);this.updateNodeCoords(s,i.x,i.y),this.di.graphStore.getNodeAdjacentConnections(s).forEach(a=>{this.updateConnectionCoords(a)})})})}updateCanvasDimensions(){const{width:t,height:e}=this.host.getBoundingClientRect();this.canvas.width=t,this.canvas.height=e}updateNodeCoords(t,e,o){const s=this.nodeIdToWrapperElementMap.get(t),{width:i,height:c}=s.getBoundingClientRect(),a=this.di.viewportTransformer.getAbsScale(),h=this.di.graphStore.getNode(t),[l,m]=h.centerFn(i,c);s.style.transform=`matrix(1, 0, 0, 1, ${e-a*l}, ${o-a*m})`}updateConnectionCoords(t){const e=this.di.graphStore.getConnection(t),o=this.di.graphStore.getPort(e.from),s=this.di.graphStore.getPort(e.to),i=o.element.getBoundingClientRect(),c=s.element.getBoundingClientRect(),a=this.host.getBoundingClientRect(),[h,l]=this.di.viewportTransformer.getAbsCoords(i.left-a.left,i.top-a.top),[m,d]=this.di.viewportTransformer.getAbsCoords(c.left-a.left,c.top-a.top),g=this.di.viewportTransformer.getAbsScale(),[u,C]=o.centerFn(i.width*g,i.height*g),[b,S]=s.centerFn(c.width*g,c.height*g),T=u+h,N=C+l,E=b+m,f=S+d,y=Math.min(T,E),A=Math.min(N,f),$=Math.abs(E-T),I=Math.abs(f-N),tt=this.connectionIdToElementMap.get(t),et=T<=E,ot=N<=f;tt.style.transform=`matrix(${et?1:-1}, 0, 0, ${ot?1:-1}, ${y}, ${A})`,e.controller.update(y,A,$,I,o,s)}}class P{constructor(){r(this,"state",{scale:1,x:0,y:0})}applyShift(t,e){this.state={scale:this.state.scale,x:this.state.scale*t+this.state.x,y:this.state.scale*e+this.state.y}}applyScale(t,e,o){this.state={scale:this.state.scale*t,x:this.state.scale*(1-t)*e+this.state.x,y:this.state.scale*(1-t)*o+this.state.y}}getViewCoords(t,e){return[(t-this.state.x)/this.state.scale,(e-this.state.y)/this.state.scale]}getViewScale(){return 1/this.state.scale}getAbsCoords(t,e){return[t*this.state.scale+this.state.x,e*this.state.scale+this.state.y]}getAbsScale(){return this.state.scale}patchState(t,e,o){this.state={scale:t??this.state.scale,x:e??this.state.x,y:o??this.state.y}}}class z{constructor(t){this.transformer=t}getViewCoords(t,e){return this.transformer.getViewCoords(t,e)}getViewScale(){return this.transformer.getViewScale()}getAbsCoords(t,e){return this.transformer.getAbsCoords(t,e)}getAbsScale(){return this.transformer.getAbsScale()}}class G{constructor(){r(this,"nodes",Object.create(null));r(this,"ports",Object.create(null));r(this,"nodePorts",Object.create(null));r(this,"portNodeId",Object.create(null));r(this,"connections",Object.create(null));r(this,"incommingConnections",Object.create(null));r(this,"outcommingConnections",Object.create(null));r(this,"cycleConnections",Object.create(null))}getAllNodes(){return Object.keys(this.nodes)}getAllPorts(){return Object.keys(this.ports)}getAllConnections(){return Object.keys(this.connections)}addNode(t,e,o,s,i){this.nodes[t]={element:e,x:o,y:s,centerFn:i},this.nodePorts[t]=Object.create(null)}hasNode(t){return this.nodes[t]!==void 0}getNode(t){return this.nodes[t]}updateNodeCoords(t,e,o){this.nodes[t].x=e,this.nodes[t].y=o}updateConnectionController(t,e){this.connections[t].controller=e}removeNode(t){this.getNodeAdjacentConnections(t).forEach(s=>{this.removeConnection(s)}),delete this.nodes[t];const o=this.nodePorts[t];Object.keys(o).forEach(s=>{delete this.portNodeId[s]}),delete this.nodePorts[t]}addPort(t,e,o,s,i){this.ports[t]={element:e,centerFn:s,direction:i},this.cycleConnections[t]={},this.incommingConnections[t]={},this.outcommingConnections[t]={},this.portNodeId[t]=o;const c=this.nodePorts[o];c!==void 0&&(c[t]=e)}getPort(t){return this.ports[t]}getPortNode(t){return this.portNodeId[t]}hasPort(t){return this.portNodeId[t]!==void 0}removePort(t){Object.keys(this.cycleConnections[t]).forEach(s=>{this.removeConnection(s)}),delete this.cycleConnections[t],Object.keys(this.incommingConnections[t]).forEach(s=>{this.removeConnection(s)}),delete this.incommingConnections[t],Object.keys(this.outcommingConnections[t]).forEach(s=>{this.removeConnection(s)}),delete this.outcommingConnections[t];const e=this.portNodeId[t];delete this.portNodeId[t];const o=this.nodePorts[e];delete o[t],delete this.ports[t]}addConnection(t,e,o,s){this.connections[t]={from:e,to:o,controller:s},e!==o?(this.outcommingConnections[e][t]=!0,this.incommingConnections[o][t]=!0):this.cycleConnections[e][t]=!0}getConnection(t){return this.connections[t]}hasConnection(t){return this.connections[t]!==void 0}removeConnection(t){const e=this.connections[t],o=e.from,s=e.to;delete this.cycleConnections[o][t],delete this.cycleConnections[s][t],delete this.incommingConnections[o][t],delete this.incommingConnections[s][t],delete this.outcommingConnections[o][t],delete this.outcommingConnections[s][t],delete this.connections[t]}getPortIncomingConnections(t){return Object.keys(this.incommingConnections[t]??{})}getPortOutcomingConnections(t){return Object.keys(this.outcommingConnections[t]??{})}getPortCycleConnections(t){return Object.keys(this.cycleConnections[t]??{})}getPortAdjacentConnections(t){return[...this.getPortIncomingConnections(t),...this.getPortOutcomingConnections(t),...this.getPortCycleConnections(t)]}getNodeIncomingConnections(t){const e=Object.keys(this.nodePorts[t]);let o=[];return e.forEach(s=>{o=[...o,...this.getPortIncomingConnections(s)]}),o}getNodeOutcomingConnections(t){const e=Object.keys(this.nodePorts[t]);let o=[];return e.forEach(s=>{o=[...o,...this.getPortOutcomingConnections(s)]}),o}getNodeCycleConnections(t){const e=Object.keys(this.nodePorts[t]);let o=[];return e.forEach(s=>{o=[...o,...this.getPortCycleConnections(s)]}),o}getNodeAdjacentConnections(t){return[...this.getNodeIncomingConnections(t),...this.getNodeOutcomingConnections(t),...this.getNodeCycleConnections(t)]}clear(){this.nodes=Object.create(null),this.ports=Object.create(null),this.nodePorts=Object.create(null),this.portNodeId=Object.create(null),this.connections=Object.create(null),this.incommingConnections=Object.create(null),this.outcommingConnections=Object.create(null),this.cycleConnections=Object.create(null)}}class B{constructor(t){this.graphStore=t}getNode(t){const e=this.graphStore.getNode(t);return e===void 0?null:{x:e.x,y:e.y}}getPort(t){const e=this.graphStore.getPortNode(t);return e===void 0?null:{nodeId:e}}getConnection(t){const e=this.graphStore.getConnection(t);return e===void 0?null:{from:e.from,to:e.to}}getAllNodes(){return this.graphStore.getAllNodes()}getAllPorts(){return this.graphStore.getAllPorts()}getAllConnections(){return this.graphStore.getAllConnections()}hasNode(t){return this.graphStore.hasNode(t)}hasPort(t){return this.graphStore.hasPort(t)}hasConnection(t){return this.graphStore.hasConnection(t)}getPortIncomingConnections(t){return this.graphStore.getPortIncomingConnections(t)}getPortOutcomingConnections(t){return this.graphStore.getPortOutcomingConnections(t)}getPortCycleConnections(t){return this.graphStore.getPortCycleConnections(t)}getPortAdjacentConnections(t){return this.graphStore.getPortAdjacentConnections(t)}getNodeIncomingConnections(t){return this.graphStore.getNodeIncomingConnections(t)}getNodeOutcomingConnections(t){return this.graphStore.getNodeOutcomingConnections(t)}getNodeCycleConnections(t){return this.graphStore.getNodeCycleConnections(t)}getNodeAdjacentConnections(t){return this.graphStore.getNodeAdjacentConnections(t)}}class O{constructor(){r(this,"counter",0)}next(){const t=`${this.counter}`;return this.counter++,t}reset(){this.counter=0}}class v{static getPortCenter(t){const{top:e,left:o,width:s,height:i}=t.element.getBoundingClientRect(),c=t.centerFn(s,i);return[o+c[0],e+c[1]]}static rotate(t,e,o){return[e[0]*t[0]-e[1]*t[1]+((1-e[0])*o[0]+e[1]*o[1]),e[1]*t[0]+e[0]*t[1]+((1-e[0])*o[1]-e[1]*o[0])]}static getDirectionVector(t,e,o){return[e*Math.cos(t??0),o*Math.sin(t??0)]}static getArrowPath(t,e,o,s,i){const a=[[0,0],[s,i],[s,-i]].map(d=>this.rotate(d,t,[0,0])).map(d=>[d[0]+e,d[1]+o]),h=`M ${a[0][0]} ${a[0][1]}`,l=`L ${a[1][0]} ${a[1][1]}`,m=`L ${a[2][0]} ${a[2][1]}`;return`${h} ${l} ${m}`}static getArrowOffsetPath(t,e,o,s,i){const a=[[s,0],[s+i,0]].map(h=>this.rotate(h,t,[0,0])).map(h=>[h[0]+e,h[1]+o]);return`M ${a[0][0]} ${a[0][1]} L ${a[1][0]} ${a[1][1]}`}}class x{constructor(t,e,o,s,i,c,a){r(this,"svg");r(this,"group");r(this,"line");r(this,"sourceArrow",null);r(this,"targetArrow",null);this.color=t,this.width=e,this.curvature=o,this.arrowLength=s,this.arrowWidth=i,this.hasSourceArrow=c,this.hasTargetArrow=a,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.pointerEvents="none",this.group=document.createElementNS("http://www.w3.org/2000/svg","g"),this.svg.appendChild(this.group),this.line=document.createElementNS("http://www.w3.org/2000/svg","path"),this.line.setAttribute("stroke",this.color),this.line.setAttribute("stroke-width",`${this.width}`),this.line.setAttribute("fill","none"),this.group.appendChild(this.line),this.group.style.transformOrigin="50% 50%",this.hasSourceArrow&&(this.sourceArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.sourceArrow.setAttribute("fill",this.color),this.group.appendChild(this.sourceArrow)),this.hasTargetArrow&&(this.targetArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.targetArrow.setAttribute("fill",this.color),this.group.appendChild(this.targetArrow)),this.svg.style.overflow="visible"}update(t,e,o,s,i,c){this.svg.style.width=`${o}px`,this.svg.style.height=`${s}px`;const a=v.getPortCenter(i),h=v.getPortCenter(c),l=a[0]<=h[0]?1:-1,m=a[1]<=h[1]?1:-1;this.svg.style.transform=`translate(${t}px, ${e}px)`,this.group.style.transform=`scale(${l}, ${m})`;const d=v.getDirectionVector(i.direction,l,m),g=v.getDirectionVector(c.direction,l,m),u=v.rotate([this.arrowLength,0],d,[0,0]),C=v.rotate([o-this.arrowLength,s],g,[o,s]),b=[u[0]+d[0]*this.curvature,u[1]+d[1]*this.curvature],S=[C[0]-g[0]*this.curvature,C[1]-g[1]*this.curvature],T=`M ${u[0]} ${u[1]}`,N=`C ${b[0]} ${b[1]}, ${S[0]} ${S[1]}, ${C[0]} ${C[1]}`,E=`M 0 0 L ${u[0]} ${u[1]} `,f=` M ${C[0]} ${C[1]} L ${o} ${s}`,y=`${this.sourceArrow?"":E}${T} ${N}${this.targetArrow?"":f}`;if(this.line.setAttribute("d",y),this.sourceArrow){const A=v.getArrowPath(d,0,0,this.arrowLength,this.arrowWidth);this.sourceArrow.setAttribute("d",A)}if(this.targetArrow){const A=v.getArrowPath(g,o,s,-this.arrowLength,this.arrowWidth);this.targetArrow.setAttribute("d",A)}}}const M=n=>()=>new x(n.color??"#5c5c5c",n.width??1,n.curvature??90,n.arrowLength??15,n.arrowWidth??4,n.hasSourceArrow??!1,n.hasTargetArrow??!1);class L{constructor(t,e,o,s,i,c,a){r(this,"svg");r(this,"group");r(this,"line");r(this,"sourceArrow",null);r(this,"targetArrow",null);this.color=t,this.width=e,this.arrowLength=o,this.arrowWidth=s,this.minPortOffset=i,this.hasSourceArrow=c,this.hasTargetArrow=a,this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.pointerEvents="none",this.group=document.createElementNS("http://www.w3.org/2000/svg","g"),this.svg.appendChild(this.group),this.line=document.createElementNS("http://www.w3.org/2000/svg","path"),this.line.setAttribute("stroke",this.color),this.line.setAttribute("stroke-width",`${this.width}`),this.line.setAttribute("fill","none"),this.group.appendChild(this.line),this.group.style.transformOrigin="50% 50%",this.hasSourceArrow&&(this.sourceArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.sourceArrow.setAttribute("fill",this.color),this.group.appendChild(this.sourceArrow)),this.hasTargetArrow&&(this.targetArrow=document.createElementNS("http://www.w3.org/2000/svg","path"),this.targetArrow.setAttribute("fill",this.color),this.group.appendChild(this.targetArrow)),this.svg.style.overflow="visible"}update(t,e,o,s,i,c){this.svg.style.width=`${o}px`,this.svg.style.height=`${s}px`;const a=v.getPortCenter(i),h=v.getPortCenter(c),l=a[0]<=h[0]?1:-1,m=a[1]<=h[1]?1:-1;this.svg.style.transform=`translate(${t}px, ${e}px)`,this.group.style.transform=`scale(${l}, ${m})`;const d=v.getDirectionVector(i.direction,l,m),g=v.getDirectionVector(c.direction,l,m),u=v.rotate([this.arrowLength+this.minPortOffset,0],d,[0,0]),C=v.rotate([o-this.arrowLength-this.minPortOffset,s],g,[o,s]),[b,S]=[o/2,s/2],T=l*(C[0]-u[0])>0?`M ${u[0]} ${u[1]} L ${b} ${u[1]} L ${b} ${C[1]} L ${C[0]} ${C[1]}`:`M ${u[0]} ${u[1]} L ${u[0]} ${S} L ${C[0]} ${S} L ${C[0]} ${C[1]}`,N=`M 0 0 L ${u[0]} ${u[1]} `,E=` M ${C[0]} ${C[1]} L ${o} ${s}`,f=v.getArrowOffsetPath(d,0,0,this.arrowLength,this.minPortOffset),y=v.getArrowOffsetPath(g,o,s,-this.arrowLength,-this.minPortOffset),A=`${this.sourceArrow?f:N}${T}${this.targetArrow?y:E}`;if(this.line.setAttribute("d",A),this.sourceArrow){const $=v.getArrowPath(d,0,0,this.arrowLength,this.arrowWidth);this.sourceArrow.setAttribute("d",$)}if(this.targetArrow){const $=v.getArrowPath(g,o,s,-this.arrowLength,this.arrowWidth);this.targetArrow.setAttribute("d",$)}}}const V=n=>()=>new L(n.color,n.width,n.arrowLength,n.arrowWidth,n.minPortOffset,n.hasSourceArrow,n.hasTargetArrow);var j=(n=>(n.Regular="regular",n.Cycle="cycle",n))(j||{});class Y{constructor(t){this.di=t}moveNodeOnTop(t){if(!this.di.graphStore.hasNode(t))throw new Error("failed to move on top nonexisting node");this.di.htmlController.moveNodeOnTop(t)}dragNode(t,e,o){if(!this.di.graphStore.hasNode(t))throw new Error("failed to drag nonexisting node");const s=this.di.graphStore.getNode(t),[i,c]=this.di.viewportTransformer.getViewCoords(s.x,s.y),a=i+e,h=c+o,[l,m]=this.di.viewportTransformer.getAbsCoords(a,h);this.di.graphStore.updateNodeCoords(t,l,m),this.di.htmlController.updateNodePosition(t)}addNode(t,e,o,s,i,c){if(t===void 0)do t=this.di.nodeIdGenerator.next();while(this.di.graphStore.hasNode(t));if(this.di.graphStore.hasNode(t))throw new Error("failed to add node with existing id");this.di.graphStore.addNode(t,e,o,s,c??this.di.options.nodes.centerFn),this.di.htmlController.attachNode(t),i!==void 0&&Object.entries(i).forEach(([a,h])=>{h instanceof HTMLElement?this.di.controller.markPort(a,h,t,this.di.options.ports.centerFn,null):this.di.controller.markPort(a,h.element,t,h.centerFn??this.di.options.ports.centerFn,h.direction??null)})}markPort(t,e,o,s,i){if(t===void 0)do t=this.di.portIdGenerator.next();while(this.di.graphStore.hasPort(t));if(!this.di.graphStore.hasNode(o))throw new Error("failed to set port on nonexisting node");if(this.di.graphStore.hasPort(t))throw new Error("failed to add port with existing id");this.di.graphStore.addPort(t,e,o,s??this.di.options.ports.centerFn,i??null)}updatePortConnections(t){if(!this.di.graphStore.hasPort(t))throw new Error("failed to unset nonexisting port");this.di.htmlController.updatePortConnections(t)}unmarkPort(t){if(!this.di.graphStore.hasPort(t))throw new Error("failed to unset nonexisting port");this.di.graphStore.getPortAdjacentConnections(t).forEach(e=>{this.removeConnection(e)}),this.di.graphStore.removePort(t)}addConnection(t,e,o,s){if(t===void 0)do t=this.di.connectionIdGenerator.next();while(this.di.graphStore.hasConnection(t));if(!this.di.graphStore.hasPort(e))throw new Error("failed to add connection from nonexisting port");if(!this.di.graphStore.hasPort(o))throw new Error("failed to add connection to nonexisting port");this.di.graphStore.addConnection(t,e,o,s(j.Regular)),this.di.htmlController.attachConnection(t)}removeConnection(t){if(!this.di.graphStore.hasConnection(t))throw new Error("failed to remove nonexisting connection");this.di.htmlController.detachConnection(t),this.di.graphStore.removeConnection(t)}removeNode(t){if(!this.di.graphStore.hasNode(t))throw new Error("failed to remove nonexisting node");this.di.htmlController.detachNode(t),this.di.graphStore.removeNode(t)}patchViewportTransform(t,e,o){this.di.viewportTransformer.patchState(t,e,o),this.di.htmlController.applyTransform()}moveContent(t,e){this.di.viewportTransformer.applyShift(-t,-e),this.di.htmlController.applyTransform()}scaleContent(t,e,o){this.di.viewportTransformer.applyScale(1/t,e,o),this.di.htmlController.applyTransform()}moveToNodes(t){if(t.length===0)return;const e=t.map(g=>this.di.graphStore.getNode(g)).filter(g=>g!==void 0);if(e.length<t.length)throw new Error("failed to move to nonexisting node");const[o,s]=e.reduce((g,u)=>[g[0]+u.x,g[1]+u.y],[0,0]),i=o/e.length,c=s/e.length,[a,h]=this.di.htmlController.getViewportDimensions(),l=this.di.viewportTransformer.getAbsScale(),m=i-l*a/2,d=c-l*h/2;this.patchViewportTransform(null,m,d)}updateNodeCoords(t,e,o){if(!this.di.graphStore.hasNode(t))throw new Error("failed to update coordinates of nonexisting node");this.di.graphStore.updateNodeCoords(t,e,o),this.di.htmlController.updateNodePosition(t)}updateConnectionOptions(t,e){if(!this.di.graphStore.hasConnection(t))throw new Error("failed to update nonexisting connection");this.di.htmlController.detachConnection(t),this.di.graphStore.updateConnectionController(t,e),this.di.htmlController.attachConnection(t)}clear(){this.di.htmlController.clear(),this.di.graphStore.clear(),this.di.nodeIdGenerator.reset(),this.di.portIdGenerator.reset(),this.di.connectionIdGenerator.reset()}destroy(){this.di.htmlController.destroy()}}class X{constructor(t){r(this,"htmlController");r(this,"viewportTransformer");r(this,"publicViewportTransformer");r(this,"controller");r(this,"graphStore");r(this,"publicGraphStore");r(this,"nodeIdGenerator");r(this,"portIdGenerator");r(this,"connectionIdGenerator");this.options=t,this.htmlController=new w(this),this.viewportTransformer=new P,this.publicViewportTransformer=new z(this.viewportTransformer),this.controller=new Y(this),this.graphStore=new G,this.publicGraphStore=new B(this.graphStore),this.nodeIdGenerator=new O,this.portIdGenerator=new O,this.connectionIdGenerator=new O}}const k=(n,t)=>[n/2,t/2],Z=()=>()=>{},H=(n,t,e,o,s,i)=>{n.fillStyle=i,n.fillRect(0,0,n.canvas.width,n.canvas.height);const c=t.getViewCoords(0,0),a=t.getViewScale(),h=o*a;let l=0,m=0,d=h/2;do d*=2,l=n.canvas.width/d,m=n.canvas.height/d;while(l*m>1e4);const g=c[0]-Math.floor(c[0]/d)*d,u=c[1]-Math.floor(c[1]/d)*d,C=s*a,b=2*Math.PI,S=g-d,T=u-d,N=n.canvas.width+g,E=n.canvas.height+u;n.fillStyle=e;for(let f=S;f<=N;f+=d)for(let y=T;y<=E;y+=d)n.beginPath(),n.arc(f,y,C,0,b),n.closePath(),n.fill()},U=(n,t,e,o)=>(s,i)=>{H(s,i,n,t,e,o)},q=(n,t)=>{n.fillStyle=t,n.fillRect(0,0,n.canvas.width,n.canvas.height)},J=n=>t=>{q(t,n)},K=n=>{switch(n==null?void 0:n.type){case"custom":return n.drawingFn;case"dots":return U(n.dotColor??"#d8d8d8",n.dotGap??25,n.dotRadius??1.5,n.color??"#ffffff");case"color":return J(n.color??"#ffffff");default:return Z()}},F=n=>{switch(n==null?void 0:n.type){case"custom":return n.controllerFactory;case"straight":return V({color:n.color??"#5c5c5c",width:n.width??1,arrowLength:n.arrowLength??15,arrowWidth:n.arrowWidth??4,minPortOffset:n.minPortOffset??15,hasSourceArrow:n.hasSourceArrow??!1,hasTargetArrow:n.hasTargetArrow??!1});default:return M({color:n.color??"#5c5c5c",width:n.width??1,curvature:n.curvature??90,arrowLength:n.arrowLength??15,arrowWidth:n.arrowWidth??4,hasSourceArrow:n.hasSourceArrow??!1,hasTargetArrow:n.hasTargetArrow??!1})}},Q=n=>{var t,e,o;return{background:{drawingFn:K(n.background??{type:"none"})},nodes:{centerFn:((t=n.nodes)==null?void 0:t.centerFn)??k},ports:{centerFn:((e=n.ports)==null?void 0:e.centerFn)??k},connections:{controllerFactory:F(n.connections??{})},layers:{mode:((o=n.layers)==null?void 0:o.mode)??"connections-follow-node"}}};class W{constructor(t){r(this,"transformation");r(this,"model");r(this,"options");r(this,"di");this.apiOptions=t,this.options=Q(this.apiOptions??{}),this.di=new X(this.options),this.transformation=this.di.publicViewportTransformer,this.model=this.di.publicGraphStore}addNode(t){return this.di.controller.addNode(t.id,t.element,t.x,t.y,t.ports,t.centerFn),this}moveNodeOnTop(t){return this.di.controller.moveNodeOnTop(t),this}removeNode(t){return this.di.controller.removeNode(t),this}markPort(t){return this.di.controller.markPort(t.id,t.element,t.nodeId,t.centerFn,t.direction),this}updatePortConnections(t){return this.di.controller.updatePortConnections(t),this}unmarkPort(t){return this.di.controller.unmarkPort(t),this}addConnection(t){const e=t.options!==void 0?F(t.options):this.di.options.connections.controllerFactory;return this.di.controller.addConnection(t.id,t.from,t.to,e),this}removeConnection(t){return this.di.controller.removeConnection(t),this}patchViewportTransform(t){return this.di.controller.patchViewportTransform(t.scale??null,t.x??null,t.y??null),this}moveContent(t){return this.di.controller.moveContent(t.x??0,t.y??0),this}scaleContent(t){return this.di.controller.scaleContent(t.scale,t.x??0,t.y??0),this}moveToNodes(t){return this.di.controller.moveToNodes(t),this}updateNodeCoords(t,e,o){return this.di.controller.updateNodeCoords(t,e,o),this}updateConnectionController(t,e){return this.di.controller.updateConnectionOptions(t,e),this}dragNode(t,e,o){return this.di.controller.dragNode(t,e,o),this}clear(){return this.di.controller.clear(),this}attach(t){return this.di.htmlController.attach(t),this}detach(){return this.di.htmlController.detach(),this}destroy(){this.di.controller.destroy()}}class D{constructor(t){r(this,"transformation");r(this,"model");r(this,"nodes",new Map);r(this,"grabbedNodeId",null);r(this,"nodeIdGenerator",new O);r(this,"element",null);r(this,"onCanvasMouseUp",()=>{this.setCursor(null),this.grabbedNodeId=null});r(this,"onCanvasMouseMove",t=>{this.grabbedNodeId!==null&&(t.stopPropagation(),this.canvas.dragNode(this.grabbedNodeId,t.movementX,t.movementY))});r(this,"onCanvasTouchStart",t=>{this.previousTouchCoords=[t.touches[0].clientX,t.touches[0].clientY]});r(this,"onCanvasTouchMove",t=>{if(this.grabbedNodeId===null||t.touches.length!==1||this.previousTouchCoords===null)return;t.stopImmediatePropagation();const[e,o]=[t.touches[0].clientX-this.previousTouchCoords[0],t.touches[0].clientY-this.previousTouchCoords[1]];this.canvas.dragNode(this.grabbedNodeId,e,o),this.previousTouchCoords=[t.touches[0].clientX,t.touches[0].clientY]});r(this,"onCanvasTouchEnd",()=>{this.previousTouchCoords=null,this.grabbedNodeId=null});r(this,"previousTouchCoords",null);this.canvas=t,this.transformation=this.canvas.transformation,this.model=this.canvas.model}addNode(t){let e=t.id;if(e===void 0)do e=this.nodeIdGenerator.next();while(this.nodes.has(e));this.canvas.addNode(t);const o=i=>{i.stopImmediatePropagation(),this.grabbedNodeId=e,this.setCursor("grab"),this.canvas.moveNodeOnTop(e)},s=i=>{i.touches.length===1&&(this.grabbedNodeId=e,this.canvas.moveNodeOnTop(e))};return this.nodes.set(e,{el:t.element,onMouseDown:o,onTouchStart:s}),t.element.addEventListener("mousedown",o),t.element.addEventListener("touchstart",s),this}removeNode(t){const e=this.nodes.get(t);return e!==void 0&&(e.el.removeEventListener("mousedown",e.onMouseDown),e.el.removeEventListener("touchstart",e.onTouchStart)),this.canvas.removeNode(t),this.nodes.delete(t),this}markPort(t){return this.canvas.markPort(t),this}updatePortConnections(t){return this.canvas.updatePortConnections(t),this}unmarkPort(t){return this.canvas.unmarkPort(t),this}addConnection(t){return this.canvas.addConnection(t),this}removeConnection(t){return this.canvas.removeConnection(t),this}patchViewportTransform(t){return this.canvas.patchViewportTransform(t),this}moveContent(t){return this.canvas.moveContent(t),this}scaleContent(t){return this.canvas.scaleContent(t),this}moveToNodes(t){return this.canvas.moveToNodes(t),this}updateNodeCoords(t,e,o){return this.canvas.updateNodeCoords(t,e,o),this}updateConnectionController(t,e){return this.canvas.updateConnectionController(t,e),this}dragNode(t,e,o){return this.canvas.dragNode(t,e,o),this}moveNodeOnTop(t){return this.canvas.moveNodeOnTop(t),this}clear(){return this.canvas.clear(),this.nodes.forEach(t=>{t.el.removeEventListener("mousedown",t.onMouseDown),t.el.removeEventListener("touchstart",t.onTouchStart)}),this.nodes.clear(),this}attach(t){return this.canvas.attach(t),this.element=t,t.addEventListener("mouseup",this.onCanvasMouseUp),t.addEventListener("mousemove",this.onCanvasMouseMove),t.addEventListener("touchstart",this.onCanvasTouchStart),t.addEventListener("touchmove",this.onCanvasTouchMove),t.addEventListener("touchend",this.onCanvasTouchEnd),t.addEventListener("touchcancel",this.onCanvasTouchEnd),this}detach(){return this.canvas.detach(),this.element!==null&&(this.element.removeEventListener("mouseup",this.onCanvasMouseUp),this.element.removeEventListener("mousemove",this.onCanvasMouseMove),this.element.removeEventListener("touchstart",this.onCanvasTouchStart),this.element.removeEventListener("touchmove",this.onCanvasTouchMove),this.element.removeEventListener("touchend",this.onCanvasTouchEnd),this.element.removeEventListener("touchcancel",this.onCanvasTouchEnd),this.element=null),this}destroy(){this.detach(),this.nodes.forEach(t=>{t.el.removeEventListener("mousedown",t.onMouseDown),t.el.removeEventListener("touchstart",t.onTouchStart)}),this.canvas.destroy()}setCursor(t){this.element!==null&&(t!==null?this.element.style.cursor=t:this.element.style.removeProperty("cursor"))}}class R{constructor(t,e){r(this,"transformation");r(this,"model");r(this,"element",null);r(this,"isMoving",!1);r(this,"prevTouches",null);r(this,"isScalable");r(this,"isShiftable");r(this,"minContentScale");r(this,"maxContentScale");r(this,"wheelSensitivity");r(this,"onMouseDown",()=>{this.setCursor("grab"),this.isMoving=!0});r(this,"onMouseMove",t=>{!this.isMoving||!this.isShiftable||this.canvas.moveContent({x:t.movementX,y:t.movementY})});r(this,"onMouseUp",()=>{this.setCursor(null),this.isMoving=!1});r(this,"onWheelScroll",t=>{if(this.element===null||this.isScalable===!1)return;t.preventDefault();const{left:e,top:o}=this.element.getBoundingClientRect(),s=t.clientX-e,i=t.clientY-o,c=t.deltaY<0?this.wheelSensitivity:1/this.wheelSensitivity,a=this.canvas.transformation.getViewScale()*c;this.checkNextScaleValid(a)&&this.canvas.scaleContent({scale:c,x:s,y:i})});r(this,"onTouchStart",t=>{this.prevTouches=this.getAverageTouch(t)});r(this,"onTouchMove",t=>{if(this.prevTouches===null||this.element===null||!this.isShiftable)return;const e=this.getAverageTouch(t);if((e.touchesCnt===1||e.touchesCnt===2)&&this.canvas.moveContent({x:e.x-this.prevTouches.x,y:e.y-this.prevTouches.y}),e.touchesCnt===2&&this.isScalable){const{left:o,top:s}=this.element.getBoundingClientRect(),i=this.prevTouches.x-o,c=this.prevTouches.y-s,a=e.scale/this.prevTouches.scale,h=this.canvas.transformation.getViewScale()*a;this.checkNextScaleValid(h)&&this.canvas.scaleContent({scale:a,x:i,y:c})}this.prevTouches=e,t.preventDefault()});r(this,"onTouchEnd",()=>{this.prevTouches=null});var s,i,c,a,h,l,m,d,g,u;this.canvas=t,this.options=e,this.transformation=this.canvas.transformation,this.model=this.canvas.model,this.isScalable=((i=(s=this.options)==null?void 0:s.scale)==null?void 0:i.enabled)!==!1,this.minContentScale=((a=(c=this.options)==null?void 0:c.scale)==null?void 0:a.minContent)??null,this.maxContentScale=((l=(h=this.options)==null?void 0:h.scale)==null?void 0:l.maxContent)??null,this.isShiftable=((d=(m=this.options)==null?void 0:m.shift)==null?void 0:d.enabled)!==!1;const o=(u=(g=this.options)==null?void 0:g.scale)==null?void 0:u.wheelSensitivity;this.wheelSensitivity=o!==void 0?o:1.2}addNode(t){return this.canvas.addNode(t),this}removeNode(t){return this.canvas.removeNode(t),this}markPort(t){return this.canvas.markPort(t),this}updatePortConnections(t){return this.canvas.updatePortConnections(t),this}unmarkPort(t){return this.canvas.unmarkPort(t),this}addConnection(t){return this.canvas.addConnection(t),this}removeConnection(t){return this.canvas.removeConnection(t),this}patchViewportTransform(t){return this.canvas.patchViewportTransform(t),this}moveContent(t){return this.canvas.moveContent(t),this}scaleContent(t){return this.canvas.scaleContent(t),this}moveToNodes(t){return this.canvas.moveToNodes(t),this}updateNodeCoords(t,e,o){return this.canvas.updateNodeCoords(t,e,o),this}updateConnectionController(t,e){return this.canvas.updateConnectionController(t,e),this}dragNode(t,e,o){return this.canvas.dragNode(t,e,o),this}moveNodeOnTop(t){return this.canvas.moveNodeOnTop(t),this}clear(){return this.canvas.clear(),this}attach(t){return this.canvas.attach(t),this.element=t,t.addEventListener("mousedown",this.onMouseDown),t.addEventListener("mousemove",this.onMouseMove),t.addEventListener("mouseup",this.onMouseUp),t.addEventListener("wheel",this.onWheelScroll),t.addEventListener("touchstart",this.onTouchStart),t.addEventListener("touchmove",this.onTouchMove),t.addEventListener("touchend",this.onTouchEnd),t.addEventListener("touchcancel",this.onTouchEnd),this}detach(){return this.canvas.detach(),this.element!==null&&(this.element.removeEventListener("mousedown",this.onMouseDown),this.element.removeEventListener("mousemove",this.onMouseMove),this.element.removeEventListener("mouseup",this.onMouseUp),this.element.removeEventListener("wheel",this.onWheelScroll),this.element.removeEventListener("touchstart",this.onTouchStart),this.element.removeEventListener("touchmove",this.onTouchMove),this.element.removeEventListener("touchend",this.onTouchEnd),this.element.removeEventListener("touchcancel",this.onTouchEnd)),this.element=null,this}destroy(){this.detach(),this.canvas.destroy()}getAverageTouch(t){const e=[],o=t.touches.length;for(let h=0;h<o;h++)e.push([t.touches[h].clientX,t.touches[h].clientY]);const s=e.reduce((h,l)=>[h[0]+l[0],h[1]+l[1]],[0,0]),i=[s[0]/o,s[1]/o],a=e.map(h=>[h[0]-i[0],h[1]-i[1]]).reduce((h,l)=>h+Math.sqrt(l[0]*l[0]+l[1]*l[1]),0);return{x:i[0],y:i[1],scale:a/o,touchesCnt:o}}checkNextScaleValid(t){const e=this.canvas.transformation.getViewScale();return!(this.maxContentScale!==null&&t>this.maxContentScale&&t>e||this.minContentScale!==null&&t<this.minContentScale&&t<e)}setCursor(t){this.element!==null&&(t!==null?this.element.style.cursor=t:this.element.style.removeProperty("cursor"))}}class _{constructor(){r(this,"coreOptions");r(this,"transformOptions");r(this,"isDraggable",!1);r(this,"isTransformable",!1)}setOptions(t){return this.coreOptions=t,this}setDraggableNodes(){return this.isDraggable=!0,this}setTransformableCanvas(t){return this.isTransformable=!0,this.transformOptions=t,this}build(){let t=new W(this.coreOptions);return this.isDraggable&&(t=new D(t)),this.isTransformable&&(t=new R(t,this.transformOptions)),t}}p.BezierConnectionController=x,p.CanvasCore=W,p.ConnectionUtils=v,p.DraggableNodesCanvas=D,p.HtmlGraphBuilder=_,p.StraightConnectionController=L,p.TransformableCanvas=R,p.createBezierConnectionControllerFactory=M,p.createStraightConnectionControllerFactory=V,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@html-graph/html-graph",
|
|
3
3
|
"author": "Dmitry Marov",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.46",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/main.js",
|
|
8
8
|
"types": "dist/main.d.ts",
|
|
@@ -35,12 +35,14 @@
|
|
|
35
35
|
"fix-lint": "eslint . --fix",
|
|
36
36
|
"build": "tsc --p ./tsconfig-build-library.json && vite build",
|
|
37
37
|
"preview": "vite preview",
|
|
38
|
-
"
|
|
39
|
-
"release-next-version": "tsx ./scripts/release-next-version.ts"
|
|
38
|
+
"beforebuild": "npm run lint && npm run check-formatting",
|
|
39
|
+
"release-next-version": "tsx ./scripts/release-next-version.ts",
|
|
40
|
+
"make-deps-graph": "npx depcruise lib --include-only \"^lib\" --output-type dot > ./deps-graph/deps-graph.dot"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@eslint/js": "^9.9.1",
|
|
43
44
|
"@types/node": "^22.5.0",
|
|
45
|
+
"dependency-cruiser": "^16.7.0",
|
|
44
46
|
"eslint": "^9.9.1",
|
|
45
47
|
"globals": "^15.9.0",
|
|
46
48
|
"prettier": "3.3.3",
|