@metadev/daga 4.2.6 → 4.2.8

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/index.cjs.js CHANGED
@@ -402,7 +402,20 @@ const linePath = (shape, points, startDirection, endDirection, minimumDistanceBe
402
402
  result += `M ${points[0][0]} ${points[0][1]}`;
403
403
  for (let i = 1; i < points.length; ++i) {
404
404
  if (i + 1 >= points.length) {
405
- nextDirection = endDirection;
405
+ switch (endDirection) {
406
+ case exports.Side.Bottom:
407
+ nextDirection = exports.Side.Top;
408
+ break;
409
+ case exports.Side.Top:
410
+ nextDirection = exports.Side.Bottom;
411
+ break;
412
+ case exports.Side.Right:
413
+ nextDirection = exports.Side.Left;
414
+ break;
415
+ case exports.Side.Left:
416
+ nextDirection = exports.Side.Right;
417
+ break;
418
+ }
406
419
  } else {
407
420
  if (Math.abs(points[i][0] - points[i - 1][0]) < Math.abs(points[i][1] - points[i - 1][1])) {
408
421
  if (points[i][1] > points[i - 1][1]) {
@@ -438,16 +451,16 @@ const linePath = (shape, points, startDirection, endDirection, minimumDistanceBe
438
451
  }
439
452
  if (nextDirection !== undefined) {
440
453
  switch (nextDirection) {
441
- case exports.Side.Bottom:
454
+ case exports.Side.Top:
442
455
  controlPoint2 = `${points[i][0]} ${points[i][1] + controlPointDistance}`;
443
456
  break;
444
- case exports.Side.Top:
457
+ case exports.Side.Bottom:
445
458
  controlPoint2 = `${points[i][0]} ${points[i][1] - controlPointDistance}`;
446
459
  break;
447
- case exports.Side.Right:
460
+ case exports.Side.Left:
448
461
  controlPoint2 = `${points[i][0] + controlPointDistance} ${points[i][1]}`;
449
462
  break;
450
- case exports.Side.Left:
463
+ case exports.Side.Right:
451
464
  controlPoint2 = `${points[i][0] - controlPointDistance} ${points[i][1]}`;
452
465
  break;
453
466
  }
@@ -460,16 +473,16 @@ const linePath = (shape, points, startDirection, endDirection, minimumDistanceBe
460
473
  let controlPoint = '';
461
474
  const controlPointDistance = (Math.abs(points[i][0] - points[i - 1][0]) + Math.abs(points[i][1] - points[i - 1][1])) / 2;
462
475
  switch (nextDirection) {
463
- case exports.Side.Bottom:
476
+ case exports.Side.Top:
464
477
  controlPoint = `${points[i][0]} ${points[i][1] + controlPointDistance}`;
465
478
  break;
466
- case exports.Side.Top:
479
+ case exports.Side.Bottom:
467
480
  controlPoint = `${points[i][0]} ${points[i][1] - controlPointDistance}`;
468
481
  break;
469
- case exports.Side.Right:
482
+ case exports.Side.Left:
470
483
  controlPoint = `${points[i][0] + controlPointDistance} ${points[i][1]}`;
471
484
  break;
472
- case exports.Side.Left:
485
+ case exports.Side.Right:
473
486
  controlPoint = `${points[i][0] - controlPointDistance} ${points[i][1]}`;
474
487
  break;
475
488
  }
@@ -482,152 +495,443 @@ const linePath = (shape, points, startDirection, endDirection, minimumDistanceBe
482
495
  }
483
496
  break;
484
497
  case exports.LineShape.Square:
498
+ currentDirection = startDirection;
485
499
  result += `M ${points[0][0]} ${points[0][1]}`;
486
- if (startDirection) {
487
- switch (startDirection) {
488
- case exports.Side.Bottom:
489
- points.splice(1, 0, [points[0][0], points[0][1] + minimumDistanceBeforeTurn]);
490
- break;
491
- case exports.Side.Top:
492
- points.splice(1, 0, [points[0][0], points[0][1] - minimumDistanceBeforeTurn]);
493
- break;
494
- case exports.Side.Right:
495
- points.splice(1, 0, [points[0][0] + minimumDistanceBeforeTurn, points[0][1]]);
496
- break;
497
- case exports.Side.Left:
498
- points.splice(1, 0, [points[0][0] - minimumDistanceBeforeTurn, points[0][1]]);
499
- break;
500
- }
501
- }
502
- if (endDirection) {
503
- switch (endDirection) {
504
- case exports.Side.Bottom:
505
- points.splice(points.length - 1, 0, [points[points.length - 1][0], points[points.length - 1][1] + minimumDistanceBeforeTurn]);
506
- break;
507
- case exports.Side.Top:
508
- points.splice(points.length - 1, 0, [points[points.length - 1][0], points[points.length - 1][1] - minimumDistanceBeforeTurn]);
509
- break;
510
- case exports.Side.Right:
511
- points.splice(points.length - 1, 0, [points[points.length - 1][0] + minimumDistanceBeforeTurn, points[points.length - 1][1]]);
512
- break;
513
- case exports.Side.Left:
514
- points.splice(points.length - 1, 0, [points[points.length - 1][0] - minimumDistanceBeforeTurn, points[points.length - 1][1]]);
515
- break;
516
- }
517
- }
518
500
  for (let i = 1; i < points.length; ++i) {
519
- if (currentDirection !== undefined) {
520
- switch (currentDirection) {
501
+ if (i + 1 >= points.length) {
502
+ switch (endDirection) {
521
503
  case exports.Side.Bottom:
522
- if (points[i][1] < points[i - 1][1] && points[i][0] !== points[i - 1][0]) {
523
- // next point is behind, we turn around
524
- result += ` H ${points[i][0]}`;
525
- result += ` V ${points[i][1]}`;
526
- currentDirection = exports.Side.Top;
527
- } else if (points[i][1] < points[i - 1][1] && points[i][0] === points[i - 1][0]) {
528
- // next point is behind on the same line, we turn around
529
- result += ` H ${points[i][0] + minimumDistanceBeforeTurn}`;
530
- result += ` V ${points[i][1]}`;
531
- result += ` H ${points[i][0]}`;
532
- currentDirection = exports.Side.Left;
533
- } else if (points[i][1] === points[i - 1][1] && points[i][0] !== points[i - 1][0]) {
534
- // next point is perpendicular to us
535
- result += ` H ${points[i][0]}`;
536
- currentDirection = points[i][0] > points[i - 1][0] ? exports.Side.Right : exports.Side.Left;
537
- } else if (points[i][1] > points[i - 1][1] && points[i][0] !== points[i - 1][0]) {
538
- // next point is after us, we turn and continue
539
- result += ` H ${points[i][0]}`;
540
- result += ` V ${points[i][1]}`;
541
- } else if (points[i][1] > points[i - 1][1] && points[i][0] === points[i - 1][0]) {
542
- // next point is in the same direction, we continue straight
543
- result += ` V ${points[i][1]}`;
544
- }
504
+ nextDirection = exports.Side.Top;
545
505
  break;
546
506
  case exports.Side.Top:
547
- if (points[i][1] > points[i - 1][1] && points[i][0] !== points[i - 1][0]) {
548
- // next point is behind, we turn around
549
- result += ` H ${points[i][0]}`;
550
- result += ` V ${points[i][1]}`;
551
- currentDirection = exports.Side.Bottom;
552
- } else if (points[i][1] > points[i - 1][1] && points[i][0] === points[i - 1][0]) {
553
- // next point is behind on the same line, we turn around
554
- result += ` H ${points[i][0] - minimumDistanceBeforeTurn}`;
555
- result += ` V ${points[i][1]}`;
556
- result += ` H ${points[i][0]}`;
557
- currentDirection = exports.Side.Right;
558
- } else if (points[i][1] === points[i - 1][1] && points[i][0] !== points[i - 1][0]) {
559
- // next point is perpendicular to us
560
- result += ` H ${points[i][0]}`;
561
- currentDirection = points[i][0] > points[i - 1][0] ? exports.Side.Right : exports.Side.Left;
562
- } else if (points[i][1] < points[i - 1][1] && points[i][0] !== points[i - 1][0]) {
563
- // next point is after us, we turn and continue
564
- result += ` H ${points[i][0]}`;
565
- result += ` V ${points[i][1]}`;
566
- } else if (points[i][1] < points[i - 1][1] && points[i][0] === points[i - 1][0]) {
567
- // next point is in the same direction, we continue straight
568
- result += ` V ${points[i][1]}`;
569
- }
507
+ nextDirection = exports.Side.Bottom;
570
508
  break;
571
509
  case exports.Side.Right:
572
- if (points[i][0] < points[i - 1][0] && points[i][1] !== points[i - 1][1]) {
573
- // next point is behind, we turn around
574
- result += ` V ${points[i][1]}`;
575
- result += ` H ${points[i][0]}`;
576
- currentDirection = exports.Side.Left;
577
- } else if (points[i][0] < points[i - 1][0] && points[i][1] === points[i - 1][1]) {
578
- // next point is behind on the same line, we turn around
579
- result += ` V ${points[i][1] + minimumDistanceBeforeTurn}`;
580
- result += ` H ${points[i][0]}`;
581
- result += ` V ${points[i][1]}`;
582
- currentDirection = exports.Side.Top;
583
- } else if (points[i][0] === points[i - 1][0] && points[i][1] !== points[i - 1][1]) {
584
- // next point is perpendicular to us
585
- result += ` V ${points[i][1]}`;
586
- currentDirection = points[i][1] > points[i - 1][1] ? exports.Side.Bottom : exports.Side.Top;
587
- } else if (points[i][0] > points[i - 1][0] && points[i][1] !== points[i - 1][1]) {
588
- // next point is after us, we turn and continue
589
- result += ` V ${points[i][1]}`;
590
- result += ` H ${points[i][0]}`;
591
- } else if (points[i][0] > points[i - 1][0] && points[i][1] === points[i - 1][1]) {
592
- // next point is in the same direction, we continue straight
593
- result += ` H ${points[i][0]}`;
594
- }
510
+ nextDirection = exports.Side.Left;
595
511
  break;
596
512
  case exports.Side.Left:
597
- if (points[i][0] > points[i - 1][0] && points[i][1] !== points[i - 1][1]) {
598
- // next point is behind, we turn around
599
- result += ` V ${points[i][1]}`;
600
- result += ` H ${points[i][0]}`;
601
- currentDirection = exports.Side.Right;
602
- } else if (points[i][0] > points[i - 1][0] && points[i][1] === points[i - 1][1]) {
603
- // next point is behind on the same line, we turn around
604
- result += ` V ${points[i][1] - minimumDistanceBeforeTurn}`;
513
+ nextDirection = exports.Side.Right;
514
+ break;
515
+ }
516
+ }
517
+ switch (currentDirection) {
518
+ case exports.Side.Bottom:
519
+ switch (nextDirection) {
520
+ case exports.Side.Bottom:
521
+ if (points[i][1] > points[i - 1][1]) {
522
+ if (points[i][0] !== points[i - 1][0]) {
523
+ result += ` V ${(points[i][1] + points[i - 1][1]) / 2}`;
524
+ result += ` H ${points[i][0]}`;
525
+ result += ` V ${points[i][1]}`;
526
+ } else {
527
+ result += ` V ${points[i][1]}`;
528
+ }
529
+ currentDirection = nextDirection;
530
+ } else {
531
+ if (points[i][0] > points[i - 1][0]) {
532
+ result += ` V ${points[i - 1][1] + minimumDistanceBeforeTurn}`;
533
+ result += ` H ${Math.max(points[i - 1][0], points[i][0]) + minimumDistanceBeforeTurn}`;
534
+ result += ` V ${points[i][1] - minimumDistanceBeforeTurn}`;
535
+ result += ` H ${points[i][0]}`;
536
+ result += ` V ${points[i][1]}`;
537
+ } else {
538
+ result += ` V ${points[i - 1][1] + minimumDistanceBeforeTurn}`;
539
+ result += ` H ${Math.min(points[i - 1][0], points[i][0]) - minimumDistanceBeforeTurn}`;
540
+ result += ` V ${points[i][1] - minimumDistanceBeforeTurn}`;
541
+ result += ` H ${points[i][0]}`;
542
+ result += ` V ${points[i][1]}`;
543
+ }
544
+ }
545
+ break;
546
+ case exports.Side.Top:
547
+ result += ` V ${Math.max(points[i - 1][1], points[i][1]) + minimumDistanceBeforeTurn}`;
605
548
  result += ` H ${points[i][0]}`;
606
549
  result += ` V ${points[i][1]}`;
607
- currentDirection = exports.Side.Bottom;
608
- } else if (points[i][0] === points[i - 1][0] && points[i][1] !== points[i - 1][1]) {
609
- // next point is perpendicular to us
550
+ break;
551
+ case exports.Side.Left:
552
+ if (points[i][1] > points[i - 1][1] + minimumDistanceBeforeTurn) {
553
+ if (points[i][0] < points[i - 1][0] - minimumDistanceBeforeTurn) {
554
+ result += ` V ${points[i][1]}`;
555
+ result += ` H ${points[i][0]}`;
556
+ } else {
557
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
558
+ result += ` H ${points[i][0] + minimumDistanceBeforeTurn}`;
559
+ result += ` V ${points[i][1]}`;
560
+ result += ` H ${points[i][0]}`;
561
+ }
562
+ } else {
563
+ if (points[i][0] < points[i - 1][0] - minimumDistanceBeforeTurn) {
564
+ result += ` V ${points[i - 1][1] + minimumDistanceBeforeTurn}`;
565
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
566
+ result += ` V ${points[i][1]}`;
567
+ result += ` H ${points[i][0]}`;
568
+ } else {
569
+ result += ` V ${points[i - 1][1] + minimumDistanceBeforeTurn}`;
570
+ result += ` H ${points[i][0] + minimumDistanceBeforeTurn}`;
571
+ result += ` V ${points[i][1]}`;
572
+ result += ` H ${points[i][0]}`;
573
+ }
574
+ }
575
+ break;
576
+ case exports.Side.Right:
577
+ if (points[i][1] > points[i - 1][1] + minimumDistanceBeforeTurn) {
578
+ if (points[i][0] > points[i - 1][0] + minimumDistanceBeforeTurn) {
579
+ result += ` V ${points[i][1]}`;
580
+ result += ` H ${points[i][0]}`;
581
+ } else {
582
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
583
+ result += ` H ${points[i][0] - minimumDistanceBeforeTurn}`;
584
+ result += ` V ${points[i][1]}`;
585
+ result += ` H ${points[i][0]}`;
586
+ }
587
+ } else {
588
+ if (points[i][0] > points[i - 1][0] + minimumDistanceBeforeTurn) {
589
+ result += ` V ${points[i - 1][1] + minimumDistanceBeforeTurn}`;
590
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
591
+ result += ` V ${points[i][1]}`;
592
+ result += ` H ${points[i][0]}`;
593
+ } else {
594
+ result += ` V ${points[i - 1][1] + minimumDistanceBeforeTurn}`;
595
+ result += ` H ${points[i][0] - minimumDistanceBeforeTurn}`;
596
+ result += ` V ${points[i][1]}`;
597
+ result += ` H ${points[i][0]}`;
598
+ }
599
+ }
600
+ break;
601
+ default:
602
+ if (points[i][1] < points[i - 1][1] + minimumDistanceBeforeTurn) {
603
+ result += ` V ${points[i - 1][1] + minimumDistanceBeforeTurn}`;
604
+ if (points[i][0] !== points[i - 1][0]) {
605
+ result += ` H ${points[i][0]}`;
606
+ }
607
+ result += ` V ${points[i][1]}`;
608
+ currentDirection = exports.Side.Top;
609
+ } else {
610
+ result += ` V ${points[i][1]}`;
611
+ currentDirection = exports.Side.Bottom;
612
+ if (points[i][0] !== points[i - 1][0]) {
613
+ result += ` H ${points[i][0]}`;
614
+ currentDirection = points[i][0] > points[i - 1][0] ? exports.Side.Right : exports.Side.Left;
615
+ }
616
+ }
617
+ break;
618
+ }
619
+ break;
620
+ case exports.Side.Top:
621
+ switch (nextDirection) {
622
+ case exports.Side.Top:
623
+ if (points[i][1] < points[i - 1][1]) {
624
+ if (points[i][0] !== points[i - 1][0]) {
625
+ result += ` V ${(points[i][1] + points[i - 1][1]) / 2}`;
626
+ result += ` H ${points[i][0]}`;
627
+ result += ` V ${points[i][1]}`;
628
+ } else {
629
+ result += ` V ${points[i][1]}`;
630
+ }
631
+ currentDirection = nextDirection;
632
+ } else {
633
+ if (points[i][0] < points[i - 1][0]) {
634
+ result += ` V ${points[i - 1][1] - minimumDistanceBeforeTurn}`;
635
+ result += ` H ${Math.min(points[i - 1][0], points[i][0]) - minimumDistanceBeforeTurn}`;
636
+ result += ` V ${points[i][1] + minimumDistanceBeforeTurn}`;
637
+ result += ` H ${points[i][0]}`;
638
+ result += ` V ${points[i][1]}`;
639
+ } else {
640
+ result += ` V ${points[i - 1][1] - minimumDistanceBeforeTurn}`;
641
+ result += ` H ${Math.max(points[i - 1][0], points[i][0]) + minimumDistanceBeforeTurn}`;
642
+ result += ` V ${points[i][1] + minimumDistanceBeforeTurn}`;
643
+ result += ` H ${points[i][0]}`;
644
+ result += ` V ${points[i][1]}`;
645
+ }
646
+ }
647
+ break;
648
+ case exports.Side.Bottom:
649
+ result += ` V ${Math.min(points[i - 1][1], points[i][1]) - minimumDistanceBeforeTurn}`;
650
+ result += ` H ${points[i][0]}`;
610
651
  result += ` V ${points[i][1]}`;
611
- currentDirection = points[i][1] > points[i - 1][1] ? exports.Side.Bottom : exports.Side.Top;
612
- } else if (points[i][0] < points[i - 1][0] && points[i][1] !== points[i - 1][1]) {
613
- // next point is after us, we turn and continue
652
+ break;
653
+ case exports.Side.Right:
654
+ if (points[i][1] < points[i - 1][1] - minimumDistanceBeforeTurn) {
655
+ if (points[i][0] > points[i - 1][0] + minimumDistanceBeforeTurn) {
656
+ result += ` V ${points[i][1]}`;
657
+ result += ` H ${points[i][0]}`;
658
+ } else {
659
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
660
+ result += ` H ${points[i][0] - minimumDistanceBeforeTurn}`;
661
+ result += ` V ${points[i][1]}`;
662
+ result += ` H ${points[i][0]}`;
663
+ }
664
+ } else {
665
+ if (points[i][0] > points[i - 1][0] + minimumDistanceBeforeTurn) {
666
+ result += ` V ${points[i - 1][1] - minimumDistanceBeforeTurn}`;
667
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
668
+ result += ` V ${points[i][1]}`;
669
+ result += ` H ${points[i][0]}`;
670
+ } else {
671
+ result += ` V ${points[i - 1][1] - minimumDistanceBeforeTurn}`;
672
+ result += ` H ${points[i][0] - minimumDistanceBeforeTurn}`;
673
+ result += ` V ${points[i][1]}`;
674
+ result += ` H ${points[i][0]}`;
675
+ }
676
+ }
677
+ break;
678
+ case exports.Side.Left:
679
+ if (points[i][1] < points[i - 1][1] - minimumDistanceBeforeTurn) {
680
+ if (points[i][0] < points[i - 1][0] - minimumDistanceBeforeTurn) {
681
+ result += ` V ${points[i][1]}`;
682
+ result += ` H ${points[i][0]}`;
683
+ } else {
684
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
685
+ result += ` H ${points[i][0] + minimumDistanceBeforeTurn}`;
686
+ result += ` V ${points[i][1]}`;
687
+ result += ` H ${points[i][0]}`;
688
+ }
689
+ } else {
690
+ if (points[i][0] < points[i - 1][0] - minimumDistanceBeforeTurn) {
691
+ result += ` V ${points[i - 1][1] - minimumDistanceBeforeTurn}`;
692
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
693
+ result += ` V ${points[i][1]}`;
694
+ result += ` H ${points[i][0]}`;
695
+ } else {
696
+ result += ` V ${points[i - 1][1] - minimumDistanceBeforeTurn}`;
697
+ result += ` H ${points[i][0] + minimumDistanceBeforeTurn}`;
698
+ result += ` V ${points[i][1]}`;
699
+ result += ` H ${points[i][0]}`;
700
+ }
701
+ }
702
+ break;
703
+ default:
704
+ if (points[i][1] > points[i - 1][1] - minimumDistanceBeforeTurn) {
705
+ result += ` V ${points[i - 1][1] - minimumDistanceBeforeTurn}`;
706
+ if (points[i][0] !== points[i - 1][0]) {
707
+ result += ` H ${points[i][0]}`;
708
+ }
709
+ result += ` V ${points[i][1]}`;
710
+ currentDirection = exports.Side.Bottom;
711
+ } else {
712
+ result += ` V ${points[i][1]}`;
713
+ currentDirection = exports.Side.Top;
714
+ if (points[i][0] !== points[i - 1][0]) {
715
+ result += ` H ${points[i][0]}`;
716
+ currentDirection = points[i][0] > points[i - 1][0] ? exports.Side.Right : exports.Side.Left;
717
+ }
718
+ }
719
+ break;
720
+ }
721
+ break;
722
+ case exports.Side.Left:
723
+ switch (nextDirection) {
724
+ case exports.Side.Left:
725
+ if (points[i][0] < points[i - 1][0]) {
726
+ if (points[i][1] !== points[i - 1][1]) {
727
+ result += ` H ${(points[i][0] + points[i - 1][0]) / 2}`;
728
+ result += ` V ${points[i][1]}`;
729
+ result += ` H ${points[i][0]}`;
730
+ } else {
731
+ result += ` H ${points[i][0]}`;
732
+ }
733
+ currentDirection = nextDirection;
734
+ } else {
735
+ if (points[i][1] < points[i - 1][1]) {
736
+ result += ` H ${points[i - 1][0] - minimumDistanceBeforeTurn}`;
737
+ result += ` V ${Math.min(points[i - 1][1], points[i][1]) - minimumDistanceBeforeTurn}`;
738
+ result += ` H ${points[i][0] + minimumDistanceBeforeTurn}`;
739
+ result += ` V ${points[i][1]}`;
740
+ result += ` H ${points[i][0]}`;
741
+ } else {
742
+ result += ` H ${points[i - 1][0] - minimumDistanceBeforeTurn}`;
743
+ result += ` V ${Math.max(points[i - 1][1], points[i][1]) + minimumDistanceBeforeTurn}`;
744
+ result += ` H ${points[i][0] + minimumDistanceBeforeTurn}`;
745
+ result += ` V ${points[i][1]}`;
746
+ result += ` H ${points[i][0]}`;
747
+ }
748
+ }
749
+ break;
750
+ case exports.Side.Right:
751
+ result += ` H ${Math.min(points[i - 1][0], points[i][0]) - minimumDistanceBeforeTurn}`;
614
752
  result += ` V ${points[i][1]}`;
615
753
  result += ` H ${points[i][0]}`;
616
- } else if (points[i][0] < points[i - 1][0] && points[i][1] === points[i - 1][1]) {
617
- // next point is in the same direction, we continue straight
754
+ break;
755
+ case exports.Side.Bottom:
756
+ if (points[i][0] < points[i - 1][0] - minimumDistanceBeforeTurn) {
757
+ if (points[i][1] > points[i - 1][1] + minimumDistanceBeforeTurn) {
758
+ result += ` H ${points[i][0]}`;
759
+ result += ` V ${points[i][1]}`;
760
+ } else {
761
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
762
+ result += ` V ${points[i][1] - minimumDistanceBeforeTurn}`;
763
+ result += ` H ${points[i][0]}`;
764
+ result += ` V ${points[i][1]}`;
765
+ }
766
+ } else {
767
+ if (points[i][1] > points[i - 1][1] + minimumDistanceBeforeTurn) {
768
+ result += ` H ${points[i - 1][0] - minimumDistanceBeforeTurn}`;
769
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
770
+ result += ` H ${points[i][0]}`;
771
+ result += ` V ${points[i][1]}`;
772
+ } else {
773
+ result += ` H ${points[i - 1][0] - minimumDistanceBeforeTurn}`;
774
+ result += ` V ${points[i][1] - minimumDistanceBeforeTurn}`;
775
+ result += ` H ${points[i][0]}`;
776
+ result += ` V ${points[i][1]}`;
777
+ }
778
+ }
779
+ break;
780
+ case exports.Side.Top:
781
+ if (points[i][0] < points[i - 1][0] - minimumDistanceBeforeTurn) {
782
+ if (points[i][1] < points[i - 1][1] - minimumDistanceBeforeTurn) {
783
+ result += ` H ${points[i][0]}`;
784
+ result += ` V ${points[i][1]}`;
785
+ } else {
786
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
787
+ result += ` V ${points[i][1] + minimumDistanceBeforeTurn}`;
788
+ result += ` H ${points[i][0]}`;
789
+ result += ` V ${points[i][1]}`;
790
+ }
791
+ } else {
792
+ if (points[i][1] < points[i - 1][1] - minimumDistanceBeforeTurn) {
793
+ result += ` H ${points[i - 1][0] - minimumDistanceBeforeTurn}`;
794
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
795
+ result += ` H ${points[i][0]}`;
796
+ result += ` V ${points[i][1]}`;
797
+ } else {
798
+ result += ` H ${points[i - 1][0] - minimumDistanceBeforeTurn}`;
799
+ result += ` V ${points[i][1] + minimumDistanceBeforeTurn}`;
800
+ result += ` H ${points[i][0]}`;
801
+ result += ` V ${points[i][1]}`;
802
+ }
803
+ }
804
+ break;
805
+ default:
806
+ if (points[i][0] > points[i - 1][0] - minimumDistanceBeforeTurn) {
807
+ result += ` H ${points[i - 1][0] - minimumDistanceBeforeTurn}`;
808
+ if (points[i][1] !== points[i - 1][1]) {
809
+ result += ` V ${points[i][1]}`;
810
+ }
811
+ result += ` H ${points[i][0]}`;
812
+ currentDirection = exports.Side.Right;
813
+ } else {
814
+ result += ` H ${points[i][0]}`;
815
+ currentDirection = exports.Side.Left;
816
+ if (points[i][1] !== points[i - 1][1]) {
817
+ result += ` V ${points[i][1]}`;
818
+ currentDirection = points[i][1] > points[i - 1][1] ? exports.Side.Bottom : exports.Side.Top;
819
+ }
820
+ }
821
+ break;
822
+ }
823
+ break;
824
+ case exports.Side.Right:
825
+ switch (nextDirection) {
826
+ case exports.Side.Right:
827
+ if (points[i][0] > points[i - 1][0]) {
828
+ if (points[i][1] !== points[i - 1][1]) {
829
+ result += ` H ${(points[i][0] + points[i - 1][0]) / 2}`;
830
+ result += ` V ${points[i][1]}`;
831
+ result += ` H ${points[i][0]}`;
832
+ } else {
833
+ result += ` H ${points[i][0]}`;
834
+ }
835
+ currentDirection = nextDirection;
836
+ } else {
837
+ if (points[i][1] > points[i - 1][1]) {
838
+ result += ` H ${points[i - 1][0] + minimumDistanceBeforeTurn}`;
839
+ result += ` V ${Math.max(points[i - 1][1], points[i][1]) + minimumDistanceBeforeTurn}`;
840
+ result += ` H ${points[i][0] - minimumDistanceBeforeTurn}`;
841
+ result += ` V ${points[i][1]}`;
842
+ result += ` H ${points[i][0]}`;
843
+ } else {
844
+ result += ` H ${points[i - 1][0] + minimumDistanceBeforeTurn}`;
845
+ result += ` V ${Math.min(points[i - 1][1], points[i][1]) - minimumDistanceBeforeTurn}`;
846
+ result += ` H ${points[i][0] - minimumDistanceBeforeTurn}`;
847
+ result += ` V ${points[i][1]}`;
848
+ result += ` H ${points[i][0]}`;
849
+ }
850
+ }
851
+ break;
852
+ case exports.Side.Left:
853
+ result += ` H ${Math.max(points[i - 1][0], points[i][0]) + minimumDistanceBeforeTurn}`;
854
+ result += ` V ${points[i][1]}`;
618
855
  result += ` H ${points[i][0]}`;
619
- }
620
- break;
621
- }
622
- } else {
623
- if (points[i][0] !== points[i - 1][0]) {
624
- result += ` H ${points[i][0]}`;
625
- currentDirection = points[i][0] > points[i - 1][0] ? exports.Side.Right : exports.Side.Left;
626
- }
627
- if (points[i][1] !== points[i - 1][1]) {
628
- result += ` V ${points[i][1]}`;
629
- currentDirection = points[i][1] > points[i - 1][1] ? exports.Side.Bottom : exports.Side.Top;
630
- }
856
+ break;
857
+ case exports.Side.Top:
858
+ if (points[i][0] > points[i - 1][0] + minimumDistanceBeforeTurn) {
859
+ if (points[i][1] < points[i - 1][1] - minimumDistanceBeforeTurn) {
860
+ result += ` H ${points[i][0]}`;
861
+ result += ` V ${points[i][1]}`;
862
+ } else {
863
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
864
+ result += ` V ${points[i][1] + minimumDistanceBeforeTurn}`;
865
+ result += ` H ${points[i][0]}`;
866
+ result += ` V ${points[i][1]}`;
867
+ }
868
+ } else {
869
+ if (points[i][1] < points[i - 1][1] - minimumDistanceBeforeTurn) {
870
+ result += ` H ${points[i - 1][0] + minimumDistanceBeforeTurn}`;
871
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
872
+ result += ` H ${points[i][0]}`;
873
+ result += ` V ${points[i][1]}`;
874
+ } else {
875
+ result += ` H ${points[i - 1][0] + minimumDistanceBeforeTurn}`;
876
+ result += ` V ${points[i][1] + minimumDistanceBeforeTurn}`;
877
+ result += ` H ${points[i][0]}`;
878
+ result += ` V ${points[i][1]}`;
879
+ }
880
+ }
881
+ break;
882
+ case exports.Side.Bottom:
883
+ if (points[i][0] > points[i - 1][0] + minimumDistanceBeforeTurn) {
884
+ if (points[i][1] > points[i - 1][1] + minimumDistanceBeforeTurn) {
885
+ result += ` H ${points[i][0]}`;
886
+ result += ` V ${points[i][1]}`;
887
+ } else {
888
+ result += ` H ${(points[i - 1][0] + points[i][0]) / 2}`;
889
+ result += ` V ${points[i][1] - minimumDistanceBeforeTurn}`;
890
+ result += ` H ${points[i][0]}`;
891
+ result += ` V ${points[i][1]}`;
892
+ }
893
+ } else {
894
+ if (points[i][1] > points[i - 1][1] + minimumDistanceBeforeTurn) {
895
+ result += ` H ${points[i - 1][0] + minimumDistanceBeforeTurn}`;
896
+ result += ` V ${(points[i - 1][1] + points[i][1]) / 2}`;
897
+ result += ` H ${points[i][0]}`;
898
+ result += ` V ${points[i][1]}`;
899
+ } else {
900
+ result += ` H ${points[i - 1][0] + minimumDistanceBeforeTurn}`;
901
+ result += ` V ${points[i][1] - minimumDistanceBeforeTurn}`;
902
+ result += ` H ${points[i][0]}`;
903
+ result += ` V ${points[i][1]}`;
904
+ }
905
+ }
906
+ break;
907
+ default:
908
+ if (points[i][0] < points[i - 1][0] + minimumDistanceBeforeTurn) {
909
+ result += ` H ${points[i - 1][0] + minimumDistanceBeforeTurn}`;
910
+ if (points[i][1] !== points[i - 1][1]) {
911
+ result += ` V ${points[i][1]}`;
912
+ }
913
+ result += ` H ${points[i][0]}`;
914
+ currentDirection = exports.Side.Left;
915
+ } else {
916
+ result += ` H ${points[i][0]}`;
917
+ currentDirection = exports.Side.Right;
918
+ if (points[i][1] !== points[i - 1][1]) {
919
+ result += ` V ${points[i][1]}`;
920
+ currentDirection = points[i][1] > points[i - 1][1] ? exports.Side.Bottom : exports.Side.Top;
921
+ }
922
+ }
923
+ break;
924
+ }
925
+ break;
926
+ default:
927
+ if (points[i][0] !== points[i - 1][0]) {
928
+ result += ` H ${points[i][0]}`;
929
+ currentDirection = points[i][0] > points[i - 1][0] ? exports.Side.Right : exports.Side.Left;
930
+ }
931
+ if (points[i][1] !== points[i - 1][1]) {
932
+ result += ` V ${points[i][1]}`;
933
+ currentDirection = points[i][1] > points[i - 1][1] ? exports.Side.Bottom : exports.Side.Top;
934
+ }
631
935
  }
632
936
  }
633
937
  break;
@@ -925,13 +1229,14 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
925
1229
  const extractLooksFromConfig = lookConfig => {
926
1230
  const {
927
1231
  selected,
928
- highlighted
1232
+ highlighted,
1233
+ selectedAndHighlighted
929
1234
  } = lookConfig,
930
- rest = __rest(lookConfig, ["selected", "highlighted"]);
1235
+ rest = __rest(lookConfig, ["selected", "highlighted", "selectedAndHighlighted"]);
931
1236
  const defaultLook = rest;
932
1237
  const selectedLook = Object.assign(Object.assign({}, defaultLook), selected);
933
1238
  const highlightedLook = Object.assign(Object.assign({}, defaultLook), highlighted);
934
- const selectedAndHighlightedLook = Object.assign(Object.assign(Object.assign({}, defaultLook), highlighted), selected);
1239
+ const selectedAndHighlightedLook = Object.assign(Object.assign(Object.assign(Object.assign({}, defaultLook), highlighted), selected), selectedAndHighlighted);
935
1240
  return {
936
1241
  defaultLook,
937
1242
  selectedLook,
@@ -3109,6 +3414,7 @@ const DIAGRAM_NODE_TYPE_DEFAULTS = {
3109
3414
  minHeight: 1,
3110
3415
  resizableX: false,
3111
3416
  resizableY: false,
3417
+ snapToGridOffset: [0, 0, 0, 0],
3112
3418
  padding: 0,
3113
3419
  label: null,
3114
3420
  ports: [],
@@ -3137,6 +3443,7 @@ class DiagramNodeType {
3137
3443
  this.minHeight = values.minHeight;
3138
3444
  this.resizableX = values.resizableX;
3139
3445
  this.resizableY = values.resizableY;
3446
+ this.snapToGridOffset = values.snapToGridOffset;
3140
3447
  this.bottomPadding = getBottomPadding(values);
3141
3448
  this.leftPadding = getLeftPadding(values);
3142
3449
  this.rightPadding = getRightPadding(values);
@@ -6274,7 +6581,10 @@ const SHAPED_LOOK_DEFAULTS = {
6274
6581
  borderStyle: exports.LineStyle.Solid
6275
6582
  };
6276
6583
  const updateLook = selection => {
6277
- selection.filter('.shaped-look').select('path').attr('d', d => generalClosedPath(d.look.shape || exports.ClosedShape.Rectangle, 0, 0, d.width, d.height)).attr('fill', d => d.look.fillColor || SHAPED_LOOK_DEFAULTS.fillColor).attr('stroke', d => d.look.borderColor || SHAPED_LOOK_DEFAULTS.borderColor).attr('stroke-width', d => `${d.look.borderThickness || SHAPED_LOOK_DEFAULTS.borderThickness}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.borderStyle || SHAPED_LOOK_DEFAULTS.borderStyle, d.look.borderThickness || SHAPED_LOOK_DEFAULTS.borderThickness));
6584
+ selection.filter('.shaped-look').select('path').attr('d', d => generalClosedPath(d.look.shape || exports.ClosedShape.Rectangle, 0, 0, d.width, d.height)).attr('fill', d => d.look.fillColor || SHAPED_LOOK_DEFAULTS.fillColor).attr('stroke', d => d.look.borderColor || SHAPED_LOOK_DEFAULTS.borderColor).attr('stroke-width', d => `${d.look.borderThickness || SHAPED_LOOK_DEFAULTS.borderThickness}px`).attr('stroke-dasharray', d => {
6585
+ var _a, _b, _c;
6586
+ return lineStyleDasharray(d.look.borderStyle || SHAPED_LOOK_DEFAULTS.borderStyle, ((_b = (_a = d.type) === null || _a === void 0 ? void 0 : _a.defaultLook) === null || _b === void 0 ? void 0 : _b.borderThickness) || ((_c = d.look) === null || _c === void 0 ? void 0 : _c.borderThickness) || SHAPED_LOOK_DEFAULTS.borderThickness);
6587
+ });
6278
6588
  selection.filter('.image-look').select('image').attr('x', 0).attr('y', 0).attr('width', d => d.width).attr('height', d => d.height).attr('href', d => d.look.backgroundImage);
6279
6589
  selection.filter('.stretchable-image-look').select('image.top-left-image').attr('x', 0).attr('y', 0).attr('width', d => d.look.leftMargin).attr('height', d => d.look.topMargin).attr('href', d => d.look.backgroundImageTopLeft);
6280
6590
  selection.filter('.stretchable-image-look').select('image.top-image').attr('x', d => d.look.leftMargin).attr('y', 0).attr('width', d => d.width - d.look.rightMargin - d.look.leftMargin).attr('height', d => d.look.topMargin).attr('href', d => d.look.backgroundImageTop);
@@ -7507,7 +7817,9 @@ class DiagramCanvas {
7507
7817
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.type.resizableX && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === exports.DiagramActions.StretchNode) {
7508
7818
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
7509
7819
  if (this.snapToGrid) {
7510
- pointerCoords = this.getClosestGridPoint(pointerCoords);
7820
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
7821
+ pointerCoords[0] += d.type.snapToGridOffset[0];
7822
+ pointerCoords[1] += d.type.snapToGridOffset[1];
7511
7823
  }
7512
7824
  d.stretch(exports.Side.Left, d.coords[0] - pointerCoords[0]);
7513
7825
  this.currentAction.to = d.getGeometry();
@@ -7541,7 +7853,9 @@ class DiagramCanvas {
7541
7853
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.type.resizableY && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === exports.DiagramActions.StretchNode) {
7542
7854
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
7543
7855
  if (this.snapToGrid) {
7544
- pointerCoords = this.getClosestGridPoint(pointerCoords);
7856
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[0], pointerCoords[1] - d.type.snapToGridOffset[1]]);
7857
+ pointerCoords[0] += d.type.snapToGridOffset[0];
7858
+ pointerCoords[1] += d.type.snapToGridOffset[1];
7545
7859
  }
7546
7860
  d.stretch(exports.Side.Top, d.coords[1] - pointerCoords[1]);
7547
7861
  this.currentAction.to = d.getGeometry();
@@ -7575,7 +7889,9 @@ class DiagramCanvas {
7575
7889
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.type.resizableX && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === exports.DiagramActions.StretchNode) {
7576
7890
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
7577
7891
  if (this.snapToGrid) {
7578
- pointerCoords = this.getClosestGridPoint(pointerCoords);
7892
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[2], pointerCoords[1] - d.type.snapToGridOffset[3]]);
7893
+ pointerCoords[0] += d.type.snapToGridOffset[2];
7894
+ pointerCoords[1] += d.type.snapToGridOffset[3];
7579
7895
  }
7580
7896
  d.stretch(exports.Side.Right, pointerCoords[0] - (d.coords[0] + d.width));
7581
7897
  this.currentAction.to = d.getGeometry();
@@ -7609,7 +7925,11 @@ class DiagramCanvas {
7609
7925
  if (this.canUserPerformAction(exports.DiagramActions.StretchNode) && d.type.resizableY && !d.removed && this.currentAction instanceof SetGeometryAction && this.currentAction.intent === exports.DiagramActions.StretchNode) {
7610
7926
  let pointerCoords = this.getPointerLocationRelativeToCanvas(event);
7611
7927
  if (this.snapToGrid) {
7612
- pointerCoords = this.getClosestGridPoint(pointerCoords);
7928
+ if (this.snapToGrid) {
7929
+ pointerCoords = this.getClosestGridPoint([pointerCoords[0] - d.type.snapToGridOffset[2], pointerCoords[1] - d.type.snapToGridOffset[3]]);
7930
+ pointerCoords[0] += d.type.snapToGridOffset[2];
7931
+ pointerCoords[1] += d.type.snapToGridOffset[3];
7932
+ }
7613
7933
  }
7614
7934
  d.stretch(exports.Side.Bottom, pointerCoords[1] - (d.coords[1] + d.height));
7615
7935
  this.currentAction.to = d.getGeometry();
@@ -7945,7 +8265,7 @@ class DiagramCanvas {
7945
8265
  if (this.canUserPerformAction(exports.DiagramActions.AddConnection) && !d.removed) {
7946
8266
  if (this.unfinishedConnection !== undefined) {
7947
8267
  const endCoords = [event.x, event.y];
7948
- (_a = this.unfinishedConnectionTracer) === null || _a === void 0 ? void 0 : _a.attr('d', getConnectionPath(this.unfinishedConnection.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, this.unfinishedConnection.startCoords, endCoords, this.unfinishedConnection.startDirection, this.unfinishedConnection.endDirection, this.unfinishedConnection.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_b = this.unfinishedConnection.startMarkerLook) === null || _b === void 0 ? void 0 : _b.width, (_c = this.unfinishedConnection.endMarkerLook) === null || _c === void 0 ? void 0 : _c.width));
8268
+ (_a = this.unfinishedConnectionTracer) === null || _a === void 0 ? void 0 : _a.attr('d', getConnectionPath(this.unfinishedConnection.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, this.unfinishedConnection.startCoords, endCoords, this.unfinishedConnection.startDirection, this.unfinishedConnection.endDirection, this.unfinishedConnection.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_b = this.unfinishedConnection.type.defaultStartMarkerLook) === null || _b === void 0 ? void 0 : _b.width, (_c = this.unfinishedConnection.type.defaultEndMarkerLook) === null || _c === void 0 ? void 0 : _c.width));
7949
8269
  const unfinishedConnectionGhostNode = (_d = this.unfinishedConnectionTracer) === null || _d === void 0 ? void 0 : _d.node();
7950
8270
  if (unfinishedConnectionGhostNode) {
7951
8271
  let margin = 2;
@@ -8093,14 +8413,14 @@ class DiagramCanvas {
8093
8413
  enterSelection.select('g.diagram-connection-end-label').append('text').style('user-select', 'none');
8094
8414
  mergeSelection.attr('opacity', d => d.removed ? 0.5 : 1).select('path.diagram-connection-path').attr('d', d => {
8095
8415
  var _a, _b;
8096
- return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.startMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.endMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8097
- }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.look.color || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.color).attr('stroke-width', d => `${d.look.thickness}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8416
+ return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.type.defaultStartMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.type.defaultEndMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8417
+ }).attr('marker-start', d => `url(#${d.id}-start-marker)`).attr('marker-end', d => `url(#${d.id}-end-marker)`).attr('stroke', d => d.look.color || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.color).attr('stroke-width', d => `${d.look.thickness}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8098
8418
  mergeSelection.select('path.diagram-connection-path-box').attr('d', d => {
8099
8419
  var _a, _b;
8100
- return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.startMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.endMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8420
+ return getConnectionPath(d.look.shape || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.shape, d.startCoords, d.endCoords, d.startDirection, d.endDirection, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness, (_a = d.type.defaultStartMarkerLook) === null || _a === void 0 ? void 0 : _a.width, (_b = d.type.defaultEndMarkerLook) === null || _b === void 0 ? void 0 : _b.width);
8101
8421
  }).attr('stroke', 'transparent')
8102
8422
  // allow generating pointer events even when it is transparent
8103
- .attr('pointer-events', 'stroke').attr('stroke-width', d => `${(d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness) + CONNECTION_PATH_BOX_THICKNESS}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8423
+ .attr('pointer-events', 'stroke').attr('stroke-width', d => `${(d.look.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness) + CONNECTION_PATH_BOX_THICKNESS}px`).attr('stroke-dasharray', d => lineStyleDasharray(d.look.style || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.style, d.type.defaultLook.thickness || DIAGRAM_CONNECTION_TYPE_DEFAULTS.look.thickness)).attr('fill', 'none');
8104
8424
  mergeSelection.data().forEach(connection => {
8105
8425
  this.updateConnectionLabelsInView(connection);
8106
8426
  this.updateConnectionMarkersInView(connection);
@@ -8391,20 +8711,16 @@ class DiagramCanvas {
8391
8711
  case exports.Side.Top:
8392
8712
  startLabelShiftX = deltaX >= 0 ? -0.5 : 0.5;
8393
8713
  endLabelShiftX = startLabelShiftX;
8394
- startLabelShiftY = -0.5;
8395
8714
  break;
8396
8715
  case exports.Side.Bottom:
8397
8716
  startLabelShiftX = deltaX >= 0 ? -0.5 : 0.5;
8398
8717
  endLabelShiftX = startLabelShiftX;
8399
- startLabelShiftY = 0.5;
8400
8718
  break;
8401
8719
  case exports.Side.Left:
8402
- startLabelShiftX = -0.5;
8403
8720
  startLabelShiftY = deltaY > 0 ? -0.5 : 0.5;
8404
8721
  endLabelShiftY = startLabelShiftY;
8405
8722
  break;
8406
8723
  case exports.Side.Right:
8407
- startLabelShiftX = 0.5;
8408
8724
  startLabelShiftY = deltaY > 0 ? -0.5 : 0.5;
8409
8725
  endLabelShiftY = startLabelShiftY;
8410
8726
  break;
@@ -8417,18 +8733,14 @@ class DiagramCanvas {
8417
8733
  switch (connection.endDirection) {
8418
8734
  case exports.Side.Top:
8419
8735
  endLabelShiftX = deltaX >= 0 ? 0.5 : -0.5;
8420
- endLabelShiftY = 0.5;
8421
8736
  break;
8422
8737
  case exports.Side.Bottom:
8423
8738
  endLabelShiftX = deltaX >= 0 ? 0.5 : -0.5;
8424
- endLabelShiftY = -0.5;
8425
8739
  break;
8426
8740
  case exports.Side.Left:
8427
- endLabelShiftX = -0.5;
8428
8741
  endLabelShiftY = deltaY > 0 ? 0.5 : -0.5;
8429
8742
  break;
8430
8743
  case exports.Side.Right:
8431
- endLabelShiftX = 0.5;
8432
8744
  endLabelShiftY = deltaY > 0 ? 0.5 : -0.5;
8433
8745
  break;
8434
8746
  default:
@@ -8452,7 +8764,23 @@ class DiagramCanvas {
8452
8764
  // don't create space for the label if the label is empty
8453
8765
  const boundingWidth = !connection.startLabel ? 0 : startLabelBoundingRect.width / this.zoomTransform.k + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
8454
8766
  const boundingHeight = !connection.startLabel ? 0 : startLabelBoundingRect.height / this.zoomTransform.k + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
8455
- const pathStartLabelPoint = pathNode.getPointAtLength(Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
8767
+ let pathStartLabelPoint;
8768
+ switch (connection.startDirection) {
8769
+ case exports.Side.Left:
8770
+ pathStartLabelPoint = pathNode.getPointAtLength(getRightMargin(labelConfiguration) + boundingWidth / 2);
8771
+ break;
8772
+ case exports.Side.Right:
8773
+ pathStartLabelPoint = pathNode.getPointAtLength(getLeftMargin(labelConfiguration) + boundingWidth / 2);
8774
+ break;
8775
+ case exports.Side.Top:
8776
+ pathStartLabelPoint = pathNode.getPointAtLength(getBottomMargin(labelConfiguration) + boundingWidth / 2);
8777
+ break;
8778
+ case exports.Side.Bottom:
8779
+ pathStartLabelPoint = pathNode.getPointAtLength(getTopMargin(labelConfiguration) + boundingWidth / 2);
8780
+ break;
8781
+ default:
8782
+ pathStartLabelPoint = pathNode.getPointAtLength(Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
8783
+ }
8456
8784
  connectionSelection.select('g.diagram-connection-start-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.backgroundColor).attr('stroke', 'none');
8457
8785
  connectionSelection.select('g.diagram-connection-start-label').attr('transform', `translate(${pathStartLabelPoint.x + startLabelShiftX * boundingWidth},${pathStartLabelPoint.y + startLabelShiftY * boundingHeight})`);
8458
8786
  }
@@ -8474,7 +8802,23 @@ class DiagramCanvas {
8474
8802
  // don't create space for the label if the label is empty
8475
8803
  const boundingWidth = !connection.endLabel ? 0 : endLabelBoundingRect.width / this.zoomTransform.k + getLeftPadding$1(labelConfiguration) + getRightPadding$1(labelConfiguration);
8476
8804
  const boundingHeight = !connection.endLabel ? 0 : endLabelBoundingRect.height / this.zoomTransform.k + getTopPadding$1(labelConfiguration) + getBottomPadding$1(labelConfiguration);
8477
- const pathEndLabelPoint = pathNode.getPointAtLength(pathLength - Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
8805
+ let pathEndLabelPoint;
8806
+ switch (connection.endDirection) {
8807
+ case exports.Side.Left:
8808
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getRightMargin(labelConfiguration) + boundingWidth / 2));
8809
+ break;
8810
+ case exports.Side.Right:
8811
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getLeftMargin(labelConfiguration) + boundingWidth / 2));
8812
+ break;
8813
+ case exports.Side.Top:
8814
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getBottomMargin(labelConfiguration) + boundingWidth / 2));
8815
+ break;
8816
+ case exports.Side.Bottom:
8817
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - (getTopMargin(labelConfiguration) + boundingWidth / 2));
8818
+ break;
8819
+ default:
8820
+ pathEndLabelPoint = pathNode.getPointAtLength(pathLength - Math.max(getLeftMargin(labelConfiguration) + boundingWidth / 2, getRightMargin(labelConfiguration) + boundingWidth / 2, getTopMargin(labelConfiguration) + boundingHeight / 2, getBottomMargin(labelConfiguration) + boundingHeight / 2));
8821
+ }
8478
8822
  connectionSelection.select('g.diagram-connection-end-label path').attr('d', pillPath(-boundingWidth / 2, -boundingHeight / 2, boundingWidth, boundingHeight)).attr('fill', labelConfiguration.backgroundColor).attr('stroke', 'none');
8479
8823
  connectionSelection.select('g.diagram-connection-end-label').attr('transform', `translate(${pathEndLabelPoint.x + endLabelShiftX * boundingWidth},${pathEndLabelPoint.y + endLabelShiftY * boundingHeight})`);
8480
8824
  }
@@ -8835,7 +9179,9 @@ class DiagramCanvas {
8835
9179
  if (this.draggingFrom[0] !== event.x || this.draggingFrom[1] !== event.y) {
8836
9180
  let newNodeCoords = [event.x - d.width / 2, event.y - d.height / 2];
8837
9181
  if (this.snapToGrid) {
8838
- newNodeCoords = this.getClosestGridPoint(newNodeCoords);
9182
+ newNodeCoords = this.getClosestGridPoint([newNodeCoords[0] - d.type.snapToGridOffset[0], newNodeCoords[1] - d.type.snapToGridOffset[1]]);
9183
+ newNodeCoords[0] += d.type.snapToGridOffset[0];
9184
+ newNodeCoords[1] += d.type.snapToGridOffset[1];
8839
9185
  }
8840
9186
  if (this.currentAction instanceof MoveAction) {
8841
9187
  const movingFrom = this.currentAction.delta;
@@ -9529,7 +9875,9 @@ class ForceLayout {
9529
9875
  }
9530
9876
  if (model.canvas && model.canvas.snapToGrid) {
9531
9877
  for (const node of model.nodes) {
9532
- const snappedCoords = model.canvas.getClosestGridPoint(node.coords);
9878
+ const snappedCoords = model.canvas.getClosestGridPoint([node.coords[0] - node.type.snapToGridOffset[0], node.coords[1] - node.type.snapToGridOffset[1]]);
9879
+ snappedCoords[0] += node.type.snapToGridOffset[0];
9880
+ snappedCoords[1] += node.type.snapToGridOffset[1];
9533
9881
  node.move(snappedCoords);
9534
9882
  }
9535
9883
  }